何时检查空值?

3

当你知道像下面的例子中 id 应该存在时,检查 null 值是一个好习惯吗?

var submission = _ctx.Submissions.FirstOrDefault(p => p.Id == id);

submission.Done = true;
_ctx.Submissions.Attach(submission);
_ctx.Entry(submission).State = EntityState.Modified;
_ctx.SaveChanges();

4
几乎每次使用 FirstOrDefault() 时,您都应该立即检查是否为 null。 - Erik Philips
有没有不检查 null 的理由?如果 submission 是 null,你还能做些有用的事情吗? - Matt Burland
“Attach”和更改“State”是多余的,从“DbSet<T>”返回的对象由更改跟踪器跟踪。 - Yuliam Chandra
每当你处理引用类型并且抛出NullReferenceException是不可接受的时候,你都应该检查是否为null。 - Preston Guillot
@PrestonGuillot - 如果系统处于意外状态,让任何类型的异常被抛出是完全可以的。正如OP所说 - 这段特定的代码从未期望返回 null - 因此无需检查是否可以让整个请求失败。(我认为在我的答案中,FirstOeDefault不是一个好方法选择)。 - Alexei Levenkov
@AlexeiLevenkov 我并不是在说永远不可以抛出空引用异常,而是明确的空值检查的目的是为了避免这种情况的发生。 - Preston Guillot
6个回答

4
如果假定id存在,您不需要检查null。事实上,在这种情况下,您应该像这样查询:
_ctx.Submissions.Single(p => p.Id == id);

Single方法在未找到项时会引发异常。另一方面,如果您正在构建WebAPI或具有特定的未找到页面,因为id由客户端发送(即可能由代码之外的某些东西导致),则可以使用SingleOrDefault,然后检查null并返回适当的HTTP状态代码或重定向到适当的页面。基本上,如果未验证数据导致null结果,则应进行检查并相应地响应。如果导致null值的参数是由代码生成的,则不应检查null,实际上应以可能不会导致null的方式查询,否则您只是掩盖了代码中的错误。
这是我的意见,是我个人经验的结果。请注意,并非每个人都同意,正如我不久前在programmers.stackexchange.com上发布的问题的不同答案所表明的那样:https://softwareengineering.stackexchange.com/questions/147480/should-one-check-for-null-if-he-does-not-expect-null

3

当你无法完全确定对象永远不会为空时,你需要检查null

话虽如此,你现在使用的是FirstOrDefault()。如果它没有符合条件的结果,它将返回null


唯一id不存在的情况是因为有人已经进入数据库并物理删除了它(可以说是孤立记录)。作为开发者,我需要考虑数据库中的“错误更新”吗? - DrZeuso
@DrZeuso 你需要考虑到可能发生的事情,这些事情可能会导致程序崩溃。如果你知道 id 可能为空,那么你应该进行处理。你不希望出现程序崩溃的情况。这有点涉及到“基于观点”的领域,因为有些人会想要在 try/catch 中使用自定义异常来处理,或者检查 null 并添加额外的业务逻辑代码。 - TyCobb
如果在生产环境中数据很好,但是由于我们目前在开发环境中有垃圾数据(不应该为空的空字段等),这使得我的代码在开发环境中崩溃。我应该在开发环境中修复数据,使其不为空,以便我的程序可以正确运行?还是在我的程序中检查空值? - DrZeuso
@DrZeuso 我认为没有理由不处理已知的错误。如果你愿意使用顶层的 try/catch 来捕获它们,只要它以你想要的方式处理错误,那么就没有需要改变的了。 - TyCobb

2
如果您认为应该始终有一个对象,而问题中不存在对象意味着程序存在错误,那么您应该使用First而不是FirstOrDefault。这样做意味着如果代码的某个假设被违反,您将尽快,响亮和尽可能地了解到问题的源头。 FirstOrDefault应该用于查询没有任何项时完全合理,并返回null值的情况。如果您处于这种情况,则在查询实际返回null或其他任何您需要执行的操作的情况下,程序应该正确运行。
您要避免的是把自己置于程序(错误地)假定查询始终至少有一项的位置,但无论如何都使用FirstOrDeafult。在这里,您最终会得到真正问题在哪里(具有应该有项目的项的查询)。并且还会出现NullReferenceExceptions,这可能需要额外的调试工作来解决。

1

为了编写具有弹性的代码,您应该检查并处理是否submission为null。


0

你需要检查 null 值,以防止由于传递 null 值而引发的错误。你可以使用 try catch 块或 if else 块来进行检查。

通过这种方式进行检查,你可以预防可能由 null 值引发的错误。


0

FirstOrDefault 将你的意图记录为“我期望的结果可能不包含任何项”。在这种情况下,你应该检查 null 并执行一些合理的回退操作。此时抛出异常看起来很奇怪。

听起来在你的情况中,你并不期望空结果,因此使用 First 并将异常处理放在更高的调用栈上,甚至让默认异常处理发生。


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