厌倦了程序中无处不在的try...catch...finally,在年前出差回公司后快放假那段有点疼的日子里按照《代码整洁之道》中剥离异常捕获的思想写了段代码。
原理:
根据C#中的委托,将要执行的函数放入封装了try...catch...finally的函数库中,这边就叫 异常剥离函数。
一、参数众多的异常剥离
1 /// <summary>
2 ///整洁函数
3 ///用来对委托进行try{}catch{} finally{}的封装
4 /// </summary>
5 public class CleanCodeInvoker
6 {
7 #region Func<out>
8 public static T InvokeDelegate<T> (Func<T,object[]>RunFunc,object[] agrs,Action FinalizeAction=null,Action<Exception> ExceptionAction=null)
9 {
10 try
11 {
12 RunFunc(args);
13 }
14 catch(Exception ex)
15 {
16 if(ExceptionAction!=null)
17 {
18 ExceptionAction(ex);
19 }
20 }
21 finally
22 {
23 if(FinalizeAction!=null)
24 {
25 FinalizeAction();
26 }
27 }
28 }
29 #endregion
30
31 }
此时,测试代码如下:

1 public void Test()
2 {
3 Func<string,object[]> TestFunc=m=>Print(m[0].ToString(),m[1].ToString());
4 string msg="it is a test";
5 string symbol="!";
6 string returnValue=CleanCodeInvoker.InvokeDelegate<string>(TestFunc,new object[]{msg,symbol});
7 Console.WriteLine(returnValue);
8 Console.Read();
9
10 }
11
12 public string Print(string msg,string symbol)
13 {
14 string returnValue=string.Format("{0}{1}",msg,symbol);
15 Console.WriteLine(returnValue);
16 return returnValue;
17 }
写完测试代码后发现,这个函数的调用实在是麻烦,需要不停的进行参数类型的转换。于是脑门一拍,把调用时的object[]换成dynamic[]。咋一看代码,省了一堆的转换过程。但是,路过的公司前辈一句话又把我一棒子打回了原型:这样子做对性能的影响是致命的!
性能!!!!!!!!!!
测试后发现,dynamic的速率比装箱慢2.5倍左右!!!!!
好吧我不用dynamic了。
好吧,我不传参数了行不行!!!
行!!!
测试代码如下:

1 public void Test()
2 {
3 string msg="it is a test";
4 string symbol="!";
5 Func<string> TestFunc=()=>Print(msg,symbol);
6 string returnValue=CleanCodeInvoker.InvokeDelegate<string>(TestFunc);
7 Console.WriteLine(returnValue);
8 Console.Read();
9
10 }
11
12 public string Print(string msg,string symbol)
13 {
14 string returnValue=string.Format("{0}{1}",msg,symbol);
15 Console.WriteLine(returnValue);
16 return returnValue;
17 }
此时,异常剥离函数修改如下:
1 /// <summary>
2 ///整洁函数
3 ///用来对委托进行try{}catch{} finally{}的封装
4 /// </summary>
5 public class CleanCodeInvoker
6 {
7 #region Func<out>
8 public static T InvokeDelegate<T> (Func<T>RunFuncAction FinalizeAction=null,Action<Exception> ExceptionAction=null)
9 {
10 try
11 {
12 return RunFunc();
13 }
14 catch(Exception ex)
15 {
16 if(ExceptionAction!=null)
17 {
18 ExceptionAction(ex);
19 }
20 }
21 finally
22 {
23 if(FinalizeAction!=null)
24 {
25 FinalizeAction();
26 }
27 }
28 }
29 #endregion
30
31 }
这里必须注意下,当进行多线程调用时,传入的参数进行值拷贝以防止程序运行时读取脏数据。