CLR via C#学习笔记-第五章-dynamic基元类型
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了CLR via C#学习笔记-第五章-dynamic基元类型,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含3540字,纯文字阅读大概需要6分钟。
内容图文
![CLR via C#学习笔记-第五章-dynamic基元类型](/upload/InfoBanner/zyjiaocheng/854/bf13372b0f644e838ea7e946775f0d05.jpg)
5.5 dynamic基元类型
dynamic的用途
C#是类型安全的编程语言。意味着所有表达式都解析成类型的实例,编译器生成的代码只执行对该类型有效的操作。
和非类型安全的语言相比,类型安全的优势在于:错误在编译时检测到,执行前是正确的。
但程序许多时候仍需处理一些运行时才会知晓的信息。
虽然可用类型安全和这些信息交互,但语法就会比较笨拙,尤其是在涉及大量字符串处理的时候,性能也会有所损失。
如果写的是纯C#应用程序,只有在使用反射的时候,才需要和运行时才能确定的信息打交道。
但许多开发者在使用C#时,都要和一些不是用C#实现的组件进行通信。
为了方便开发人员使用反射或者与其他组件通信,C#编译器允许将表达式的类型标记为dynamic。
还可将表达式的结果放到变量中,并将变量类型标记为dynamic。
然后,可以用这个dynamic表达式、变量调用成员,比如字段、属性、索引器、方法、委托以及一元、二元转换操作符。
代码使用dynamic表达式调用成员时,编译器生成特殊的IL代码来描述所需的操作。
这种特殊的代码称为payload,有效载荷。在运行时,payload代码根据dynamic表达式、变量引用的对象的实际类型来决定具体执行的操作。
dynamic的使用
以下代码进行了演示。
internal static class DynamicDemo { public static void Main() { dynamic value; for(Int32 demo=0;demo<2;demo++) { value=(demo==0)?(dynamic)5:(dynamic)"A"; value=value+value; M(value); } } private static void M(Int32 n){Console.WriteLine("M(Int32):"+n);} private static void M(String s){Console.WriteLine("M(String):"+s);} }
执行Main会得到以下输出:
M(Int32):10 M(String):AA
理解代码
要理解发生的事情,首先就得搞清+操作符。他的两个操作数的类型时dynamic。
由于value是dynamic,所以C#编译器生成payload代码在运行时检查value的实际类型,决定+操作符实际要干什么。
dynamic的更多使用
如果字段、方法参数或方法返回值的类型时dynamic,编译器会将该类型转换为System.Object,
并在元数据中向字段、参数、或返回类型应用System.Runtime.CompilerServices.DynamicAttribute的实例。
如果局部变量被指定为dynamic,则变量类型也会成为Object,但不会向局部变量应用DynamicAttribute,因为他限制在方法内部使用。
由于dynamic其实就是Object,所以方法签名不能仅靠dynamic和Object的变化来区分。
泛型类(引用类型)、结构(值类型)、接口、委托或方法的泛型类型实参也可以是dynamic类型。
编译器将dynamic转换成Object,并向必要的各种元数据类型应用DynamicAttribute。
注意,使用的泛型代码是已经编译好的,会将类型视为Object。编译器不在泛型代码中生成payload代码,所以不会执行动态调度。
dynamic隐式转型
所有表达式都能隐式转型为dynamic,因为所有表达式最终都生成从Object派生的类型。
正常情况,编译器不允许写代码将表达式从Object隐式转型为其他类型,必须显式转型。
但是,编译器允许使用隐式转型语法将表达式从dynamic转型为其他类型。
Object o1=123;//OK,从Int32隐式转型为Object,装箱 Int32 n1=o1;//Error,不允许从Object到Int32的隐式转型 Int32 n2=(Int32)o1;//OK,从Object显式转型为Int32,拆箱 dynamic d1=123;//Ok,从Int32隐式转型为dynamic,装箱 In32 n3=d1;//OK,从dynamic隐式转型为Int32,拆箱
从dynamic转型为其他类型时,虽然编译器允许省略显式转型,但CLR会在运行时验证转型来确保类型安全性。
如果对象类型不兼容要转换成的类型,CLR会抛出异常。
注意,dynamic表达式的求值结果是一个动态表达式。
dynamic和var
dynamic d=123; var result=M(d);//注意,var result等同于dynamic result
代码之所以能通过编译,是因为编译时不知道调用哪M方法,从而不知道M的返回类型。
所以编译器假定result变量具有dynamic类型。 如果M方法的返回类型时void,会抛出异常。
重要提示
1.不要混淆dynamic和var。var声明局部变量只是一种简化语法,var只能在方法内部声明局部变量,而dynamic可用于局部变量、字段和参数。
2.表达式不能转型为var,但能转型为dynamic。
3.必须显式初始化用var声明的变量,但无需初始化用dynamic声明的变量。
作者指出C#编译器会生成payload代码,在运行时根据对象实际类型判断要执行什么操作。
这些paylo代码使用了称为运行时绑定器runtime binder的类。
内容总结
以上是互联网集市为您收集整理的CLR via C#学习笔记-第五章-dynamic基元类型全部内容,希望文章能够帮你解决CLR via C#学习笔记-第五章-dynamic基元类型所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。