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; }
(onIResult
andIResult<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; }
(onIResult
andIResult<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.,null
for reference types,0
forint
) ifIsFailure
istrue
. Always checkIsSuccess
before accessingValue
to avoid unexpectednull
references 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:
-
InvalidOperationException
ifIsFailure
istrue
. - A custom exception type if
exceptionFactory
is 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; }
(onIResult
andIResult<T>
) -
Purpose: Provides access to a collection of structured error information. This list will be empty if
IsSuccess
istrue
. -
See Also:
ErrorInfo
Struct -
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; }
(onIResult
andIResult<T>
) -
Purpose: A convenience property that returns the
Message
of the firstErrorInfo
in theErrors
list. If theErrors
list 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; }
(onIResult
andIResult<T>
) -
Purpose: Represents the overall semantic status of the operation (e.g.,
Ok
,NotFound
,BadRequest
). -
See Also:
IResultStatus
Interface,ResultStatuses
Static 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
, transformsValue
to a new typeU
. -
Bind<T, U>(...)
: IfIsSuccess
, passesValue
to 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 bothIsSuccess
andIsFailure
paths, producing a unified output.
These methods embody robust inspection and conditional execution, making your code cleaner and more resilient.