“C# 4 引入了一个新类型 dynamic。该类型是一种静态类型,但类型为 dynamic 的对象会跳过静态类型检查。"
——Microsoft Docs[1]
静态的"动态"
dynamic
是C# 4中加入的一个新的“上下文关键字”,它指示动态类型。我们可以直接创建一个dynamic类型的变量,可以将任意对象赋值给它。如下所示:
dynamic dynVar1 = 1;
dynamic dynVar2 = new Object();
当我们在代码中使用了dynamic
类型时,就是在告诉编译器关闭对该对象的运行时检查,而在运行时确定对象类型。比如,以下代码可以成功编译:
dynamic numericDyn = 80;
numericDyn.Greet();
但是在这段代码会抛出一个运行时异常RuntimeBinderException
,提示我们类型int
不包含方法Greet()
的定义。这说明了在底层,dynamic
变量类型在运行时仍然是确定的,也就是说,C#依然是静态类型化语言。当我们在一个dynamic
变量上调用GetType()
时,会输出该对象的实际类型。如下所示:
Console.WriteLine(numericDyn.GetType());
// Console prints System.Int32
要注意的是,在使用dynamic
类型的变量时,编译器无法对该变量所指向的对象作任何类型推断,也无法枚举方法与属性。因此,IntelliSense和重构工具在此时失效。
下面这个例子可以清晰地说明这一点。我们首先创建一个类,再用一个dynamic
类型变量装载一个Cat
对象的引用,再试图重构Cat
中的一个方法。
完整代码:
using System;
namespace DynamicKeywordTest
{
class Program
{
static void Main(string[] args)
{
dynamic dynCat = new Cat();
dynCat.Meow();
}
class Cat
{
public void Meow()
{
Console.WriteLine(String.Format("Cat {0} meows.", this.GetHashCode()));
}
}
}
}
使用Visual Studio
的重构工具,将方法Meow()
重命名为Honk()
,我们发现dynCat.Meow()并没有更改。
var
, object
和dynamic
关键字var
用于编译时类型推断。编译器在编译时自动确定var
代表的类型。如下列代码:
var varInt = 1;
var varStr = "Hello, Vars!";
关闭优化编译,使用.NET Reflector
反编译得到
int num = 1;
string str = "Hello, Vars!";
该关键字可以在编译时得到类型信息,于是可以进行IntelliSense和重构。
类型object
是所有对象的基类,有着与dynamic
相似的用法,但是必须进行强制转换才可以用子类的方法、属性等。如:
object objCat = new Cat();
objCat.Meow(); // CS1061 'object' does not contain a definition of 'Meow'
((Cat)objCat).Meow(); // OK
dynamic dynCat = new Cat();
dynCat.Meow(); // OK, but no IntelliSense
这些关键字可以混用,如:
dynamic dynObj = new Object();
var anotherObj = dynObj;
最终,dynObj
类型为dynamic
,anotherObj
类型为dynamic
。
结语
本文只是对于dynamic
关键字的第一次探索,更多信息可以在Microsoft Docs和其他博文,如这篇中找到。由于这是笔者的第一篇文章,不足之处请各位读者多多指正,敬请期待下一篇文章。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。