TOC

This article is currently in the process of being translated into Chinese (~90% done).

数据类型:

The dynamic Type

微软在C#版本4.0中引入了一种新类型:动态类型。这其实是一种静态类型,但与其它静态类型不同的是,编译器并不会检查动态对象的(潜在)成员。这提供了某些动态/弱类型语言的优点,同时又在所有其它方面保留了强类型语言的优点。

定义动态类型跟定义其它类型的方法是一样的 - 简单使用dynamic关键字替代数据类型即可:

dynamic d1;
dynamic d2 = "A string";
dynamic d3 = 42;

这里有三个不同的对象 - 第一个现在真正的什么也不是(null),第二个是个字符串,第三个是个整数。这是由编译器在运行时确定的,根据是赋给变量的值的类型。也就是说编译器不会检查对这些变量进行的操作,如下例所展示的那样:

dynamic d1;
dynamic d2 = "A string";
dynamic d3 = 42;
Console.WriteLine(d2.Length);
Console.WriteLine(d3.Length);

字符串类型有个长度属性,用于确定字符串的长度,但整数类型就没有这个属性。上例试图在两个变量上都使用长度属性,但编译器对此不会作出反应 - 如果这些变量是定义为string和integer类型的,编译器就会介入。但是,因为定义的是动态(dynamic)类型,上述代码只会简单地被编译,然后运行。不过,一旦解释器到达最后一行代码,就会抛出一个异常,显然这里访问了一个并不存在的属性。

上例也展示了动态类型的危险之处 - 必需仔细检查所做的操作及确保每个属性和方法调用的拼写正确,因为编译器不会帮忙检查,基本上会把代码中的错误全部放过。

动态对象

dynamic关键字当然也可以用来定义比整数和字符串更复杂的类型。最重要的例子就是用来指向一个匿名对象,象这样:

dynamic user = new
{
    Name = "John Doe",
    Age = 42
};
Console.WriteLine(user.Name + " is " + user.Age + " years old");

这样就可以在不定义类的情况下直接创建对象。dynamic关键字可用于定义指向此类对象的变量,不过var关键字也可以,而且可能在多数情况下还更合适些。

既然叫做动态(dynamic)类型,就可能让人以为可以随意增加属性了,象这样:

dynamic user = new
{
    Name = "John Doe",
    Age = 42
};
user.HomeTown = "New York";

由于动态类型没有编译时的检查,上述代码还真可以通过编译进入运行,因为编译器不会真的去校验HomeTown属性是否存在,但是一旦运行到最后一行,就会有异常抛出。虽然动态(dynamic)类型非常的动态,还是不允许动态地增加属性。要想这样做,可以使用ExpandoObject类型,这会在下一章介绍。

改变类型

定义为动态类型的变量并非是无类型的。实际上,C#会在内部把其作为被赋值的类型来处理。在一开始的那个例子中展示了定义为动态的变量可以被赋字符串或整数值,然后使用属于这些类型的属性。不过,动态类型变量的类型可能轻易就会改变 - 简单地赋个新值就可以了。如下例所示:

dynamic user = new
{
    Name = "John Doe",
    Age = 42
};
Console.WriteLine(user.GetType() + ": " + user.Name + " is " + user.Age + " years old");
user = "Jane Doe";
Console.WriteLine(user.GetType() + ": String.Length = " + user.Length);

注意此例中对user变量的使用:它先指向一个匿名对象,然后被赋了一个简单的字符串值。代码中使用C#中所有类型都有的GetType() 方法对类型进行检查,然后又都访问了此变量当前所属类型有的属性(匿名对象的姓名/年龄属性,然后是字符串对象上的长度属性)。

总结

dynamic关键字允许使用类型不确定的变量 - 其行为与其所指向的数据的类型一样。可以轻易地给动态类型变量赋新值,如果所赋的新值类型与原来值的类型不同,动态类型的类型自动就发生了变化。

编译器不会检查动态类型变量,不管代码访问的属性存不存在。这让动态类型变量非常的灵活,但也使得程序本身变得非常容易出错。鉴于此,应该严格把对dynamic关键字的使用限制在非用其就不可能实现的功能范围内。适合使用dynamic关键字的例子有与COM组件的交互操作和与象JSON及XML这类数据进行交互的时候。


This article has been fully translated into the following languages: Is your preferred language not on the list? Click here to help us translate this article into your language!