C# dynamic关键字的使用方法

C#是一种类型安全的编程语言(所有表达式都能解析成某个类型的实例,在编译器生成的代码中,只会执行对这个类型有效的操作),和非类型安全的语言相比,类型安全的优势就体现出来了:
1.许多错误能在编译时检测到,取保代码在执行它之前是正确的。
2.编译时语言通常能生成更小,更快的代码。(在编译时进行更多的假设,并在IL和元数据中落实那些假设)

为了方便开发人员使用反射或者与基本组件通信,dynamic诞生了!
一下代码展示了如何利用反射在一个String目标("根据我找类型")上调用一个方法(“Contains”),向它传递一个实参(“我只是一个string参数”),并将结果存储到局部变量result中。


代码如下:

static void Main()
        {
            object target = "根据我找类型";
            object arg = "我只是个string参数";
            Type[] argtype = new Type[] { arg.GetType()};
            System.Reflection.MethodInfo method = target.GetType().GetMethod("Contains", argtype);

object[] argm = new object[] { arg};
            Boolean result=Convert.ToBoolean(method.Invoke(target,argm));
}

现在,有了dynamic!


代码如下:

static void Main()
        {
            dynamic target = "根据我找类型";
            dynamic arg = "参数";
            Boolean result = target.Contains(arg);
}

是不是发现有了显著的简化。


代码如下:

static void Main()
        {
            Application excel = new Application();
            excel.Visible = true;
            excel.Workbooks.Add(Type.Missing);
            ((Range)excel.Cells[1, 1]).Value = http://www.jb51.net/smailxiaobai/archive/2011/11/25/"放入单元格的字符";//如果没有dynamic类型,excel.Cells[1,1]的返回值是objec类型,必须先把它转换为Rang类型才能访问Value属性。
            excel.Cells[1, 1].Value = http://www.jb51.net/smailxiaobai/archive/2011/11/25/"放入单元格的字符";//为COM对象生成一个可由“运行时”调用的包装程序集时,COM方法中使用的任何variant实际都会被转换为dynamic,这称为动态化(dynamicfication)。
            //所以这里excel.Cells[1,1]是dynamic类型,可以不必显示把它转换成Range类型也能访问它的Value。动态化显著简化了与COM对象的互操作。
        }

看到了dynamic的神奇,那再让我们刨根问底吧。
我们可以用dynamic表达式或变量调用一个成员,比如字段,属性/索引器,方法,委托,以及一元/二元/转换操作符,当我们的代码使用dynamic表达式或变量调用一个成员时,编译器会生成特殊的IL代码来描述所需的操作。
这种特殊的代码称为payload(有效载荷)(这些payload代码使用了一个称为运行时绑定器(runtime binder)的类),在运行时,payload代码根据当前由dynamic表达式/变量引用的对象的实际类型来决定具体的操作。
看这个例子:


代码如下:

static void Main()
        {
            for (int i = 0; i < 2; i++)
            {
                dynamic arg = (i == 0) ? (dynamic)10 : "A";
                dynamic result = plus(arg);//第一次循环i==0 ,arg=10;所以调用plus时,返回的是int类型。第二次是string类型。
                M(result);//payload代码判断出传给M的值的实际类型,然后调用相应的重载方法。
            }
          Console.ReadKey();
        }
        static dynamic plus(dynamic arg) { return arg+arg;}
        static  void M(int n) { Console.WriteLine("M(int):{0}", n); }
       static void M(string s) { Console.WriteLine("M(string):{0}", s); }
    }

在字段类型,方法参数类型或方法类型被指定为dynamic的前提下,编译器会将这个类型转换为System.Object,并在元数据中向字段,参数或者返回类型应用System.Runtime.CompilerSevices.DynamicAttribute的一个实例。如果是一个局部变量被指定为dynamic,变量类型也会成为Object,但不会向局部变量应用DynamicAttribute,应为它的使用限制在方法之内。
由于dynamic就是object 所以不仅仅将dynamic变成object,或者object变成dynamic就获取两个不同的方法签名。例子:


代码如下:

object dd(dynamic i) { return i; }
 dynamic dd( object i) {return i; }

这就通不过编译。
dynam的类型转换:


代码如下:

static void Main()
        {
            object o = 123;//(装箱)
            Int32 n = o;//错误!不允许从object到int32的隐式转换。
            Int32 n1 = (Int32)o;//从object显示转换到int32。(拆箱)

dynamic od = 123;//(装箱)
            dynamic os = "dsfsdf";
            Int32 ns = os;//运行时报错。
            Int32 nd = od;//从dynamic隐式转换为int32(拆箱)
            //在本例中可看出,dynamic转为其他类型时,允许省略显示转型。
            //但是CLR会在运行时验证转型,确保类型安全。如果对象类型不兼容要转换成的类型,clr就会抛出一个InvalidCastException异常。
        }

dynamic和var的区别:
1.var声明一个局部变量只是一种简化语法,它要求编译器根据一个表达式推断具体的数据类型。
2.var只能用于声明方法内部的局部变量,而dynamic可用于局部变量,字段,参数。
3.表达式不能转型为var,但能转型为dynamic。
4.必须显式初始化用var声明的变量,但无需初始化用dynam声明的变量。
使用dynamic应注意:
在运行时,Microsoft.Csharp.dll必须加载到AppDomain中,这回损害程序性能,并增大内错耗用,Microsoft.Csharp.dll还会加载System.dll和System.Core.dll,如果使用dynamic与COM组件互操作,还会加载System.Dynamic.dll,payload代码执行时会在运行时生成动态代码。这些代码会进入一个驻留在内存的程序集,称为“匿名寄宿的DynamicMethods程序集”(Anonymously Hosted DynamicMethods Assembly).
当一个特性的调用使用具有相同运行时类型的dynamic实参发出了大量调用时,这个代码可以增强调度的性能。
虽然dynamic能简化语法,但是动态求值功能产生的额外开销也是不容忽视的,毕竟加载所有这些程序集以及额外的内存消耗,会对性能产生额外的影响。如果程序中只是一两个地方需要动态行为,或许传统的做法会更加高效。

(0)

