欧美成人午夜免费全部完,亚洲午夜福利精品久久,а√最新版在线天堂,另类亚洲综合区图片小说区,亚洲欧美日韩精品色xxx

扣丁學(xué)堂Java培訓(xùn)分享c#使用dynamic類型優(yōu)化反射的方法

2019-03-18 13:51:54 2208瀏覽

研究Java開(kāi)發(fā)的小伙伴們有多少知道或者是了解dynamic的嗎?c#使用dynamic類型優(yōu)化反射的方法有哪些有多少的小伙伴知道呢?本篇文章扣丁學(xué)堂Java培訓(xùn)小編就給讀者們探討一下c#使用dynamic類型優(yōu)化反射的方法,希望對(duì)小伙伴們有所幫助。



扣丁學(xué)堂Java培訓(xùn)分享c#使用dynamic類型優(yōu)化反射的方法



什么是dynamic類型?


微軟給出的官方文檔中這樣解釋:在通過(guò) dynamic 類型實(shí)現(xiàn)的操作中,該類型的作用是繞過(guò)編譯時(shí)類型檢查。 改為在運(yùn)行時(shí)解析這些操作。 dynamic 類型簡(jiǎn)化了對(duì) COM API(例如 Office Automation API)、動(dòng)態(tài) API(例如 IronPython 庫(kù))和 HTML 文檔對(duì)象模型 (DOM) 的訪問(wèn)。在大多數(shù)情況下,dynamic 類型與 object 類型的行為類似。  


但是,如果操作包含 dynamic 類型的表達(dá)式,那么不會(huì)通過(guò)編譯器對(duì)該操作進(jìn)行解析或類型檢查。 編譯器將有關(guān)該操作信息打包在一起,之后這些信息會(huì)用于在運(yùn)行時(shí)評(píng)估操作。 在此過(guò)程中,dynamic類型的變量會(huì)編譯為 object 類型的變量。 因此,dynamic 類型只在編譯時(shí)存在,在運(yùn)行時(shí)則不存在。


dynamic的出現(xiàn)讓C#具有了弱語(yǔ)言類型的特性。編譯器在編譯的時(shí)候不再對(duì)類型進(jìn)行檢查,編譯期默認(rèn)dynamic對(duì)象支持你想要的任何特性。



下例中生成的類型是一致的:



dynamic dyn = "Fode";       Object obj = "Fode";
// Rest the mouse pointer over dyn and obj to see their
// types at compile time.
System.Console.WriteLine(dyn.GetType());
System.Console.WriteLine(obj.GetType());



其輸出結(jié)果都是String類型,可知CLR可以正確的識(shí)別出dynamic是哪種類型,在反編譯看看其生成的IL代碼:



IL_0000: nop
IL_0001: ldstr "Fode"
IL_0006: stloc.0
IL_0007: ldstr "Fode"
IL_000c: stloc.1
IL_000d: call valuetype [mscorlib]System.ConsoleKeyInfo [mscorlib]System.Console::ReadKey()
IL_0012: pop
IL_0013: ret



JIT編譯器將dynamic識(shí)別為String類型,并將其推算到運(yùn)算棧中(IL代碼中 ldstr(將新對(duì)象引用推送到存儲(chǔ)在元數(shù)據(jù)中的字符串文字)、(stloc.*)從評(píng)估堆棧的頂部彈出當(dāng)前值,并將其存儲(chǔ)在索引*處的本地變量列表中),不同IL代碼也不所謂,前文只是介紹dynamic這個(gè)類型關(guān)鍵字,只需要你知道他的類型是繞過(guò)編譯器就可以,如以下操作,Object類型就會(huì)報(bào)編譯的錯(cuò)誤。但是,對(duì)于 dyn + 3,不會(huì)報(bào)告任何錯(cuò)誤。 在編譯時(shí)不會(huì)檢查包含 dyn 的表達(dá)式,原因是 dyn 的類型為 dynamic。



dynamic dyn = "Fode";
Object obj = "Fode";
dyn = dyn + 3;
obj = obj + 3; //這句代碼編譯器會(huì)報(bào)錯(cuò)



