为什么必须在catch块中的throw语句之前返回语句

时间:2013-09-26 10:21:24

标签: c# computer-science

以下代码会抱怨

try
{
    session.Save(obj);
    return true;
}
catch (Exception e)
{
    throw e;
    return false;  // this will be flagged as unreachable code
}

然而这不会:

try
{
    session.Save(obj);
    return true;
}
catch (Exception e)
{
    return false;
    throw e;
}

我不明白......我认为我的csc101告诉我,return语句应该始终是函数中的最后一个语句,并且它退出函数并将控制权返回给调用代码。为什么这会违背我教授的逻辑,为什么只有其中一个产生警告?

5 个答案:

答案 0 :(得分:13)

return将退出该方法; throw 退出该方法,假设它不在try内。它只能退出一次!

因此无论顺序如何 - throw / return中的第一个有效地结束了该方法。

作为更一般的反馈,但是:如果意图是在失败时返回false,那么您只需要:

try
{
    session.Save(obj);
    return true;
}
catch
{
    return false;
}

就我个人而言,我会说这是错误的代码 - 它隐藏了来自调用者的实际问题,使调试变得非常困难。它没有告诉我们为什么它失败了。我会说更好的方法就是让异常泡沫。在这种情况下,返回true是没有意义的,因为我们永远不会返回false - 并且只有重新抛出它才能捕获异常。所以整个方法变成:

session.Save(obj);

(没有其他任何要求)


如果您的问题是“为什么只有其中一个产生警告”:一个公平的问题,但编译器不是必需来发现 您。也许应该发现它。我怀疑 gmcs 发现这一点并发出警告 - 单声道编译器更愿意指出愚蠢。


编辑:正如所料,[g] mcs输出:

Program.cs(15,13): warning CS0162: Unreachable code detected
Program.cs(28,13): warning CS0162: Unreachable code detected

代码如下 - 所以它确实将两个用途都报告为警告:

class Program
{
    static void Main() { }
    static void DoSomething() { }
    bool ReturnFirst()
    {
        try
        {
            DoSomething();
            return true;
        }
        catch
        {
            return false;
            throw; // line 15
        }
    }
    bool ThrowFirst()
    {
        try
        {
            DoSomething();
            return true;
        }
        catch
        {
            throw;
            return false; // line 28
        }
    }
}

答案 1 :(得分:12)

您错了:两者您的示例都会引发 Dead code 编译器错误,因为throwreturn都标记了方法的出口点并且在此之后不允许进一步的代码。

但是,无论编译器是否允许,throwreturn下面的代码仍然无效,永远不会有机会执行。

(注意:这个问题最初标记为Java,我的第一句话与Java编译器语义有关)

答案 2 :(得分:1)

因为代码块中return语句之后的任何代码都无法访问。

答案 3 :(得分:0)

此答案基于C#,可能适用于或不适用于Java。

在这种情况下,您实际上不需要return语句。 throw将是该功能的最后一步。

在此示例中,returnthrow都将结束当前函数。无论你把它们放在哪个方向,然后首先总是阻止第二个可以到达。

注意throw语句何时结束该函数的例外情况是它是否包含在try块中。在这种情况下,throw函数将结束剩余的try块代码的执行,并移动到最相关的catch块 - 或finally块,如果{{1} }}不适用。

您的代码应如下所示:

catch

但是,如果您正在做的只是重新抛出异常,那么无论如何都没有太多的意义。


专门回答您唯一的问题:

  

为什么这会玷污我教授的逻辑?

你的教授是错的,还是你误解了他们

答案 4 :(得分:0)

“归来假”;由于“扔e”,在catch块中无法访问就在它之前。当代码在catch块中执行时,第一行是throw,这意味着你立即将异常抛出到调用方法,因此任何后续代码都不会被执行。

try
    {
        session.Save(obj);
        return true;
    }
    catch(Exception e)
    {
        throw e; //Throws exception to calling method
        return false;  //this will be flagged as unreachable code

    }

我希望这会有所帮助。