您的位置:首页 > 编程语言 > C#

探寻C# 4.0新特性之dynamic关键字

2009-10-11 23:02 531 查看
Visual Studio2010 beta2就要发布了,这两天抽空看了下C#新增的功能。其中一个很重要的就是对动态语言的支持,在.Net framework 4.0里C#可以和一些建立在CLR基础上的动态语言譬如Iron Python有很方便的互操作。在语言层面,C#引进了新的关键字:dynamic.

可以先看一段程序:

class Program
{
static void Main(string[] args)
{
dynamic myObject = GetSomeList();
myObject.NonExistsMethod();
}

private static dynamic GetSomeList()
{
return new List<int>();
}
}

我们可以看到方法GetSomeList()定义的返回类型是dynamic, 上面例子里实际返回的类型是List<int>。而事实上这里可以返回任何类型,int, string, StringBuilder都可以,因为我们定义了它的返回类型是“动态”的。

再看myObject, 我们调用了它的方法"NonExistsMethod”,正如其名,这个方法在任何地方都是不存在的。但是上述程序可以在Visual Studio2010里编译通过,没有任何错误!如果我们把NonExistsMethod替换成实际存在的方法,譬如Sort(), 运行也是没有问题的。也就是说,如果某个变量是dynamic类型的,那么编译器允许你调用任何存在或者不存在的方法。这些方法会一直到运行时才在被绑定,如果不存在,当然就会有异常抛出。

看到这里相信大家觉得dynamic和某个东西很像,没错,就是和object很像!一个dynamic类型的引用和object一样,可以指向任何类型,GetSomeList()方法就是这样的用法。但是又似乎有点不同,譬如我们可以调用任何方法,极大地增强了动态性。编译上述例子并在reflector里查看过后,我们可以发现C#其实在编译上确实把它作为了object, GetSomeList() 会被编译成:

[return: Dynamic]
private static object GetSomeList()
{
return new List<int>();
}

而对dynamic对象的调用会被编译成:

CallSite<Action<CallSite, object>> site;
site = CallSite<Action<CallSite, object>>.Create(
Binder.InvokeMember(CSharpBinderFlags.ResultDiscarded,
"NonExistsMethod",
null,
typeof(Program),
new CSharpArgumentInfo[] { CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null) }
));
site.Target.Invoke(site, myObject);

我们可以看到在神秘的dynamic背后,NonExistsMethod被处理成了动态绑定用的字符串。而一个新的类型System.Runtime.CompilerServices.CallSite<T>被引入在.Net 4.0里用来支持这样的动态绑定。

那么dynamic的引入有什么意义呢?MSDN给出了这样的答案:

1)可以和动态语言互操作,可以同时享受动态语言的灵活和.Net的强大

2)可以支持自顶而下的开发方式,从顶层的架构开始搭起会很容易,调用不存在的方法(甚至这个类都根本不存在)编译也没有问题。

引人深思的是dynamic的引入可以使C#可以和动态语言一样,失去编译器的保护。尤其在对代码重构的时候,如果代码中存在对dynamic的滥用,将会造成巨大的麻烦。所以在使用这样一件强大武器的时候,也请记住,它是一把双刃剑:)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: