【C#复习总结】dynamic
介绍
C# 4 引入了一个新类型 dynamic
。 该类型是一种静态类型,但类型为 dynamic
的对象会跳过静态类型检查。 大多数情况下,该对象就像具有类型 object
一样。 在编译时,将假定类型化为 dynamic
的元素支持任何操作。 因此,不必考虑对象是从 COM API、从动态语言(例如 IronPython)、从 HTML 文档对象模型 (DOM)、从反射还是从程序中的其他位置获取自己的值。 但是,如果代码无效,则在运行时会捕获到错误。
var与dynamic对比
1、var编译时替换为实际类型,而dynamic实际是object类型。
一旦被编译,编译期会自动匹配var 变量的实际类型,并用实际类型来替换该变量的申明,这看上去就好像我们在编码的时候是用实际类型进行申明的。而dynamic被编译后,实际是一个object类型,只不过编译器会对dynamic类型进行特殊处理,让它在编译期间不进行任何的类型检查,而是将类型检查放到了运行期。
2、智能感知。
以var声明的变量,支持“智能感知”,因为visual studion能推断出var类型的实际类型,而以dynamic声明的变量却不支持“智能感知”,因为编译器对其运行期的类型一无所知。对dynamic变量使用“智能感知”,会提示“此操作将在运行时解析”。
简单案例
编写一个hello world的测试程序,定义DynamicTest类型,并增加Welcome方法,其参数为name.
然后创建dynamic对象,调用Welcome方法。参数为空。
using System; namespace DynamicSample { class Program { static void Main(string[] args) { dynamic obj = new DynamicTest(); obj.Welcome(); } } class DynamicTest { public void Welcome(string name) { Console.WriteLine("Hello {0},welcome to dynamic world.",name); } } }
看看发生什么事情呢,通过测试发现:
编译通过,没有任何异常。
运行时抛出异常,异常信息:
未处理Microsoft.CSharp.RuntimeBinder.RuntimeBinderException HResult=-2146233088 Message=“Welcome”方法没有采用“0”个参数的重载 Source=Anonymously Hosted DynamicMethods Assembly StackTrace: 在 CallSite.Target(Closure , CallSite , Object ) 在 System.Dynamic.UpdateDelegates.UpdateAndExecuteVoid1[T0](CallSite site, T0 arg0) 在 DynamicSample.Program.Main(String[] args) 位置 E:\Donet\C#\DynamicSample\DynamicSample\Program.cs:行号 13 在 System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args) 在 System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args) 在 Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly() 在 System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx) 在 System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx) 在 System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state) 在 System.Threading.ThreadHelper.ThreadStart() InnerException:
修正后:
class Program { static void Main(string[] args) { dynamic obj = new DynamicTest(); string name = "Tom"; obj.Welcome(name); Console.WriteLine("Input any key to exit."); Console.ReadKey(); } }
如果改为var,定义该对象,并调用方法,代码如下,编译器会报错:
var v1 = new DynamicTest(); v1.Welcome();
错误信息:
错误 CS7036 未提供与“DynamicTest.Welcome(string)”的必需形参“name”对应的实参 DynamicSample Program.cs 15 错误 CS7036 There is no argument given that corresponds to the required formal parameter 'name' of 'DynamicTest.Welcome(string)' DynamicSample
dynamic应用范围
1、在声明中,作为属性、字段、索引器、参数、返回值或类型约束的类型,都可以使用dynamic。dynamic in several different declarations.">
2、在显式类型转换中,作为转换的目标类型。任何对象都可以隐式转为dynamic。
3、在以类型充当值(如 is 运算符或 as 运算符右侧)或者作为 typeof 的参数成为构造类型的一部分的任何上下文中。
通过一个实例来具体说明:
class DynamicUser { ////// 字段 /// public dynamic userid; /// /// 属性 /// public dynamic UserName { get; set; } /// /// 玩游戏 /// (dynamic可以作为参数、返回值等) /// /// /// public dynamic Play(dynamic game) { dynamic defaultGame = "Play Basketball."; dynamic secGame = "Play with mud."; if (game is int) { return defaultGame; } else { return secGame; } } /// /// 显式类型转换 /// public void ConvertToDynamic(object obj) { dynamic d; d = (dynamic)obj; Console.WriteLine(d); } /// /// 类型判定 /// (dynamic 可以使用is、as、typeof) /// public void TypeCheck() { int age = 20; Console.WriteLine("Age is Dynamic? {0}",age is dynamic); dynamic d = age as dynamic; Console.WriteLine("Age:{0}",d); Console.WriteLine("List 's type is {0} ",typeof(List<dynamic>)); } }
测试用例:
DynamicUser user = new DynamicUser(); user.userid = 123; user.UserName = "Lucy"; user.ConvertToDynamic(user.userid); user.ConvertToDynamic(user.UserName); user.TypeCheck(); Console.WriteLine("Input any key to exit."); Console.ReadKey();
应用
1、自动反射
2、COM组件互操作
3、混合编程,例如IronRuby和IronPython
4、处理Html DOM对象
5、还有一种应用,数据传输中格式转换,如:对象转json等,很方便