LINQ:何时使用SingleOrDefault与FirstOrDefault()以及过滤标准
考虑IEnumerable扩展方法SingleOrDefault()
和FirstOrDefault()
MSDN文档SingleOrDefault
:
返回序列的唯一元素,如果序列为空,则返回默认值; 如果序列中有多个元素,则此方法会引发异常。
而来自MSDN的FirstOrDefault
(大概在使用OrderBy()
或OrderByDescending()
或根本不使用时),
返回序列的第一个元素
考虑一些示例查询,使用这两种方法时并不总是很清楚:
var someCust = db.Customers
.SingleOrDefault(c=>c.ID == 5); //unlikely(?) to be more than one, but technically COULD BE
var bobbyCust = db.Customers
.FirstOrDefault(c=>c.FirstName == "Bobby"); //clearly could be one or many, so use First?
var latestCust = db.Customers
.OrderByDescending(x=> x.CreatedOn)
.FirstOrDefault();//Single or First, or does it matter?
题
在您的LINQ查询中决定使用SingleOrDefault()
和FirstOrDefault()
时, 您遵循或建议了哪些约定 ?
无论何时使用SingleOrDefault
,都明确指出查询最多SingleOrDefault
得到一个结果。 另一方面,当使用FirstOrDefault
时,查询可以返回任意数量的结果,但是您声明您只需要第一个结果。
我个人发现语义非常不同,并根据预期的结果使用适当的语义,提高了可读性。
如果结果集返回0个记录:
SingleOrDefault
返回类型的默认值(例如,默认值为int) FirstOrDefault
返回该类型的默认值 如果结果集返回1记录:
SingleOrDefault
返回该记录 FirstOrDefault
返回该记录 如果结果集返回许多记录:
SingleOrDefault
引发异常 FirstOrDefault
返回第一条记录 结论:
如果要在结果集包含许多记录时抛出异常,请使用SingleOrDefault
。
如果您始终需要1条记录,而不管结果集包含什么内容,请使用FirstOrDefault
有
两者之间。
语义差异:
FirstOrDefault
返回可能为多个的第一项(如果不存在,则返回默认值)。 SingleOrDefault
假设有一个项目并返回它(或者如果不存在则返回默认值)。 多个项目违反合同,会引发异常。 性能差异
FirstOrDefault
通常更快,它会迭代直到找到元素,并且只有当它找不到时才迭代整个枚举。 在很多情况下,找到一件物品的可能性很大。
SingleOrDefault
需要检查是否只有一个元素,因此总是迭代整个枚举。 确切地说,它迭代直到找到第二个元素并引发异常。 但在大多数情况下,没有第二个因素。
结论
如果您不在意有多少物品或无法检查唯一性(例如,在一个非常大的集合中),请使用FirstOrDefault
。 当您在将项目添加到集合时检查唯一性时,在搜索这些项目时再次检查它可能太昂贵。
如果您不必关心性能太多,并希望确保单个项目的假设对读者是清楚的并在运行时进行检查,则使用SingleOrDefault
。
在实践中,即使在您假定单个项目的情况下,您也经常使用First
/ FirstOrDefault
来提高性能。 您应该还记得Single
/ SingleOrDefault
可以提高可读性(因为它表示单个项目的假设)和稳定性(因为它会检查它)并适当地使用它。
上一篇: LINQ: When to use SingleOrDefault vs. FirstOrDefault() with filtering criteria