程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> C#中的ThenBy是如何實現的

C#中的ThenBy是如何實現的

編輯:C#入門知識

C#中給繼承自IEnumerable的對象(最熟知的就是List了)提供了很豐富的擴展方法,涉及列表操作的方方面面。而擴展方法ThenBy就是很有意思的一個,它的實現也很巧妙。   如果有這樣的一個Team類,裡面有三個屬性。   Team.cs   public class Team {     public Team (string name, int timeCost, int score)     {         this.Name = name;         this.TimeCost = timeCost;         this.Score = score;     }       public string Name {         get;         private set;     }       public int TimeCost {         get;         private set;     }       public int Score {         get;         private set;     }   } 然後我們有一個Team的List。   List<Team> teams = new List<Team> (); teams.Add (new Team ("teamA", 10, 22)); teams.Add (new Team ("teamB", 12, 20));   teams.Add (new Team ("teamC", 8, 18)); 那麼如何求出teams中得分最高的那個隊伍那?這個很簡單,只需要一句話即可。     var result = teams.OrderByDescending (team => team.Score).First (); Console.WriteLine (result.Name); // teamA 由於List實現了IEnumerable接口,而System.Linq中的Enumerable類中有針對IEnumerable接口的名為OrderByDescending的擴展方法,所以我們直接調用這個擴展方法可以對List按照指定的key進行降序排列,再調用First這個擴展方法來獲取列表中的第一個元素。   如果我的List變成這個樣子。     List<Team> teams = new List<Team> (); teams.Add (new Team ("teamA", 10, 18)); teams.Add (new Team ("teamB", 12, 16)); teams.Add (new Team ("teamC", 8, 18)); 由於有可能兩組以上的隊伍都可能拿到最高分,那麼在這些最高分的隊伍中,我們選取用時最少的作為最終優勝者。有人說那可以這樣寫。     var result = teams.OrderByDescending (team => team.Score).OrderBy(team => team.TimeCost).First (); 先對列表按Score降序排列,再對列表按TimeCost升序排列,然後取結果中的第一個元素。看來貌似是正確的,但其實是錯誤的。因為第一次調用OrderByDescending方法後返回了一個排序後的數組,再調用OrderBy是另外一次排序了,它會丟棄上一次排序,這與我們定的先看積分,如果積分相同再看耗時的規則違背。   那麼應該如何實現那?C#給我們提供了一個叫做ThenBy的方法,可以滿足我們的要求。     var result = teams.OrderByDescending (team => team.Score).ThenBy(team => team.TimeCost).First ();   Console.WriteLine (result.Name); // teamC 新的問題又來了。第一次調用OrderByDescending方法時返回的是一個新對象,再對這個新對象調用ThenBy時,它只有記錄了上一次排序規則,才能達到我們想要的效果。那麼C#是如何記錄上次排序使用的key那?   這就先要看OrderByDescending方法是如何實現了的。查看源碼發現OrderByDescending有兩個重載,實現如下。     public static IOrderedEnumerable<TSource> OrderByDescending<TSource, TKey> (this IEnumerable<TSource> source, Func<TSource, TKey> keySelector) {     return source.OrderByDescending (keySelector, null); }   public static IOrderedEnumerable<TSource> OrderByDescending<TSource, TKey> (this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, IComparer<TKey> comparer) {     Check.SourceAndKeySelector (source, keySelector);     return new OrderedSequence<TSource, TKey> (source, keySelector, comparer, SortDirection.Descending);   } 在第二個重載中我們看到OrderByDescending方法返回時的是一個繼承了IOrderedEnumerable接口的對象OrderedSequence。這個對象記錄了我們的排序規則。   而我們再查看下ThenBy方法的定義。   public static IOrderedEnumerable<TSource> ThenBy<TSource, TKey> (this IOrderedEnumerable<TSource> source, Func<TSource, TKey> keySelector, IComparer<TKey> comparer) {     Check.SourceAndKeySelector (source, keySelector);     return source.CreateOrderedEnumerable<TKey> (keySelector, comparer, false); }   public static IOrderedEnumerable<TSource> ThenBy<TSource, TKey> (this IOrderedEnumerable<TSource> source, Func<TSource, TKey> keySelector) {     return source.ThenBy (keySelector, null); } 我們可以看到ThenBy這個擴展方法追加到的對象類型要實現IOrderedEnumerable接口,而OrderBy方法恰好返回的就是這個類型接口對象。那我們再看看IOrderedEnumerable接口的定義。     using System; using System.Collections; using System.Collections.Generic;   namespace System.Linq {     public interface IOrderedEnumerable<TElement> : IEnumerable<TElement>, IEnumerable     {         //         // Methods         //         IOrderedEnumerable<TElement> CreateOrderedEnumerable<TKey> (Func<TElement, TKey> keySelector, IComparer<TKey> comparer, bool descending);     }   } 其繼承自IEnumerable接口,並且要實現一個名為CreateOrderedEnumerable的方法,正是ThenBy方法實現中調用的這個方法。

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