在try & catch中使用return与在finally中使用return有何不同?

14

这两种方法哪一个更具风险?哪一个更好?还是说你可以将它们打印出来,然后随意选择一个?

我现在理解了finally是如何工作的,所以我想这样做:

try { 
    stuff that changes something... 
}
catch (System.Exception ex) { 
    something.worked = false; 
    something.err = ex.Message; 
}
finally { 
    stuff.close();
    return something; 
}

但是我看到过:

try { 
    stuff that changes something...
    return something; 
}
catch (System.Exception ex) { 
    something.worked = false; 
    something.err = ex.Message; 
    return something; 
}
finally { 
    stuff.close(); 
}

2
@Dlev - 除了第一个不是有效的C#代码,所以它不能实现。那么它怎么能更可取呢?这个问题真的应该再问一遍,其中任何代码都是有效的代码,否则它有点无意义。 - Security Hound
@Ramhound 抱歉,我的意思是前者不是合法的C#。后者在语法上实际上是有效的。 - dlev
3个回答

19

无法从finally中进行return。您将收到编译器错误:

控件不能离开 finally 子句的主体


如果目标类实现了IDisposable,那么我会这样做:

using (stuff s = new stuff())
{
    return stuff;
}
或者
using (stuff s = new stuff())
{
    try
    {
        // do stuff
        return stuff;
    }
    catch (Exception ex)
    {
        // do logging or another stuff
        return something;
    }
}

如果需要/可能的话,将为您调用Dispose()


糟糕!下次在询问之前先尝试编译,自己!控制流不能离开 finally 块是有道理的,因为 finally 块需要特别注意。 - ChuckNeuros
2
@user540903:嗯,是的,你应该编译它。但不要太自责了;有些语言中finally返回是合法的,这些语言由于此原因具有一些相当奇怪的控制流语义。总的来说,这是一个合理的问题,只是对于C#来说不适用。 - Eric Lippert
@Eric 我相当确定Java是其中一种语言。根据我记忆,最近的return会覆盖之前的任何返回值,所以try { throw new BlahException(); } catch { return 1; } finally { return 2; }实际上会向调用者返回一个2 - dlev
@dlev:没错。JavaScript 也允许从 finally 返回,具有相同的语义;最后一个返回值生效。 - Eric Lippert

17

就我个人而言,我两种都不会选,而是会使用


try { 
    stuff that changes something... 
}
catch (System.Exception ex) { 
    something.worked = false; 
    something.err = ex.Message; 
}
finally { 
    stuff.close();    
}
return something; 

finally 语句中,还要检查是否需要关闭/释放对象,因为如果它们失败了,可能从未被打开/设置。

此外,请参见这里:在 try catch finally 块中返回是否是不好的实践?


1
我同意这个观点,正如abatishchev所说,你不能在finally中使用return语句。我认为在catch块中也不应该使用return语句。如果你使用了try catch语句并且没有重新抛出异常,那么无论如何都会返回结果;如果你重新抛出异常,那么它永远不会返回结果。因此,你只需要一个return语句而不是两个。 - Ben Robinson
1
从try/catch/finally中返回不被视为“结构化编程”。我同意Tim和Ben的观点。 - Bahri Gungor

0

第二种方法没有风险。但是允许在异常情况下返回不同的值。


1
那么在try和catch块中返回一个变量并将其设置为不同的值,但只有一个返回位于整个try/catch块之外。 - Ben Robinson
返回变量的值也可以让你在异常情况下返回不同的值。 - Security Hound

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接