2009-08-05 30 views
12

我想要實現的做法有些不同的算法,只是爲了看看我有多糟糕真的很和,以獲得更好:對C#:如何實現IOrderedEnumerable <T>

不管怎麼說,我想我會嘗試使用IEnumerable<T>IOrderedEnumerable<T>和其他.Net集合類型只是爲了兼容(以便我寫的內容稍後可以更容易地使用)。

但我找不到一種方法來返回IOrderedEnumerable<T>的實例,而不是使用OrderBy和ThenBy擴展方法。所以我想我必須創建自己的類來實現這個接口。但接口對我來說不太合理,說實話。它可能,但我不確定。

我創建了一個空類,添加了接口,然後讓ReSharper爲我添加空實現。它看起來像這樣:

class MyOrderedEnumerable<T> : IOrderedEnumerable<T> 
{ 
    /// <summary> 
    /// Performs a subsequent ordering on the elements of an <see cref="T:System.Linq.IOrderedEnumerable`1"/> according to a key. 
    /// </summary> 
    /// <returns> 
    /// An <see cref="T:System.Linq.IOrderedEnumerable`1"/> whose elements are sorted according to a key. 
    /// </returns> 
    /// <param name="keySelector">The <see cref="T:System.Func`2"/> used to extract the key for each element.</param><param name="comparer">The <see cref="T:System.Collections.Generic.IComparer`1"/> used to compare keys for placement in the returned sequence.</param><param name="descending">true to sort the elements in descending order; false to sort the elements in ascending order.</param><typeparam name="TKey">The type of the key produced by <paramref name="keySelector"/>.</typeparam><filterpriority>2</filterpriority> 
    public IOrderedEnumerable<T> CreateOrderedEnumerable<TKey>(Func<T, TKey> keySelector, IComparer<TKey> comparer, bool descending) 
    { 
     throw new NotImplementedException(); 
    } 

    /// <summary> 
    /// Returns an enumerator that iterates through the collection. 
    /// </summary> 
    /// <returns> 
    /// A <see cref="T:System.Collections.Generic.IEnumerator`1"/> that can be used to iterate through the collection. 
    /// </returns> 
    /// <filterpriority>1</filterpriority> 
    public IEnumerator<T> GetEnumerator() 
    { 
     throw new NotImplementedException(); 
    } 

    /// <summary> 
    /// Returns an enumerator that iterates through a collection. 
    /// </summary> 
    /// <returns> 
    /// An <see cref="T:System.Collections.IEnumerator"/> object that can be used to iterate through the collection. 
    /// </returns> 
    /// <filterpriority>2</filterpriority> 
    IEnumerator IEnumerable.GetEnumerator() 
    { 
     return GetEnumerator(); 
    } 
} 

什麼我不明白的是CreateOrderedEnumerable方法。究竟是什麼意思?那麼,我想它當然會創建一個有序的枚舉,但是如何?排序算法本身應該放在那裏?它會排序?沒有收集任何項目進入該方法,那麼它是爲了獲得收集訂單?你將如何使用課堂?這是否意味着要實施例如一個私人幫手類內的東西,需要排序的東西?

然後代替MyOrderedEnumerable<T> : IOrderedEnumerable<T>的,你可能有一個QuickSorter<T> : IOrderedEnumerable<T>是花了集合在其構造和分類的時候,那個CreateOrderedEnumerable方法被調用......但隨後會發生什麼,如果有人打電話GetEnumerator,開始該方法之前枚舉被稱爲?


哈哈,剛發現我剛纔問了一些類似的東西here。但那只是如果有可能返回一個。所以我想這個問題是對我到達的答案的答覆=)

回答

11

我有一個sample implementation你可以看看。它不是以任何方式高效的,但它應該讓你開始。

基本上IOrderedEnumerable<T>只需要有一個當前排序的想法,所以它可以創建一個新的。假設你已經有一個IComparer<T>你建立一個新的說法是這樣的:

int Compare(T first, T second) 
{ 
    if (baseComparer != null) 
    { 
     int baseResult = baseComparer.Compare(first, second); 
     if (baseResult != 0) 
     { 
      return baseResult; 
     } 
    } 
    TKey firstKey = keySelector(first); 
    TKey secondKey = keySelector(second); 

    return comparer.Compare(firstKey, secondKey);   
} 

所以基本上你創建comparers從「最顯著」上升到「最顯著」走出鏈。你也需要把位在那裏「降」,但很容易:)

在上面掛的樣品,在三個不同的方面進行了三個不同的等級來表示已存在於MiscUtil

  • ReverseComparer :反轉現有IComparer<T>的結果
  • LinkedComparer:從兩個創建一個比較器,具有一個主站和一個從
  • ProjectionComparer:創建基於從原始項密鑰的投影一個比較器,委託給另一個比較器來比較這些鍵。

比較器很適合像這樣鏈接在一起。

+0

甜!將立即檢查它=) – Svish 2009-08-05 18:29:51

+0

所以它會根據你給它的新比較器重新排序?要麼?不知道我是否明白... – Svish 2009-08-05 18:43:33

+0

它不會重新排序 - 它會根據舊訂單和新比較創建新訂單並添加新訂單。它不會使用舊序列本身,除非得到原始的無序數據。請看代碼以獲取更多詳細信息:) – 2009-08-05 18:46:46

1

假設你的班級有一些內部存儲變量,它們實現IEnumerable(例如List<T>)。這種方法的實現很簡單,在這種情況下:

private List<T> data = new List<T>(); 

public IOrderedEnumerable<CalculationResult> CreateOrderedEnumerable<TKey>(Func<CalculationResult, TKey> keySelector, IComparer<TKey> comparer, bool descending) 
{ 
    return descending ? 
     data.OrderByDescending(keySelector, comparer) 
    : data.OrderBy(keySelector, comparer); 
} 
+0

這是錯誤的。 CreateOrderedEnumerable由「ThenBy」LINQ函數調用,並且必須保留已經存在的順序。使用你的代碼片段實現CreateOrderedEnumerable將覆蓋順序,導致你的實現中斷接口語義。 – Zarat 2015-05-29 14:50:22