C#學習之動態化–dynamic

來源:互聯網
上載者:User

前段時間,一直分析關於dynamic這塊的case,但是對於dynamic和DLR卻只有一些很模糊的概念,最近好好研究了一下這一塊,有點一知半解,嘿嘿。

什麼是動態,什麼又是動態語言運行時

 動態即為在編譯的時候不執行類型檢查,僅在運行時識別對象的類型。這樣的話,如果調用了一個類型沒有的方法或是屬性,在編譯的時候並不會報錯,但在運行時才會捕獲這些錯誤資訊。

程式設計語言可分為靜態化語言和動態話語言,C#最初是設計為純靜態化語言,但為了改進與動態語言和架構之間的互通性,最終決定利用dynamic關鍵字來支援這一功能。

    public static void M(dynamic arg)    {        dynamic result = arg + arg;        Console.WriteLine(arg.GetType() + ":" + result);    }    static void Main(string[] args)    {        for (int i = 0; i < 2; i++)        {            dynamic d = (i == 0) ? 5 : (dynamic)"Demo";            M(d);        }    }    //output:    //System.Int32:10    //System.String:DemoDemo

如上所見,能把不同的類型對象分配給dynamic變數,並在運行時確定對象的類型,已經執行相應的操作,如int類型,+執行求和,而對於string執行串連。
那麼,在編譯時間,c#編譯器到底是如何解析dynamic類型啦,我們通過IL看下方法M的定義:

 .method public hidebysig static void  M(object arg) cil managed  {    .param [1]    .custom instance void [System.Core]System.Runtime.CompilerServices.DynamicAttribute::.ctor() = ( 01 00 00 00 )     // Code size       448 (0x1c0)    .maxstack  15    .locals init ([0] object result,             [1] class [Microsoft.CSharp]Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo[] CS$0$0000)    IL_0000:  nop    IL_0001:  ldsfld     class [System.Core]System.Runtime.CompilerServices.CallSite`1<class [mscorlib]System.Func`4<class [System.Core]System.Runtime.CompilerServices.CallSite,object,object,object>> Program/'<M>o__SiteContainer0'::'<>p__Site1'    IL_0006:  brtrue.s   IL_0041

實際上,代碼使用dynamic運算式/變數來調用一個成員時,編譯器會產生特殊的IL代碼來描述所需的操作,這種特殊的代碼稱為payload(有效載荷)。而對於dynamic類型,實際上被解析為object類型,此外,對於像property,方法參數,編譯器還會為此加上一個DynamicAttribute,而對於方法內部的局部定義的dynamic類型,是不會加這個attribute的。

 

動態運行時,即Dynamic Language Runtime(DLR).首先它實現了動態語言和.NET Framework之間的互操作,其次,它將動態行為引入C#和Visual Basic之中。

C#語言環境中的dynamic概念指的就是關鍵字dynamic和DLR。

 

Dynamic, object and Var之間的區別

 object表示System.Object類型,是C#類階層中的根類型。object一般是在編譯時間無法確定物件類型時使用,它經常運用在各種互通性情形中。object經常會有顯示轉換問題:

object obj = 10;Console.WriteLine(obj.GetType());int result = (int)obj;   //  int result=obj; Error:Connot implicitly convert type 'object' to 'int'

var是從c# 3.0 起添加的關鍵字,用於隱式類型化局部變數已經匿名型別。用var關鍵字聲明變數時,編譯時間會根據初始化字串來推斷該變數的類型,並在運行時無法更改該變數的類型。vari經常和linq結合使用。

var var1 = 10;Console.WriteLine(var1.GetType());int result = var1;// var1="test"; 在將string賦值給var1將會發生error,因為var類型確定了,就不能更改類型,所以只能把整數賦給它。

dynamic在某種程度上說依賴於object,因為dynamic類型在後台都是使用System.Object類型。但與object不同,dynamic類型在編譯時間不需要執行顯示轉換操作,它僅在運行時識別類型。

dynamic d = 10;Console.WriteLine(d.GetType()); //output: System.Int32int result = d;d = "test";Console.WriteLine(d.GetType());// output :System.String

 

反射與dynamic

 有時候我們不知道某對象的精確類型,但知道這個對象所擁有的某方法,為了調用這個方法,我們可以使用反射:

object calc = GetCalculator();Type calcType = calc.GetType();object res = calcType.InvokeMember("Add",BindingFlags.InvokeMethod, null, new object[] { 10,20 });int sum = Convert.ToInt32(res);

而使用dynamic,將會使代碼更簡潔,易讀,易懂:

dynamic calc = GetCalculator();int sum = calc.Add(10, 20);

總結:dynamic可以是我們以更簡潔的方式完成互通性。同時c#還提供一些動態類,提供讓我們自己對自己的類建立封裝,如DynamicObject類。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.