Skip to content

Instantly share code, notes, and snippets.

@MichalBrylka
Created February 5, 2024 11:09
Show Gist options
  • Save MichalBrylka/0a1258028cc91494d1990593e7f18262 to your computer and use it in GitHub Desktop.
Save MichalBrylka/0a1258028cc91494d1990593e7f18262 to your computer and use it in GitHub Desktop.
Result public
// See https://aka.ms/new-console-template for more information
using ConsoleApp1;
var nameEntities = new[] { "", null, "Dawid", "Kacper", "Wojciech", "Michał M", "Michał B", "Rafał", "Anna", "Floris" }
.Select(CreateUser).ToList();
var index = 0;
foreach (var ne in nameEntities)
{
if (ne.TryGetValue(out var u)) Console.WriteLine($"{index++}. User created: {u}");
if (ne.TryGetError(out var err)) Console.Error.WriteLine($"{index++}. Failed: {err}");
}
//static Result<MyEnum> Parse(string name) => name switch
//{
// "A" => MyEnum.A,
// "B" => MyEnum.B,
// "C" => MyEnum.C,
// _ => MyApiExpectedErrors.EnumCannotBeParsed
//};
static Result<User> CreateUser(string? name)
{
if (string.IsNullOrEmpty(name)) return MyApiExpectedErrors.ValidationFailed;
if (Random.Shared.NextDouble() > 0.8) return MyApiExpectedErrors.DatabaseNotOnline;
try
{
if (Random.Shared.NextDouble() > 0.5) throw new Exception("Something went wrong in upstream");
return new User(Random.Shared.Next(), name);
}
catch (Exception e)
{
// TODO use logger
var fore = Console.ForegroundColor;
Console.ForegroundColor = ConsoleColor.Red;
Console.Error.WriteLine(e);
Console.ForegroundColor = fore;
return (Error)e.Message;
}
}
enum MyEnum { A, B, C }
public static class MyApiExpectedErrors
{
public static readonly Error DatabaseNotOnline = new("DatabaseNotOnline", "Cannot connect to DB");
public static readonly Error ValidationFailed = new("ValidationFailed", "Some data is wrong");
public static readonly Error EnumCannotBeParsed = new("EnumParseFailed", $"Cannot parse enum. Valid labels are: {string.Join(", ", Enum.GetNames<MyEnum>())}");
}
public record User(int Id, string Name);
#nullable enable
using System.Diagnostics.CodeAnalysis;
namespace ConsoleApp1;
public sealed record Error(string Code, string? Description = null)
{
private const string UNEXPECTED = "UNEXPECTED";
public static explicit operator Error(string description) => new(UNEXPECTED, description);
}
public class Result<TValue>
{
private readonly TValue? Value;
private readonly Error? Error;
[MemberNotNullWhen(true, nameof(Value))]
[MemberNotNullWhen(false, nameof(Error))]
public bool IsSuccess { get; }
private Result(TValue value)
{
Value = value;
Error = default;
IsSuccess = true;
}
private Result(Error error)
{
Value = default;
Error = error;
IsSuccess = false;
}
public static Result<TValue> Success(TValue value) => new(value);
public static Result<TValue> Failure(Error error) => new(error);
public static implicit operator Result<TValue>(TValue result) => new(result);
public static implicit operator Result<TValue>(Error error) => new(error);
public void Invoke(Action<TValue> success, Action<Error>? failure = null)
{
if (IsSuccess) success(Value);
else failure?.Invoke(Error);
}
public bool TryGetValue([NotNullWhen(true)] out TValue? value)
{
if (IsSuccess)
{
value = Value;
return true;
}
else
{
value = default;
return false;
}
}
public bool TryGetError([NotNullWhen(true)] out Error? error)
{
if (!IsSuccess)
{
error = Error;
return true;
}
else
{
error = default;
return false;
}
}
public override string ToString()
{
if (IsSuccess) return Value.ToString() ?? "";
else return Error.ToString() ?? "";
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment