在采用无效代码路径时抛出哪个异常?

时间:2014-02-18 18:09:21

标签: c# exception

我发现自己编写了一些方法,其中存在一个永远不会发生的代码路径。这是一个简化的例子:

double Foo(double x) {
    int maxInput = 100000;
    double castMaxInput = (double)maxInput;
    if (x < 0 || x > castMaxInput || double.IsNaN(x)) {
        return double.NaN;
    }
    double r = 0;
    for (double boundary = 1; boundary<=castMaxInput; boundary++) {
        if (x <= boundary) {
            r += boundary * (x + 1 - boundary);
            return r;
        }
        else {
            r += boundary;
        }
    }

    // we should never get here.
    throw new SomeException();
}

这里最有意义的例外是

TheAuthorOfThisMethodScrewedUpException() 

因为如果我们到达for循环的末尾,那就是正在发生的事情。不幸的是,使用上面构造的方法,编译器似乎不够聪明,无法确定for循环之后的代码永远不会发生。所以你不能在那里什么也没有,或者编译器会抱怨“并非所有的代码路径都返回一个值”。是的,除了之前我还可以在循环之后输入return double.NaN。但这会掩盖问题的根源。

我的问题是 - 是否存在适当的例外情况?

4 个答案:

答案 0 :(得分:8)

我使用InvalidOperationException class。这意味着应用程序已达到不应该处于的状态。

throw new InvalidOperationException("Invalid state.");

你也可以Debug.Assert表示某事是真的,或者只是Debug.Fail当执行到达特定点时。

Debug.Fail("This should never happen!");

但是,只有在定义DEBUG条件时,调试断言/失败才能在发布模式下工作。取决于您的要求是否合乎需要。

作为@AlexD correctly points out,还有Trace class及其相应的AssertFail方法,它们将在运行时中运行,以帮助隔离和修复问题在定义TRACE条件时(默认情况下在“项目属性构建”选项卡中设置),不会干扰正在运行的系统


顺便说一句,要回答标题中的问题:如果需要,可以创建自己的例外。

[Serializable]
public class TheAuthorOfThisMethodScrewedUpException : InvalidOperationException
{
    private const string DefaultMessage = "The author of this method screwed up!";

    public TheAuthorOfThisMethodScrewedUpException()
        : this(DefaultMessage, null)
    { }

    public TheAuthorOfThisMethodScrewedUpException(Exception inner)
        : base(DefaultMessage, inner)
    { }

    public TheAuthorOfThisMethodScrewedUpException(string message)
        : this(message, null)
    { }

    public TheAuthorOfThisMethodScrewedUpException(string message, Exception inner)
        : base(message, inner)
    { }

    protected TheAuthorOfThisMethodScrewedUpException(
      System.Runtime.Serialization.SerializationInfo info,
      System.Runtime.Serialization.StreamingContext context)
        : base(info, context)
    { }
}

把它扔给别人。

throw new TheAuthorOfThisMethodScrewedUpException();

答案 1 :(得分:2)

不要抛出新的Exception(),它会导致代码尝试捕获异常时出现问题。您可以使用的通用特定异常是:

throw new InvalidOperationException("Appplication invariants violated");

这假设你希望在生产中发生错误,假设错误比发射导弹和结束世界更好。其他开发人员宁愿使用一种方法,假设在生产中可以忽略不变量,但在开发时不能忽略,如果我们结束这个世界,我们就不在乎。

答案 2 :(得分:1)

创建Custom Exception

看起来很容易
public class TheAuthorOfThisMethodScrewedUpException: Exception
{
    public EmployeeListNotFoundException()
    {
    }

    public EmployeeListNotFoundException(string message)
        : base(message)
    {
    }

    public EmployeeListNotFoundException(string message, Exception inner)
        : base(message, inner)
    {
    }
}

然后

throw new TheAuthorOfThisMethodScrewedUpException("I am so sorry, this should never happen call me for more info")

答案 3 :(得分:0)

轻松!使用代码段!

例外+ TAB + TAB

它会为你创造一个新的例外。这个片段产生了这个。

[Serializable]
    public class MyException : Exception
    {
        public MyException() { }
        public MyException(string message) : base(message) { }
        public MyException(string message, Exception inner) : base(message, inner) { }
        protected MyException(
          System.Runtime.Serialization.SerializationInfo info,
          System.Runtime.Serialization.StreamingContext context)
            : base(info, context) { }
    }

您只需要更改名称和..完成! ;)