Skip to content

Instantly share code, notes, and snippets.

@lucasteles
Last active August 16, 2022 11:54
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save lucasteles/ee7b0d4ab3126476312daf65e5980e5d to your computer and use it in GitHub Desktop.
Save lucasteles/ee7b0d4ab3126476312daf65e5980e5d to your computer and use it in GitHub Desktop.
Result<TOk,TError> C# Sample
using System;
#region 'Implementaçao exemplo do result'
public static class Result {
public static Result<TSuccess,TFailure> Ok<TSuccess, TFailure>(TSuccess value) => new OkResult<TSuccess, TFailure>(value);
public static Result<TSuccess,TFailure> Error<TSuccess, TFailure>(TFailure value) => new ErrorResult<TSuccess, TFailure>(value);
}
public abstract class Result<TOk, TError> {
public static implicit operator Result<TOk, TError>(TOk value) => Result.Ok<TOk, TError>(value);
public static implicit operator Result<TOk, TError>(TError value) => Result.Error<TOk, TError>(value);
public Result<TMap, TError> Select<TMap>(Func<TOk, TMap> map) =>
this switch {
Ok<TOk>(var value) => map(value),
Error<TError>(var value) => value,
_ => Result.Error<TMap, TError>(default),
};
public Result<TMap, TError> Bind<TMap>(Func<TOk, Result<TMap, TError>> bind) =>
this switch {
Ok<TOk>(var value) => bind(value),
Error<TError>(var value) => new ErrorResult<TMap, TError>(value),
_ => Result.Error<TMap, TError>(default),
};
public Result<TResult, TError> SelectMany<TMap, TResult>(
Func<TOk, Result<TMap, TError>> bind,
Func<TOk, TMap, TResult> project) =>
Bind(a => bind(a).Select(b => project(a,b)));
public Result<TOk, TMapError> SelectError<TMapError>(Func<TError, TMapError> map) =>
this switch {
Ok<TOk>(var value) => value,
Error<TError>(var value) => map(value),
_ => Result.Error<TOk, TMapError>(default),
};
public Result<TMap, TMapError> Select<TMap, TMapError>(
Func<TOk, TMap> map, Func<TError, TMapError> mapError
) => Select(map).SelectError(mapError);
public T Match<T>(Func<TOk, T> ok, Func<TError, T> error) =>
this switch {
Ok<TOk>(var value) => ok(value),
Error<TError>(var value) => error(value),
_ => error(default),
};
public TOk Default(TOk defaultValueIfError) =>
this switch {
Ok<TOk>(var value) => value,
Error<TError> _ => defaultValueIfError,
_ => defaultValueIfError,
};
}
public interface Ok<TSuccess> {void Deconstruct(out TSuccess ret);}
public interface Error<TError> {void Deconstruct(out TError ret);}
public sealed class OkResult<TOk, TError> : Result<TOk, TError>, Ok<TOk> {
readonly TOk _value;
public OkResult(TOk value) => _value = value;
public void Deconstruct(out TOk ret) => ret = _value;
}
public sealed class ErrorResult<TOk, TError> : Result<TOk, TError>, Error<TError> {
readonly TError _value;
public ErrorResult(TError value) => _value = value;
public void Deconstruct(out TError ret) => ret = _value;
}
#endregion
public static class Program {
public static Result<int, string> DivideNumeros(int a, int b)
{
if( b == 0 )
return "Nao pode dividir por zero";
else
return a / b;
}
public static void Main() {
var a = DivideNumeros(4,2); // a is Ok(2)
var bar = a.Select(x => x + 1); // bar is Ok(3)
// zera valor se for erro
var baz = a.Default(0);
var foo =
from q in a
from w in DivideNumeros(q, 2)
select q + w; // foo is Ok(3)
// le o valor dentro do result
var result = foo switch {
Ok<int>(var v) => $"O valor é {v}",
Error<string>(var err) => $"Ocorreu um problema: {err}",
_ => string.Empty,
};
// le o valor dentro do result (outra forma)
var result2 = foo.Match(
ok: n => $"O valor é {n}",
error: err => $"Ocorreu um problema: {err}"
);
// le o valor dentro do result (outra forma)
var result3 = foo
.Select(n => $"O valor é {n}")
.Default("Algo deu errado");
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment