最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

c#使用dynamic類型優(yōu)化反射的方法

 更新時(shí)間:2018年12月05日 10:47:32   作者:Fode  
dynamic是FrameWork4.0的新特性,下面這篇文章主要給大家介紹了關(guān)于c#使用dynamic類型優(yōu)化反射的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

什么是dynamic類型?

微軟給出的官方文檔中這樣解釋:在通過 dynamic 類型實(shí)現(xiàn)的操作中,該類型的作用是繞過編譯時(shí)類型檢查。 改為在運(yùn)行時(shí)解析這些操作。 dynamic 類型簡(jiǎn)化了對(duì) COM API(例如 Office Automation API)、動(dòng)態(tài) API(例如 IronPython 庫)和 HTML 文檔對(duì)象模型 (DOM) 的訪問。在大多數(shù)情況下,dynamic 類型與 object 類型的行為類似。 但是,如果操作包含 dynamic 類型的表達(dá)式,那么不會(huì)通過編譯器對(duì)該操作進(jìn)行解析或類型檢查。 編譯器將有關(guān)該操作信息打包在一起,之后這些信息會(huì)用于在運(yùn)行時(shí)評(píng)估操作。 在此過程中,dynamic類型的變量會(huì)編譯為 object 類型的變量。 因此,dynamic 類型只在編譯時(shí)存在,在運(yùn)行時(shí)則不存在。

dynamic的出現(xiàn)讓C#具有了弱語言類型的特性。編譯器在編譯的時(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)鍵字,只需要你知道他的類型是繞過編譯器就可以,如以下操作,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#具有了若語言的特性。編譯器在編譯時(shí)候不再對(duì)該類型進(jìn)行檢查,編譯器默認(rèn)dynamic對(duì)象支持開發(fā)者想要的任何特征。比如,即使你對(duì) GetStudent()方法返回的對(duì)象一無所知,也可以像以下執(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ì)象沒有包含該屬性
  //dyn.PrintAge(); //這行代碼會(huì)報(bào)錯(cuò)誤,訪問級(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í)際上是編譯期間拋給我門的“語法糖”,一旦被編譯,編譯器會(huì)自動(dòng)匹配var變量的實(shí)際類型,并用實(shí)際類型來替換給變量的聲明,這看上去就好像我們?cè)诰幋a的時(shí)候用實(shí)際類型進(jìn)行聲明一樣,優(yōu)點(diǎn)也顯而易見,當(dāng)【賦值方】類型發(fā)生變化時(shí),【實(shí)現(xiàn)方】無需改變其類型,因?yàn)関ar會(huì)自動(dòng)去適配。而dynamic被編譯后,實(shí)際上是一個(gè)Object類型,只不過編譯器會(huì)對(duì)dynamic類型進(jìn)行特殊處理,讓它在編譯期間不進(jìn)行任何的類型檢查,而是將類型檢查放到了運(yùn)行期。這從VS這個(gè)IDE就能看出,在編輯窗口中,var支持【智能感知】,因?yàn)関s能推斷出var類型的實(shí)際類型;而dynamic聲明的變量卻不支持【智能感知】,因?yàn)閷?duì)其運(yùn)行期的類型一無所知。對(duì)dynamic變量使用【智能感知】會(huì)提示"此操作將在運(yùn)行時(shí)解析"。

BB了這么久,重點(diǎn)來了,利用好了動(dòng)態(tài)類型dynamic的這個(gè)特性,可以簡(jiǎn)化C#中的反射語法,更高深的優(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é)果沒有什么好講的,就是一個(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)化不以為然,畢竟代碼看起來并沒有減少多少,但是,如果考慮到效率兼優(yōu)美兩個(gè)特性,那么dynamic的優(yōu)勢(shì)就顯現(xiàn)出來了。對(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é)果如下所示:

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

總結(jié):

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

代碼下載:http://xiazai.jb51.net/201812/yuanma/ConsoleApp2_jb51.rar

好了,以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,如果有疑問大家可以留言交流,謝謝大家對(duì)腳本之家的支持。

