Skip to content

Instantly share code, notes, and snippets.

@itn3000
Last active February 2, 2018 06:16
Show Gist options
  • Save itn3000/7ff0dac543c81f95bdd26673324f18b9 to your computer and use it in GitHub Desktop.
Save itn3000/7ff0dac543c81f95bdd26673324f18b9 to your computer and use it in GitHub Desktop.
Result type like rust's std::result::Result<T, E>
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}");
}
}
}
@itn3000
Copy link
Author

itn3000 commented Apr 7, 2017

async版追加

@itn3000
Copy link
Author

itn3000 commented Feb 2, 2018

boolオペレーター追加

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment