zoukankan      html  css  js  c++  java
  • C#学习之动态化dynamic

    什么是动态,什么又是动态语言运行时

    动态即为在编译的时候不执行类型检查,仅在运行时识别对象的类型。这样的话,如果调用了一个类型没有的方法或是属性,在编译的时候并不会报错,但在运行时才会捕获这些错误信息。

    编程语言可分为静态化语言和动态话语言,C#最初是设计为纯静态化语言,但为了改进与动态语言和框架之间的互操作性,最终决定利用dynamic关键字来支持这一功能。

    View Code
     1  public static void M(dynamic arg)
     2     {
     3         dynamic result = arg + arg;
     4         Console.WriteLine(arg.GetType() + ":" + result);
     5     }
     6     static void Main(string[] args)
     7     {
     8         for (int i = 0; i < 2; i++)
     9         {
    10             dynamic d = (i == 0) ? 5 : (dynamic)"Demo";
    11             M(d);
    12         }
    13     }
    14     //output:
    15     //System.Int32:10
    16     //System.String:DemoDemo

    如上所见,能把不同的类型对象分配给dynamic变量,并在运行时确定对象的类型,已经执行相应的操作,如int类型,+执行求和,而对于string执行连接。
    那么,在编译时,c#编译器到底是如何解析dynamic类型啦,我们通过IL看下方法M的定义:

    View Code
     1  .method public hidebysig static void  M(object arg) cil managed
     2   {
     3     .param [1]
     4     .custom instance void [System.Core]System.Runtime.CompilerServices.DynamicAttribute::.ctor() = ( 01 00 00 00 ) 
     5     // Code size       448 (0x1c0)
     6     .maxstack  15
     7     .locals init ([0object result,
     8              [1class [Microsoft.CSharp]Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo[] CS$0$0000)
     9     IL_0000:  nop
    10     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'
    11     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经常会有显示转换问题:

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

    var是从c# 3.0 起添加的关键字,用于隐式类型化局部变量已经匿名类型。用var关键字声明变量时,编译时会根据初始化字符串来推断该变量的类型,并在运行时无法更改该变量的类型。vari经常和linq结合使用。

    View Code
    1 var var1 = 10;
    2 Console.WriteLine(var1.GetType());
    3 int result = var1;
    4 // var1="test"; 在将string赋值给var1将会发生error,因为var类型确定了,就不能更改类型,所以只能把整数赋给它。

    dynamic在某种程度上说依赖于object,因为dynamic类型在后台都是使用System.Object类型。但与object不同,dynamic类型在编译时不需要执行显示转换操作,它仅在运行时识别类型。

    View Code
    dynamic d = 10;
    Console.WriteLine(d.GetType()); //output: System.Int32
    int result = d;
    d = "test";
    Console.WriteLine(d.GetType());// output :System.String

     

    反射与dynamic

    有时候我们不知道某对象的精确类型,但知道这个对象所拥有的某方法,为了调用这个方法,我们可以使用反射:

    View Code
    1 object calc = GetCalculator();
    2 Type calcType = calc.GetType();
    3 object res = calcType.InvokeMember("Add",BindingFlags.InvokeMethod, nullnew object[] { 10,20 });
    4 int sum = Convert.ToInt32(res);

    而使用dynamic,将会使代码更简洁,易读,易懂:

    View Code
    1 dynamic calc = GetCalculator();
    2 int sum = calc.Add(1020);

    总结:dynamic可以是我们以更简洁的方式完成互操作性。同时c#还提供一些动态类,提供让我们自己对自己的类创建封装,如DynamicObject类。

  • 相关阅读:
    python day03--字符串
    python day02--运算符,编码
    python day01
    数据库:对 null 和notnull,单表操作,多表操作 。
    数据库的介绍
    数据库对表的操作练习。
    数据库基础知识:介绍
    并发编程知识总结,软件开发架构,socket套接字模板,粘包问题,struct解决粘包问题,上传大文件数据,socketserver,关于操作系统的发展史,进程,线程。
    Event事件,进程池与线程池,高性能爬取梨视频,协程,协程的目的,gevent。
    GIL全局解释器锁,多线程的作用,死锁现象,信号量(了解),线程队列。
  • 原文地址:https://www.cnblogs.com/blosaa/p/2547264.html
Copyright © 2011-2022 走看看