Last active
August 29, 2015 14:06
-
-
Save zakky-dev/56f592e6209cd6ca9c6d to your computer and use it in GitHub Desktop.
try-catch-finallyの式化やってみた
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.Collections.Generic; | |
namespace Expression | |
{ | |
public static class Expression | |
{ | |
public static ETry<TResult> Try<TResult>(Func<TResult> tryBlock) | |
{ | |
return new ETry<TResult>(tryBlock); | |
} | |
public class ETry<TResult> | |
{ | |
private Func<TResult> tryBlock; | |
internal ETry(Func<TResult> block) | |
{ | |
tryBlock = block; | |
} | |
internal EWith<TResult> With<HandlingException>(Func<HandlingException, TResult> block) | |
where HandlingException : Exception | |
{ | |
return EWith<TResult>.Create<HandlingException>(tryBlock, block); | |
} | |
internal EFinally<TResult> Finally(Action block) | |
{ | |
return new EFinally<TResult>(tryBlock, block); | |
} | |
} | |
public class EWith<TResult> | |
{ | |
private Func<TResult> tryWithBlock; | |
private bool isCached = false; | |
private EWith(Func<TResult> tryBlock) | |
{ | |
tryWithBlock = tryBlock; | |
} | |
internal static EWith<TResult> Create<HandlingException>(Func<TResult> tryBlock, Func<HandlingException, TResult> withBlock) | |
where HandlingException : Exception | |
{ | |
return new EWith<TResult>(tryBlock).With<HandlingException>(withBlock); | |
} | |
internal EWith<TResult> With<HandlingException>(Func<HandlingException, TResult> block) | |
where HandlingException : Exception | |
{ | |
var child = tryWithBlock; | |
tryWithBlock = () => | |
{ | |
try | |
{ | |
return child(); | |
} | |
catch (HandlingException exn) | |
{ | |
if (!isCached) | |
{ | |
isCached = true; | |
return block(exn); | |
} | |
throw; | |
} | |
}; | |
return this; | |
} | |
internal EFinally<TResult> Finally(Action block) | |
{ | |
return new EFinally<TResult>(tryWithBlock, block); | |
} | |
public static implicit operator TResult(EWith<TResult> self) | |
{ | |
return self.tryWithBlock(); | |
} | |
} | |
public class EFinally<TResult> | |
{ | |
private Func<TResult> block; | |
internal EFinally(Func<TResult> tryBlock, Action finallyBlock) | |
{ | |
block = () => | |
{ | |
try | |
{ | |
return tryBlock(); | |
} | |
finally | |
{ | |
finallyBlock(); | |
} | |
}; | |
} | |
public static implicit operator TResult(EFinally<TResult> self) | |
{ | |
return self.block(); | |
} | |
} | |
} | |
class Program | |
{ | |
static void Main(string[] args) | |
{ | |
var ls = new List<string>(); | |
int ret = | |
Expression.Try(() => { ls.Add("try"); throw new InvalidCastException(""); return ls.Count; }) | |
.With<InvalidCastException>(exn => { ls.Add("with InvalidCastException"); return ls.Count; }) | |
.With<InvalidOperationException>(exn => { ls.Add("with InvalidOperationException"); return ls.Count; }) | |
.With<Exception>(exn => { ls.Add("with Exception"); return ls.Count; }) | |
.Finally(() => ls.Add("finally")); | |
Console.WriteLine(ret); | |
foreach (var l in ls) | |
{ | |
Console.WriteLine(l); | |
} | |
Console.ReadKey(false); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment