建议15: 使用dynamic来简化反射实现
生活随笔
收集整理的這篇文章主要介紹了
建议15: 使用dynamic来简化反射实现
小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
建議15: 使用dynamic來(lái)簡(jiǎn)化反射實(shí)現(xiàn)dynamic是Framework 4.0的新特性。dynamic的出現(xiàn)讓C#具有了弱語(yǔ)言類(lèi)型的特性。編譯器在編譯的時(shí)候不再對(duì)類(lèi)型進(jìn)行檢查,編譯器默認(rèn)dynamic對(duì)象支持開(kāi)發(fā)者想要的任何特性。比如,即使你對(duì)GetDynamicObject方法返回的對(duì)象一無(wú)所知,也可以像如下這樣進(jìn)行代碼的調(diào)用,編譯器不會(huì)報(bào)錯(cuò):dynamic dynamicObject = GetDynamicObject();
Console.WriteLine(dynamicObject.Name);
Console.WriteLine(dynamicObject.SampleMethod());
當(dāng)然,如果運(yùn)行時(shí)dynamicObject不包含指定的這些特性(如上文中帶返回值的方法SampleMethod),運(yùn)行時(shí)程序會(huì)拋出一個(gè)RuntimeBinderException異常:“System.Dynamic.ExpandoObject”未包含“SampleMethod”的定義。注意 有人會(huì)將var這個(gè)關(guān)鍵字與dynamic進(jìn)行比較。實(shí)際上,var和dynamic完全是兩個(gè)概念,根本不應(yīng)該放在一起比較。var實(shí)際上是編譯期拋給我們的“語(yǔ)法糖”,一旦被編譯,編譯期會(huì)自動(dòng)匹配var 變量的實(shí)際類(lèi)型,并用實(shí)際類(lèi)型來(lái)替換該變量的聲明,這看上去就好像我們?cè)诰幋a的時(shí)候是用實(shí)際類(lèi)型進(jìn)行聲明的。而dynamic被編譯后,實(shí)際是一個(gè)object類(lèi)型,只不過(guò)編譯器會(huì)對(duì)dynamic類(lèi)型進(jìn)行特殊處理,讓它在編譯期間不進(jìn)行任何的類(lèi)型檢查,而是將類(lèi)型檢查放到了運(yùn)行期。這從Visual Studio的編輯器窗口就能看出來(lái)。以var聲明的變量支持“智能感知”,因?yàn)閂isual Studio能推斷出var類(lèi)型的實(shí)際類(lèi)型;而以dynamic聲明的變量卻不支持“智能感知”,因?yàn)榫幾g器對(duì)其運(yùn)行期的類(lèi)型一無(wú)所知。對(duì)dynamic變量使用“智能感知”,會(huì)提示“此操作將在運(yùn)行時(shí)解析”。利用dynamic的這個(gè)特性,可以簡(jiǎn)化C#中的反射語(yǔ)法。在dynamic出現(xiàn)之前,假設(shè)存在類(lèi),代碼如下所示:public class DynamicSample
{ public string Name { get; set; } public int Add(int a, int b) { return a + b; }
}
我們這樣使用反射,調(diào)用方代碼如下所示:DynamicSample dynamicSample = new DynamicSample();
var addMethod = typeof(DynamicSample).GetMethod("Add");
int re = (int)addMethod.Invoke(dynamicSample, new object[] { 1, 2 });
在使用dynamic后,代碼看上去更簡(jiǎn)潔了,并且在可控的范圍內(nèi)減少了一次拆箱的機(jī)會(huì),代碼如下所示:
dynamic dynamicSample2 = new DynamicSample();
int re2 = dynamicSample2.Add(1, 2);
我們可能會(huì)對(duì)這樣的簡(jiǎn)化不以為然,畢竟代碼看起來(lái)并沒(méi)有減少多少,但是,如果考慮到效率兼優(yōu)美兩個(gè)特性,那么dynamic的優(yōu)勢(shì)就顯現(xiàn)出來(lái)了。如果對(duì)上面的代碼執(zhí)行1000000次,如下所示:
int times = 1000000;
DynamicSample reflectSample = new DynamicSample();
var addMethod = typeof(DynamicSample).GetMethod("Add");
Stopwatch watch1 = Stopwatch.StartNew();
for (var i = 0; i < times; i++)
{ addMethod.Invoke(reflectSample, new object[] { 1, 2 });
}
Console.WriteLine(string.Format("反射耗時(shí):{0} 毫秒", watch1.ElapsedMilliseconds));
dynamic dynamicSample = new DynamicSample();
Stopwatch watch2 = Stopwatch.StartNew();
for (int i = 0; i < times; i++)
{ dynamicSample.Add(1, 2);
}
Console.WriteLine(string.Format("dynamic耗時(shí):{0} 毫秒", watch2.ElapsedMilliseconds));
輸出為:
反射耗時(shí):2575 毫秒
dynamic耗時(shí):76 毫秒
可以看到,沒(méi)有優(yōu)化的反射實(shí)現(xiàn),上面這個(gè)循環(huán)上的執(zhí)行效率大大低于dynamic實(shí)現(xiàn)的效果。如果對(duì)反射實(shí)現(xiàn)進(jìn)行優(yōu)化,代碼如下所示:
DynamicSample reflectSampleBetter = new DynamicSample();
var addMethod2 = typeof(DynamicSample).GetMethod("Add");
var delg = (Func<DynamicSample, int, int, int>)Delegate.CreateDelegate(typeof( Func<DynamicSample, int, int, int>), addMethod2);
Stopwatch watch3 = Stopwatch.StartNew();
for (var i = 0; i < times; i++)
{ delg(reflectSampleBetter, 1, 2);
}
Console.WriteLine(string.Format("優(yōu)化的反射耗時(shí):{0} 毫秒", watch3.ElapsedMilliseconds));
輸出為:
優(yōu)化的反射耗時(shí):12 毫秒
可以看到,優(yōu)化后的反射實(shí)現(xiàn),其效率和dynamic在一個(gè)數(shù)量級(jí)上。可是它帶來(lái)了效率,卻犧牲了代碼的整潔度,這種實(shí)現(xiàn)在我看來(lái)是得不償失的。所以,現(xiàn)在有了dynamic類(lèi)型,建議大家:始終使用dynamic來(lái)簡(jiǎn)化反射實(shí)現(xiàn)。
?
轉(zhuǎn)載于:https://www.cnblogs.com/xust/articles/3081397.html
與50位技術(shù)專(zhuān)家面對(duì)面20年技術(shù)見(jiàn)證,附贈(zèng)技術(shù)全景圖總結(jié)
以上是生活随笔為你收集整理的建议15: 使用dynamic来简化反射实现的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Cocos2d-x 中 CCProgre
- 下一篇: pingall脚本