15 var i = 5;
16 var s = "Hello";
17 var d = 1.0;
18 var numbers = new int[] {1, 2, 3};
19 var orders = new Dictionary<int,Order>();
局部變量的聲明變得非常方便, 編譯器會根據(jù)上下文自動推導(dǎo)出變量的類型.這個功能在3.0中被廣泛使用.
下面的代碼更加方便:
15 var sum = 0;
16 var intArray = new [] { 1,2,3,4}; //used to be new int[](1,2,3,4)
17 foreach ( var i in intArray )
18 {
19 sum += i;
20 }
在匿名類型的支持下,你甚至可以這樣玩.
15 var contacts = new[]
16 {
17 new {
18 Name = "idior",
19 Website= new[] { "idior.cnblogs.com", "www.alphatom.com" }
20 },
21
22 new {
23 Name = "dudu",
24 PhoneNumbers = new[] { "www.aopdotnet.com" }
25 }
26 };
可見3.0下的代碼是多么的簡潔.
需要注意的是這里的var和javascript中可不一樣. 它是強類型的, 也就是說var sum=0;其中的sum的類型仍然是int.
只不過這個推導(dǎo)過程由編譯器做了, 如果你查看反編譯的源代碼你會發(fā)現(xiàn)var sum=0; 變成了int sum=0;
之所以要引入var, 更多的由于Linq中查詢結(jié)果的需要. 因為對于復(fù)雜的查詢語句, 你很難判斷出返回的結(jié)果類型,甚至有時返回的是匿名類型,這個時候var就會大大減輕程序員的負(fù)擔(dān).
Extension methods
在2.0的集合一文中, 我對新List<T>加入的Foreach方法大加贊揚了一番, 同時也指出其不足, 并提供了一個擴(kuò)展方法. 現(xiàn)在有了Extension Method的支持,要想對原有類擴(kuò)展擴(kuò)展功能簡直太方便了.
比如我想為所有的集合類加入Foreach的方法.
24 class Static Algorithm
25 {
26 public static void ForEach<T>(this IEnumerable<T> collection, Action<T> action)
27 {
28 foreach (T obj in collection)
29 {
30 action(obj);
31 }
32 }
33
34 public static void ForSpecification<T>(this IEnumerable<T> collection, Action<T> action, Predicate<T> filter)
35 {
36 foreach (T obj in collection)
37 {
38 if (filter(obj))
39 action(obj);
40 }
41 }
42 }
來看看如何使用:
15 var numbers = new [] {"hello", "world", "Linq"};
16
17 numbers.ForEach (delegate(string str) // equal to Algorithm.ForEach(numbers,...)
18 {
19 Console.WriteLine(str);
20 }
21 );
Extension methods名副其實, 確實為功能擴(kuò)展帶來了極大的方便.
如果你接觸過AOP的話,你會發(fā)現(xiàn)它和AOP中的靜態(tài)橫切(Mixin)的作用很象. Extension methods是否真的將擴(kuò)展的方法加入原來的類型當(dāng)中, 就像多繼承那樣? 答案是否定的, 這里僅僅是一個語法糖,編譯器會自動將numbers.ForEach(...) 變回到Algorithm.ForEach(numbers,...).
Lambda Expressions
如果說你現(xiàn)在還沒有習(xí)慣使用匿名方法, 沒關(guān)系,一年后你也會不自覺的使用到它, 而Lambda Expressions則是對匿名方法的進(jìn)一步增強, 兩年后你就會使用它來代替匿名方法.
如果你看了我在CollectionClosureMethod in .Net 一文中利用匿名方法對Martin Fowler的CollectionClosureMethod in Ruby的模擬, 但是覺得很丑陋的話, 那么請你看看下面的代碼:
15 managers = employees.select {|e| e.manager?} //ruby
16
17 List<Employee> managers = employees.FindAll(delegate(Employee e)
18 {
19 return e.IsManager == true;
20 }); //C# 2.0
21
22 var managers = employees.Select(e => e.IsManager==true); //C# 3.0
21 offices = employees.collect {|e| e.office} //ruby
22
23 List<Office> offices = employees.ConvertAll<Office>(delegate(Employee e)
24 {
25 return e.Office;
26 }); //C# 2.0
27
28 var offices = employees.Select(e => e.Office); //C# 3.0
有關(guān)Lambda表達(dá)式的更多內(nèi)容請見這里.
Object and Collection initializers
對象的初始化的代碼將變得異常簡潔.
15 var idior = new Person{Name = "ning", Surname = "xu"};
16
17 var persons = new List<Person>
18 {
19 new Person{Name = "ning", Surname = "xu"},
20 new Person{Name = "Foo", Surname = "Bar"}
21 }
Anonymous types
15 var idior = new
16 {
17 Name = "idior", WebSite = http://idior.cnblogs.com/};
18 Console.WriteLine(idior.WebSite);
19 }
Query Expressions
將關(guān)系型查詢語句引入面向?qū)ο蟮氖澜? 大大增強了語法安全性, 很久以前我也對此有過介紹.
15 from c in customers
16 where c.City == "London"
17 select c
相應(yīng)的Lambda表達(dá)式描述
15 customers.Where(c => c.City == "London")
該語法的表達(dá)能力非常強, 對where , select , group , orderby , into 的語法都有支持.
結(jié)合前面的Anonymous types. 還可以方便的獲得多個查詢結(jié)果,并包裝成類
15 var payingCustomers = from c in db.Customers
16 where c.Orders.Count > 0
17 select new { Email = c.Email, Name = c.Name };
18 foreach (var c in payingCustomers)
19 {
20 SendDiscountOffer(c.Email, c.Name);
21 }
這個功能將徹底改變持久層的操作.
以上僅僅是對Linq 的初步認(rèn)識, 變化之大遠(yuǎn)遠(yuǎn)超出2.0較之于1.0. 看了之后實在心癢癢的, Linq在動態(tài)語言和Function Programming方面的能力大大增強. 再對比一下java那邊, 似乎還沒聽到6.0的什么消息, 不知道他們將如何應(yīng)對.net的下一波沖擊!
以上的介紹將各個新增功能分開逐一介紹, 表面看了好像僅僅是增強了一些新的語法, 增加了C#語言的靈活性, 甚至?xí)腥苏J(rèn)為此舉得不償失, 但是最重要的概念不是在于這些小的語言點,而是通過它們的合作而產(chǎn)生的LINQ. 將類似關(guān)系型(實際還是面向?qū)ο蟮?的語言引入到C#中,大大增強了C#對于數(shù)據(jù)的操作能力(內(nèi)存數(shù)據(jù)---集合, 外部數(shù)據(jù)--DataBase,XML ).
Linq何時才能用? 雖然在語法層面Linq加入了很多新的內(nèi)容, 但是在做完上面的范例之后, 你會發(fā)現(xiàn)Linq中并沒有在CLR底層加入什么新的元素. 所有新的功能仍然是建立在泛型的基礎(chǔ)上,然后由編譯器完成大部分的代碼轉(zhuǎn)化和生成. 以上的程序集在reflector中都是可以被反編譯的,并沒有什么新的底層元素不可被識別. 因此,個人估計只要MS不斷推出Linq新的測試版本, 我想Linq并不需要等到Orcas才能發(fā)布.或許在.Net 2.1時就可以正式發(fā)布了. Orcas應(yīng)該不止是Linq這么簡單, 它應(yīng)該會在底層加入新的元素, 這樣才叫主版本的變化嘛,就像2.0加入了泛型.
推而廣之, 如果你想為.Net增強新的功能,比如加入AOP的功能, 那么你也可以考慮實現(xiàn)自己的一套增強型編譯器. 不過C++好像就是這樣被毀掉的.
真怕以后出現(xiàn)n多版本的C#.
Orcas的相關(guān)資源
浙公網(wǎng)安備 33010602011771號