C#多个空检查与分支单个空检查

时间:2018-04-11 08:18:59

标签: c#

我正在阅读框架代码(dotnet471rs3)并在Path(System.IO)中遇到了这段代码

public static String Combine(String path1, String path2, String path3, String path4) {
        if (path1 == null || path2 == null || path3 == null || path4 == null)
            throw new ArgumentNullException((path1 == null) ? "path1" : (path2 == null) ? "path2" : (path3 == null) ? "path3" : "path4");

这样做更好
if (path1 == null)
   throw new ArgumentNullException("path1");
else if (path2 == null)
   throw new ArgumentNullException("path2");

忽略这里使用的名称或缺少,但我的问题是为什么一个人完成了另一个?或者是因为它可能与性能等没有区别?我忽略了一些简单的东西吗?

1 个答案:

答案 0 :(得分:1)

效果

他们大多数等价。它们之间存在微小的差异,但它很小,以至于它可以被忽略用于所有实际目的。

例如,让我们看看如果path1为空,会发生什么:

原始

  • ||将立即解析为true,因此不再评估其他空检查(explanation)。
  • 然而,原作会再次在throw行执行相同的空检查。

您的版本

  • 无论如何都不会检查任何其他操作数,所以它显然只执行一次空检查,就像原始一样。
  • 它不需要在throw行执行相同的空检查,因为它知道path1为空(而不是原始的,它只知道其中一条路径为空,但它忘记了哪一个。)

由于您抛出异常并退出该方法,因此将忽略后续的if块。 如果您没有抛出异常而是记录消息然后继续使用该方法,则会有所不同

  • 原始版本不会检查剩余的path变量是否为null。它只会记录遇到的第一个空值。
  • 您的版本仍会执行所有其他检查,并会记录找到的每个空值的消息。

可读性

我更喜欢你的版本。它更清晰。它也打开了方法抽象的大门;你可以,例如将其重写为:

ThrowIfNull(path1);
ThrowIfNull(path2);
ThrowIfNull(path3);
ThrowIfNull(path4);

ThrowIfNull的实现似乎很简单,我已经省略了它)

摘要

  • 性能差异可以根据if体是否退出方法(在这种情况下你更快)或者不是(在这种情况下原始速度更快,因为它不是检查第二个空值)
  • 您的版本比原版更具可读性。
  • 执行一些额外的空检查所产生的性能成本并不超过此处的可读性参数;在我看来。为了便于阅读,我会选择你的版本。