dynamic类型允许编写忽略编译期间的类型检查的代码。编译器假定,给dynamic类型的对象定义的任操作都是有效的。如果该操作无效,则在代码运行之前不会检测该错误,如下面的示例所示:
这个示例没有编译,因为它调用了staticPerson.GetFullName方法。因为Person 对象上的方法不接受两个参数,所以编译器会提示出错。如果注释掉该行代码,这个示例就会编译。如果执行它,就会发生一个运行错误。所抛出的异常是RuntimeBinderException 异常。RuntimeBinder对象会在运行时判断该调用,确定Person类是否支持被调用的方法。
与 var 关键字不同,定义为dynamic的对象可以在运行期间改变其类型。注意在使用var关键字时,对象类型的确定会证迟。类型一旦确定,就不能改变。动态对象的类型可以改变,而且可以改变影次,这不同于把对象的类型事转换为另一种类型。在强制转换对象的类型时,是用另一种兼容的类聚们建一个新对象。如,不能把int强制转换为Penon对象。在下面的示例中,如果对象是动态对象,就可以把它从int变成Persor类型:
static void Main(string[] args)
{
//var staticperson = new Person();
//dynamic dynamicPerson = new Person();
//staticperson.GetFullName("John", "Smith");
//dynamicPerson.GetFullName("Jchn", "Smith");
dynamic dyn;
dyn = 100;
Console.WriteLine(dyn.GetType());
Console.WriteLine(dyn);
dyn = "This is a string";
Console.WriteLine(dyn.GetType());
Console.WriteLine(dyn);
dyn = new Person() { FirstName = "Bugs", LastName = "Bunny" };
Console.WriteLine(dyn.GetType());
Console.WriteLine($"{dyn.FirstName} {dyn.LastName}");
Console.ReadKey();
}
执行这段代码可以看出,dyn对象的类型实际上从System.Int32变成System.String.再变成Person。如果 dyn声明为int 或string,这段代码就不会编译。
注意:对于dynamic 类型有两个限制。动态对象不支持扩展方法,匿名函数(lambda表达式)也不能用作动态方法调用的参数,因此LINQ不能用于动态对象,大多数LINQ调用大都是扩展方法,而lambda表达式用作这些扩展方法的参数.