数组还是迭代器 - 在返回一个或两个元素的调用中,哪种具有更好的性能特征(内存方面)?

5
假设我们有如下伪 C# 中的方法:
```csharp ```

请注意,这里没有提供任何代码。

static IEnumerable<T> Iterator<T>()
{
    switch (SomeCondition)
    {
        case CaseA:
            yield return default(T);
        case CaseB:
            yield return default(T);
            yield return default(T);
        case CaseC:
            yield return default(T);
        default:
            break;
    }
}

static IEnumerable<T> Array<T>()
{
    switch (SomeCondition)
    {
        case CaseA:
            return new[] { default(T) };
        case CaseB:
            return new[] { default(T), default(T) };
        case CaseC:
            return new[] { default(T) };
        default:
            break;
    }
}

如果我们有许多类似于这种方法的调用,哪个会消耗更少的内存(和更少的GC周期)?编写自己的Enumerable/Enumerator来实现这种Enumerable.Once()场景是否有意义?

6
当您启用适当的优化并以发布构建方式编译和运行这两个示例时,会发生什么? - Anthony Pegram
5
两者都不太可能成为瓶颈,选择最易读的那个。 - H H
方法必须完全符合这些签名吗?这肯定是一个瓶颈吗?使用案例是什么?这里有一些有趣的选项,但我们需要更多信息。 - Jon Skeet
3个回答

1

这个比其他两个都要快:

static T[] Array<T>()
{
    switch (SomeCondition)
    {
        case CaseA:
            return new[1];
        case CaseB:
            return new[2];
        case CaseC:
            return new[1];
        default:
            break;
    }
}

但这并不会有太大的影响。


1

这取决于T。例如,大型结构、字符串或字节数组会更适合使用迭代器。但总的来说,对于一个或两个项目,数组可能更小。

但这忽略了重点。它之所以更快,是因为问题空间太小,不足以对性能产生显著影响:一个或两个项目序列不太可能成为应用程序性能的驱动因素。在这种情况下,与其关注性能,我更担心其他因素,如清晰度、可维护性和养成良好习惯。

其中,你可以认为数组更清晰或更干净,因为尚未遇到迭代器的程序员仍然可以轻松理解它。个人而言,我更喜欢yield迭代器,因为我希望养成先考虑迭代器而不是数组的习惯,因为迭代器往往具有更好的性能特性,并且我希望鼓励他人养成同样的习惯。


+1 - "我更担心其他因素,比如清晰度、可维护性和养成良好习惯" 完全同意! - Brian Dishaw
你有一些性能数据来支持你的说法吗?因为据我所见,数组或迭代器的副本数量应该是相等的(数组一次性付出,迭代器每次返回时分期付款)。当元素数量非常大时,数组可能会受到性能影响,因为它使用更多的内存,但在大多数情况下,迭代数组比迭代可枚举对象要快。yield return本身也有一些开销,用于跟踪协程状态。 - Ben Voigt

0

数组占用更少的内存和循环,但如果您想对返回的数据进行操作,则应选择迭代器,因为迭代器实现了最佳算法,最终可以加快速度。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接