【问题标题】:Why do we need Single() in LINQ?为什么我们在 LINQ 中需要 Single()?
【发布时间】:2011-05-14 20:54:52
【问题描述】:

为什么扩展方法Single()的主要用途是?

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

编辑:
我确实了解 Single 在做什么,因此您无需在问题中解释此方法的作用。

【问题讨论】:

    标签: c# .net linq extension-methods ienumerable


    【解决方案1】:

    这对于声明性陈述很有用

    我想要列表中的单个元素,如果有多个匹配项,那么就大错特错了

    很多时候,程序需要根据特定谓词将一组元素简化为有趣的元素。如果有多个匹配,则表明程序中存在错误。如果没有 Single 方法,程序将需要再次遍历可能昂贵列表的部分。

    比较

    Item i = someCollection.Single(thePredicate);
    

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

    后者需要两个语句,并迭代一个可能很昂贵的列表两次。不好。

    注意:是的First可能更快,因为它只需要迭代枚举直到第一个匹配的元素。其余元素无关紧要。另一方面Single 必须考虑整个枚举。如果多个匹配项对您的程序没有影响并且表明没有编程错误,那么可以使用First

    【讨论】:

    • 我以为第 2 2 行类似于 Single 在幕后所做的事情?它必须评估整个集合,这就是它知道抛出超过 1 个匹配的异常的方式 - 但它可以节省您每次都必须编写该代码。正是因为这个原因,我认为 Single 比 First 慢?
    • @RichardW1001 我的第二个代码 sn-p 和实际的Single 实现之间的区别在于枚举被枚举的次数。在Single 实现中,最坏的情况是1 次,而在我的代码sn-p 中,最坏的情况是2 次。首先是可能更快,因为它可以在看到匹配元素的那一刻停止枚举。所以如果它是第一个元素,那么枚举很快。如果匹配元素是最后一个元素,那么FirstSingle 的性能几乎相同
    • @JaredPar 很好的解释。我可以在 LINQ to Objects 中看到它的使用,但在 LINQ to SQL/Entities 中看不到它,因为它通常用于具有唯一字段的表中(例如Id),并且您永远不会有两个值相同的Id,因为它们是主键,您不能插入相同的Id 两次。
    • @Oscar 我对 LINQ to SQL 的细节不太熟悉,所以我很难肯定地发表评论。我的直觉是你的断言是正确的。
    • 同样的推理也适用于 linq 2 sql。如果您检查生成的 sql,您会看到它实际上生成了 SELECT TOP 2,以便在返回多个元素时能够抛出。
    【解决方案2】:

    使用Single 可让您记录您对结果数量的期望,并尽早失败,如果错误则坚决失败。除非您为了自己的利益而享受长时间的调试会话,否则我会说这对于提高代码的健壮性非常有用。

    【讨论】:

      【解决方案3】:

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

      【讨论】:

      • 我知道,但是在数据库中的1:1 ID:Name 关系中,我们可以使用First(),它会更快。
      【解决方案4】:

      Single 将返回类/对象的单个实例,而不是集合。当您通过 Id 获得单个记录时非常方便。我从没想过会超过一排。

      【讨论】:

        猜你喜欢
        • 2019-06-09
        • 2014-06-18
        • 2017-02-26
        • 2011-04-03
        • 2017-07-27
        • 2020-09-21
        • 2020-03-09
        • 2018-12-24
        • 2012-04-08
        相关资源
        最近更新 更多