相关推荐

  • 详解C# 匿名对象(匿名类型)、var、动态类型 dynamic

    随着C#的发展,该语言内容不断丰富,开发变得更加方便快捷,C# 的锋利尽显无疑.C# 语言从诞生起就是强类型语言,这一性质到今天不曾改变,我想以后也不会变.既然是强类型语言,那编写任一程序均要求满足下面的基本条件: 1.变量声明必须指明其类型 2.变量类型明确后,其类型在Runtime亦不能改变 代码如下: public class Student { public string Name { get; set; } public int Age { get; set; } public str

  • C#动态对象(dynamic)详解(实现方法和属性的动态)

    C#的动态对象的属性实现比较简单,如果要实现动态语言那种动态方法就比较困难,因为对于dynamic对象,扩展方法,匿名方法都是不能用直接的,这里还是利用对象和委托来模拟这种动态方法的实现,看起来有点javascript的对象味道: 1) 定义一个委托,参数个数可变,参数都是object类型:这里的委托多有个dynamic参数,代表调用这个委托的动态对象本身. public delegate object MyDelegate(dynamic Sender, params object[] PMs

  • C# 反射与dynamic最佳组合示例代码

    在 C# 中反射技术应用广泛,至于什么是反射.........你如果不了解的话,请看下段说明,否则请跳过下段.广告一下:喜欢我文章的朋友请关注一下我的blog,这也有助于提高本人写作的动力. 反射:当你背对一个美女或帅哥却不能回头仔细观察研究时(纯属虚构,如有巧合.纯属雷同),一面小镜子就能满足你的需求.在 C# 编程过程中也经常遇到类似的情况:有一个别人写的 dll 类库你想使用却没程序文档资料......此时通过 C# Runtime 提供的功能,你可以把该 dll 类库加载到你的程序中,并

  • C# Dynamic关键字之:解析dynamic就是Object

    C# 4.0提供了一个dynamic 关键字,那么什么是dynamic,究竟dynamic是如何工作的呢? 从最简单的示例开始: 复制代码 代码如下: static void Main(string[] args)        {            dynamic dyn = 1;            object obj = 1;            //在编译时将鼠标放到 "dyn"  和"obj"中可以发现:             // dyn:局

  • C# Dynamic关键字之:调用属性、方法、字段的实现方法

    新建类Product: 复制代码 代码如下: class Product{    public string name;    public int Id { get; set; } public void ShowProduct()    {        Console.WriteLine("Id={0} ,Name={1}", Id, name);    }} Main方法代码如下: 复制代码 代码如下: static void Main(string[] args){    /

  • C# Dynamic之:ExpandoObject,DynamicObject,DynamicMetaOb的应用(上)

    ExpandoObject:表示一个对象,该对象包含可在运行时动态添加和移除的成员. 复制代码 代码如下: dynamic dynEO = new ExpandoObject();dynEO.number = 10;dynEO.Increment = new Action(() => { dynEO.number++; }); Console.WriteLine(dynEO.number);dynEO.Increment();Console.WriteLine(dynEO.number); dy

  • C# dynamic关键字的使用方法

    C#是一种类型安全的编程语言(所有表达式都能解析成某个类型的实例,在编译器生成的代码中,只会执行对这个类型有效的操作),和非类型安全的语言相比,类型安全的优势就体现出来了:1.许多错误能在编译时检测到,取保代码在执行它之前是正确的.2.编译时语言通常能生成更小,更快的代码.(在编译时进行更多的假设,并在IL和元数据中落实那些假设) 为了方便开发人员使用反射或者与基本组件通信,dynamic诞生了!一下代码展示了如何利用反射在一个String目标("根据我找类型")上调用一个方法(&qu

  • C#中dynamic关键字的正确用法(推荐)

    dynamic是FrameWork4.0的新特性.dynamic的出现让C#具有了弱语言类型的特性.编译器在编译的时候不再对类型进行检查,编译期默认dynamic对象支持你想要的任何特性.比如,即使你对GetDynamicObject方法返回的对象一无所知,你也可以像如下那样进行代码的调用,编译器不会报错: dynamic dynamicObject = GetDynamicObject(); Console.WriteLine(dynamicObject.Name); Console.Writ

  • 浅析C# Dynamic关键字

    dynamic关键字和动态语言运行时(DLR)是.Net 4.0中新增的功能. 什么是"动态"? 编程语言有时可以划分为静态类型化语言和动态类型化语言.C#和Java经常被认为是静态化类型的语言,而Python.Ruby和JavaScript是动态类型语言. 一般而言,动态语言在编译时不会对类型进行检查,而是在运行时识别对象的类型.这种方法有利有弊:代码编写起来更快.更容易,但无法获取编译器错误,只能通过单元测试和其他方法来确保应用正常运行. C#最初是作为纯静态语言创建的,但是C#4

  • Python查询阿里巴巴关键字排名的方法

    本文实例讲述了Python查询阿里巴巴关键字排名的方法.分享给大家供大家参考.具体如下: 这里使用python库urllib及pyquery基本东西的应用,实现阿里巴巴关键词排名的查询,其中涉及到urllib代理的设置,pyquery对html文档的解析 1. urllib 基础模块的应用,通过该类获取到url中的html文档信息,内部可以重写代理的获取方法 class ProxyScrapy(object): def __init__(self): self.proxy_robot = Pro

  • java中this与super关键字的使用方法

    java中this与super关键字的使用方法 这几天看到类在继承时会用到this和super,这里就做了一点总结,与各位共同交流,有错误请各位指正~ this this是自身的一个对象,代表对象本身,可以理解为:指向对象本身的一个指针. this的用法在java中大体可以分为3种: 1.普通的直接引用 这种就不用讲了,this相当于是指向当前对象本身. 2.形参与成员名字重名,用this来区分: class Person { private int age = 10; public Perso

  • PHP使用微信开发模式实现搜索已发送图文及匹配关键字回复的方法

    本文实例讲述了PHP使用微信开发模式实现搜索已发送图文及匹配关键字回复的方法.分享给大家供大家参考,具体如下: 用户发送关键字,搜索相应的图文进行回复. 模拟登陆就不说了 右键看"已发送"图片页的源代码,图文部分是json格式的. 复制代码 代码如下: {"msg_item":[{"id":80630,"type":9,"fakeid":"2397007301","nick_n

  • 详谈PHP面向对象中常用的关键字和魔术方法

    PHP面向对象中常用的关键字   final 1.final不能修饰成员属性(类中常量不是用这个关键字) 2.final只能修饰类和方法 作用: 使用final修饰的类不能被子类继承 使用final修饰的方法不能被子类覆盖 用来限制类不被继承,方法不被覆盖就使用final <?php //final修饰的类不能被继承 final class Person{ var $name; var $age; var $sex; function __construct($name,$age,$sex){

  • Java this 关键字的使用方法详解

    Java this 关键字的使用方法详解 构造方法中的this关键字 构造方法是一个类的对象在通过new关键字创建时自动调用的,在程序中不能向调用其他方法一样通过方法名(也就是类名)来调用.但如果一个类有多个构造方法,可以在一个构造方法中通过this(paras-)来调用其他的构造方法. 使用this来调用其他构造方法有如下几个约束. 1) 只能在构造方法中通过this来调用其他构造方法,普通方法中不能使用. 2) 不能通过this递归调用构造方法,即不能在一个构造方法中通过this直接或间接调

  • Java中的break和continue关键字的使用方法总结

    一.作用和区别   break的作用是跳出当前循环块(for.while.do while)或程序块(switch).在循环块中的作用是跳出当前正在循环的循环体.在程序块中的作用是中断和下一个case条件的比较.   continue用于结束循环体中其后语句的执行,并跳回循环程序块的开头执行下一次循环,而不是立刻循环体.   二.其他用途   break和continue可以配合语句标签使用. 这个都很简单,下面给个综合实例,看看就明白 了: /** * Created by IntelliJ

随机推荐