Skip to content

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 devolverContrato
Solo éxito o falloVoidResult
Un valorResult<T>
Un valor y una raíz de error conocidaResult<T, TError>
Una secuencia síncronaEnumerableResult<T>
Una secuencia asíncronaAsyncEnumerableResult<T>
Un hub de publicaciónStreamResult<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:

  1. El método devuelve un contrato Result.
  2. El consumidor comprueba IsOk, IsError o usa Match.
  3. En éxito lee Value o enumera la secuencia.
  4. En fallo lee Error y consulta sus razones.

Empieza con elegir el contrato correcto, continúa con devolver un valor y después consulta leer el error.

Uso personal limitado. Uso comercial sujeto a autorización escrita.