Skip to content

Result API Reference

ferdi kurnaz edited this page Aug 27, 2026 · 2 revisions

Result API Reference

This page lists every public method on the non-generic Result type (used when an operation has no return value).

Creating a Result

Result.Success()

Creates a successful result with no error.

Result result = Result.Success();

Result.Failure(Error error)

Creates a failed result with the given error.

Result result = Result.Failure(new Error("Save.Failed", "Disk is full."));

Implicit conversion from Error

You can skip .Failure() and just assign an Error directly:

Result result = new Error("Save.Failed", "Disk is full.");

Turning exceptions into a Result

Result.Try(Action action)

Runs the given code. If it finishes normally, you get a successful Result. If it throws an exception, the exception is caught automatically and turned into a failed Result.

Result result = Result.Try(() =>
{
    File.Delete("data.txt");
});

If File.Delete throws an exception, result.IsFailure will be true, and result.Error.Code will be the exception's type name (for example "IOException"), while result.Error.Description will be the exception's message.

Result.TryAsync(Func<Task> action)

Same idea as Try, but for asynchronous (async) code.

Result result = await Result.TryAsync(async () =>
{
    await _repository.SaveAsync(entity);
});

Reading the outcome

Match(Action onSuccess, Action<Error> onFailure)

Runs one of two actions, depending on whether the result succeeded or failed. Nothing is returned.

result.Match(
    onSuccess: () => Console.WriteLine("Saved!"),
    onFailure: error => Console.WriteLine($"Error: {error.Description}")
);

Match<TResult>(Func<TResult> onSuccess, Func<Error, TResult> onFailure)

Same idea, but each branch returns a value of type TResult. This is useful when you want to turn a Result into something else, like a message or an HTTP response.

string message = result.Match(
    onSuccess: () => "Saved!",
    onFailure: error => $"Error: {error.Description}"
);

MatchAsync(Func<Task> onSuccess, Func<Error, Task> onFailure)

An asynchronous version of Match. Use this when your success/failure branches need to await something (like logging to a database, or calling another async API). Nothing is returned.

await result.MatchAsync(
    onSuccess: () => _logger.LogInfoAsync("Saved!"),
    onFailure: error => _logger.LogErrorAsync(error.Description)
);

MatchAsync<TResult>(Func<Task<TResult>> onSuccess, Func<Error, Task<TResult>> onFailure)

Same idea, but each branch returns a Task<TResult>, so the whole call can be awaited to get a final value.

string message = await result.MatchAsync(
    onSuccess: () => Task.FromResult("Saved!"),
    onFailure: error => Task.FromResult($"Error: {error.Description}")
);

Transforming and chaining

Map<T>(Func<T> func)

If the result is successful, runs func and wraps its return value in a new Result<T>. If the result already failed, the failure (and its error) is passed along, and func is not called.

Result<int> lengthResult = result.Map(() => "hello".Length);

MapAsync<T>(Func<Task<T>> func)

An asynchronous version of Map. If the result is successful, awaits func and wraps the returned value in a Result<T>. Returns a Task<Result<T>>.

Result<int> lengthResult = await result.MapAsync(async () =>
{
    var text = await _client.GetTextAsync();
    return text.Length;
});

Bind(Func<Result> func)

If the result is successful, runs func (which itself returns another Result) and returns that new result. If the original result already failed, the same failure is returned, and func is not called.

Use this to chain multiple steps that can each fail.

Result finalResult = Result.Success()
    .Bind(() => ValidateName("John"))
    .Bind(() => ValidateEmail("john@example.com"));

Bind<T>(Func<Result<T>> func)

Same as Bind, but the next step in the chain returns a Result<T> (a value) instead of a plain Result.

Result<User> userResult = Result.Success()
    .Bind(() => ValidateName("John"))
    .Bind(() => CreateUser("John", "john@example.com")); // returns Result<User>

BindAsync(Func<Task<Result>> func)

An asynchronous version of Bind. If the result is successful, awaits func (which returns a Task<Result>) and returns its result. Returns a Task<Result>.

Result finalResult = await Result.Success()
    .BindAsync(() => SaveToDatabaseAsync(entity));

BindAsync<T>(Func<Task<Result<T>>> func)

Same idea, but the next step returns a Task<Result<T>> (a value-producing async step).

Result<User> userResult = await Result.Success()
    .BindAsync(() => CreateUserAsync("John", "john@example.com"));

Chaining tip: All ...Async methods return a Task, so you await the whole chain once, either at the very end, or right before you need the result. You can freely mix synchronous (Map, Bind) and asynchronous (MapAsync, BindAsync) steps — see Async Operations for a full chaining example.

Summary table

Method Purpose
Success() Create a successful Result
Failure(Error) Create a failed Result
Try(Action) Catch exceptions and turn them into a Result
TryAsync(Func<Task>) Same as Try, for async code
Match(Action, Action<Error>) React to success/failure, no return value
Match<TResult>(Func<TResult>, Func<Error,TResult>) React to success/failure, return a value
MatchAsync(Func<Task>, Func<Error,Task>) Async version of Match, no return value
MatchAsync<TResult>(Func<Task<TResult>>, Func<Error,Task<TResult>>) Async version of Match, returns a value
Map<T>(Func<T>) Turn a Result into a Result<T> on success
MapAsync<T>(Func<Task<T>>) Async version of Map
Bind(Func<Result>) Chain to another Result-returning step
Bind<T>(Func<Result<T>>) Chain to a Result<T>-returning step
BindAsync(Func<Task<Result>>) Async version of Bind
BindAsync<T>(Func<Task<Result<T>>>) Async version of Bind<T>

See also: Result API Reference.

Clone this wiki locally