好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

C#学习之动态化dynamic

C#学习之动态化dynamic

前段时间,一直分析关于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.Int32 
 int  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类。

 

分类:  C#语言

作者: Leo_wl

    

出处: http://www.cnblogs.com/Leo_wl/

    

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

版权信息

查看更多关于C#学习之动态化dynamic的详细内容...

  阅读:49次