14

下面的代码会抱怨

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

4

5 回答 5

18

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

所以不管顺序如何——第一个 throw/return有效结束方法。

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

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

就个人而言,我会说这是一个糟糕的代码——它对调用者隐藏了实际问题,使得调试变得非常困难。它没有告诉我们失败的原因。我想说更好的方法就是让异常冒泡。在这种情况下,没有必要返回true,因为我们永远不会返回false- 捕获异常只是为了重新抛出它是没有意义的。于是整个方法就变成了:

session.Save(obj);

(没有其他要求)


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


编辑:正如预期的那样,[g]mcs 输出:

Program.cs(15,13):警告 CS0162:检测到无法访问的代码

Program.cs(28,13):警告 CS0162:检测到无法访问的代码

对于下面的代码 - 所以它确实将两种用途都报告为警告:

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
        }
    }
}
于 2013-09-26T10:36:23.487 回答
12

您错了:您的两个示例都引发了死代码编译器错误,因为两者都throw标记return了方法的退出点,并且不允许超出该点的其他代码。

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

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

于 2013-09-26T10:24:55.000 回答
1

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

于 2013-09-26T10:24:48.923 回答
0

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

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

在本例中,returnthrow都将结束当前函数。无论您以哪种方式放置它们,第一个总是会阻止第二个被访问。

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

您的代码应如下所示:

try
{
    session.Save(obj);

    return true;
}
catch(Exception e)
{
    throw e;
}

但是,如果您所做的只是重新抛出异常,那么无论如何使用 try/catch 并没有多大意义。


要具体回答您唯一的问题:

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

好吧,要么你的教授错了,要么你误解了他们

于 2013-09-26T10:24:49.450 回答
0

“返回错误;” 由于“throw 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

    }

我希望这有帮助。

于 2013-09-26T10:32:31.677 回答