【问题标题】:C#: How to implement IOrderedEnumerable<T>C#:如何实现 IOrderedEnumerable<T>
【发布时间】:2009-08-05 18:23:10
【问题描述】:

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

无论如何,我想我会尝试使用IEnumerable&lt;T&gt;IOrderedEnumerable&lt;T&gt; 以及其他.Net 集合类型,只是为了兼容(这样我写的东西以后可以更容易地使用)。

但除了使用 OrderBy 和 ThenBy 扩展方法之外,我找不到返回 IOrderedEnumerable&lt;T&gt; 实例的方法。所以我想我必须创建自己的类来实现这个接口。但老实说,界面对我来说不太有意义。可能,但我不确定。

我创建了一个空类,添加了接口,然后让 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 方法。它究竟是什么意思?好吧,我想它当然会创建一个有序的可枚举,但是如何呢?排序算法本身是否应该进入那里?它会排序什么?该方法没有项目集合,那么在哪里订购集合?你会如何使用这个类?它是否意味着作为一个私有帮助器类来实现,例如需要对东西进行排序的东西?

然后你可能有一个QuickSorter&lt;T&gt; : IOrderedEnumerable&lt;T&gt;,而不是MyOrderedEnumerable&lt;T&gt; : IOrderedEnumerable&lt;T&gt;,它在其构造函数中获取一个集合,并在调用CreateOrderedEnumerable 方法时对其进行排序......但是如果有人调用GetEnumerator,会发生什么情况并在调用该方法之前开始枚举?


哈哈,刚刚发现我前段时间问过类似的问题here。但这只是如果有可能返回一个。所以我想这个问题是对我得到的一个答案的回应=)

【问题讨论】:

    标签: c# .net interface ienumerable


    【解决方案1】:

    我有一个sample implementation,你可以看看。它的设计目的并非以任何方式提高效率,但它应该可以帮助您入门。

    基本上IOrderedEnumerable&lt;T&gt; 只需要知道它当前的顺序,就可以创建一个新的。假设您已经有一个IComparer&lt;T&gt;,您可以通过以下方式构建一个新的:

    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&lt;T&gt; 的结果
    • LinkedComparer:从两个中创建一个比较器,一主一从
    • ProjectionComparer:根据从原始项目到键的投影创建一个比较器,委托给另一个比较器来比较这些键。

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

    【讨论】:

    • 甜蜜!将立即检查=)
    • 所以它会根据你给它的新比较器重新排序?要么?不知道我是否理解...
    • 它不会自行重新排序 - 它会根据旧顺序和新比较创建具有新顺序的新序列。除了获取原始无序数据外,它不会使用旧序列本身。查看代码以获取更多详细信息:)
    • 顺便说一句,不要因为被它弄糊涂而感到难过——我也这样做了很长一段时间。这需要一些时间才能让你头脑清醒。
    • @HereticMonkey:感谢您的编辑。这在 C# in Depth 站点中显示了一个错误,我现在正在修复它:) 将在编辑工作时回滚...
    【解决方案2】:

    大概,您的类将有一些实现IEnumerable(例如List&lt;T&gt;)的内部存储变量。这种情况下这个方法的实现很简单:

    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);
    }
    

    【讨论】:

    • 这是错误的。 CreateOrderedEnumerable 由“ThenBy”LINQ 函数调用,并且必须保留已经存在的排序。使用您的 sn-p 实现 CreateOrderedEnumerable 将覆盖顺序,导致您的实现破坏接口语义。
    猜你喜欢
    • 2010-10-24
    • 1970-01-01
    • 1970-01-01
    • 2017-01-15
    • 2012-07-03
    • 2014-12-20
    • 1970-01-01
    • 2018-02-15
    • 1970-01-01
    相关资源
    最近更新 更多