使用类型 dynamic(C# 编程指南)Using type dynamic (C# Programming Guide)

C# 4 引入了一个新类型 dynamicC# 4 introduces a new type, dynamic. 该类型是一种静态类型,但类型为 dynamic 的对象会跳过静态类型检查。The type is a static type, but an object of type dynamic bypasses static type checking. 大多数情况下,该对象就像具有类型 object 一样。In most cases, it functions like it has type object. 在编译时,将假定类型化为 dynamic 的元素支持任何操作。At compile time, an element that is typed as dynamic is assumed to support any operation. 因此,不必考虑对象是从 COM API、从动态语言(例如 IronPython)、从 HTML 文档对象模型 (DOM)、从反射还是从程序中的其他位置获取自己的值。Therefore, you do not have to be concerned about whether the object gets its value from a COM API, from a dynamic language such as IronPython, from the HTML Document Object Model (DOM), from reflection, or from somewhere else in the program. 但是,如果代码无效,则在运行时会捕获到错误。However, if the code is not valid, errors are caught at run time.

例如,如果以下代码中的实例方法 exampleMethod1 只有一个形参,则编译器会将对该方法的第一个调用 ec.exampleMethod1(10, 4) 识别为无效,因为它包含两个实参。For example, if instance method exampleMethod1 in the following code has only one parameter, the compiler recognizes that the first call to the method, ec.exampleMethod1(10, 4), is not valid because it contains two arguments. 该调用将导致编译器错误。The call causes a compiler error. 编译器不会检查对该方法的第二个调用 dynamic_ec.exampleMethod1(10, 4),因为 dynamic_ec 的类型为 dynamicThe second call to the method, dynamic_ec.exampleMethod1(10, 4), is not checked by the compiler because the type of dynamic_ec is dynamic. 因此,不会报告编译器错误。Therefore, no compiler error is reported. 但是,该错误不会被无限期疏忽。However, the error does not escape notice indefinitely. 它将在运行时被捕获,并导致运行时异常。It is caught at run time and causes a run-time exception.

static void Main(string[] args)
{
    ExampleClass ec = new ExampleClass();
    // The following call to exampleMethod1 causes a compiler error 
    // if exampleMethod1 has only one parameter. Uncomment the line
    // to see the error.
    //ec.exampleMethod1(10, 4);

    dynamic dynamic_ec = new ExampleClass();
    // The following line is not identified as an error by the
    // compiler, but it causes a run-time exception.
    dynamic_ec.exampleMethod1(10, 4);

    // The following calls also do not cause compiler errors, whether 
    // appropriate methods exist or not.
    dynamic_ec.someMethod("some argument", 7, null);
    dynamic_ec.nonexistentMethod();
}
class ExampleClass
{
    public ExampleClass() { }
    public ExampleClass(int v) { }

    public void exampleMethod1(int i) { }

    public void exampleMethod2(string str) { }
}

在这些示例中,编译器的作用是将有关每个语句的预期作用的信息一起打包到类型化为 dynamic 的对象或表达式。The role of the compiler in these examples is to package together information about what each statement is proposing to do to the object or expression that is typed as dynamic. 在运行时,将对存储的信息进行检查,并且任何无效的语句都将导致运行时异常。At run time, the stored information is examined, and any statement that is not valid causes a run-time exception.

大多数动态操作的结果是其本身 dynamicThe result of most dynamic operations is itself dynamic. 例如,如果将鼠标指针放在以下示例中使用的 testSum 上,则 IntelliSense 将显示类型“(局部变量)dynamic testSum” 。For example, if you rest the mouse pointer over the use of testSum in the following example, IntelliSense displays the type (local variable) dynamic testSum.

dynamic d = 1;
var testSum = d + 3;
// Rest the mouse pointer over testSum in the following statement.
System.Console.WriteLine(testSum);

结果不为 dynamic 的操作包括:Operations in which the result is not dynamic include:

  • dynamic 到另一种类型的转换。Conversions from dynamic to another type.
  • 包括类型为 dynamic 的自变量的构造函数调用。Constructor calls that include arguments of type dynamic.

例如,以下声明中 testInstance 的类型为 ExampleClass,而不是 dynamicFor example, the type of testInstance in the following declaration is ExampleClass, not dynamic:

var testInstance = new ExampleClass(d);

下一节“转换”中介绍了转换示例。Conversion examples are shown in the following section, "Conversions."

转换Conversions

动态对象和其他类型之间的转换非常简单。Conversions between dynamic objects and other types are easy. 这样,开发人员将能够在动态行为和非动态行为之间切换。This enables the developer to switch between dynamic and non-dynamic behavior.

任何对象都可隐式转换为动态类型,如以下示例所示。Any object can be converted to dynamic type implicitly, as shown in the following examples.

dynamic d1 = 7;
dynamic d2 = "a string";
dynamic d3 = System.DateTime.Today;
dynamic d4 = System.Diagnostics.Process.GetProcesses();

反之,隐式转换也可动态地应用于类型为 dynamic 的任何表达式。Conversely, an implicit conversion can be dynamically applied to any expression of type dynamic.

int i = d1;
string str = d2;
DateTime dt = d3;
System.Diagnostics.Process[] procs = d4;

使用类型为 dynamic 的参数重载决策Overload resolution with arguments of type dynamic

如果方法调用中的一个或多个参数的类型为 dynamic,或者方法调用的接收方的类型为 dynamic,则会在运行时(而不是在编译时)进行重载决策。Overload resolution occurs at run time instead of at compile time if one or more of the arguments in a method call have the type dynamic, or if the receiver of the method call is of type dynamic. 在以下示例中,如果唯一可访问的 exampleMethod2 方法定义为接受字符串参数,则将 d1 作为参数发送不会导致编译器错误,但却会导致运行时异常。In the following example, if the only accessible exampleMethod2 method is defined to take a string argument, sending d1 as the argument does not cause a compiler error, but it does cause a run-time exception. 重载决策之所以会在运行时失败,是因为 d1 的运行时类型为 int,而 exampleMethod2 要求为字符串。Overload resolution fails at run time because the run-time type of d1 is int, and exampleMethod2 requires a string.

// Valid.
ec.exampleMethod2("a string");

// The following statement does not cause a compiler error, even though ec is not
// dynamic. A run-time exception is raised because the run-time type of d1 is int.
ec.exampleMethod2(d1);
// The following statement does cause a compiler error.
//ec.exampleMethod2(7);

动态语言运行时Dynamic language runtime

动态语言运行时 (DLR) 是 .NET Framework 4 中的一个新 API。The dynamic language runtime (DLR) is a new API in .NET Framework 4. 它提供了支持 C# 中 dynamic 类型的基础结构,还提供了 IronPython 和 IronRuby 等动态编程语言的实现。It provides the infrastructure that supports the dynamic type in C#, and also the implementation of dynamic programming languages such as IronPython and IronRuby. 有关 DLR 的详细信息,请参阅动态语言运行时概述For more information about the DLR, see Dynamic Language Runtime Overview.

COM 互操作COM interop

C# 4 包括若干功能,这些功能改善了与 COM API(例如 Office 自动化 API)的互操作体验。C# 4 includes several features that improve the experience of interoperating with COM APIs such as the Office Automation APIs. 这些改进之处包括 dynamic 类型以及命名参数和可选参数的用法。Among the improvements are the use of the dynamic type, and of named and optional arguments.

通过将类型指定为 object,许多 COM 方法都允许参数类型和返回类型发生变化。Many COM methods allow for variation in argument types and return type by designating the types as object. 这样,就必须显式强制转换值,以便与 C# 中的强类型变量保持协调。This has necessitated explicit casting of the values to coordinate with strongly typed variables in C#. 如果使用 -link(C# 编译器选项)选项进行编译,则可以通过引入 dynamic 类型将 COM 签名中出现的 object 看作是 dynamic 类型,从而避免大量的强制转换。If you compile by using the -link (C# Compiler Options) option, the introduction of the dynamic type enables you to treat the occurrences of object in COM signatures as if they were of type dynamic, and thereby to avoid much of the casting. 例如,以下语句对比了在使用 dynamic 类型和不使用 dynamic 类型的情况下如何访问 Microsoft Office Excel 电子表格中的单元格。For example, the following statements contrast how you access a cell in a Microsoft Office Excel spreadsheet with the dynamic type and without the dynamic type.

// Before the introduction of dynamic.
((Excel.Range)excelApp.Cells[1, 1]).Value2 = "Name";
Excel.Range range2008 = (Excel.Range)excelApp.Cells[1, 1];
// After the introduction of dynamic, the access to the Value property and
// the conversion to Excel.Range are handled by the run-time COM binder.
excelApp.Cells[1, 1].Value = "Name";
Excel.Range range2010 = excelApp.Cells[1, 1];
标题Title 说明Description
dynamicdynamic 描述 dynamic 关键字的用法。Describes the usage of the dynamic keyword.
动态语言运行时概述Dynamic Language Runtime Overview 提供有关 DLR 的概述,DLR 是一种运行时环境,它将一组适用于动态语言的服务添加到公共语言运行时 (CLR)。Provides an overview of the DLR, which is a runtime environment that adds a set of services for dynamic languages to the common language runtime (CLR).
演练:创建和使用动态对象Walkthrough: Creating and Using Dynamic Objects 提供有关如何创建自定义动态对象以及创建访问 IronPython 库的对象的分步说明。Provides step-by-step instructions for creating a custom dynamic object and for creating a project that accesses an IronPython library.
如何使用 C# 功能访问 Office 互操作对象How to access Office interop objects by using C# features 演示如何创建一个项目,该项目使用命名参数和可选参数、dynamic 类型以及可简化对 Office API 对象的访问的其他增强功能。Demonstrates how to create a project that uses named and optional arguments, the dynamic type, and other enhancements that simplify access to Office API objects.