程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> 關於.NET >> 如何正確看待Linq的DistinctBy擴展和ForEach擴展

如何正確看待Linq的DistinctBy擴展和ForEach擴展

編輯:關於.NET

在微軟標准的Linq中,並沒有DistinctBy擴展和ForEach擴展,但在平時使用工作中卻又經常需要使用到這 兩個功能,照理來說,微軟在Linq中應該包含這兩個擴展才對,可事實上為什麼並沒有呢?本文我就來說說自 己對這兩個擴展的理解!

關於DistinctBy擴展

顧名思義,DistinctBy擴展就是根據一個鍵值進 行唯一性的篩選,將有重復鍵值的元素剔除,僅保留一個!當然Linq中有Distinct擴展,但其功能簡直是弱爆 了!用過的同志相信都對Distinct擴展吐槽無數遍了吧!如果你要使用Distinct擴展實現DistinctBy擴展的功 能,還要專門定義一個輔助類!Oh,My God!這簡直是對程序員的謀殺!但是等經歷過無數個糾結之後,我突 然發現,微軟在標准的Linq中實際上是包含了DistinctBy擴展的功能的,只不過不那麼直接,看下面的示例代 碼:

class Person
         {
             public int Age { get; set; }
             public string Name { get; set; }
             public override string ToString()
             {
                 return string.Format("Age:{0}  Name:{1}", Age, Name);
             }
         }
         [STAThread]
         static void Main()
         {
             var persons = new[] { 
                 new Person{Age = 10,Name="a"},
                 new Person{Age = 10,Name="b"},
                 new Person{Age = 10,Name="c"},
                 new Person{Age = 20,Name="d"}
             };
             foreach (var p in persons.GroupBy(o=>o.Age).Select(g=>g.First()))
             {
                 Console.WriteLine(p);
             }
         }

運行結果

從結果看,代碼成功完成了根 據鍵值Age進行Distinct的操作。

明眼人可能一眼就看出來了,不錯,就是使用GroupBy、Select和 First這三個子操作組合出DistinctBy的功能!只不過實現一個DistinctBy功能需要寫這麼做代碼實在是不好 ,於是可以封裝一下,把GroupBy、Select和First這三個子操作的組合封裝成一個DistinctBy擴展方法,就可 以方便的使用了。封裝的代碼 too simple,就不貼上來了!

關於ForEach擴展

為什麼微軟不在 Linq中添加ForEach擴展,這個問題的討論在網上已經很多了,總結一下主要是有下面幾點原因:

1.Linq中已經有Select擴展了,因此不必在實現一個ForEach,因為在大多數情況下可以用Select來實 現ForEach的功能(當然我不建議這樣做,因為Select是延遲操作,如果僅僅實現ForEach功能,有些時候代碼 不能夠按照設計意圖正確運行);

2.ForEach破壞了Linq的編程模式,就是說破壞了鏈式編程模式,所 謂鏈式編程,大概的意思就是將多個操作通過點號"."鏈接在一起,相信寫過Linq的同志很清楚這 句話的含義吧!

我看到網上有人這麼來設計ForEach擴展:

public static void 

ForEach<T>(this IEnumerable<T> source, Action<T> foreachAction)
         {
             foreach (var t in source)
             {
                 foreachAction(t);
             }
         }

我不得不說這是簡直是對Linq的“亵渎”啊,試想,如果別人使用了你的這個ForEach之 後,後續操作豈不是成天方夜譚了嗎?所以說這樣設計ForEach是萬萬不可的!即使勉強要設計,也要設計成 這樣才對啊!

public static IEnumerable<T> ForEach<T>(this 

IEnumerable<T> source, Action<T> foreachAction)
         {
             foreach (var t in source)
             {
                 foreachAction(t);
             }
             return source;
         }

而且在我看來,這樣添加ForEach擴展並不妥當,原因在於:這樣設計的ForEach擴展, 破壞了Linq的延遲操作特性!

所以說,我認為微軟不在Linq中包含ForEach擴展算是一個正確的選擇, 如果要用到ForEach功能,還是老老實實用foreach語句來寫吧!其實也並不復雜!

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved