Zentient Results Api Reference Inspection Querying - ulfbou/Zentient.Results GitHub Wiki
After an operation returns an IResult or IResult<T>, you'll need to inspect its state to determine whether it was successful or a failure, access its value (if successful), or retrieve error details (if failed). Zentient.Results provides straightforward properties and utility methods for this purpose, allowing you to query the result's state and data effectively.
These properties provide the fundamental way to determine the outcome of an operation.
-
Signature:
bool IsSuccess { get; }(onIResultandIResult<T>) - Purpose: Indicates whether the operation completed successfully. This is the primary way to check for a positive outcome.
-
Example:
using Zentient.Results; IResult<int> divisionResult = Divide(10, 2); if (divisionResult.IsSuccess) { Console.WriteLine($"Division was successful: {divisionResult.Value}"); } else { Console.WriteLine($"Division failed."); }
-
Signature:
bool IsFailure { get; }(onIResultandIResult<T>) -
Purpose: Indicates whether the operation failed. This is the logical opposite of
IsSuccess. -
Example:
using Zentient.Results; IResult saveResult = SaveData("invalid data"); if (saveResult.IsFailure) { Console.WriteLine($"Data save failed: {saveResult.Error}"); } else { Console.WriteLine($"Data saved successfully."); }
When dealing with IResult<T>, you'll need to access the encapsulated value. Zentient.Results offers several ways to do this, ranging from direct (but potentially unsafe) property access to robust methods that handle failure scenarios gracefully.
-
Signature:
T? Value { get; }(onIResult<T>) -
Purpose: Retrieves the successful value of type
T. -
Important: This property will return
default(T)(e.g.,nullfor reference types,0forint) ifIsFailureistrue. Always checkIsSuccessbefore accessingValueto avoid unexpectednullreferences or default values in failure scenarios. -
Example:
using Zentient.Results; IResult<User> userResult = GetUserById(123); if (userResult.IsSuccess) { User user = userResult.Value; // Safe access after checking IsSuccess Console.WriteLine($"User Name: {user.Name}"); } else { Console.WriteLine($"Could not retrieve user."); }
-
Signature:
-
public T GetValueOrDefault(T fallback)(onIResult<T>) -
public T GetValueOrDefault()(onIResult<T>, returnsdefault(T)on failure)
-
- Purpose: Provides a safe way to get the successful value or return a specified fallback value if the result is a failure.
-
Parameters:
-
fallback: The value to return if the result is a failure.
-
-
Example:
using Zentient.Results; IResult<int> parseResult = ParseNumber("abc"); // Assume this fails int parsedNumber = parseResult.GetValueOrDefault(-1); // Returns -1 if parseResult is a failure Console.WriteLine($"Parsed number: {parsedNumber}"); // Output: -1 IResult<string> nameResult = GetUserName(456); // Assume this succeeds string userName = nameResult.GetValueOrDefault("Guest"); // Returns "Alice" if successful, "Guest" if failed Console.WriteLine($"User name: {userName}");
-
Signature:
-
public T GetValueOrThrow()(onIResult<T>) -
public T GetValueOrThrow(string message)(onIResult<T>) -
public T GetValueOrThrow(Func<Exception> exceptionFactory)(onIResult<T>)
-
- Purpose: Retrieves the value if the result is successful, otherwise throws an exception. This is useful in contexts where a failure at this point indicates a critical error that should halt execution, or when you've already handled the failure path and expect success.
-
Throws:
-
InvalidOperationExceptionifIsFailureistrue. - A custom exception type if
exceptionFactoryis provided.
-
-
Example:
using Zentient.Results; public User GetUserOrThrow(int userId) { IResult<User> userResult = GetUserById(userId); return userResult.GetValueOrThrow($"Failed to get user with ID {userId}"); // Throws InvalidOperationException on failure } try { User user = GetUserOrThrow(999); // Assume this fails Console.WriteLine($"User: {user.Name}"); } catch (InvalidOperationException ex) { Console.WriteLine($"Error: {ex.Message}"); // Output: Error: Failed to get user with ID 999 }
When an IResult or IResult<T> is a failure, you'll need to retrieve the details about what went wrong.
-
Signature:
IReadOnlyList<ErrorInfo> Errors { get; }(onIResultandIResult<T>) -
Purpose: Provides access to a collection of structured error information. This list will be empty if
IsSuccessistrue. -
See Also:
ErrorInfoStruct -
Example:
using Zentient.Results; using System.Linq; IResult registrationResult = RegisterUser("test", "bad_password"); // Assume this returns multiple validation errors if (registrationResult.IsFailure) { Console.WriteLine("Registration Errors:"); foreach (var error in registrationResult.Errors) { Console.WriteLine($"- {error.Code}: {error.Message}"); } }
-
Signature:
string? Error { get; }(onIResultandIResult<T>) -
Purpose: A convenience property that returns the
Messageof the firstErrorInfoin theErrorslist. If theErrorslist is empty, it returnsnull. -
Example:
using Zentient.Results; IResult loginResult = Authenticate("user", "wrong_pass"); // Assume this fails with one error if (loginResult.IsFailure) { Console.WriteLine($"Login failed: {loginResult.Error}"); // Output: Login failed: Invalid credentials. }
The Status property provides a standardized way to understand the overall semantic outcome of the operation, often mapping to HTTP status codes.
-
Signature:
IResultStatus Status { get; }(onIResultandIResult<T>) -
Purpose: Represents the overall semantic status of the operation (e.g.,
Ok,NotFound,BadRequest). -
See Also:
IResultStatusInterface,ResultStatusesStatic Class -
Example:
using Zentient.Results; IResult deleteResult = DeleteResource("nonexistent-id"); // Assume this returns NotFound if (deleteResult.Status == ResultStatuses.NotFound) { Console.WriteLine("Resource was not found for deletion."); } else if (deleteResult.Status.IsSuccess) { Console.WriteLine("Resource deleted successfully."); } else { Console.WriteLine($"Operation failed with status: {deleteResult.Status.Code} ({deleteResult.Status.Description})"); }
While Map, Bind, Then, OnSuccess, OnFailure, and Match are powerful inspection and transformation tools, they are primarily covered in the Functional Utilities section due to their role in chaining and composition. However, their purpose often involves inspecting the result's state and acting upon it.
-
Map<T, U>(...): IfIsSuccess, transformsValueto a new typeU. -
Bind<T, U>(...): IfIsSuccess, passesValueto a function that returns a newIResult<U>. -
Then<T>(...): IfIsSuccess, passesValue(or just proceeds for non-generic) to a function returning a non-genericIResult. -
OnSuccess(...)/Tap(...): IfIsSuccess, performs a side-effecting action withValue. -
OnFailure(...): IfIsFailure, performs a side-effecting action withErrors. -
Match(...): Forces handling of bothIsSuccessandIsFailurepaths, producing a unified output.
These methods embody robust inspection and conditional execution, making your code cleaner and more resilient.