翻译:Visual C# 4.0的新特性-第三部分-Dynamic ExpendoObject
This is the third post of what’s new in Visual Studio C# 4.0.
这是《Visual Studio C# 4.0 的新特性》系列第三篇文章。
At the former posts we covered optional parameters, Named Parameters at this post we will cover C# Dynamics and ExpandoObject
在了解过可选参数(optional parameters)和命名参数(Named Parameters)之后,我们这次来熟悉下C#的动态特性(Dynamics)和ExpandoObject类。
dynamic & ExpendoObject
dynamic类型和ExpendoObject类
C# 1.0 introduced us to the managed world (based on Microsoft perception)
C# 1.0带领我们走进托管的世界(基于微软的观点)
C# 2.0 brought us Genetic types.
C# 2.0带来泛型类型。
C# 3.0 introduced us to new concept – LINQ
C# 3.0介绍了新的概念-LINQ(语言集成查询)
C# 4.0 highlight is all about Dynamic Types
C# 4.0的主打特性是动态类型。
Say for example that you have the need to create an object on the spot and use it in a local scope, without dynamic type you had to define a class and then create the object. you could do it at runtime using reflection emit, code dom etc…now its much simpler !
举例来说,你要在局部范围立即创建一个对象,没有dynamic类型,你不得不先定义一个类然后再创建这个对象。虽然你可以在运行时通过反射、Emit、CodeDom等技术类库做这些事,但是现在更简单。
All you have to do it to create an object of the type dynamic and using a special builder called ExpandoObject you can now define your object on the fly and use it.
所有你要做的就是创建一个dynamic类型的对象,用一个特殊的构建器叫ExpandoObject。现在你能立即定义这个对象并且使用它。
(译者注:using System.Dynamic)
2 {
3 static void Main(string[] args)
4 {
5 dynamic person = new ExpandoObject();
6 person.Firstname="ohad";
7 person.Lastname = "israeli";
8
9 Console.WriteLine(person.Firstname);
10 Console.WriteLine(person.Lastname);
11
12 Console.ReadLine();
13 }
14 }
15
You may say… wow this is cool.. well wait and see some more cool stuff..
你可能会说…哇哦,帅呆了…。等一下,下面还有更帅的。
Now lets add to this example and say that you would like to add a functionality to this object, what about adding person.Fullname in order to join the first and last name of the person and return it back.
现在,我们来看这个例子,比如你想要给这个对象加个功能,就是person.Fullname。作用是把姓和名连接成字符串,然后返回它。
2 {
3 static void Main(string[] args)
4 {
5 dynamic person = new ExpandoObject();
6 person.Firstname="ohad";
7 person.Lastname = "israeli";
8 person.Fullname = new Func<string>(delegate() { return person.Firstname + " " + person.Lastname; });
9 //译者注:如下文所述,正确的写法应该是:person.Fullname = new Func<string>(() => person.Firstname + " " + person.Lastname);
10 Console.WriteLine(person.Firstname);
11 Console.WriteLine(person.Lastname);
12 Console.WriteLine(person.Fullname());
13
14 Console.ReadLine();
15 }
16 }
17
As you can see we can point the new object properties to lambda expressions such as Func<string> and define on the spot a function that will return the full name of the person.
正如你看到的,我们能指定一个对象属性到lambda表达式(译者注:其实这是个泛型委托Func<TResult>)如Func<string>,然后当场定义一个函数(译者注:匿名函数)返回这个人的完整姓名。
Note that on line 12 you need to call the function and not use it as property – person.Fullname()
注意第12行你需要调用一个函数而不是把它用作属性——person.Fullname()。
What will happen if you forget the () by the end of the function name ? (note the change on line 12)
在函数名称的结尾,如果你忘了写()会发生什么情况呢?(注意下面代码的第12行)。
2 {
3 static void Main(string[] args)
4 {
5 dynamic person = new ExpandoObject();
6 person.Firstname="ohad";
7 person.Lastname = "israeli";
8 person.Fullname = new Func<string>(delegate() { return person.Firstname + " " + person.Lastname; });
9
10 Console.WriteLine(person.Firstname);
11 Console.WriteLine(person.Lastname);
12 Console.WriteLine(person.Fullname);
13
14 Console.ReadLine();
15 }
16 }
17
The result will be the lambda expression itself instead of the result of the lamba expression:
结果就是lambda表达式本身将代替lambda表达式的结果:
israeli
System.Func`1[System.String]
You can also add methods and not just functions using the Action expression: (note line 9)
你也可以用Action表达式增加methods而不只是functions:(注意第9行)(译者注:这句咋翻译?求解!)
2 {
3 static void Main(string[] args)
4 {
5 dynamic person = new ExpandoObject();
6 person.Firstname="ohad";
7 person.Lastname = "israeli";
8 person.Fullname = new Func<string>(delegate() { return person.Firstname + " " + person.Lastname; });
9 person.CallOhad = new Action(() => { Console.WriteLine("Hi Ohad are you there ?"); });
10
11 Console.WriteLine(person.Firstname);
12 Console.WriteLine(person.Lastname);
13 Console.WriteLine(person.Fullname());
14
15 person.CallOhad();
16
17 Console.ReadLine();
18 }
19 }
20
In conclusion dynamic types are cool but and there is a big but !
最后,dynamic类型是很帅,但是有个很重要的问题!
They are hard to debug and some of their functionality is only being tested at runtime this is why it is very important that whenever you use dynamic types test, test, and do some more testing using unit test of your code.
他们很难去调试,并且有些功能只能在运行时才能被测试。这就是为什么当你用dynamic类型时,单元测试在你的代码中变得很重要,很重要。
If you follow the following code you will notice that each of the calls to the properties in lines 11,12,13 begins with a small letter instead of uppercase. This code will compile without any errors but of course the code will fail at runtime as the properties / function names are all uppercase.
如果你按照下面的代码书写你会发现,第11、12、13行调用的每个属性的首字母都被小写代替了。代码在编译时不会发生任何错误,但是所有首字母是大写的属性/方法一定会运行失败。
2 {
3 static void Main(string[] args)
4 {
5 dynamic person = new ExpandoObject();
6 person.Firstname="ohad";
7 person.Lastname = "israeli";
8 person.Fullname = new Func<string>(delegate() { return person.Firstname + " " + person.Lastname; });
9 person.CallOhad = new Action(() => { Console.WriteLine("Hi Ohad are you there ?"); });
10
11 Console.WriteLine(person.firstname);
12 Console.WriteLine(person.lastname);
13 Console.WriteLine(person.fullname());
14
15 person.CallOhad();
16
17 Console.ReadLine();
18 }
19 }
20
译者添加:如person.firstname会发生RuntimeBinderExceptionwasunhandled异常:
'System.Dynamic.ExpandoObject' does not contain a definition for 'firstname'。