动态查找

来源:互联网 发布:昆山杜克大学 知乎 编辑:程序博客网 时间:2024/05/17 04:45

前面介绍过var,var关键字不是一个类型,所以并没有违反C#的“强类型化”方法论。但在C# 4 引入了“动态变量”的概念,顾名思义,动态变量是类型不固定的变量。引入动态变量的主要目的是在许多情况下,都希望使用C#处理另一种语言创建的对象。这包括与旧技术的交互燥作,例如Component Object Model(COM),以及处理动态语言,例如JavaScript、Python 和Ruby。

例如,假定代码从JavaScript 中获得了一个带Add()方法的对象,该方法把两个数字加在一起。如果没有动态查找功能,调用这个方法的代码就如下所示:

ScriptObject jsObj = SomeMethodThatGetsTheObject();

int sum = Convert.ToInt32(jsObj.Invoke("Add", 2, 3));

ScriptObject 类型提供了一种访问JavaScript 对象的方式,但不能执行如下操作:

int sum = jsObj.Add(2, 3);

动态查找功能改变了这一切,它允许编写上述代码。

另一个可一使用动态查找功能的情形是处理未知类型的C#对象。这听起来似乎很古怪,但这种情形出现的次数比我们想象得多。如果需要编写一些泛型代码,来处理它接收的输入,这也是一个重要的功能。处理这种情形的“旧”方法称为“反射(reflection)”,它涉及使用类型信息来访问类型和成员。实际上,反射的语法非常类似于上述代码中访问JavaScript 对象的语法,也非常麻烦。

在后台,动态查找功能由Dynamic Language Runtime(动态语言运行库,DLR)支持。与CLR 一样,DLR 是.NET 4 的一部分。

使用dynamic 关键字,以用于定义变量。例如:

dynamic myDynamicVar;

注:

1)与前面介绍的var 关键字不同,的确存在dynamic 类型,所以在声明myDynamicVar 时,无需初始化它的值。

2)dynamic 类型不同寻常之处是,它仅在编译期间存在,在运行期间它会被System.Object 类型替代。这是较细微的实现细节,但必须记住这一点。

无论myDynamicVar 实际包含什么值,这行代码都会编译。但是,如果所请求的成员不存在,

在执行这行代码时会生成一个RuntimeBinderException 类型的异常。

我们还是来看一个栗子:

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

//为包含RuntimeBindingException 异常的名称空间添加一个using 语句

using Microsoft.CSharp.RuntimeBinder;

namespace Ch14Ex03

{

//接着定义两个类MyClass1 和MyClass2,其中MyClass1 包含Add()方法,而MyClass2 不含成员

class MyClass1

{

public int Add(int var1, int var2)

{

return var1 + var2;

}

}

class MyClass2

{

}

class Program

{

static int callCount = 0;

//注意dynamic 关键字可以用作方法的返回类型

static dynamic GetValue()

{

if (callCount++ == 0)

{

return new MyClass1();

}

return new MyClass2();

}

static void Main(string[] args)

{

try

{

dynamic firstResult = GetValue();

dynamic secondResult = GetValue();

Console.WriteLine("firstResult is: {0}",

firstResult.ToString());

Console.WriteLine("secondResult is: {0}",

secondResult.ToString());

Console.WriteLine("firstResult call: {0}", firstResult.Add(2, 3));

Console.WriteLine("secondResult call: {0}",

secondResult.Add(2, 3));

}

//这些代码放在try ... catch 块中,以捕获可能发生的RuntimeBinderException 类型的异常。

catch (RuntimeBinderException ex)

{

Console.WriteLine(ex.Message);

}

Console.ReadKey();

}

}

}

我想这个栗子很好理解,dynamic 关键字也可以用于其他需要类型名的地万,例如方法参数。Add()方法可以重写为:

public int Add(dynamic var1, dynamic var2)

{

return var1 + var2;

}

传送给var1 和var2 的值在运行期间检查,可以确定加号+是否存在一个兼容的运算符定义。如果传送了两个int 值,就存在这样的运算符。如果使用了不兼容的值,就抛出RuntimeBinderException 异常。

对于大多数自己编写的C#代码,应避免使用dynamic 关键字。但是,如果需要使用它,就应使用它,并会喜欢上它——而不像过去那些可怜的程序员那样没有这个强大的工具可用。

原创粉丝点击