介绍
但是,如果代码无效,则在运行时会捕获到错误。
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应用范围
2、在显式类型转换中,作为转换的目标类型。任何对象都可以隐式转为dynamic。
typeof 的参数成为构造类型的一部分的任何上下文中。
通过一个实例来具体说明:
class DynamicUser
{
/// <summary>
/// 字段
/// </summary>
public dynamic userid;
/// <summary>
/// 属性
/// </summary>
public dynamic UserName { get; set; }
/// <summary>
/// 玩游戏
/// (dynamic可以作为参数、返回值等)
/// </summary>
/// <param name="game"></param>
/// <returns></returns>
public dynamic Play(dynamic game)
{
dynamic defaultGame = "Play Basketball.";
dynamic secGame = "Play with mud.";
if (game is int)
{
return defaultGame;
}
else
{
return secGame;
}
}
/// <summary>
/// 显式类型转换
/// </summary>
public void ConvertToDynamic(object obj)
{
dynamic d;
d = (dynamic)obj;
Console.WriteLine(d);
}
/// <summary>
/// 类型判定
/// (dynamic 可以使用is、as、typeof)
/// </summary>
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<dynamic>'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();
测试结果:
dynamic的执行效率
关于dynamic的效率问题,这里暂不展开,后续专门来讨论...
应用
1、自动反射
2、COM组件互操作
3、混合编程,例如IronRuby和IronPython
4、处理Html DOM对象
5、还有一种应用,数据传输中格式转换,如:对象转json等,很方便