Class Result
Factory methods for non-generic Result.
public class Result : IResultBase
- Inheritance
-
Result
- Implements
- Derived
-
Result<TValue>
- Inherited Members
- Extension Methods
Constructors
Result()
Initializes a new instance of the Result class with no reasons. This constructor is protected and used internally for creating successful results.
protected Result()
Result(IReason)
Initializes a new instance of the Result class with a single reason. This constructor is protected and used internally.
protected Result(IReason reason)
Parameters
reasonIReasonThe reason associated with this result.
Properties
Errors
Gets the error reasons. Empty when IsSuccess is true.
public ImmutableList<IError> Errors { get; }
Property Value
IsFailure
Gets a value indicating whether this result represents a failed outcome.
public bool IsFailure { get; }
Property Value
IsSuccess
Gets a value indicating whether this result represents a successful outcome.
public bool IsSuccess { get; }
Property Value
Reasons
Gets all reasons (both errors and successes) attached to this result.
public ImmutableList<IReason> Reasons { get; }
Property Value
Successes
Gets the success reasons. Empty when IsFailure is true.
public ImmutableList<ISuccess> Successes { get; }
Property Value
Methods
Combine(params Result[])
Combines results with params syntax.
public static Result Combine(params Result[] results)
Parameters
resultsResult[]
Returns
Combine(IEnumerable<Result>)
Combines results - ALL must succeed for combined result to succeed. If any fail, returns failed result with all errors. Only preserves success reasons if ALL succeeded.
public static Result Combine(IEnumerable<Result> results)
Parameters
resultsIEnumerable<Result>
Returns
Examples
var validation = Result.Combine(
ValidateEmail(email),
ValidateAge(age),
ValidateName(name)
);
CombineParallelAsync(IEnumerable<Task<Result>>)
Combines results from parallel async operations. Waits for all tasks even if some fail.
public static Task<Result> CombineParallelAsync(IEnumerable<Task<Result>> resultTasks)
Parameters
resultTasksIEnumerable<Task<Result>>
Returns
Deconstruct(out bool, out ImmutableList<IError>)
Deconstructs the result into success flag and errors.
public void Deconstruct(out bool isSuccess, out ImmutableList<IError> errors)
Parameters
isSuccessboolerrorsImmutableList<IError>
Examples
var (isSuccess, errors) = DoSomething();
if (!isSuccess) HandleErrors(errors);
Fail(IError)
Creates a failed result with an error reason.
public static Result Fail(IError error)
Parameters
errorIErrorThe error reason to include.
Returns
- Result
A failed Result with the specified error reason.
Examples
var error = new ValidationError("Invalid email format");
var result = Result.Fail(error);
Fail(IEnumerable<IError>)
Creates a failed result with multiple error reasons.
public static Result Fail(IEnumerable<IError> errors)
Parameters
errorsIEnumerable<IError>Collection of error reasons.
Returns
- Result
A failed Result with the specified error reasons.
Examples
var errors = new[]
{
new ValidationError("Name is required"),
new ValidationError("Email is invalid")
};
var result = Result.Fail(errors);
Fail(IEnumerable<string>)
Creates a failed result with multiple error messages.
public static Result Fail(IEnumerable<string> messages)
Parameters
messagesIEnumerable<string>Collection of error messages.
Returns
- Result
A failed Result with the specified error messages.
Examples
var errors = new[] { "Name is required", "Email is invalid" };
var result = Result.Fail(errors);
Fail(string)
Creates a failed result with an error message.
public static Result Fail(string message)
Parameters
messagestringThe error message to include.
Returns
- Result
A failed Result with the specified error message.
Examples
var result = Result.Fail("Operation failed");
Console.WriteLine(result.IsFailure); // true
FailIf(bool, IError)
Returns Fail if condition is true, otherwise Ok with error.
public static Result FailIf(bool condition, IError error)
Parameters
Returns
- Result
Fail if condition is true, otherwise Ok.
Examples
var error = new ValidationError("Account is suspended");
var result = Result.FailIf(user.IsSuspended, error);
FailIf(bool, string)
Returns Fail if condition is true, otherwise Ok.
public static Result FailIf(bool condition, string errorMessage)
Parameters
Returns
Examples
var result = Result.FailIf(age < 18, "Must be 18 or older");
FailIf(bool, string, string)
Returns Fail if condition is true, otherwise Ok with success message.
public static Result FailIf(bool condition, string errorMessage, string successMessage)
Parameters
conditionboolThe condition to evaluate.
errorMessagestringThe error message if condition is true.
successMessagestringThe success message if condition is false.
Returns
- Result
Fail if condition is true, otherwise Ok with success message.
Examples
var result = Result.FailIf(
age < 18,
"Must be 18 or older",
"Age validation passed"
);
FailIf(Func<bool>, string)
Evaluates condition lazily.
public static Result FailIf(Func<bool> predicate, string errorMessage)
Parameters
predicateFunc<bool>Function that returns the condition to evaluate.
errorMessagestringThe error message if condition is true.
Returns
- Result
Fail if condition is true, otherwise Ok.
Examples
var result = Result.FailIf(
() => _database.IsAccountSuspended(userId),
"Account is suspended"
);
FailIfAsync(Func<Task<bool>>, string)
Async version.
public static Task<Result> FailIfAsync(Func<Task<bool>> predicate, string errorMessage)
Parameters
predicateFunc<Task<bool>>Async function that returns the condition to evaluate.
errorMessagestringThe error message if condition is true.
Returns
Examples
var result = await Result.FailIfAsync(
() => _api.IsAccountSuspendedAsync(userId),
"Account is suspended"
);
MatchAsync(Func<Task>, Func<ImmutableList<IError>, Task>, CancellationToken)
Asynchronously executes one of two async actions based on success or failure.
public Task MatchAsync(Func<Task> onSuccess, Func<ImmutableList<IError>, Task> onFailure, CancellationToken cancellationToken = default)
Parameters
onSuccessFunc<Task>Async action to execute on success.
onFailureFunc<ImmutableList<IError>, Task>Async action to execute on failure with errors.
cancellationTokenCancellationTokenOptional cancellation token.
Returns
- Task
A task representing the async operation.
Match<TOut>(Func<TOut>, Func<ImmutableList<IError>, TOut>)
Matches result to one of two functions based on success or failure.
public TOut Match<TOut>(Func<TOut> onSuccess, Func<ImmutableList<IError>, TOut> onFailure)
Parameters
onSuccessFunc<TOut>Function to execute on success.
onFailureFunc<ImmutableList<IError>, TOut>Function to execute on failure with errors.
Returns
- TOut
The result of the executed function.
Type Parameters
TOutThe return type.
Merge(params Result[])
Merges multiple results with params syntax.
public static Result Merge(params Result[] results)
Parameters
resultsResult[]
Returns
Merge(IEnumerable<Result>)
Merges multiple results, preserving all reasons. Returns failed if ANY result is failed, success only if ALL succeeded.
public static Result Merge(IEnumerable<Result> results)
Parameters
resultsIEnumerable<Result>
Returns
Examples
var results = new[] {
Result.Ok().WithSuccess("Step 1"),
Result.Ok().WithSuccess("Step 2"),
Result.Fail("Error in step 3")
};
var merged = Result.Merge(results);
// merged.IsFailure == true
// merged.Errors contains "Error in step 3"
// merged.Successes contains "Step 1", "Step 2"
Ok()
Creates a successful result with no value.
public static Result Ok()
Returns
- Result
A successful Result.
Examples
var result = Result.Ok();
Console.WriteLine(result.IsSuccess); // true
Ok(ISuccess)
Creates a successful result with a success reason.
public static Result Ok(ISuccess success)
Parameters
successISuccessThe success reason to include.
Returns
- Result
A successful Result with the success reason.
Examples
var success = new Success("User created");
var result = Result.Ok(success);
Ok(IEnumerable<string>)
Creates a successful result with multiple success messages.
public static Result Ok(IEnumerable<string> messages)
Parameters
messagesIEnumerable<string>Collection of success messages.
Returns
- Result
A successful Result with the messages.
Examples
var messages = new[] { "Validated", "Processed" };
var result = Result.Ok(messages);
Ok(ImmutableList<ISuccess>)
Creates a successful result with multiple success reasons.
public static Result Ok(ImmutableList<ISuccess> successes)
Parameters
successesImmutableList<ISuccess>Collection of success reasons.
Returns
- Result
A successful Result with the success reasons.
Examples
var successes = new[]
{
new Success("Validated"),
new Success("Processed")
};
var result = Result.Ok(successes);
Ok(string)
Creates a successful result with a success message.
public static Result Ok(string message)
Parameters
messagestringThe success message to include.
Returns
- Result
A successful Result with the message.
Examples
var result = Result.Ok("Operation completed successfully");
OkIf(bool, IError)
Returns Ok if condition is true, otherwise Fail with error.
public static Result OkIf(bool condition, IError error)
Parameters
Returns
- Result
Ok if condition is true, otherwise a failed result.
Examples
var error = new ValidationError("User must be active");
var result = Result.OkIf(user.IsActive, error);
OkIf(bool, string)
Returns Ok if condition is true, otherwise Fail with message.
public static Result OkIf(bool condition, string errorMessage)
Parameters
conditionboolThe condition to evaluate.
errorMessagestringThe error message if condition is false.
Returns
- Result
Ok if condition is true, otherwise a failed result.
Examples
var result = Result.OkIf(age >= 18, "Must be 18 or older");
OkIf(bool, string, string)
Returns Ok with success message if condition is true, otherwise Fail.
public static Result OkIf(bool condition, string errorMessage, string successMessage)
Parameters
conditionboolThe condition to evaluate.
errorMessagestringThe error message if condition is false.
successMessagestringThe success message if condition is true.
Returns
- Result
Ok with success message if condition is true, otherwise a failed result.
Examples
var result = Result.OkIf(
age >= 18,
"Must be 18 or older",
"Age validation passed"
);
OkIf(Func<bool>, string)
Evaluates condition lazily - useful for expensive checks.
public static Result OkIf(Func<bool> predicate, string errorMessage)
Parameters
predicateFunc<bool>Function that returns the condition to evaluate.
errorMessagestringThe error message if condition is false.
Returns
- Result
Ok if condition is true, otherwise a failed result.
Examples
var result = Result.OkIf(
() => _database.IsUserActive(userId),
"User is not active"
);
OkIfAsync(Func<Task<bool>>, string)
Async version - evaluates condition asynchronously.
public static Task<Result> OkIfAsync(Func<Task<bool>> predicate, string errorMessage)
Parameters
predicateFunc<Task<bool>>Async function that returns the condition to evaluate.
errorMessagestringThe error message if condition is false.
Returns
Examples
var result = await Result.OkIfAsync(
() => _api.CheckUserExistsAsync(userId),
"User does not exist"
);
Recover(Func<ImmutableList<IError>, Result>)
Recovers from a failure by invoking recover with the current errors.
If the result is successful, it is returned unchanged.
public Result Recover(Func<ImmutableList<IError>, Result> recover)
Parameters
recoverFunc<ImmutableList<IError>, Result>Function that receives the current errors and returns a new result.
Returns
- Result
The original result if successful; otherwise the result of
recover.
Examples
Result result = await DeleteUser(id)
.Recover(errors => ArchiveUser(id));
RecoverAsync(Func<ImmutableList<IError>, Task<Result>>, CancellationToken)
Asynchronously recovers from a failure by invoking recover with the current errors.
If the result is successful, it is returned unchanged.
public Task<Result> RecoverAsync(Func<ImmutableList<IError>, Task<Result>> recover, CancellationToken cancellationToken = default)
Parameters
recoverFunc<ImmutableList<IError>, Task<Result>>Async function that receives the current errors and returns a new result.
cancellationTokenCancellationTokenOptional cancellation token.
Returns
Retry(Func<Task<Result>>, int, TimeSpan?, double, CancellationToken)
Retries an async non-generic operation up to maxRetries times.
public static Task<Result> Retry(Func<Task<Result>> operation, int maxRetries = 3, TimeSpan? delay = null, double backoffFactor = 1, CancellationToken cancellationToken = default)
Parameters
operationFunc<Task<Result>>maxRetriesintdelayTimeSpan?backoffFactordoublecancellationTokenCancellationToken
Returns
Retry<T>(Func<Task<Result<T>>>, int, TimeSpan?, double, CancellationToken)
Retries an async operation that returns Result<T> up to maxRetries times. Uses configurable delay with optional exponential backoff.
public static Task<Result<T>> Retry<T>(Func<Task<Result<T>>> operation, int maxRetries = 3, TimeSpan? delay = null, double backoffFactor = 1, CancellationToken cancellationToken = default)
Parameters
operationFunc<Task<Result<T>>>The async operation to retry.
maxRetriesintMaximum number of retries after the first attempt. Default is 3.
delayTimeSpan?Delay between retries. Default is 1 second.
backoffFactordoubleMultiplier applied to delay after each retry. Default is 1.0 (constant delay). Use 2.0 for exponential backoff.
cancellationTokenCancellationTokenOptional cancellation token.
Returns
Type Parameters
T
Examples
// Simple retry
var result = await Result.Retry(() => CallExternalApi(), maxRetries: 3);
// Exponential backoff
var result = await Result.Retry(
() => CallExternalApi(),
maxRetries: 3,
delay: TimeSpan.FromSeconds(1),
backoffFactor: 2.0);
Tap(Action)
Executes a side effect without modifying the result. Useful for logging, telemetry, or other side effects that shouldn't affect the result flow.
public Result Tap(Action action)
Parameters
actionActionThe action to execute if the result is successful.
Returns
- Result
The original result unchanged.
Examples
var result = Result.Ok()
.Tap(() => Console.WriteLine("Operation completed successfully"));
TapAsync(Func<Task>, CancellationToken)
Executes a side effect asynchronously without modifying the result. Useful for async logging, telemetry, or other side effects that shouldn't affect the result flow.
public Task<Result> TapAsync(Func<Task> action, CancellationToken cancellationToken = default)
Parameters
actionFunc<Task>The async action to execute if the result is successful.
cancellationTokenCancellationTokenOptional cancellation token.
Returns
Examples
var result = await Result.Ok()
.TapAsync(async () => await logger.LogAsync("Operation completed"));
ToResult<TValue>(Func<TValue>)
Converts this Result to a Result with a value from a func valueFactory. If this Result is failed, returns a failed Result<TValue> with the same reasons. If this Result is successful, executes the valueFactory to create the value.
public Result<TValue> ToResult<TValue>(Func<TValue> valueFactory)
Parameters
valueFactoryFunc<TValue>Function to create the value for the successful case.
Returns
- Result<TValue>
A new Result<TValue> with the factory-created value or the original errors.
Type Parameters
TValueThe type of the value.
Examples
var result = Result.Ok();
var userResult = result.ToResult(() => CreateUserFromDatabase());
// userResult.IsSuccess == true
// userResult.Value contains the user from database
ToResult<TValue>(TValue)
Converts this Result to a Result with a value. If this Result is failed, returns a failed Result<TValue> with the same reasons. If this Result is successful, returns a successful Result<TValue> with the provided value.
public Result<TValue> ToResult<TValue>(TValue value)
Parameters
valueTValueThe value to use for the successful case.
Returns
- Result<TValue>
A new Result<TValue> with the provided value or the original errors.
Type Parameters
TValueThe type of the value.
Examples
var result = Result.Ok();
var userResult = result.ToResult(new User { Name = "John" });
// userResult.IsSuccess == true
// userResult.Value.Name == "John"
ToString()
Returns a string representation of the Result.
public override string ToString()
Returns
Try(Action, Func<Exception, IError>?)
Executes an operation and wraps the result in a Result. If the operation throws an exception, returns a failed Result with an ExceptionError.
public static Result Try(Action operation, Func<Exception, IError>? errorHandler = null)
Parameters
operationActionThe operation to execute.
errorHandlerFunc<Exception, IError>Optional custom error handler. If null, creates an ExceptionError.
Returns
- Result
A successful Result, or a failed Result with the error.
Examples
// Simple usage
var result = Result.Try(() => File.WriteAllText("file.txt", "content"));
// With custom error handler
var result = Result.Try(
() => DeleteFile(path),
ex => new Error($"Failed to delete file: {ex.Message}")
.WithTags("FilePath", path)
);
TryAsync(Func<Task>, Func<Exception, IError>?, CancellationToken)
Asynchronously executes an operation and wraps the result in a Result. If the operation throws an exception, returns a failed Result with an ExceptionError.
public static Task<Result> TryAsync(Func<Task> operation, Func<Exception, IError>? errorHandler = null, CancellationToken cancellationToken = default)
Parameters
operationFunc<Task>The async operation to execute.
errorHandlerFunc<Exception, IError>Optional custom error handler. If null, creates an ExceptionError.
cancellationTokenCancellationTokenOptional cancellation token.
Returns
Examples
// Simple usage
var result = await Result.TryAsync(
async () => await File.WriteAllTextAsync("file.txt", "content")
);
// With custom error handler
var result = await Result.TryAsync(
async () => await DeleteFileAsync(path),
ex => new Error($"Failed to delete file: {ex.Message}")
.WithTags("FilePath", path)
);
Validate<T1, T2, TResult>(Result<T1>, Result<T2>, Func<T1, T2, TResult>)
Validates two independent results and maps their values to a combined result. Runs ALL validations independently — errors accumulate, not short-circuited.
public static Result<TResult> Validate<T1, T2, TResult>(Result<T1> r1, Result<T2> r2, Func<T1, T2, TResult> mapper)
Parameters
Returns
- Result<TResult>
Type Parameters
T1T2TResult
Examples
Result<OrderDto> dto = Result.Validate(
ValidateName(request.Name),
ValidateEmail(request.Email),
(name, email) => new OrderDto(name, email));
// If both fail, dto.Errors contains BOTH errors simultaneously
Validate<T1, T2, T3, TResult>(Result<T1>, Result<T2>, Result<T3>, Func<T1, T2, T3, TResult>)
Validates three independent results and maps their values to a combined result. Runs ALL validations independently — errors accumulate, not short-circuited.
public static Result<TResult> Validate<T1, T2, T3, TResult>(Result<T1> r1, Result<T2> r2, Result<T3> r3, Func<T1, T2, T3, TResult> mapper)
Parameters
Returns
- Result<TResult>
Type Parameters
T1T2T3TResult
Examples
Result<OrderDto> dto = Result.Validate(
ValidateName(request.Name),
ValidateEmail(request.Email),
ValidateAge(request.Age),
(name, email, age) => new OrderDto(name, email, age));
Validate<T1, T2, T3, T4, TResult>(Result<T1>, Result<T2>, Result<T3>, Result<T4>, Func<T1, T2, T3, T4, TResult>)
Validates four independent results and maps their values to a combined result. Runs ALL validations independently — errors accumulate, not short-circuited.
public static Result<TResult> Validate<T1, T2, T3, T4, TResult>(Result<T1> r1, Result<T2> r2, Result<T3> r3, Result<T4> r4, Func<T1, T2, T3, T4, TResult> mapper)
Parameters
Returns
- Result<TResult>
Type Parameters
T1T2T3T4TResult
Examples
Result<OrderDto> dto = Result.Validate(
ValidateName(request.Name),
ValidateEmail(request.Email),
ValidateAge(request.Age),
ValidateAddress(request.Address),
(name, email, age, address) => new OrderDto(name, email, age, address));
WhenAll<T>(IEnumerable<Task<Result<T>>>)
Runs multiple async Result operations concurrently and returns an ImmutableList of values. If all succeed, returns Ok with the list of values. If any fail, aggregates all errors from all failed results.
public static Task<Result<ImmutableList<T>>> WhenAll<T>(IEnumerable<Task<Result<T>>> tasks)
Parameters
tasksIEnumerable<Task<Result<T>>>
Returns
- Task<Result<ImmutableList<T>>>
Type Parameters
T
Examples
var tasks = userIds.Select(id => GetUser(id));
var result = await Result.WhenAll(tasks);
WhenAll<T>(params Task<Result<T>>[])
Runs multiple async Result operations concurrently (params variant).
public static Task<Result<ImmutableList<T>>> WhenAll<T>(params Task<Result<T>>[] tasks)
Parameters
Returns
- Task<Result<ImmutableList<T>>>
Type Parameters
T
WhenAll<T1, T2>(Task<Result<T1>>, Task<Result<T2>>)
Runs two async Result operations concurrently and returns a typed tuple. If all succeed, returns Ok with the tuple of values. If any fail, aggregates all errors from all failed results.
public static Task<Result<(T1, T2)>> WhenAll<T1, T2>(Task<Result<T1>> task1, Task<Result<T2>> task2)
Parameters
Returns
Type Parameters
T1T2
Examples
var result = await Result.WhenAll(GetUser(id), GetAccount(id));
if (result.IsSuccess)
{
var (user, account) = result.Value;
}
WhenAll<T1, T2, T3>(Task<Result<T1>>, Task<Result<T2>>, Task<Result<T3>>)
Runs three async Result operations concurrently and returns a typed tuple.
public static Task<Result<(T1, T2, T3)>> WhenAll<T1, T2, T3>(Task<Result<T1>> task1, Task<Result<T2>> task2, Task<Result<T3>> task3)
Parameters
Returns
Type Parameters
T1T2T3
WhenAll<T1, T2, T3, T4>(Task<Result<T1>>, Task<Result<T2>>, Task<Result<T3>>, Task<Result<T4>>)
Runs four async Result operations concurrently and returns a typed tuple.
public static Task<Result<(T1, T2, T3, T4)>> WhenAll<T1, T2, T3, T4>(Task<Result<T1>> task1, Task<Result<T2>> task2, Task<Result<T3>> task3, Task<Result<T4>> task4)
Parameters
Returns
Type Parameters
T1T2T3T4
WithError(IError)
Adds an error reason to the result. Note: This will make the result failed if it wasn't already.
public Result WithError(IError error)
Parameters
errorIErrorThe error reason to add.
Returns
- Result
A new Result with the added error reason.
Examples
var error = new Error("Database connection failed");
var result = Result.Ok().WithError(error);
// result.IsFailure will be true
WithError(string)
Adds an error reason with a message to the result. Note: This will make the result failed if it wasn't already.
public Result WithError(string message)
Parameters
messagestringThe error message.
Returns
- Result
A new Result with the added error reason.
Examples
var result = Result.Ok()
.WithError("Operation failed");
// result.IsFailure will be true
Exceptions
- ArgumentException
Thrown when the message is null or empty.
WithErrors(IEnumerable<IError>)
Adds multiple error reasons to the result. Note: This will make the result failed if it wasn't already.
public Result WithErrors(IEnumerable<IError> errors)
Parameters
errorsIEnumerable<IError>The error reasons to add.
Returns
- Result
A new Result with the added error reasons.
Examples
var errors = new List<IError>
{
new Error("Invalid email"),
new Error("Password too short")
};
var result = Result.Ok().WithErrors(errors);
// result.IsFailure will be true
Exceptions
- ArgumentException
Thrown when the errors list is empty.
WithReason(IReason)
Adds a reason to the result.
public Result WithReason(IReason reason)
Parameters
reasonIReasonThe reason to add.
Returns
- Result
A new Result with the added reason.
Examples
var result = Result.Ok()
.WithReason(new Success("Operation completed"));
WithReasons(ImmutableList<IReason>)
Adds multiple reasons to the result.
public Result WithReasons(ImmutableList<IReason> reasons)
Parameters
reasonsImmutableList<IReason>The reasons to add.
Returns
- Result
A new Result with the added reasons.
Examples
var reasons = new List<IReason> { new Success("Validated"), new Success("Processed") };
var result = Result.Ok().WithReasons(reasons);
Exceptions
- ArgumentException
Thrown when the reasons list is empty.
WithSuccess(ISuccess)
Adds a success reason to the result.
public Result WithSuccess(ISuccess success)
Parameters
successISuccessThe success reason to add.
Returns
- Result
A new Result with the added success reason.
Examples
var success = new Success("Operation completed");
var result = Result.Ok().WithSuccess(success);
WithSuccess(string)
Adds a success reason with a message to the result.
public Result WithSuccess(string message)
Parameters
messagestringThe success message.
Returns
- Result
A new Result with the added success reason.
Examples
var result = Result.Ok()
.WithSuccess("Operation completed successfully");
Exceptions
- ArgumentException
Thrown when the message is null or empty.
WithSuccesses(IEnumerable<ISuccess>)
Adds multiple success reasons to the result.
public Result WithSuccesses(IEnumerable<ISuccess> successes)
Parameters
successesIEnumerable<ISuccess>The success reasons to add.
Returns
- Result
A new Result with the added success reasons.
Examples
var successes = new List<ISuccess>
{
new Success("Validated"),
new Success("Processed")
};
var result = Result.Ok().WithSuccesses(successes);
Exceptions
- ArgumentException
Thrown when the successes list is empty.