Skip to content

Instantly share code, notes, and snippets.

@Keboo
Last active April 18, 2018 18:35
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Keboo/021fdef8f641b7cf89c1db9338a1b47d to your computer and use it in GitHub Desktop.
Save Keboo/021fdef8f641b7cf89c1db9338a1b47d to your computer and use it in GitHub Desktop.
A simple result implementation using the null object pattern.
public class Service
{
public Result<Person> FindPerson(string query)
{
try
{
Person person = ...;
return person ?? Result.NotFound<Person>(); //Not strictly neccisary; the implicit operator will do a null check.
}
catch (Exception e)
{
//Do stuff with the exception
return Result.Exception<Person>(e);
}
}
}
public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
public static class Result
{
public static Result<T> NotFound<T>(string message = null) where T : class =>
new Result<T>(new NotFoundError(message));
public static Result<T> Exception<T>(Exception exception, string message = null) where T : class =>
new Result<T>(new ExceptionError(exception, message));
}
public interface IResultError
{
string Message { get; }
}
public class NotFoundError : IResultError
{
public string Message { get; }
public NotFoundError(string message = null)
{
Message = message ?? "Item not found";
}
}
public class ExceptionError : IResultError
{
public ExceptionError(Exception exception, string message = null)
{
Exception = exception;
Message = message ?? exception.Message;
}
public Exception Exception { get; }
public string Message { get; }
}
public struct Result<T> where T : class
{
public T Item { get; }
private readonly IReadOnlyList<IResultError> _Errors;
public IReadOnlyList<IResultError> Errors => _Errors ?? Array.Empty<IResultError>();
public bool IsSuccess { get; }
private Result(T item)
{
Item = item;
IsSuccess = true;
_Errors = Array.Empty<IResultError>();
}
public Result(params IResultError[] errors)
{
if (errors?.Any() != true) throw new ArgumentException("At least one error is required", nameof(errors));
_Errors = errors;
Item = default;
IsSuccess = false;
}
public T GetItemOrDefault(T @default = default) => IsSuccess ? Item : @default;
public static implicit operator Result<T>(T item) => item != default(T) ? new Result<T>(item) : Result.NotFound<T>();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment