Skip to main content

Match / MatchAsync

Match is a terminal operator — it consumes the Result and produces a final value by branching on success or failure. Unlike other pipeline operators, Match does not return a Result.

Signatures

// On Result<T> (instance method)
TResult Match<TResult>(Func<T, TResult> onSuccess, Func<Error, TResult> onFailure)
Task<TResult> MatchAsync<TResult>(Func<T, Task<TResult>> onSuccess, Func<Error, Task<TResult>> onFailure)

// Pipeline extensions (for Task<Result<T>>)
Task<TResult> MatchAsync<T, TResult>(this Task<Result<T>> resultTask,
Func<T, TResult> onSuccess, Func<Error, TResult> onFailure)
Task<TResult> MatchAsync<T, TResult>(this Task<Result<T>> resultTask,
Func<T, Task<TResult>> onSuccess, Func<Error, Task<TResult>> onFailure)

When to use

Use Match when you want to exit the pipeline and produce a final value:

  • Building a response message
  • Choosing a return value
  • Rendering different UI

Basic example

var result = Divide(10, 2);

string message = result.Match(
onSuccess: value => $"Answer: {value}",
onFailure: error => $"Error: {error.Message}"
);

Console.WriteLine(message); // "Answer: 5"

In a pipeline

string response = await GetUserAsync(userId)
.Validate(u => u.IsActive, Error.Validation("Inactive"))
.Map(u => u.ToDto())
.MatchAsync(
onSuccess: dto => $"Welcome, {dto.Name}!",
onFailure: err => $"Sorry: {err.Message}"
);

Switch / SwitchAsync

Switch is like Match but performs actions instead of returning a value:

result.Switch(
onSuccess: user => _logger.LogInformation("Found {Name}", user.Name),
onFailure: error => _logger.LogWarning("Failed: {Code}", error.Code)
);

await result.SwitchAsync(
onSuccess: async user => await _notifier.NotifyAsync(user),
onFailure: async error => await _alerter.AlertAsync(error)
);

Practical example — API response

app.MapGet("/users/{id}", async (int id, IUserRepository repo, IProblemDetailsMapper mapper) =>
{
return await repo.GetByIdAsync(id)
.MatchAsync(
onSuccess: user => Results.Ok(user),
onFailure: error => Results.Problem(mapper.ToProblemDetails(error))
);
});
tip

For ASP.NET Core, prefer ToHttpResult() from Spur.AspNetCore — it handles the Match + Problem Details mapping for you automatically.

See also