厌倦了程序中无处不在的try...catch...finally,在年前出差回公司后快放假那段有点疼的日子里按照《代码整洁之道》中剥离异常捕获的思想写了段代码。
原理:根据C#中的委托,将要执行的函数放入封装了try...catch...finally的函数库中,这边就叫 异常剥离函数。一、参数众多的异常剥离1 ///2 ///整洁函数 3 ///用来对委托进行try{}catch{} finally{}的封装 4 /// 5 public class CleanCodeInvoker 6 { 7 #region Func8 public static T InvokeDelegate (Func RunFunc,object[] agrs,Action FinalizeAction=null,Action 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 }
此时,测试代码如下:
View Code
1 public void Test() 2 { 3 FuncTestFunc=m=>Print(m[0].ToString(),m[1].ToString()); 4 string msg="it is a test"; 5 string symbol="!"; 6 string returnValue=CleanCodeInvoker.InvokeDelegate (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 FuncTestFunc=()=>Print(msg,symbol); 6 string returnValue=CleanCodeInvoker.InvokeDelegate (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 ///2 ///整洁函数 3 ///用来对委托进行try{}catch{} finally{}的封装 4 /// 5 public class CleanCodeInvoker 6 { 7 #region Func8 public static T InvokeDelegate (Func RunFuncAction FinalizeAction=null,Action 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 }
这里必须注意下,当进行多线程调用时,传入的参数进行值拷贝以防止程序运行时读取脏数据。