探索C# dynamic关键字 (1) - 简介

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, objectdynamic

关键字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类型为dynamicanotherObj类型为dynamic

结语

本文只是对于dynamic关键字的第一次探索,更多信息可以在Microsoft Docs和其他博文,如这篇中找到。由于这是笔者的第一篇文章,不足之处请各位读者多多指正,敬请期待下一篇文章。

参考资料

  1. Using type dynamic (C# Programming Guide) (Microsoft Docs)
  2. 了解 C# 4 中的 Dynamic 关键字 (博客园)

你可能感兴趣的:(c#)