Last active
August 16, 2022 11:54
-
-
Save lucasteles/ee7b0d4ab3126476312daf65e5980e5d to your computer and use it in GitHub Desktop.
Result<TOk,TError> C# Sample
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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