Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 当找到多个元素时,为什么Single()不直接返回?_C#_.net_Linq_Internals - Fatal编程技术网

C# 当找到多个元素时,为什么Single()不直接返回?

C# 当找到多个元素时,为什么Single()不直接返回?,c#,.net,linq,internals,C#,.net,Linq,Internals,在使用反编译器检查该方法时,我(大致)在该方法中发现了以下代码: foreach (TSource current in source) { if (predicate(current)) { result = current; num += 1L; } } if (num > 1L) { throw Error.MoreThanOneMatch(); } 如您所见,它在投掷之前会在所有项目上循环。当num>1时,它为什

在使用反编译器检查该方法时,我(大致)在该方法中发现了以下代码:

foreach (TSource current in source)
{
    if (predicate(current))
    {
        result = current;
        num += 1L;
    }
}

if (num > 1L)
{
     throw Error.MoreThanOneMatch();
}

如您所见,它在投掷之前会在所有项目上循环。当
num>1
时,它为什么不中断?

同意,从性能角度来看,它会更好(编辑:如果我们希望有多个项目与谓词匹配,我们不应该这样做):

看起来他们决定让分析结果更加清晰,并将其与枚举源分离。但我想知道为什么不使用简单开关:

switch((int)num)
{
   case 0: throw Error.NoMatch();
   case 1: return local;
   default:
       throw Error.MoreThanOneMatch();    
}

关于性能问题——我认为假设在您真正期望单个结果时应该调用
Single
。零个或多个结果是异常路径,不应经常发生(与任何异常一样)。因此,如果源包含许多匹配谓词的项,则程序的逻辑错误更大。

By
Single
的意思是,正好是一个,而不是一个,也不是多个
它枚举所有项目,以确保只有一项。
如果没有异常或存在多个异常,则会引发异常。
SingleOrDefault
如果有更多,则抛出,如果没有,则返回
default(T)
/
null

您要查找的是
FirstOrDefault
,如果它找到与谓词匹配的第一个枚举,它将破坏枚举
First
如果没有则抛出,如果找到了第一个,则还会中断(直接从返回)它的foreach

FirstOrDefault的来源

foreach (TSource current in source)
{
    if (predicate(current))
    {
        return current;
    }
}
return default(TSource);
而First的源不是返回默认值

throw Error.NoMatch();

谢谢你的提问。LINQ团队决定在这里循环到底,这真的很有趣。文斯,这部分的可枚举单实现和可查询单实现之间有什么区别吗?你在哪里找到这个实现的?使用Reflector,我看到了完全不同的东西,如果找到第二个元素,它会立即返回。从性能上看,这可能并不完美。但至少结果是可以预测的。谓词是为任何元素执行的,因此,如果谓词有副作用,那么它对所有元素都是可预测的。如果在第二次命中时出现单断点,则很难判断谓词执行了哪些元素。所以我想说,在某些情况下这更安全,但在大多数情况下性能较差。@Thomaslevsque 3.5汇编或4.0?我想您的交换机解决方案需要枚举整个源代码。但是当前带有if的解决方案在知道存在一些重复性时会立即抛出异常。@Ondra当前解决方案不会立即抛出异常。看看源代码。我的开关块是一个重构的
num
分析块,来自原始实现。这个开关应该在枚举之后放置这是我最初的想法,但问题是,如果找到两个匹配的元素,为什么没有在该点抛出异常,而不是遍历列表的其余部分然后抛出异常?对不起,我的错误,
SingleOrDefault
从不抛出,如果有多个或没有,则返回null<代码>单个是抛出的。我的猜测是:他们希望迭代在抛出异常之前完成。如果它们在枚举中间抛出一个异常,它可能会引起一些副作用(如枚举器)。接下来从Internet下载一个项目,除此之外,连接不正确。closed@Ondra是的,这是一个老问题,但不是,人们永远不应该相信枚举器/产量方法已经“完成”(关于实现IEnumerator的Reset方法,经常提到没有人指定必须触发,foreach也没有;yield方法也不应该处理打开/关闭db连接,因为它们在“结束”之前不一定执行)
SingleOrDefault
在有多个项时会抛出异常,就像
Single
一样。区别在于没有项时:
Single
抛出,
SingleOrDefault
返回
默认值(T)
(对于引用类型为空)
throw Error.NoMatch();