C#Linq技術中SelectMany(...)的內部實現推測


對於聲明為:public static IEnumerable<TResult> SelectMany<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, IEnumerable<TResult>> selector);而言,調用它的形式就是: AList.SelectMany(itm=>itm.listProp);  // 其中AList中的屬性里有 也是集合的 屬性listProp。listProp集合元素類型是TResult。

對於 AList.Select(itm=>itm.listProp)返回的是 IEnumerable<List<TResult>>

現在對於聲明為:public static IEnumerable<TResult> SelectMany<TSource, TCollection, TResult>(this IEnumerable<TSource> source, Func<TSource, IEnumerable<TCollection>> collectionSelector, Func<TSource, TCollection, TResult> resultSelector);

// TResult 中的字段 可以由 TSource和TCollection一起構成,當然也可以只 由TCollection的某些字段單獨構成。

// 可以 假設:Class中有GradeId和ClassId字段和 List<Student> studs,而Student只有ClassId沒有GradeId;那么

// IEnumerable<TSource>就是 Class的集合。 而 IEnumerable<TCollection>就是 Class中 Student的集合。

// 這時候調用 SelectMany的形式就是 classes.SelectMany(class=>class.studs,(class,stud)=>new{GradeId=class.GradeId,StudentId=stud.StudentId,...});

// 其中 classes就是 source, stud則是 studs中的元素。且如果方法中出現了兩個委托參數,一般而言第二個委托需要間接用到第一個委托的返回值。

// 這個例子就說明了,為什么第二個委托里需要傳 class。

 1      // 調用的時候是 source.SelectMany(i=>i.listProp,(i,s)=>...); i就是下面的itm
       // TSource就類似ClassTCollection就類似 Student; TResult則是 第二個委托的返回值的 類型,可以是匿名類型
2 public IEnumerable<TResult> SelectMany<TSource,TCollection,TResult>(source,collectionSelector,resultSelector) 3 { 4 IEnumerable<TResult> listResult = new IEnumerable<TResult>();
         // source就類似上面的 classes
5 foreach(var itm in source) 6 { 7 // collectionSelector(itm)返回的是 itm.listProp; 8 // itm.listProp的類型 就是 TCollection 類型。 9 IEnumerable<TCollection> blockCollection = collectionSelector(itm); // blockCollection類似某class 的studs 10 // 如果沒有后面的 resultSelector那么這時候實際上會執行 listResult.AddRange(blockList); 11 12 // IEnumerable<TResult> blockResult=new List<TResult> 13 foreach(var citm in blockCollection)// 類似上面的studs 14 { 15 // 這里之所以用到 itm 是因為 TResult 中的字段未必都是 citm 里進行了刪減,而還包括一些擴增,擴增的 16 // 字段就可以是 itm中的。 舉個栗子: itm是 Trade(有多個Order,即是 blockCollection),而 citm則是 Order, 17 // 那么這時候返回的 Result未必 是 Order的屬性縮減后得到的新的 對象,還可以是 itm中除了 blockCollection屬性外的 18 // 其它屬性,例如收貨人姓名 和 Order中的屬性進行拼接。(注意,Order之前是沒有收貨人姓名的,因為一個 Order必然是 19 // 屬於一個具體的 Trade,而一個Trade是由一個 買家購買物品產生的,故只需要在 Trade中有收件人姓名即可。這里我們 20 // 將收件人姓名這個屬性 整合到了 Order中形成 'Order ,即 TResult。 21 // 所以說,之前覺得 itm是沒必要的是因為自己沒有搞懂 這個SelectMany的功能。總以為 對一個結構進行修改形成新的 22 // 結構只是說 對原來的結構進行 修剪, 現在才知道,實際上還可以 對原來的結構進行 增加,而用什么增加,既可以是 23 // 無關的數據,也可以是該結構的上級的數據。 24 listResult.Add(resultSelection(itm, citm)); // resultSelection(itm,citm)的返回值就是 TResult 對象 25 } 26 } 27 return listResult; 28 }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM