【问题标题】:Whether to check for null是否检查null
【发布时间】:2011-01-31 10:37:07
【问题描述】:

我知道您应该始终检查传入参数的方法是否为 null。但是,如果我在这种情况下使用引用局部变量的 try/catch 怎么办。我真的需要在下面检查 null 吗?因为如果它为 null 并且下一行代码尝试使用refundResponse 变量,它无论如何都会捕获它:

    public string DoRefund(...)
    {
        try
        {
    ......
            string refundTransactionID = string.Empty;
    ......

            RefundTransactionResponseType refundResponse = transaction.DoRefund(...);

            if (refundResponse != null)
                refundTransactionID = refundResponse.RefundTransactionID;
    .....
        }
        catch (Exception ex)
        {
            LogError(ex);
            return ex.ToString();
        }
    }

请记住,我专门讨论的是局部变量并检查方法内部的变量,而不是方法的传入参数。

我在这里要问的是我是否需要在设置refundTransactionID 之前检查null 还是我只是设置它而不假设编译器将处理并抛出如果它为null 将被捕获并作为返回在这种情况下给调用者的字符串。

或者应该是

if (refundResponse == null)
                return null;

或者只是完全检查这个局部变量分配,然后因为在这种情况下我有一个 try/catch,我通过将异常作为字符串返回给调用者来自然地处理编译器拾取的任何异常(发回字符串不是我的决定,这是我老板的要求……所以暂时绕过那个辩论):

 refundTransactionID = refundResponse.RefundTransactionID;

最终,该方法后面的代码的其余部分取决于有效的refundTransactionID。

【问题讨论】:

  • 捕获所有异常并将响应作为字符串返回对我来说似乎很奇怪,而且通常可能不是很好的编程实践。在某些情况下,您想捕获所有错误 - 想到 Web 服务调度程序 - 但这样的业务逻辑似乎不适合。
  • 这是一种网络服务方法..
  • 返回字符串取决于 Web 服务的使用方式。你怎么能说不将错误作为字符串返回?那你会返回什么?除了错误消息之外,我没有看到任何有用的返回信息。

标签: c# error-handling


【解决方案1】:

例外是针对特殊情况。如果您可以检查持续性错误,请检查!

【讨论】:

  • 是的,但是如果我尝试使用refundResponse,如果由于某种原因它永远为空,编译器已经会抛出一个空异常。那么,当编译器无论如何都会抛出异常并且编译器的异常消息足够好时,为什么要在这种情况下抛出异常呢?这就是我正在争论的问题......也许我错了,但如果它为空并且我没有在那里检查它会如何下降...... try/catch 会捡起它。
  • 我只是在设置 transactionID 之前检查 null。这就是我要特别问的问题。我真的需要为局部变量执行此操作还是让编译器自然抛出异常如果当它到达尝试设置该事务 ID 的行时。
  • 那么什么是例外情况,null?
  • @coffeeaddict:有点,但取决于调用者和您的应用程序类型(例如库、Web 服务、本地类)。如果你认为它永远不会是null,那么检查是不值得的。 OTOH,如果您有可能传入 null 的未知呼叫者,您可能希望以更好的方式指出问题所在。它更多的是一种意见,而不是“法律”。此外,除了错误之外,null 可能还有其他含义。
【解决方案2】:

我知道你应该经常检查 传入参数到 null 的方法。

不,不一定。您应该指定的是您的方法的 contract。指定为 null 参数抛出 NullPointer/NullReferenceException 是完全可以接受的(并且很常见)。那么你就不需要任何检查了。

您也可以检查 null,但这只有在您实际上可以有效地处理 null 时才有意义(例如,替换默认值)。

【讨论】:

  • 尽管如此,当不应该是 null 的参数接收到 null 值时,在 .NET 上通常会抛出 ArgumentNullException
  • @sleske:通常最好在方法的开头抛出一个ArgumentNullException,其中包含有关为空参数的信息。如果您只是忽略错误输入并让您的代码在稍后的某个时间抛出NullReferenceException,那么您可能已经在此之前进行了几次内部调用。到那时,异常可能来自一些未记录的内部函数,并且参数名称可能与外部可见名称不同,因此对调用者没有直接意义。
  • 帕维尔,这不是论据。它是方法内的局部变量。
  • @Pavel,@Mark:谢谢你的信息,好点。我来自 Java,在那里抛出 NPE 很常见。 Jave 没有 ArgumentNullException(只是 IllegalArgumentException)。不过,这种区别很有趣。
  • @coffeeaddict,我在评论这个具体的答案(它谈论合同和参数),而不是在问题上。
