厭倦了程序中無處不在的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 }
這里必須注意下,當進行多線程調用時,傳入的參數進行值拷貝以防止程序運行時讀取臟數據。