但是,如果代码无效,则在运行时会捕获到错误。
dynamic 类型简化了对 COM API(例如 Office Automation API)、动态 API(例如 IronPython 库)和 HTML 文档对象模型 (DOM) 的访问。
因此,dynamic 类型只在编译时存在,在运行时则不存在。
IntelliSense 对 dyn 显示“dynamic” ,对 obj 显示“object” 。
class Program { static void Main(string[] args) { dynamic dyn = 1; object obj = 1; System.Console.WriteLine(dyn.GetType()); System.Console.WriteLine(obj.GetType()); } }
输出结果:
若要查看编译时 dyn 与 obj 之间的区别,请在前面示例的声明和 WriteLine 语句之间添加下列两行:
dyn = dyn + 3; obj = obj + 3;
在编译时不会检查包含 dyn 的表达式,原因是 dyn 的类型为 dynamic。
dynamic 关键字可以直接出现,也可以作为构造类型的组件在下列情况中出现:
-
下面的类定义在多个不同的声明中使用
dynamic。
class ExampleClass { // 动态字段 static dynamic field; // 动态属性 dynamic prop { get; set; } // 动态返回类型和动态类型参数 public dynamic exampleMethod(dynamic d) { // 局部动态变量 dynamic local = "Local variable"; int two = 2; if (d is int) { return local; } else { return two; } } }
-
在显式类型转换中,作为转换的目标类型。
static void convertToDynamic() { dynamic d; int i = 20; d = (dynamic)i; Console.WriteLine(d); string s = "Example string."; d = (dynamic)s; Console.WriteLine(d); DateTime dt = DateTime.Today; d = (dynamic)dt; Console.WriteLine(d); } // 输出结果: // 20 // Example string. // 7/25/2018 12:00:00 AM
- 例如,可以在下列表达式中使用
dynamic。
int i = 8; dynamic d; // 使用 is 操作符 // 在此处动态类型和object相似,The dynamic type behaves like object。除非 somevar 的值为 null ,否则以下表达式将返回true if (someVar is dynamic) { } // 使用 as 操作符 d = i as dynamic; // 使用typeof, 作为构造类型的一部分 Console.WriteLine(typeof(List<dynamic>)); // 以下语句导致编译器错误 //Console.WriteLine(typeof(dynamic));
Main 方法也将编译时类型检查与运行时类型检查进行了对比。using System; namespace DynamicExamples { class Program { static void Main(string[] args) { ExampleClass ec = new ExampleClass(); Console.WriteLine(ec.exampleMethod(10)); Console.WriteLine(ec.exampleMethod("value")); // 下面的语句会引发编译器异常。因为 exampleMethod 方法仅包含一个参数 //Console.WriteLine(ec.exampleMethod(10, 4)); dynamic dynamic_ec = new ExampleClass(); Console.WriteLine(dynamic_ec.exampleMethod(10)); // 因为 dynamic_ec 是 dynamic 类型, 下面的调用(传递了2个参数)不会引发编译器异常。 // 但是在运行时会引发异常。 //Console.WriteLine(dynamic_ec.exampleMethod(10, 4)); } } class ExampleClass { static dynamic field; dynamic prop { get; set; } public dynamic exampleMethod(dynamic d) { dynamic local = "Local variable"; int two = 2; if (d is int) { return local; } else { return two; } } } } // 输出结果: // Local variable // 2 // Local variable
在运行时,将对存储的信息进行检查,并且任何无效的语句都将导致运行时异常。
例如,如果将鼠标指针放在以下示例中使用的 testSum 上,则 IntelliSense 将显示类型“(局部变量)dynamic testSum” 。
dynamic d = 1; var testSum = d + 3; System.Console.WriteLine(testSum);
结果不为 dynamic 的操作包括:
- 从
dynamic到另一种类型的转换。 - 包括类型为
dynamic的自变量的构造函数调用。
例如,以下声明中 testInstance 的类型为 ExampleClass,而不是 dynamic:
var testInstance = new ExampleClass(d);
这样,开发人员将能够在动态行为和非动态行为之间切换。
任何对象都可隐式转换为动态类型,如以下示例所示。
dynamic d1 = 7; dynamic d2 = "a string"; dynamic d3 = System.DateTime.Today; dynamic d4 = System.Diagnostics.Process.GetProcesses();
反之,隐式转换也可动态地应用于类型为 dynamic 的任何表达式。
int i = d1; string str = d2; DateTime dt = d3; System.Diagnostics.Process[] procs = d4;
d1 的运行时类型为 int,而 exampleMethod2 要求为字符串。ec.exampleMethod2("a string"); ec.exampleMethod2(d1);
命名参数和可选参数的用法。
例如,以下语句对比了在使用 dynamic 类型和不使用 dynamic 类型的情况下如何访问 Microsoft Office Excel 电子表格中的单元格。
// 引入动态之前 ((Excel.Range)excelApp.Cells[1, 1]).Value2 = "Name"; Excel.Range range2008 = (Excel.Range)excelApp.Cells[1, 1];
// 在引入 dynamic 之后,对 value 属性的访问以及到 excel.range 的转换将由运行时 COM 绑定器处理 excelApp.Cells[1, 1].Value = "Name"; Excel.Range range2010 = excelApp.Cells[1, 1];
其他技术请参考
| Title | 说明 |
|---|---|
| dynamic | 描述 dynamic 关键字的用法。 |
| 动态语言运行时概述 | 提供有关 DLR 的概述,DLR 是一种运行时环境,它将一组适用于动态语言的服务添加到公共语言运行时 (CLR)。 |
| 演练:创建和使用动态对象 | 提供有关如何创建自定义动态对象以及创建访问 IronPython 库的对象的分步说明。 |
| 如何:通过使用 Visual C# 功能访问 Office 互操作对象 | 演示如何创建一个项目,该项目使用命名参数和可选参数、dynamic 类型以及可简化对 Office API 对象的访问的其他增强功能。 |