dynamic是Framework 4.0的新特性。dynamic的出現(xiàn)讓C#具有了若語(yǔ)言的特性。編譯器在編譯時(shí)候不再對(duì)該類型進(jìn)行檢查,編譯器默認(rèn)dynamic對(duì)象支持開(kāi)發(fā)者想要的任何特征。比如,即使你對(duì) GetStudent()方法返回的對(duì)象一無(wú)所知,也可以像以下執(zhí)行代碼的調(diào)用,編譯器不會(huì)報(bào)錯(cuò):



static void Main(string[] args)
{
dynamic dyn = GetStudent();
//正確的操作
Console.WriteLine(dyn.Age);
Console.WriteLine(dyn.Name);
dyn.PrintName();
//錯(cuò)誤的操作
//Console.WriteLine(dyn.Birthday); //該對(duì)象沒(méi)有包含該屬性
//dyn.PrintAge(); //這行代碼會(huì)報(bào)錯(cuò)誤,訪問(wèn)級(jí)別不夠
Console.ReadKey();
}
static Student GetStudent()
{
Student student = new Student();
student.Age = 21;
student.Name = "Fode";
return student;
}
class Student
{
public String Name { get; set; }
public Int32 Age { get; set; }
public void PrintName()
{
Console.WriteLine(this.Name);
}
private void PrintAge()
{
Console.WriteLine(this.Age);
}
}



如果運(yùn)行時(shí)dyn對(duì)象不包含指定的特性(屬性、字段、方法等),運(yùn)行時(shí)會(huì)拋出一個(gè)運(yùn)行時(shí)的錯(cuò)誤 RuntimeBinderException。


注意:有人可能會(huì)將var關(guān)鍵字與dynamic進(jìn)行比較。實(shí)際上,var和dynamic完全是兩回事,兩個(gè)不同的概念。var實(shí)際上是編譯期間拋給我門(mén)的“語(yǔ)法糖”,一旦被編譯,編譯器會(huì)自動(dòng)匹配var變量的實(shí)際類型,并用實(shí)際類型來(lái)替換給變量的聲明,這看上去就好像我們?cè)诰幋a的時(shí)候用實(shí)際類型進(jìn)行聲明一樣,優(yōu)點(diǎn)也顯而易見(jiàn),當(dāng)【賦值方】類型發(fā)生變化時(shí),【實(shí)現(xiàn)方】無(wú)需改變其類型,因?yàn)関ar會(huì)自動(dòng)去適配。而dynamic被編譯后,實(shí)際上是一個(gè)Object類型,只不過(guò)編譯器會(huì)對(duì)dynamic類型進(jìn)行特殊處理,讓它在編譯期間不進(jìn)行任何的類型檢查,而是將類型檢查放到了運(yùn)行期。這從VS這個(gè)IDE就能看出,在編輯窗口中,var支持【智能感知】,因?yàn)関s能推斷出var類型的實(shí)際類型;而dynamic聲明的變量卻不支持【智能感知】,因?yàn)閷?duì)其運(yùn)行期的類型一無(wú)所知。對(duì)dynamic變量使用【智能感知】會(huì)提示"此操作將在運(yùn)行時(shí)解析"。


現(xiàn)在,重點(diǎn)來(lái)了,利用好了動(dòng)態(tài)類型dynamic的這個(gè)特性,可以簡(jiǎn)化C#中的反射語(yǔ)法,更高深的優(yōu)化將在以后的博客推出。在dynamic出現(xiàn)之前,我們先用基礎(chǔ)反射獲取一個(gè)類中的方法,并執(zhí)行它:



static void Main()
{
DynamicObj obj = new DynamicObj();
var fun = obj.GetType().GetMethod(nameof(obj.CallFun));
Int32 result = (Int32)fun.Invoke(obj, new Object[] { "Fode" });
Console.WriteLine(result);
Console.ReadKey();
}
public class DynamicObj
{
public Int32 CallFun(String str)
{
return str.Length;
}
}



其結(jié)果沒(méi)有什么好講的,就是一個(gè)用反射調(diào)用 CallFun() 方法的例子,而用dynamic之后,代碼看上去更簡(jiǎn)潔了,并且在可控制的范圍內(nèi)減少了一次拆箱的操作,代碼如下:



dynamic dyn = new DynamicObj();
Int32 result = dyn.CallFun("Fode");
Console.WriteLine(result);



可能我們會(huì)對(duì)這樣的簡(jiǎn)化不以為然,畢竟代碼看起來(lái)并沒(méi)有減少多少,但是,如果考慮到效率兼優(yōu)美兩個(gè)特性,那么dynamic的優(yōu)勢(shì)就顯現(xiàn)出來(lái)了。對(duì)上面的代碼個(gè)執(zhí)行10000000次,在進(jìn)行分析,如下所示:



CodeTimer.Time("使用dynamic", 10000000, () => { //執(zhí)行里面的代碼10000000次
dynamic dyn = new DynamicObj();
Int32 result = dyn.CallFun("Fode");
});
CodeTimer.Time("使用基礎(chǔ)反射", 10000000, () => { //執(zhí)行里面的代碼10000000次
DynamicObj obj = new DynamicObj();
var fun = obj.GetType().GetMethod(nameof(obj.CallFun));
Int32 result = (Int32)fun.Invoke(obj, new Object[] { "Fode" });
});
Console.ReadKey();



其運(yùn)行結(jié)果如下所示:


Java學(xué)習(xí)


從以上結(jié)果看出,使用dynamic使用時(shí)間為481ms,基礎(chǔ)反射使用時(shí)間為3063ms,CPU和時(shí)間上相差了5倍多,測(cè)試器 CodeTimer 的代碼隨后會(huì)貼出。



結(jié):


可以看到雖然用dynamic優(yōu)化后的反射跟基礎(chǔ)反射的相比,效率雖然在同一個(gè)數(shù)量級(jí)上??墒腔A(chǔ)反射卻沒(méi)有dynamic代碼簡(jiǎn)潔,因此建議:始終使用dynamic來(lái)簡(jiǎn)化反射實(shí)現(xiàn)(前提你知道你要是實(shí)現(xiàn)的類型),在往后的隨筆,將會(huì)提出用ExpressionTree和Emit技術(shù)深度優(yōu)化反射。



以上就是扣丁學(xué)堂Java在線學(xué)習(xí)小編給大家分享的c#使用dynamic類型優(yōu)化反射的方法,希望對(duì)小伙伴們有所幫助,想要了解更多內(nèi)容的小伙伴可以登錄扣丁學(xué)堂官網(wǎng)咨詢。想要學(xué)好Java開(kāi)發(fā)小編給大家推薦口碑良好的扣丁學(xué)堂,扣丁學(xué)堂有專業(yè)老師制定的Java學(xué)習(xí)路線圖輔助學(xué)員學(xué)習(xí),此外還有與時(shí)俱進(jìn)的Java視頻教程供大家學(xué)習(xí),想要學(xué)好Java開(kāi)發(fā)技術(shù)的小伙伴快快行動(dòng)吧??鄱W(xué)堂Java技術(shù)交流群:670348138。


扣丁學(xué)堂微信公眾號(hào)

【關(guān)注微信公眾號(hào)獲取更多學(xué)習(xí)資料】



查看更多關(guān)于“Java開(kāi)發(fā)資訊”的相關(guān)文章>>



標(biāo)簽: 參加Java培訓(xùn)學(xué)習(xí)靠譜嗎 Java培訓(xùn) Java基礎(chǔ)教程 Java學(xué)習(xí)視頻 Java教學(xué)視頻 java入門(mén)教程 Java教程視頻 java在線學(xué)習(xí) java在線視頻 java在線教程

熱門(mén)專區(qū)

暫無(wú)熱門(mén)資訊

課程推薦

微信
微博
15311698296

全國(guó)免費(fèi)咨詢熱線

郵箱:codingke@1000phone.com

官方群:148715490

北京千鋒互聯(lián)科技有限公司版權(quán)所有   北京市海淀區(qū)寶盛北里西區(qū)28號(hào)中關(guān)村智誠(chéng)科創(chuàng)大廈4層
京ICP備2021002079號(hào)-2   Copyright ? 2017 - 2022
返回頂部 返回頂部