【解决方案3】:

您应该在该实例中检查 null。您的应用程序逻辑应该能够处理这些情况,而无需异常。

【讨论】:

  • 好吧,在这种情况下,我正在上游处理它。尝试中发生的任何异常都将返回给调用者,在这种情况下,这是一个 Web 服务方法,我的老板出于某种原因只想返回一个字符串,上面写着“成功”或“失败”,这对我来说很糟糕实践。这就像在交易发生时返回一个真/假,这是错误的。
【解决方案4】:

测试的替代方法是Null Object pattern。 transaction::DoRefund() 方法没有返回 Null 或有效交易,而是返回一个 null 对象:一个提供与 RefundTransactionResponseType 实例相同的接口的对象,但它的方法什么也不做。这样就无需测试是否为 Null。

应该明智地使用,因为这很容易隐藏问题。

【讨论】:

  • 啊,我的一个朋友也推荐了这个。好的。但是如果你的老板说不呢?你不能使用那种模式。 ;)
  • 请记住,此 Web 服务方法也将从 .NET 以外的另一种语言调用......并不是说它会影响您对我的问题的响应。
【解决方案5】:

不,你不需要检查空值,那里。但是,这又引发了另一个问题,您真的需要检查传入参数中的 null 吗?

记住:这是一种行为。你必须测试这种行为。

【讨论】:

    【解决方案6】:

    但如果你不能在那个时候继续,让异常传播。

    【讨论】:

      【解决方案7】:

      不,看起来您不应该在此处检查 null。而且我也不会检查所有传入参数的 null (正如您的描述所暗示的那样)。

      您将 transactionID 作为字符串或异常消息返回也很奇怪。该方法的调用者如何知道是否发生了异常?

      如果你真的想记录异常,可以这样:

          public string DoRefund(...) 
          { 
              try 
              {
                  return transaction.DoRefund(...).RefundTransactionID; 
              } 
              catch (Exception ex) 
              { 
                  LogError(ex); 
                  throw ex;
              } 
          }
      

      【讨论】:

      • 我相信这会清除此堆栈跟踪。但也许会做一个 LogError(ex);扔;这将在堆栈中继续异常。
      • 好吧,我的老板是唯一的调用者,他的要求是让我的 Web 服务中的所有这些 Web 服务方法返回“成功”或“失败”。所以在这种情况下,他可以检查“已批准”,如果未批准,他会收到一条错误消息。
      • 好吧,我没有抛出我的捕获...是的,你是对的,但我将捕获的异常(如果假设响应变量为空)作为字符串返回给调用者...再次,这是将其作为字符串返回的要求。
      【解决方案8】:

      您应该检查 null 而不是让异常处理来处理它。正如 leppie 所说,异常是针对异常情况而不是正常的控制流。如果您知道可能会发生什么问题,那么您应该优雅地处理它们。

      要记住的另一件事是异常对性能的影响。当抛出异常时,JVM 必须展开调用堆栈。在您的示例中,异常也会被记录。所有这些都需要时间,而且比简单的“if”检查要慢得多。

      【讨论】:

        【解决方案9】:

        我建议检查 null 然后进行某种软错误处理,而不是让它捕获并抛出错误消息。

        【讨论】:

        • 好吧,在这种情况下,错误处理是在调用者端完成的。因为这是我的老板为他的管理系统使用的一种 Web 服务方法,这就是我被告知要做的,返回一个字符串。是的,我认为这很愚蠢。
        【解决方案10】:

        这取决于何时 (refundResponse == null) 对您的程序意味着什么。如果这有一些意义,那么报告更多信息的错误是有意义的。如果它永远不会发生并且表明 DoRefund 方法存在缺陷,那么我认为允许 null 稍后导致异常是可以的。在后一种情况下,如果您怀疑该方法以及它的行为是否符合预期,我只会进行具体检查。

        【讨论】:

          猜你喜欢
          • 2011-08-12
          • 2021-01-08
          • 1970-01-01
          • 1970-01-01
          • 2014-03-24
          • 2014-07-16
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多