【问题标题】:Exceptions vs "if" in C#C# 中的异常与“如果”
【发布时间】:2011-01-23 11:51:45
【问题描述】:

我有一个控制流问题。在我的公司中,我们创建了很多 bool 方法,如果出现错误,它们会返回 false。示例:

public bool Foo(string path, string fileName, ref string error)
{
    if (path == null)
    {
        error = "path is null";
        return false;
    }
    path += fileName;
    return true;
}

如您所见,它很丑陋。我想用它来处理这样的异常:

public voidFoo(string path, string fileName, ref string error)
{
    if (path == null)
    {
        throw new SomeException("Path is null.");
    }
    path += fileName;
    return true;
}

但我们担心开销。我们应该吗?

【问题讨论】:

  • 您真正想要的是删除第二个示例中丑陋的error 参数。
  • 伙计们,我们真的需要这么多相同的答案吗?
  • 如果在调用voidFoo 之前确保path 不是null,则开销为零。

标签: c# exception exception-handling


【解决方案1】:

如果抛出异常,那么try...catch 的开销可以忽略不计。所以,经验法则是:

  • 如果异常可能被抛出(即,如果path == null 是“支持”的场景),则使用返回值。
  • 如果异常不太可能,即如果path == null 通常仅在使用您的函数的开发人员出错时发生,则使用异常。

【讨论】:

    【解决方案2】:

    您不应该将异常用作流控制的一种形式。

    一般来说,抛出异常比检查失败值要昂贵得多 - 在这种情况下,如果 path 永远不应该为 false 并且应该始终存在,则空 path 是一种异常情况和异常应该被抛出。

    在方法设计方面 - 您不应该依赖调用方法来检查返回值。如果有人忘记检查,如果返回false 会发生什么?一个例外使这个问题消失了,因为显然发生了一些不好的事情并且您的代码停止运行。

    【讨论】:

    • 你的意思是:永远不应该将异常用作常规流控制的一种形式。
    【解决方案3】:

    应为异常情况保留异常,例如资源不可用。磁盘空间或网络连接。

    使用异常来控制流是完全错误的,它闻起来不对。

    使用布尔返回码是一种方法。您还可以创建一个描述错误原因的错误对象,而不是通过引用返回。

    【讨论】:

      【解决方案4】:

      这种情况有多异常?抛出和捕获异常会产生您在一般使用中可能不愿意承担的开销。

      从风格上讲,出于性能和理解方面的原因,使用异常进行流控制是不受欢迎的。如果这是(不是双关语)异常事件,我会使用异常。如果性能是关键(并且您应该衡量这一点 - premature optimisation being the root of all evil 等),那么更优化的解决方案是使用返回值。

      这种情况令人头疼的是,可能会忽略或滥用返回值(通常是falsenull)。

      【讨论】:

        【解决方案5】:

        所有书籍都说您应该使用异常来指示错误。如果你使用 if's,那么 50% 的源代码行是关于返回错误消息的,并且很难阅读源代码并查看它是否没有错误。

        仅在您预计会发生许多错误且计算时间对您非常重要的时间紧迫的场景中使用返回值。

        【讨论】:

          【解决方案6】:

          我喜欢例外。我只是做。当然,这取决于您在哪里实施。

          例如,我希望有一些非常基本的类来抛出异常,因为我不希望这些类承担不抛出它的责任。

          C# 的好处是您不必捕获每个异常,因为如果出错它只会进一步抛出异常。因此,这将为您节省大量代码。否则,布尔值将是:if false -> return false; if false -> return false;。我认为会是开销。

          当然,在某些时候,您必须捕获您的异常,但这由实施者选择在哪里进行。你当然不想要一些巨大的捕捉块,但只有在你想捕捉它的地方,你应该捕捉它。

          我会去的。

          【讨论】:

            【解决方案7】:

            这取决于您认为“假”状态是否异常。或者换句话说,通常不会预期。

            例如,如果您将一个对象传递给一个没有任何意义的方法,如果该方法为 null 以使其工作,那么您可能应该抛出 ArgumentNullException:

            public void Foo(object obj)
            {
                if(obj == null) throw new ArgumentNullException("obj", "Object cannot be null.");
            
                //
            }
            

            【讨论】:

              猜你喜欢
              • 2012-06-17
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多