C# 4.0又开始添加新的技术特点,这次它的老师是来自动态语言python与ruby。MS fans们以极大的热情和开放的心态,投入这场静态语言与动态语言的融合中去。
除了进一步完善了DLR这个为动态语言而设计的runtime(这一完美设计基本就宣判了 ruby.net的死刑,奠定了ironruby的胜局),C# 4.0也为此打开了门户,在C# 4.0中,添加dynamic这一关键字,这个关键字告诉编译器:“别担心我要做什么,运行时的时候就明了”。请看例子
- using System;
- using Microsoft.CSharp.RuntimeBinder;
- using System.Scripting.Actions;
- using System.Linq.Expressions;
- namespace ConsoleApplication1
- {
- publicclass Program
- {
- staticvoid Main(string[] args)
- {
- DoSomethingDynamic(7);
- DoSomethingDynamic(new Actor());
- DoSomethingDynamic(new DynamicThing());
- Console.ReadLine();
- }
- staticvoid DoSomethingDynamic(dynamic thing)
- {
- try
- {
- thing.Act();
- }
- catch (RuntimeBinderException)
- {
- Console.WriteLine("thing does not implement Act");
- }
- }
- }
- publicclass Actor
- {
- publicvoid Act()
- {
- Console.WriteLine("Actor.Act() was called");
- }
- }
- publicclass DynamicThing : IDynamicObject
- {
- public MetaObject GetMetaObject(System.Linq.Expressions.Expression parameter)
- {
- returnnew CustomMetaObject(parameter);
- }
- }
- publicclass CustomMetaObject : MetaObject
- {
- public CustomMetaObject(Expression parameter) : base(parameter, Restrictions.Empty){ }
- public override MetaObject Call(CallAction action, MetaObject[] args)
- {
- Console.WriteLine("A method named: '{0}' was called", action.Name);
- returnthis;
- }
- }
- }
using System; using Microsoft.CSharp.RuntimeBinder; using System.Scripting.Actions; using System.Linq.Expressions; namespace ConsoleApplication1 { public class Program { static void Main(string[] args) { DoSomethingDynamic(7); DoSomethingDynamic(new Actor()); DoSomethingDynamic(new DynamicThing()); Console.ReadLine(); } static void DoSomethingDynamic(dynamic thing) { try { thing.Act(); } catch (RuntimeBinderException) { Console.WriteLine("thing does not implement Act"); } } } public class Actor { public void Act() { Console.WriteLine("Actor.Act() was called"); } } public class DynamicThing : IDynamicObject { public MetaObject GetMetaObject(System.Linq.Expressions.Expression parameter) { return new CustomMetaObject(parameter); } } public class CustomMetaObject : MetaObject { public CustomMetaObject(Expression parameter) : base(parameter, Restrictions.Empty){ } public override MetaObject Call(CallAction action, MetaObject[] args) { Console.WriteLine("A method named: '{0}' was called", action.Name); return this; } } }
例子中的方法DoSomethingDynamic(dynamic thing),拥有一个带有dynamic关键字的变量thing。我们调用thing的方法Act(); 编译器无法检查thing是不是有Act方法直到运行的时候,为保险起见,我们用个try-catch块来捕捉异常。当然另一方面,鸭子类型(duck type)使得编程时无法使用智能提示,你可以在变量后面随手涂鸦,thing.Foo(), thing + 56, thing.X = "hello", var y = thing[12],这堆东西都能被编译。
接下来,我们在Main入口里反复调用了DoSomethingDynamic,传送了不同类型的参数:
首先是整数类型7。Int32没有Act方法,所以RuntimeBinderException被抛出。
其实是一个正常的类Actor带有一个Act方法,因此一切正常。
最后是继承了IDynamicObject的类DynamicThing ,IDynamicObject只有一个GetMetaObject方法需要被实现. GetMetaObject返回一个MetaObject,而你要做的实现一个如何处理方法调用的CustomMetaObject.我们的 CustomMetaObject重载了Call方法,并简单打印出方法的名字.
C# 现在主要还是静态类型语言,而Anders确定静态类型对于大型可伸缩系统是更好的范例。同时他也觉察到了动态特性的魅力,并为C#添加了诸如VB和其他动态语言的特性。