【问题标题】:What Exception to throw when a branch should in theory be impossible to reach?当理论上应该无法到达分支时抛出什么异常?
【发布时间】:2017-08-08 09:32:11
【问题描述】:

就像这个例子:

public MatchResult GetResult(int home, int away)
{
    if ( home == away )
        return MatchResult.Draw;
    else if ( home > away )
        return MatchResult.HomeWins;
    else if ( home < away )
        return MatchResult.AwayWins;

    throw new Exception("Should be impossible");
}

我知道我可以用else 作为最后一个语句来解决这个问题,但我通常更喜欢明确。当然,这是出于示例目的的简化情况。

旁边:是编译器抛出not all code paths return a value的原因,因为情况对编译器来说太复杂了或者因为其他原因(比如我们可以理论上改变@的值987654325@ 中途被来自不同线程的非托管代码或其他什么?)

【问题讨论】:

  • 我看不到编译器如何从您的代码中生成该错误,因为所有分支都有返回值或至少抛出异常。但是,您的第一个问题非常基于意见,因此将被关闭。无论如何:一个参数怎么可能既不相等,又不大于或小于另一个?您认为如何才能达到例外?
  • 话虽如此,ReSharper 等代码分析工具可能会将您的异常代码标记为无法访问,您应该将其删除。
  • ReSharper 也不会检测到这一点,只是对其进行了测试。
  • 情况其实并不算太复杂,但是编译器是故意保守的。即使是像int a = 1; if (a &gt; 0) return 0; 这样在方法中没有任何其他内容的微不足道的东西也会被标记,即使代码显然总是返回。确切的规则是documented
  • @LasseV.Karlsen 事实上,ReShaper 在我们只有if-statements 的事实上苦苦挣扎。从最后一个else 中删除if 将使其找到问题。

标签: c# exception compilation


【解决方案1】:

我知道我可以在最后一个语句中使用 else 来解决这个问题,但我通常更喜欢明确。

您可以在不告诉编译器的情况下保持显式。因为明确的唯一原因是为了帮助人类读者,所以用评论代替实际的 if 可以让您两全其美:程序员会看到条件,而编译器不会用不必要的 throws 或returns.

if ( home == away )
    return MatchResult.Draw;
else if ( home > away )
    return MatchResult.HomeWins;
else // if ( home < away )
    return MatchResult.AwayWins;

在你真正需要抛出异常的情况下,因为某些分支是不可能达到的,最好的做法是使用断言:

if (!CheckNonNegative(arg)) {
    throw new ArgumentException(nameof(arg));
}
...
if (arg == 0) {
    ... // Do something
} else {
    Debug.Assert(arg > 0, "Method has checked arg to be non-negative");
    ... // Do something else
}

【讨论】:

  • 当我们的编译器期望返回值时,最后一个示例是否仍然会抛出编译错误?
  • @DirkBoer 如果您询问是否可以使用断言代替throw,答案是“否”,因为断言在发布模式下处于关闭状态。
【解决方案2】:

我认为(如果要抛出异常 - 我宁愿更改代码)这应该抛出NotSupportedException。一般情况下,如果调用了一个方法,但是对象的当前状态不支持当时的方法调用,就会抛出这个异常。

可以说,如果逻辑法则已经失效,那么您将处于不受支持的状态并且无法完成该方法。

【讨论】:

    猜你喜欢
    • 2015-05-12
    • 1970-01-01
    • 1970-01-01
    • 2010-09-12
    • 1970-01-01
    • 2020-08-21
    • 2016-01-22
    • 1970-01-01
    • 2011-05-06
    相关资源
    最近更新 更多