C# 4.0 中新的数据类型dynamic 的用法

来源:互联网 发布:有网络微信发不出去 编辑:程序博客网 时间:2024/06/06 03:39
C# 4.0中dynamic的用法
C# 4.0引入了一个新类型:dynamic,它是一个静态类型,然而该类型的对象实例却能够绕过静态类型检查的过程。在大多数情况下,该类型像object类那样工作。在编译时间,一个dynamic类的实例支持任何操作,因此,不需要担心该对象是从某个COM API、或是像IronPython之类的动态语言、从HTML DOM中、或者是反射(reflection)、或程序的其他什么地方取得的。不过,如果代码执行的操作是无效的,错误会在运行时被捕获。
例如,下面代码段中的实例方法exampleMethod1仅有一个参数,编译器能够在编译时识别出调用ec.exampleMethod1(10,4)时无效的;这是个编译错误。第二个调用dynamic_ec.exampleMethod1(10,4)不受静态类型检查。因此编译器不会报编译错误。然而,该错误并不会永远隐藏起来;它会涨运行时被捕获并触发一个运行时异常。
static void Main(string[] args){
    ExampleClass ec = new ExampleClass();
    dynamic dynamic_ec = new ExampleClass();
    dynamic_ec.exampleMethod1(10, 4);
    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调用IronPython的例子:

using IronPython.Hosting;
using Microsoft.Scripting.Hosting;

Console.WriteLine("Loading random.py...");
ScriptRuntime py = Python.CreateRuntime();
dynamic random = py.UseFile("random.py");
Console.WriteLine("random.py loaded!");
var items = Enumerable.Range(1, 7).ToArray();

for (int s = 0; s < 10000; s++) {
    random.shuffle(items);
    Console.Write("Sequence {0}: ", s);
    foreach (int i in items) {
        Console.Write("{0} ", i);
    }
    Console.WriteLine();
}

对于类型为dynamic的对象或者表达式,编译器的角色就是将每个表达式预期执行的动作封装起来,在运行时刻,对储存的信息进行检查,任何无效语句均会触发运行时异常。
大多数dynamic操作的结果的类型也是dynamic的。例如,如果将鼠标指针停留在下例的testSum上,智能提示会显示 (local variable) dynamic testSum。
dynamic d = 1;
var testSum = d + 3;
// 将鼠标指针停留在下面的testSum上.
System.Console.WriteLine(testSum);

类型转换
Dynamic类型的实例和其他类型的实例间的转换是很简单的,开发人员能够很方便地在dyanmic和非dynamic行为间切换。任何实例都能隐式转换为dynamic类型实例,见下面的例子:
dynamic d1 = 7;
dynamic d2 = "a string";
dynamic d3 = System.DateTime.Today;
dynamic d4 = System.Diagnostics.Process.GetProcesses();

Conversely, an implicit conversion can be dynamically applied to any expression of type dynamic.
反之亦然,类型为dynamic的任何表达式也能够隐式转换为其他类型。
int i = d1;
string str = d2;
DateTime dt = d3;
System.Diagnostics.Process[] procs = d4;

方法中含有dynamic类型参数的重载问题
如果调用一个方法是传递了dynamic类型的对象,或者被调用的对象是dynamic类型的,那么重载的判断是发生在运行时而不是编译时。

动态语言运行时(dynamic language runtime DLR)
动态语言运行时是.NET Framework 4 Beta 1中的一组新的API,它提供了对c#中dynamic类型的支持,也实现了像IronPython和IronRuby之类的动态程序设计语言。

COM互操作性
C# 4.0包含了多个特性,改进了与传统COM API接口如Office自动化等的互操作性。Dynamic类型、命名参数以及可选参数也属于改进中的一部分。
许多的COM方法允许其参数和返回值类型为object,因此对于强类型语言如C#来说,就需要做大量的强制类型转换。然而在C# 4.0中,如果在编译时加上/link选项,则dynamic类型就会起新的效果:它使得COM接口方法签名中的object类型(参数类型或返回类型)被视为dynamic,因而能够避免大量的类型转换工作。例如,下面的语句对此进行了对比。
// 没有用 dynamic.
((Excel.Range)excel.Cells[1, 1]).Value2 = "Name";
Excel.Range range = (Excel.Range)excel.Cells[1, 1];

// 用了dynamic, 
excel.Cells[1, 1].Value = "Name";
Excel.Range range = excel.Cells[1, 1];