探寻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的滥用,将会造成巨大的麻烦。所以在使用这样一件强大武器的时候,也请记住,它是一把双刃剑:)
可以先看一段程序:
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的滥用,将会造成巨大的麻烦。所以在使用这样一件强大武器的时候,也请记住,它是一把双刃剑:)
相关文章推荐
- C# 4.0 新特性dynamic、可选参数、命名参数等
- C#4.0 新特性 动态类型Dynamic
- C# 4.0新特性dynamic有何用处?(转载)
- C# 动态语言特性,dynamic 关键字研究
- C# 4.0 Dynamic关键字全解析(转)
- C#4.0 新特性, dynamic, 可选参数,协变与抗变 (转)
- C# 4.0 Dynamic关键字全解析
- 精进不休 .NET 4.0 (4) - C# 4.0 新特性之命名参数和可选参数, 动态绑定(dynamic), 泛型协变和逆变, CountdownEvent, Barrier
- C# 4.0 新特性dynamic、可选参数、命名参数等
- C# 4.0 新特性dynamic、可选参数、命名参数等
- C#4.0中的dynamic关键字和ExpandoObject对象
- C# 4.0 新增 dynamic关键字介绍
- C# 4.0新特性dynamic作用浅析
- C#4.0中的dynamic关键字和ExpandoObject对象
- 深入C# 4.0 新特性dynamic、可选参数、命名参数的详细介绍
- (转)C#4.0的dynamic和var及object关键字辨析
- 精进不休 .NET 4.0 (4) - C# 4.0 新特性之命名参数和可选参数, 动态绑定(dynamic), 泛型协变和逆变, CountdownEvent, Barrier
- C# 4.0 新特性dynamic、可选参数、命名参数等
- C# 动态语言特性,dynamic 关键字研究
- C# 4.0新特性dynamic作用浅析