安全使用.FirstOrDefault()方法?

3
当使用Enumerable.FirstorDefault()时,我是否需要捕获可能抛出的ArgumentNullException异常,当操作的集合为null时?
过去,我总是像这样做:
WorkflowColorItemType associatedColor = ColorItems
    .Where(ci => ci.AssociatedState == WorkflowStateStatus.NotStarted)
    .FirstOrDefault();

if (associatedColor != null)
{
    this.ColorItems.CurrentColor = associatedColor;
}

在这段代码片段的情况下,我不认为ColorItems会是null,但是把每个类似这样的片段都放在try catch块中,以便处理ColorItems集合可能为null的情况,这是一个好习惯吗?

4
你可以直接在Where的位置上调用FirstOrDefault,两者是完全一样的。 - aybe
2
顺便说一句,我认为.FirstOrDefault()调用永远不会引起异常。它是.Where()在(可能)空值上操作的。 - Michael
我不会将它包装在try catch块中。你可以在运行查询之前始终检查集合是否等于null。 - Smeegs
3个回答

4
如果您不希望集合为空,并且集合为空将导致程序出错,那么请不要使用FirstOrDefault,而是使用First。因为您不期望出现这种情况,所以您需要引起注意,因为这表明出现了问题。
如果集合为空是完全有效的,并且只有在至少有一个项目时才想使用第一个项目,则使用FirstOrDefault并提供空检查即可。
对于集合为null和为空应用相同的逻辑。如果允许集合为null,则使用if进行检查。如果不允许集合为null(这通常是大多数集合的情况),则不应该检查,应该抛出异常以便发现和修复代码中的错误。试图捕获异常并继续执行会掩盖错误,从而防止您找到并修复它

1
这是不正确的,因为即使ColorItems可能永远不会为空,但在.FirstOrDefault()之前发生的.Where()可能导致一个空集合。 - Charles Boyung
@Servy - 他的假设是ColorItems永远不会为空(但可能仍然为空)。但即使他假设ColorItems永远不会为空,你也不能假设.Where永远不会为空,因为你正在限制.ColorItems在.Where中的结果。 - Charles Boyung
我邀请大家查看FirstOrDefault的文档。如果它查询的IEnumerable<T>为空,它抛出null异常。http://msdn.microsoft.com/en-us/library/bb340482(v=vs.110).aspx - Ryan Lundy
@Servy,我想不出任何这样的情况。你能吗?与大多数对象不同(例如默认的“顾客”会是什么样子?),对于集合来说有一个非常明显的默认情况:一个集合。期望集合时永远没有传递null的理由。如果您能想到一个合法的需求,我很想知道它是什么。 - Ryan Lundy
@Kyralessa 首先想到的是利用延迟初始化。如果它是null,那么意味着你需要去获取结果;如果它是空的,那么意味着你已经获取了结果,但没有任何内容。然后,提供延迟初始化抽象层的任何东西都不应该在外部公开null集合。 - Servy
显示剩余9条评论

1
是的,当然。你需要一直保持防御性。
事实上,如果 associatedColor 为 null,那么意味着出现了问题,因此你需要处理它。
事实上,您的代码曾经被包装在 try/catch 块中来处理异常,由于异常是“昂贵”的,这是处理异常情况的更便宜、更好的方法。
无论如何,我几乎总是使用 FirstOrDefault 或类似的东西,比如 SingleOrDefault,然后再进行 null 检查。

1
或者使用即将推出的C# 6的?.操作符 ;-) - Uwe Keim

0
内置的LINQ函数(如此处的.Where())如果没有结果,则始终返回一个空的可枚举对象,而不是null。因此,在执行.Where()之后无需检查null。
根据ColorItems的来源,您应该检查对象是否为null:
if (ColorItems != null) 
{
}
else
{
}

在代码周围放置try/catch块是没有必要的,但为了安全起见,您应该检查null。实际上,在像这样的情况下使用try/catch,其中您可以仅检查空对象,是一种不良的编程实践。


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