2

我有一个包含 5000 多个项目的通用集合。所有项目都是独一无二的,所以我使用 SingleOrDefault 从集合中提取一个项目。今天我使用 Red Gate ANTS 分析器查看代码,发现我的 SingleOrDefault 调用在 5000 次迭代中(~3.5 秒)有 1800 万次命中,而当我将其更改为 FirstOrDefault 时,它有 900 万次命中(~1.5 秒)。

我使用 SingleOrDefault 因为我知道集合中的所有项目都是独一无二的。

编辑:问题将是为什么 FirstOrDefault 比 SingleOrDefault 快,即使这是我们应该使用 SingleOrDefault 的确切场景。

4

5 回答 5

9

SingleOrDefault()如果有多个,则引发异常。为了确定这一点,它必须验证不超过一个。

另一方面,FirstOrDefault()一旦找到它就可以停止寻找。因此,我希望它在许多情况下会快得多。

于 2013-05-20T19:06:06.807 回答
4

SingleOrDefault(predicate)确保最多有一个项目与给定谓词匹配,因此即使它在集合开头附近找到匹配项目,它仍然必须继续到IEnumerable.

FirstOrDefault(predicate)一旦在集合中找到匹配的项目,它就会停止。如果您的“第一场比赛”均匀分布在IEnumerable整个IEnumerable.

对于一系列N项目,SingleOrDefault将运行您的谓词N时间,FirstOrDefault并将运行您的谓词(平均)N/2次。这就解释了为什么您看到SingleOrDefault的“点击次数”是FirstOrDefault.

如果您知道您将永远只有一个匹配项,因为您的收藏来源由您和您的系统控制,那么您最好使用FirstOrDefault. 例如,如果您的收藏来自用户,那么将其SingleOrDefault用作对用户输入的检查可能是有意义的。

于 2013-05-20T19:05:21.753 回答
1

我非常怀疑之间的选择SingleOrDefaultFirstOrDefault成为您的瓶颈。我认为分析工具有望突出更大的鱼来煎炸。您自己的指标表明,对于任何给定的迭代,这相当于一个几乎无法分辨的时间单位。

但我建议使用符合您期望的那个。即,是否有多个与谓词匹配的错误?如果是,请使用强制执行该期望的方法。SingleOrDefault. (同样,如果没有任何错误,只需使用Single。)如果不止一个错误,请随意使用First变体。

正如其他答案所讨论的那样,现在应该很明显为什么一个可能比另一个快一点。一个是强制执行约束,这当然是通过执行逻辑来完成的。另一个没有执行该特定约束,因此不会被它延迟。

于 2013-05-20T20:19:19.657 回答
1

FirstOrDefault 将在第一次点击时返回。SinglerOrDefault 不会在第一次点击时返回,但也会查看所有其他元素以检查其是否唯一。所以 FirstOrDefault 在大多数情况下会更快。如果您不需要唯一性检查,请使用 FirstOrDefault。

于 2013-05-20T19:10:51.817 回答
0

我使用 LinqPad 运行测试,这表明使用 Single 和 SingleOrDefault 的查询比使用 First 或 FirstOrDefault 的查询快。这些测试是针对大型数据集的相当简单的查询(不涉及连接)。我没想到会是这样的结果,事实上我试图向另一个开发人员证明我们应该使用 First 和 FirstOrDefault,但是当证明表明 Single 实际上更快时,我的论点的基础就消失了。在某些情况下,First 更快,但不要认为它是一揽子案例。

于 2016-10-06T10:47:35.907 回答