SingleOrDefault()的最佳实践

4

我希望改进我的代码。我能放心地将第一个示例重写为第二个示例吗?

IQueryable<PDF> pdfList = (from pdfobj in pdfDataContext.PDFs
                           where pdfobj.Id == pdfId
                           select pdfobj);
if (pdfList.Count() > 0)
{
  PDF pdfOldWay = pdfList.FirstOrDefault();
  pdfOldWay. // do something. (pdfOldWay can't be null here...)
}

--

PDF pdfNewWay = (from pdfobj in pdfDataContext.PDFs 
                 where pdfobj.Id == pdfId 
                 select pdfobj).SingleOrDefault();
if (pdfNewWay != null)
{
  // do something
}

--

编辑:

抱歉没有表述清楚。我的问题是直接获取PDF对象,而不必先使用列表。我不想检查数量是否大于0,因为这看起来不好。


如果您能格式化您的代码示例,使其不需要滚动,那将非常有帮助,特别是当滚动内容非常关键时。我现在会进行编辑,但是如果您以后能够自己完成它,我们会很感激。 - Jon Skeet
抱歉。将来我一定会做的。 - radbyx
“安全地”是什么意思?第二种方法可能会抛出第一种方法不会抛出的异常。所以,安全是否意味着相同的功能性?还是意味着其他东西? - Rune FS
调用SingleOrDefault()方法时是否真的无法抛出NullPointException异常?因为我不知道答案,所以我采用了第一种(黑客?)解决方案。 - radbyx
1
在您的情况下,FirstOrDefault或SingleOrDefault是最好的选择。在其他情况下,如果您期望多个结果,请使用.Any()而不是Count > 0。计数比仅查看是否存在更昂贵。 - jessehouwing
4个回答

10

是的,看起来是安全的。你还可以稍微简化一下查询:

PDF pdfNewWay = pdfDataContext.PDFs.SingleOrDefault(p => p.Id == pdfId);
if (pdfNewWay != null)
{
  // do something
}
SingleOrDefault和FirstOrDefault之间唯一的区别就是,如果找到多个匹配项,SingleOrDefault会抛出异常,所以除非你需要进行这种检查,否则最好坚持使用FirstOrDefault。

如果没有找到元素,单个也会抛出异常。 - Bilal Fazlani
@Denis 不,那是真的。 SingleOrDefault 不会抛出异常,这可能是你想表达的意思? - user677526

6

在第二种情况下,您应该也使用FirstOrDefault,因为SingleOrDefault如果有多个项,则会引发异常。这对您来说可以吗?

另一方面,如果您想确保某个id只有一个pdfobject,则最好使用SingleOrDefault。


顺便提一下,如果是 LINQ-To-Entity,则不能使用 SingleOrDefault。 - Rune FS
这也是正确的,谢谢。我选择了另一个答案,因为它还帮助我简化了我的代码。 - radbyx

3

如果保证数据总是只有0或1行,那么使用SingleOrDefault是最好的解决方案。


1
我不知道我们的解决方案是否非常好。但是即使我可以保证最多只有一个实例,我们仍然使用SingleOrDefault()。这个参数的意义在于,如果有多个具有相同ID的实例,则会出现错误/异常,抛出异常是很好的,因为我会得到通知。 - radbyx
除此之外,我完全同意你的观点 - 谢谢。 - radbyx

0

是的,您将获得相同的结果,我没有看到任何问题。


请注意第一个示例中的FirstOrDefault和第二个示例中的SingleOrDefault之间的区别。 - Jon Skeet

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