讀【157個完美化C#的建議】一書的理解筆記 - 015
重點:反映類別中的語法有兩種1.反射Reflection 2.Dynamic ,通常用Dynamic語法簡潔且比一般的Reflection快 (差14倍)
流程說明 |
1. FCL 1.0 的reflection |
2. FCL 2.0 的dynamic |
3. reflection與dynamic的效能比較 |
4. 結論 |
1. FCL 1.0 的reflection
我們有以下類別的內容
/// <summary>
/// 範例類別
/// </summary>
public class DyamicSample
{
public string Name { get; set; }
public int Add(int a, int b)
{
return a + b;
}
}
在.net FrameWork Class Libary 1.0 的時代只有以下反射呼叫類別內的函式
取得Add的函式方法內容,然後進行委派(執行),取得result = 3
//==== A FCL 1.0 沒有Dynamic的時代,必須透過反射取得Method ====
DyamicSample origin = new DyamicSample();
//取得類別 DyamicSample 裡面的Method 名稱叫 Add ※如果沒有就是Null
var addMetohd = typeof(DyamicSample).GetMethod("Add");
//取得到後,可以對該方法進行委派,取得結果
int result = (int)addMetohd.Invoke(origin, new object[] { 1, 2 });
2. FCL 2.0 的dynamic
在.net FrameWork Class Libary 1.0 之後提供了dynamic,程式碼更簡潔了
//==== B FCL 2.0 以後有了Dynamic 可以更快速、間單的取得Method ===
dynamic origin2 = new DyamicSample();
int result2 = origin2.Add(1, 2);
3. reflection與dynamic的效能比較
我們在主程式進行 1. 一般reflection 2.優化reflection (委派呼叫) 3.Dynamic
各跑10000000(一千萬次),比較效能,如下
//進行 10000000 次的比較,可以展顯出兩者差異
string rateResult = Compare(10000000);
textBox1.Text = rateResult;
Compare() 是基於以下比較的函式
/// <summary>
/// 比較反射與Dynamic的速度差異
/// </summary>
public string Compare(int times)
{
string resultMessage = string.Empty;
//----------以下是反射
//建立碼表計時器
Stopwatch sw = new Stopwatch();
DyamicSample origin = new DyamicSample();
var addMetohd = typeof(DyamicSample).GetMethod("Add");
sw.Restart();
for (int i = times; i > 0; i--)
{
addMetohd.Invoke(origin, new object[] { 1, 2 });
}
resultMessage += string.Format("反射(Reflect)耗費:{0} 毫秒 \r\n", sw.ElapsedMilliseconds);
sw.Stop();
//----------以下是反射 優化
DyamicSample originPeformance = new DyamicSample();
var addMetohdPeformance = typeof(DyamicSample).GetMethod("Add");
//優化部分-執行委派 FCL 3.0提供以下方法
var delegateObj = (Func<DyamicSample, int, int, int>)Delegate.CreateDelegate(
typeof(Func<DyamicSample, int, int, int>),
addMetohdPeformance
);
sw.Restart();
for (int i = times; i > 0; i--)
{
delegateObj(originPeformance, 1, 2);
}
resultMessage += string.Format("反射優化(Reflect)耗費:{0} 毫秒 \r\n", sw.ElapsedMilliseconds);
sw.Stop();
dynamic dynamicObj = new DyamicSample();
//----------以下是Dynamic
sw.Restart();
for (int i = times; i > 0; i--)
{
dynamicObj.Add(1, 2);
}
resultMessage += string.Format("Dynamic 耗費:{0} 毫秒 \r\n", sw.ElapsedMilliseconds);
sw.Stop();
return resultMessage;
}
得到出結果如下:
4.結論
在需要反射類別物件的情況下,建議用Dynamic,因為優化的Reflection雖然更快,但在千萬筆的執行中只差0.2秒,但失去了程式碼的乾淨
對於維護成本相對提高6倍 (軟體工程師每看一行Code 都是時間成本)。
10000000次的執行耗費時間 | 程式碼行數 | 評論 | |
Reflection | 5.8 秒 | 3行 | 效能差,不建議使用 |
優化Reflection | 0.2 秒 | 6行 | 效能最佳,但程式碼失去簡潔,除非是巨型專案,才較推薦 |
Dynamic | 0.4 秒 | 1行 | 效能不錯,程式碼簡潔,通常選擇 |
github連結(Vs2015) : 點我下載