Apariencia
Introducción a Result
Una operación puede terminar de dos formas: producir el dato solicitado o informar por qué no pudo producirlo. Result hace explícitas esas dos posibilidades en el tipo que devuelve el método.
El problema que resuelve
Sin un resultado explícito, el consumidor suele tener que interpretar convenciones ambiguas:
csharp
int? cantidad = LeerCantidad(texto);
// ¿null significa entrada inválida, ausencia o un error interno?También puede depender de excepciones para fallos esperados:
csharp
try
{
var cantidad = LeerCantidad(texto);
}
catch (FormatException)
{
// El flujo normal queda mezclado con el control excepcional.
}Result<T> reemplaza esas convenciones por un contrato visible:
csharp
Result<int> resultado = LeerCantidad(texto);
if (resultado.TryGetValue(out var cantidad))
Console.WriteLine($"Cantidad: {cantidad}");
else
Console.WriteLine(resultado.Error.Message);El compilador muestra que el método puede fallar y el consumidor debe elegir cómo tratar cada rama.
Result expresa estado; Error explica el fallo
Result responde a una pregunta: ¿la operación terminó correctamente?
Error responde a otra: ¿qué ocurrió y cuáles fueron sus razones?
csharp
Result<int> resultado = Result<int>.Fail(
Error.Create("No se pudo guardar el pedido.")
.WithReason("El stock disponible es insuficiente."));El resultado conserva la raíz de Error. Las consultas de tipos, razones, metadatos y rutas pertenecen a platform.errors; se realizan sobre resultado.Error después de comprobar que el resultado falló.
Qué no hace Result
Result no captura automáticamente excepciones, no convierte la cancelación en un error y no ejecuta validaciones. Una excepción que ocurre dentro de Map, Bind o una enumeración sigue propagándose, salvo que el código la capture y la convierta explícitamente.
Usa un resultado para fallos esperados del contrato de la operación. Reserva las excepciones para situaciones excepcionales, errores de programación o fallos que el método no puede representar de forma útil.
Elegir el contrato
| La operación necesita devolver | Contrato |
|---|---|
| Solo éxito o fallo | VoidResult |
| Un valor | Result<T> |
| Un valor y una raíz de error conocida | Result<T, TError> |
| Una secuencia síncrona | EnumerableResult<T> |
| Una secuencia asíncrona | AsyncEnumerableResult<T> |
| Un hub de publicación | StreamResult<T> |
Result es la base común. No se instancia directamente ni ofrece fábricas Result.Ok() o Result.Fail(); las fábricas pertenecen a los contratos concretos.
Una regla sencilla
Usa esta secuencia mental:
- El método devuelve un contrato
Result. - El consumidor comprueba
IsOk,IsErroro usaMatch. - En éxito lee
Valueo enumera la secuencia. - En fallo lee
Errory consulta sus razones.
Empieza con elegir el contrato correcto, continúa con devolver un valor y después consulta leer el error.