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

下面的代码会抱怨

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语句应该始终是函数中的最后一个语句,它退出函数并将控制权返回给调用代码。 为什么这会违背我教授的逻辑,为什么只有其中一个产生警告?

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

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

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

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

就个人而言,我会说这是错误的代码 – 它隐藏了调用者的实际问题,使得调试非常困难。 它告诉我们它失败的原因 。 我会说更好的方法就是让exception泡沫化 。 在这种情况下,没有任何一点返回true ,因为我们永远不会返回false – 并且只是为了重新抛出它而没有必要捕获exception。 所以整个方法变成:

 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 } } } 

你错了:你的两个例子都引发了死代码编译错误,因为throwreturn标记了方法的出口点,并且在该点之外不允许进一步的代码。

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

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

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

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

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

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

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

您的代码应如下所示:

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

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


要专门回答您的唯一问题:

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

那么你的教授是错的,或者你误解了他们

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

 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 } 

我希望这有帮助。