C#:如何实现IOrderedEnumerable <t> </t>

时间:2009-08-05 18:23:10

标签: c# .net interface ienumerable

我想为练习实施一些不同的算法,只是为了看看我到底有多糟糕并且变得更好:p

无论如何,我想我会尝试使用IEnumerable<T>IOrderedEnumerable<T>以及其他.Net集合类型来兼容(这样我以后写的内容就可以更容易使用了。)

但除了使用OrderBy和ThenBy扩展方法之外,我找不到返回IOrderedEnumerable<T>实例的方法。所以我想我必须创建自己的类来实现这个接口。但说实话,界面对我来说并不合理。可能,但我不确定。

我创建了一个空类,添加了接口,然后让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。但那只是有可能返回一个。所以我想这个问题是对我到那里的一个答案的回应=)

2 个答案:

答案 0 :(得分:12)

我有一个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);        
}

所以基本上你创建了一系列比较器,从“最不重要”到“最重要”。你还需要把“降序”位放在那里,但这很容易:)

在上面链接的示例中,三个不同的方面在MiscUtil中已经存在的三个不同的类中表示:

  • ReverseComparer:撤消现有IComparer<T>的结果
  • LinkedComparer:从两个创建一个比较器,一个主服务器和一个服务器
  • ProjectionComparer:根据从原始项到键的投影创建一个比较器,委托给另一个比较器来比较这些键。

比较者非常适合像这样链接在一起。

答案 1 :(得分:0)

据推测,您的类将有一些实现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);
}