相關(guān)文章

  • C#解決SQlite并發(fā)異常問題的方法(使用讀寫鎖)

    C#解決SQlite并發(fā)異常問題的方法(使用讀寫鎖)

    這篇文章主要介紹了C#解決SQlite并發(fā)異常問題的方法,通過使用讀寫鎖達(dá)到多線程安全訪問,進(jìn)而解決SQLite并發(fā)異常的問題,具有一定參考借鑒價(jià)值,需要的朋友可以參考下
    2016-07-07
  • Unity3D實(shí)戰(zhàn)之答題系統(tǒng)的實(shí)現(xiàn)

    Unity3D實(shí)戰(zhàn)之答題系統(tǒng)的實(shí)現(xiàn)

    本文將用Unity3D制作一個(gè)答題系統(tǒng),可以從文本文檔中提取題目和分?jǐn)?shù),然后綁定到UI上,在答題的過程中,自動(dòng)判斷分?jǐn)?shù),自動(dòng)判斷正確率。感興趣的可以學(xué)習(xí)一下
    2022-03-03
  • 利用WPF實(shí)現(xiàn)Windows屏保的制作

    利用WPF實(shí)現(xiàn)Windows屏保的制作

    屏保程序的本質(zhì)上就是一個(gè)Win32?窗口應(yīng)用程序。本文將利用WPF實(shí)現(xiàn)Windows屏保的制作,文中的示例代碼簡(jiǎn)潔易懂,對(duì)我們學(xué)習(xí)WPF有一定幫助,感興趣的可以了解一下
    2022-07-07
  • C#使用分部類設(shè)計(jì)實(shí)現(xiàn)一個(gè)計(jì)算器

    C#使用分部類設(shè)計(jì)實(shí)現(xiàn)一個(gè)計(jì)算器

    分部類是C#4.5中的一個(gè)新特性,它的出現(xiàn)使得程序的結(jié)構(gòu)更加合理,代碼組織更加緊密,本文將使用分部類設(shè)計(jì)實(shí)現(xiàn)一個(gè)簡(jiǎn)單的計(jì)算器,感興趣的小伙伴可以了解下
    2024-02-02
  • C#服務(wù)生命周期:Singleton、Scoped、Transient用法及說明

    C#服務(wù)生命周期:Singleton、Scoped、Transient用法及說明

    文章介紹了三種服務(wù)生命周期:?jiǎn)卫?、作用域和瞬態(tài),并討論了如何在ASP.NETCore中使用這些生命周期管理服務(wù),單例在應(yīng)用程序生命周期中只有一個(gè)實(shí)例,作用域在每個(gè)請(qǐng)求中創(chuàng)建一個(gè)新實(shí)例,瞬態(tài)每次請(qǐng)求時(shí)創(chuàng)建一個(gè)新實(shí)例
    2025-01-01
  • C#解決訪問API顯示基礎(chǔ)連接已經(jīng)關(guān)閉的問題

    C#解決訪問API顯示基礎(chǔ)連接已經(jīng)關(guān)閉的問題

    最近在 Web 部署百度 AI 圖像識(shí)別 AipSdk.dll 封裝庫的時(shí)候,在調(diào)用OCR圖像識(shí)別 API 的時(shí)候,顯示為 “ 基礎(chǔ)連接已經(jīng)關(guān)閉: 接收時(shí)發(fā)生錯(cuò)誤,” ,并且運(yùn)行后直接崩潰,所以本文給大家介紹了C#解決訪問API顯示基礎(chǔ)連接已經(jīng)關(guān)閉的問題,需要的朋友可以參考下
    2024-12-12
  • 用 C# Winform做出全透明的磨砂玻璃窗體效果代碼

    用 C# Winform做出全透明的磨砂玻璃窗體效果代碼

    就是一個(gè)簡(jiǎn)單的例子, 調(diào)用系統(tǒng)的 dwm 去重繪窗口. 只能在 Vista 和 7 之后才可以, 并且要確保已經(jīng)開啟主題服務(wù)等等, 總之不是非常實(shí)用, 好玩而已
    2011-05-05
  • Unity實(shí)現(xiàn)植物識(shí)別示例詳解

    Unity實(shí)現(xiàn)植物識(shí)別示例詳解

    這篇文章主要介紹了如何通過Unity接入百度AI實(shí)現(xiàn)植物識(shí)別,接口返回植物的名稱,并支持獲取識(shí)別結(jié)果對(duì)應(yīng)的百科信息。感興趣的可以了解一下
    2022-01-01
  • C#解決多IfElse判斷語句和Switch語句問題的方法分享

    C#解決多IfElse判斷語句和Switch語句問題的方法分享

    這篇文章主要為大家介紹C#如何使用設(shè)計(jì)模式中的策略模式和委托來解決多個(gè)IfElse判斷語句和Switch語句,這種替換方式在其他語言也一樣可以做到,感興趣的可以了解一下
    2022-12-12
  • C#實(shí)現(xiàn)字符串模糊匹配的方法小結(jié)

    C#實(shí)現(xiàn)字符串模糊匹配的方法小結(jié)

    在C#中實(shí)現(xiàn)字符串的模糊匹配可以借助正則表達(dá)式或者一些模糊匹配算法來實(shí)現(xiàn),文章通過代碼示例講解的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作有一定的幫助,需要的朋友可以參考下
    2024-07-07

最新評(píng)論

郴州市| 湖州市| 福清市| 阳山县| 额济纳旗| 徐州市| 托克托县| 宁武县| 准格尔旗| 方正县| 天气| 彝良县| 普宁市| 古田县| 石家庄市| 仁布县| 洪泽县| 改则县| 长垣县| 黄梅县| 曲水县| 栾川县| 安图县| 阜新| 清原| 兴宁市| 莒南县| 临江市| 田东县| 长兴县| 萨嘎县| 鹰潭市| 舟曲县| 上饶县| 得荣县| 明星| 青神县| 万全县| 肥西县| 保康县| 威远县|