Last active
February 2, 2018 06:16
-
-
Save itn3000/7ff0dac543c81f95bdd26673324f18b9 to your computer and use it in GitHub Desktop.
Result type like rust's std::result::Result<T, E>
This file contains hidden or 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; | |
| using System.Threading.Tasks; | |
| namespace optionalresulttest | |
| { | |
| public static class Result | |
| { | |
| public static Result<T> From<T>(Func<T> generateFunc) | |
| { | |
| try | |
| { | |
| return new Result<T>(generateFunc()); | |
| } | |
| catch (Exception e) | |
| { | |
| return new Result<T>(e); | |
| } | |
| } | |
| // factory method for create Result | |
| public static async Task<Result<T>> FromAsync<T>(Func<Task<T>> generateFunc) | |
| { | |
| try | |
| { | |
| return new Result<T>(await generateFunc().ConfigureAwait(false)); | |
| } | |
| catch (Exception e) | |
| { | |
| return new Result<T>(e); | |
| } | |
| } | |
| } | |
| // optional type like rust's std::result::Result<T, E> | |
| public struct Result<T> | |
| { | |
| internal readonly T Ok; | |
| internal readonly Exception Err; | |
| internal Result(Exception e) | |
| { | |
| Err = e; | |
| Ok = default(T); | |
| } | |
| internal Result(T v) | |
| { | |
| Err = null; | |
| Ok = v; | |
| } | |
| /// extract value from Result, if error, exception will be thrown | |
| public T Unwrap() | |
| { | |
| if (IsErr()) | |
| { | |
| throw new AggregateException("unwrap error", Err); | |
| } | |
| else | |
| { | |
| return Ok; | |
| } | |
| } | |
| /// do function when value is OK, or return Error | |
| public Result<T> AndThen(Func<T, T> func) | |
| { | |
| if (Err == null) | |
| { | |
| try | |
| { | |
| return new Result<T>(func(Ok)); | |
| } | |
| catch (Exception e) | |
| { | |
| return new Result<T>(e); | |
| } | |
| } | |
| else | |
| { | |
| return new Result<T>(Err); | |
| } | |
| } | |
| // do function when error, or return value | |
| public Result<T> OrElse(Func<Exception, T> func) | |
| { | |
| if (IsErr()) | |
| { | |
| try | |
| { | |
| return new Result<T>(func(Err)); | |
| } | |
| catch (Exception e) | |
| { | |
| return new Result<T>(e); | |
| } | |
| } | |
| else | |
| { | |
| return new Result<T>(Ok); | |
| } | |
| } | |
| // not set error(you can do Unwrap() safely) | |
| public bool IsOk() | |
| { | |
| return Err == null; | |
| } | |
| // set error(cause exception when call Unwrap()) | |
| public bool IsErr() | |
| { | |
| return Err != null; | |
| } | |
| // transform another value when OK, or return Error result | |
| public Result<TRet> Map<TRet>(Func<T, TRet> func) | |
| { | |
| if (IsOk()) | |
| { | |
| try | |
| { | |
| return new Result<TRet>(func(Ok)); | |
| } | |
| catch (Exception e) | |
| { | |
| return new Result<TRet>(e); | |
| } | |
| } | |
| else | |
| { | |
| return new Result<TRet>(Err); | |
| } | |
| } | |
| // Unwrap when OK, or return default value | |
| public T UnwrapOr(T defaultValue) | |
| { | |
| if (IsOk()) | |
| { | |
| return Ok; | |
| } | |
| else | |
| { | |
| return defaultValue; | |
| } | |
| } | |
| // Unwrap when OK, or return the value created by function | |
| public T UnwrapOrElse(Func<Exception, T> func) | |
| { | |
| if (IsOk()) | |
| { | |
| return Ok; | |
| } | |
| else | |
| { | |
| return func(Err); | |
| } | |
| } | |
| // get error if Result has error, or null | |
| public Exception GetError() | |
| { | |
| return Err; | |
| } | |
| public static implicit operator bool(Result<T> r) | |
| { | |
| return r.IsOk(); | |
| } | |
| } | |
| class Program | |
| { | |
| static void Main(string[] args) | |
| { | |
| Environment.GetEnvironmentVariable(""); | |
| var result = Result.From(() => int.Parse("1")) | |
| .AndThen(x => | |
| { | |
| Console.WriteLine($"andthen: {x}"); | |
| return x; | |
| }) | |
| .OrElse(x => | |
| { | |
| Console.WriteLine($"orelse: {x}"); | |
| return 0; | |
| }) | |
| .UnwrapOr(-1) | |
| ; | |
| Result<int> hoge; | |
| if((hoge = Result.From(() => 100))) | |
| { | |
| Console.WriteLine($"result1 from true"); | |
| }else{ | |
| Console.WriteLine($"result1 from false"); | |
| } | |
| if(Result.From<int>(() => throw new NotImplementedException())) | |
| { | |
| Console.WriteLine($"result2 from true"); | |
| }else{ | |
| Console.WriteLine($"result2 from false"); | |
| } | |
| var aresult = Result.FromAsync(() => Task.FromResult(1)).Result; | |
| var aresult2 = Result.FromAsync<int>(() => throw new NotImplementedException()).Result; | |
| Console.WriteLine($"{aresult.IsErr()},{aresult.IsOk()}"); | |
| Console.WriteLine($"{aresult2.IsErr()},{aresult2.IsOk()}"); | |
| Console.WriteLine($"Hello World!{result}"); | |
| } | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
async版追加