-
Notifications
You must be signed in to change notification settings - Fork 0
ResultT API Reference
This page lists every public method on the generic Result<T> type (used when an operation returns a value on success, for example Result<User> or Result<int>).
Result<T> has everything that Result has, plus a Value property and a few extra methods.
public T Value { get; }Holds the actual result value. It is only meaningful when IsSuccess is true. On failure, Value is the default value for the type (for example null for reference types, or 0 for int).
Tip: Always check
IsSuccess(or useMatch) before readingValue, to avoid using a meaningless default value by mistake.
Result<int> result = Result<int>.Success(42);Result<int> result = Result<int>.Failure(new Error("Parse.Failed", "Not a number."));You can skip the explicit calls above:
Result<int> result = 42; // same as Success(42)
Result<int> result2 = new Error("Parse.Failed", "..."); // same as Failure(error)This makes it very easy to return a plain value or a plain error from a method that is declared to return Result<T>.
Runs func. If it succeeds, wraps the returned value in a successful Result<T>. If it throws, the exception becomes the Error of a failed Result<T>.
Result<int> result = Result<int>.Try(() => int.Parse("10"));Same idea, for asynchronous code.
Result<User> result = await Result<User>.TryAsync(async () =>
{
return await _repository.GetByIdAsync(id);
});result.Match(
onSuccess: user => Console.WriteLine($"Found: {user.Name}"),
onFailure: error => Console.WriteLine($"Error: {error.Description}")
);string message = result.Match(
onSuccess: user => $"Found: {user.Name}",
onFailure: error => $"Error: {error.Description}"
);An asynchronous version of Match. Use it when your success/failure branches need to await something.
await result.MatchAsync(
onSuccess: user => _notifier.SendWelcomeEmailAsync(user),
onFailure: error => _logger.LogErrorAsync(error.Description)
);Same idea, but each branch returns a Task<TResult>, so you get a final awaited value.
string message = await result.MatchAsync(
onSuccess: user => Task.FromResult($"Found: {user.Name}"),
onFailure: error => Task.FromResult($"Error: {error.Description}")
);If successful, runs action using the current Value, then returns a plain successful Result (no value). Useful when you just need a side effect (like logging), and want to "downgrade" a Result<T> to a plain Result.
Result result = userResult.Map(user => Console.WriteLine(user.Name));If successful, transforms the current Value into a new value of type TResult, wrapped in a new Result<TResult>. If the original result failed, the failure passes through unchanged.
Result<string> nameResult = userResult.Map(user => user.Name);An asynchronous version of Map(Action<T>). If successful, awaits action using the current Value, then returns a successful plain Result. Returns a Task<Result>.
Result result = await userResult.MapAsync(user => _auditLog.RecordAsync(user.Id));An asynchronous version of Map<TResult>. If successful, awaits func and wraps the returned value in a Result<TResult>. Returns a Task<Result<TResult>>.
Result<string> nameResult = await userResult.MapAsync(async user =>
{
return await _translator.TranslateAsync(user.Name);
});If successful, calls func with the current Value. func returns a plain Result. Use this when the next step doesn't need to return a value, like deleting something.
Result deleteResult = userResult.Bind(user => _repository.Delete(user.Id));If successful, calls func with the current Value. func returns another Result<TResult>. This lets you chain multiple value-producing steps together.
Result<Order> orderResult = userResult.Bind(user => CreateOrderForUser(user));An asynchronous version of Bind(Func<T, Result>). If successful, awaits func with the current Value. Returns a Task<Result>.
Result deleteResult = await userResult.BindAsync(user => _repository.DeleteAsync(user.Id));An asynchronous version of Bind<TResult>. If successful, awaits func with the current Value, and returns its Result<TResult>. Returns a Task<Result<TResult>>.
Result<Order> orderResult = await userResult.BindAsync(user => CreateOrderForUserAsync(user));Chaining tip: Because every
...Asyncmethod returns aTask, you can chain several of them together andawaitonce at the end. See the updated Async Operations page for a full example that mixes sync and async steps in one pipeline.
This is a common question, so here is a simple rule:
- Use
Mapwhen your next step is a plain function that cannot fail and just returns a normal value (orvoid/an action). - Use
Bindwhen your next step already returns aResultorResult<T>(it can succeed or fail on its own).
// Map: int -> string (a plain transformation)
Result<string> textResult = numberResult.Map(n => n.ToString());
// Bind: string -> Result<User> (a step that can itself fail)
Result<User> userResult = textResult.Bind(text => FindUserByName(text));If you use Map where you should use Bind, you would end up with something like Result<Result<User>> (a "result inside a result"), which is confusing. Bind avoids that by "flattening" the chain.
| Method | Purpose |
|---|---|
Success(T value) |
Create a successful Result<T>
|
Failure(Error) |
Create a failed Result<T>
|
Try(Func<T>) |
Catch exceptions, return Result<T>
|
TryAsync(Func<Task<T>>) |
Same as Try, for async code |
Match(Action<T>, Action<Error>) |
React to success/failure, no return value |
Match<TResult>(Func<T,TResult>, Func<Error,TResult>) |
React to success/failure, return a value |
MatchAsync(Func<T,Task>, Func<Error,Task>) |
Async version of Match, no return value |
MatchAsync<TResult>(Func<T,Task<TResult>>, Func<Error,Task<TResult>>) |
Async version of Match, returns a value |
Map(Action<T>) |
Run a side effect, downgrade to plain Result
|
MapAsync(Func<T,Task>) |
Async version of Map(Action<T>)
|
Map<TResult>(Func<T,TResult>) |
Transform the value into a new Result<TResult>
|
MapAsync<TResult>(Func<T,Task<TResult>>) |
Async version of Map<TResult>
|
Bind(Func<T, Result>) |
Chain to a step that returns a plain Result
|
BindAsync(Func<T, Task<Result>>) |
Async version of Bind
|
Bind<TResult>(Func<T, Result<TResult>>) |
Chain to a step that returns another Result<TResult>
|
BindAsync<TResult>(Func<T, Task<Result<TResult>>>) |
Async version of Bind<TResult>
|
Next: see Chaining with Map and Bind for a step-by-step walkthrough.