gpt4 book ai didi

c# - 为什么 Enumerable.Single() 迭代所有元素,即使已经找到多个元素?

转载 作者:IT王子 更新时间:2023-10-29 03:43:51 30 4
gpt4 key购买 nike

在分析我们的一个应用程序时,我们发现某些代码出现神秘的减速,我们正在为一个大型集合调用 Enumerable.Single(source, predicate),其中有多个项目与集合开始附近的谓词。

调查显示the implementation of Enumerable.Single()如下:

public static TSource Single<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate) 
{
TSource result = default(TSource);
long count = 0;
// Note how this always iterates through ALL the elements:
foreach (TSource element in source) {
if (predicate(element)) {
result = element;
checked { count++; }
}
}
switch (count) {
case 0: throw Error.NoMatch();
case 1: return result;
}
throw Error.MoreThanOneMatch();
}

该实现将遍历序列中的每个元素,即使不止一个元素已经与谓词匹配。

以下实现似乎会产生相同的结果:

public static TSource Single<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate)
{
TSource result = default(TSource);
long count = 0;
foreach (TSource element in source) {
if (predicate(element)) {
if (count == 1) // Exit loop immediately if more than one match found.
throw Error.MoreThanOneMatch();

result = element;
count++; // "checked" is no longer needed.
}
}

if (count == 0)
throw Error.NoMatch();

return result;
}

有谁知道为什么实际实现不使用这种明显的优化?有什么我想念的吗? (我无法想象如此明显的优化会被忽略,因此一定有一些具体的原因。)

(注意:我意识到这个问题可能会吸引一些意见的答案;我希望得到的答案能够提供迭代所有元素的具体原因。如果答案实际上是“因为设计者不认为这样的优化是necessary”,那么这个问题是无法回答的,我想我应该删除它......)


为了进行比较,请查看不采用谓词的 Single() 的实现:

public static TSource Single<TSource>(this IEnumerable<TSource> source) 
{
IList<TSource> list = source as IList<TSource>;
if (list != null) {
switch (list.Count) {
case 0: throw Error.NoElements();
case 1: return list[0];
}
}
else {
using (IEnumerator<TSource> e = source.GetEnumerator()) {
if (!e.MoveNext()) throw Error.NoElements();
TSource result = e.Current;
if (!e.MoveNext()) return result;
}
}
throw Error.MoreThanOneElement();
}

在这种情况下,他们努力为 IList 添加优化。

最佳答案

你似乎不是唯一一个这么想的人。 .NET Core implementation有一个优化版本:

using (IEnumerator<TSource> e = source.GetEnumerator())
{
while (e.MoveNext())
{
TSource result = e.Current;
if (predicate(result))
{
while (e.MoveNext())
{
if (predicate(e.Current))
{
throw Error.MoreThanOneMatch();
}
}

return result;
}
}
}

所以回答你的问题:除了开发人员没有考虑优化这个用例之外,似乎没有“好的”理由。

关于c# - 为什么 Enumerable.Single() 迭代所有元素,即使已经找到多个元素?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53042806/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com