Operaciones Funcionales
Result<T> y Result soportan métodos de composición funcional que permiten programación orientada a ferrocarriles — encadenar operaciones donde un fallo en cualquier paso cortocircuita el resto.
Map
Transforma el valor dentro de un result exitoso. En caso de fallo, propaga el error sin cambios.
Result<string> orderId = Result<string>.Ok("order-42");
Result<int> orderNumber = orderId.Map(id => int.Parse(id.Split('-')[1]));
// Result<int>.Ok(42)
Bind
Encadena operaciones que retornan Result<T>. Habilita composición sin sentencias if anidadas.
Result<OrderDto> result = await GetOrderAsync(orderId)
.Bind(order => ValidateOrder(order))
.Bind(order => EnrichWithCustomer(order));
MapAsync / BindAsync
Versiones async para transformaciones asíncronas:
Result<string> result = await Result<Guid>.Ok(productId)
.MapAsync(async id =>
{
var product = await _repository.GetAsync(id);
return product.Name;
});
Tap
Ejecuta un efecto secundario en caso de éxito sin cambiar el result. Útil para logging o publicar eventos.
result.Tap(orderId =>
{
_logger.LogInformation("Orden creada: {OrderId}", orderId);
});
OnFailure
Ejecuta un efecto secundario en caso de fallo. Útil para logging de errores.
result.OnFailure((error, errorType) =>
{
_logger.LogWarning("Falló al obtener producto: {Error} ({ErrorType})", error, errorType);
});
Match
Branching exhaustivo — provee un handler para ambos casos de éxito y fallo:
string message = result.Match(
onSuccess: product => $"Encontrado: {product.Name}",
onFailure: (error, errorType) => $"Error: {error}"
);
Ejemplo de Encadenamiento
public async Task<Result<OrderConfirmationDto>> PlaceOrder(PlaceOrderCommand command)
{
return await ValidateInventory(command)
.BindAsync(async _ => await ReserveStock(command))
.BindAsync(async _ => await ChargePayment(command))
.BindAsync(async _ => await CreateOrder(command))
.MapAsync(async orderId => await BuildConfirmation(orderId))
.Tap(confirmation =>
_logger.LogInformation("Orden {Id} creada", confirmation.OrderId))
.OnFailure((error, type) =>
_logger.LogWarning("Orden falló: {Error}", error));
}