为什么我们需要在LINQ中使用Single()?

8

Single()扩展方法的主要目的是什么?

我知道如果序列中有多个与谓词匹配的元素,它会抛出异常,但是我仍然不理解在哪种情况下它可能有用

编辑:
我确实理解Single在做什么,所以你不需要在你的问题中解释这个方法正在做什么。

4个回答

15

声明性地陈述是很有用的

我想要列表中的单个元素,如果有多个匹配项,则表示程序出现了问题。

在程序需要根据特定谓词将一组元素缩减为感兴趣的一个元素时,使用Single方法非常有用。如果有多个匹配项,则表明程序出现了错误。如果没有Single方法,程序需要多次遍历潜在昂贵的列表部分。

比较:

Item i = someCollection.Single(thePredicate);

To

Contract.Requires(someCollection.Where(thePredicate).Count() == 1);
Item i = someCollection.First(thePredicate);

后者需要两个语句并且可能需要两次迭代昂贵的列表。不好。
注意:是的, First 可能更快,因为它只需要迭代枚举器找到第一个匹配的元素即可。其他元素无关紧要。另一方面,Single 必须考虑整个枚举器。如果多个匹配对您的程序没有影响,并且不表示编程错误,则使用First

我认为第二个和第三个代码行背后的操作类似于Single的工作原理?它必须评估整个集合,这就是它知道如何为多个匹配项抛出异常的原因 - 但这样可以避免每次编写该代码。我认为正是因为这个原因,Single比First慢? - RichardW1001
@JaredPar 很好的解释。我可以看到它在LINQ to Objects中的用途,但在LINQ to SQL/Entities中不太常用,因为它通常用于具有唯一字段(例如Id)的表格,而您永远不会有两个具有相同Id值的记录,因为这些是主键,您无法插入相同的Id两次。 - Oscar Mederos
@Oscar 我对LINQ to SQL的细节不太熟悉,所以很难确定地发表评论。我的直觉是你的说法是正确的。 - JaredPar
@JaredPar:我不明白为什么Single()First()只有在所需元素是最后一个时才相似。First()调用MoveNext()一次,而Single()调用两次以验证它是否是唯一的元素(如果第二次返回true,则抛出异常)。 Single() 永远不必遍历整个集合. - Allon Guralnek
@All,OP指的是SingleFirst的重载,它们接受一个谓词表达式。这意味着它必须枚举序列直到找到第一个与谓词匹配的元素。 - JaredPar
显示剩余4条评论

3

使用Single允许您记录对结果数量的期望,并在结果不正确时及早失败。除非您喜欢长时间的调试会话,否则我会说它极其有用,可以提高您代码的鲁棒性。


2
每个LINQ操作符都返回一个序列,因此是一个 IEnumerable<T>。要获取实际元素,您需要其中的一个 FirstLastSingle 方法 - 如果您确定序列只包含一个元素,则使用后者。例如,数据库中的1:1 ID:Name映射。

我知道,但在数据库中的1:1 ID:Name关系中,我们可以使用First(),这样会更快。 - Oscar Mederos

0

Single会返回类/对象的单个实例,而不是集合。当您通过Id获取单个记录时非常方便。我从未期望超过一行。


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