From f99d035621971e5d3b3949a6d0c704083828a4d8 Mon Sep 17 00:00:00 2001 From: chylex <contact@chylex.com> Date: Tue, 10 Apr 2018 19:45:41 +0200 Subject: [PATCH] Add a Result class that acts as an Either monad for a value or exception --- Data/Result.cs | 36 ++++++++++++++++++++++++++++++++++++ TweetDuck.csproj | 1 + 2 files changed, 37 insertions(+) create mode 100644 Data/Result.cs diff --git a/Data/Result.cs b/Data/Result.cs new file mode 100644 index 00000000..2c582723 --- /dev/null +++ b/Data/Result.cs @@ -0,0 +1,36 @@ +using System; + +namespace TweetDuck.Data{ + sealed class Result<T>{ + public bool HasValue => exception == null; + + public T Value => HasValue ? value : throw new InvalidOperationException("Requested value from a failed result."); + public Exception Exception => exception ?? throw new InvalidOperationException("Requested exception from a successful result."); + + private readonly T value; + private readonly Exception exception; + + public Result(T value){ + this.value = value; + this.exception = null; + } + + public Result(Exception exception){ + this.value = default(T); + this.exception = exception ?? throw new ArgumentNullException(nameof(exception)); + } + + public void Handle(Action<T> onSuccess, Action<Exception> onException){ + if (HasValue){ + onSuccess(value); + } + else{ + onException(exception); + } + } + + public Result<R> Select<R>(Func<T, R> map){ + return HasValue ? new Result<R>(map(value)) : new Result<R>(exception); + } + } +} diff --git a/TweetDuck.csproj b/TweetDuck.csproj index 27df5cbd..fd09944d 100644 --- a/TweetDuck.csproj +++ b/TweetDuck.csproj @@ -259,6 +259,7 @@ </Compile> <Compile Include="Core\Notification\Screenshot\TweetScreenshotManager.cs" /> <Compile Include="Data\ResourceLink.cs" /> + <Compile Include="Data\Result.cs" /> <Compile Include="Data\Serialization\FileSerializer.cs" /> <Compile Include="Data\InjectedHTML.cs" /> <Compile Include="Data\Serialization\ITypeConverter.cs" />