LINQ Any()和Single()与SingleOrDefault()的空检查
本文关键字:检查 SingleOrDefault Single Any LINQ | 更新日期: 2023-09-27 18:06:47
在什么情况下每个解决方案都优于其他解决方案?
示例1:
if (personList.Any(x => x.Name == "Fox Mulder"))
{
this.Person = personList.Single(x => x.Name == "Fox Mulder");
}
示例2:
var mulder = personList.SingleOrDefault(x => x.Name == "Fox Mulder");
if (mulder != null)
{
this.Person = mulder;
}
Single
和SingleOrDefault
都将枚举超过第一个匹配结果的集合,以验证是否只有一个元素匹配标准,并在下一个匹配或集合结束时停止。第一个示例将稍微慢一些,因为Any
调用将枚举足够的集合(可能是全部)来确定是否有元素满足条件,在第一次匹配或集合结束时停止。
还有一个关键的区别:第一个例子可能会抛出异常。如果正好有一个, Single
将返回匹配的元素,否则抛出异常。使用Any
检查并不能验证这一点;它只验证至少有一个。
SingleOrDefault
方法在这里更可取。
这里有三种情况
情形1:没有项符合条件
选项1:.Any
枚举整个集合并返回false;.Single
从未执行过。
选项2:.SingleOrDefault
枚举整个集合并返回null。
选项本质上是等价的。
案例2:恰好有一项匹配条件
选项1:Any
枚举足够的集合以找到单个匹配(可以是第一项,也可以是整个集合)。接下来,Single
枚举整个集合以查找该项目,并确认没有其他项目符合条件。
选项2:SingleOrDefault
枚举整个集合,返回唯一匹配的。
在这种情况下,选项2更好(正好是一次迭代,与(1,2]迭代相比)
案例3:多个元素符合条件
选项1:Any
枚举足够的值来找到第一个匹配。Single
枚举了足够的数目来找到第二个匹配项,抛出异常。
选项2:SingleOrDefault
枚举足够的值来找到第二个匹配,抛出异常。
都抛出异常,但选项2更快到达。
选项3:
this.Person = personList.FirstOrDefault(x => x.Name == "Fox Mulder");
如果使用实体框架并且name是主键,则:
this.person = db.personList.Find("Fox Mulder");
如果this.Person
是空的,或者如果没有找到这个人,你希望this.Person
被空覆盖。FirstOrDefault是最快的,因为它会在匹配的第一条记录处停止,而不是遍历整个集合,但是如果找到多条记录,它不会抛出异常。在这种情况下,实体框架解决方案甚至更好,因为Find将使用EF缓存,甚至可能根本不必访问数据源。
从is
和as
准则推断:
见下面,从使用'as'CLR中的关键字:
// Bad code - checks type twice for no reason
if (randomObject is TargetType)
{
TargetType foo = (TargetType) randomObject;
// Do something with foo
}
通过使用Any
和Single
,您也检查了两次列表。同样的逻辑似乎也适用:Not only is this checking twice, but it may be checking different things,
即,在多线程应用程序中,检查和赋值之间的列表可能不同。在极端情况下,当调用Single
时,与Any
一起发现的项目可能不再存在。
使用这个逻辑,除非给出相反的证据,否则我将在所有情况下都倾向于例子2。