17

有谁知道是否有特定原因或设计决定在 C# 中不包含反向枚举器?reverse_iterator如果有一个等价于 C++就像 Enumerator 是等价于 C++ 一样,那就太好了iterator。可以反向迭代的集合只会实现类似 IReverseEnumerable 的东西,并且可以执行以下操作:

List<int>.ReverseEnumerator ritr = collection.GetReverseEnumerator();
while(rtir.MoveNext())
{
 // do stuff
}

这样,您将能够以相同的方式迭代 Lists 和 LinkedLists,而不是对一个链接使用索引器,对另一个链接使用先前的链接,从而实现更好的抽象

4

4 回答 4

21

完全有可能实现这一点。就个人而言,我几乎从不反向迭代。如果我需要这样做,我会先调用 .Reverse()。可能这也是 .NET BCL 设计者的想法。

默认情况下,所有功能都未实现。它们需要被设计、实施、测试、记录和支持。- 雷蒙德陈

这就是为什么您不实现提供很少实用性的功能的原因。你从最重要的特性开始(比如从前到后迭代)。你在预算用尽或你认为没有意义的地方停下来继续。

.NET 基类库中没有很多东西。直到 .NET 4 甚至还没有File.EnumerateLines. 而且我敢说,对于大多数人来说,这样的功能比反向迭代更重要。

您可能在反向迭代很常见的业务领域工作。我的经验是相反的。作为框架设计师,您只能猜测谁将使用您的框架以及这些人需要什么功能。很难划清界限。

于 2012-02-17T23:54:02.943 回答
15

它不可用,因为它是IEnumerator仅向前的迭代器。它只有一个MoveNext()方法。这使得界面非常通用,是 Linq 的核心。有很多真实世界的集合不能向后迭代,因为这需要存储。例如,大多数流都是这样的。

Linq 提供了一个带有Reverse()扩展方法的解决方案。它首先存储元素,然后向后迭代它们。然而,这可能非常浪费,它需要 O(n) 存储。它缺少对已经可索引的集合的可能优化。您可以修复:

static class Extensions {
    public static IEnumerable<T> ReverseEx<T>(this IEnumerable<T> coll) {
        var quick = coll as IList<T>;
        if (quick == null) {
            foreach (T item in coll.Reverse()) yield return item;
        }
        else {
            for (int ix = quick.Count - 1; ix >= 0; --ix) {
                yield return quick[ix];
            }
        }
    }
}

示例用法:

        var list = new List<int> { 0, 1, 2, 3 };
        foreach (var item in list.ReverseEx()) {
            Console.WriteLine(item);
        }

您需要对 LinkedList 进行专门化,因为它没有实现但仍允许通过and属性IList<T>进行快速向后迭代。尽管不使用该类要好得多,但它的 CPU 缓存局部性很差。当您不需要便宜的刀片时,请始终青睐。它可能看起来像这样:LastLinkedListNode.PreviousList<T>

    public static IEnumerable<T> ReverseEx<T>(this LinkedList<T> list) {
        var node = list.Last;
        while (node != null) {
            yield return node.Value;
            node = node.Previous;
        }
    }
于 2012-02-18T13:59:43.883 回答
3

线索在 OP 的最后一行:在 Lists 和 LinkedLists 上使用它。

所以,对于 a List,这个会很好地工作:

    public static IEnumerable<T> AsReverseEnumerator<T>(this IReadOnlyList<T> list)
    {
        for (int i = list.Count; --i >= 0;) yield return list[i];
    }

使用IReadOnlyList在它的工作方面提供了很大的灵活性。

类似的东西是可能的LinkedLists

于 2019-08-08T02:02:54.073 回答
0

问题涉及枚举器,而不是枚举。如果您必须返回一个 IEnumerator(例如,当绑定到 wpf / uwp / winui 中的自定义数据源对象时),您可以这样做:

var reverseList = myList.AsEnumerable().Reverse().ToList();

return reverseList.GetEnumerator()

丑陋、复杂且有效,即完全遵守框架指南。

于 2021-02-23T17:19:35.250 回答