为什么我的finally 块在C# 中不起作用?
我一直在帮助一位同事调试他们代码中的一些奇怪行为。 以下示例说明了这一点:
static void Main(string[] args)
{
string answer = Sample();
Console.WriteLine(answer);
}
public static string Sample()
{
string returnValue = "abc";
try
{
return returnValue;
}
catch (Exception)
{
throw;
}
finally
{
returnValue = "def";
}
}
该示例返回什么?
您可能认为由于finally块,它返回“def”,但实际上,它返回“abc”? 我已单步执行代码并确认finally 块确实被调用。
真正的答案是,您首先不应该编写这样的代码,但我仍然对其行为感到困惑。
编辑:根据一些答案澄清流程。
当您单步执行代码时,finally 会在返回之前执行。
I've been helping a colleague debug some strange behavior in their code. The following sample illustrates this:
static void Main(string[] args)
{
string answer = Sample();
Console.WriteLine(answer);
}
public static string Sample()
{
string returnValue = "abc";
try
{
return returnValue;
}
catch (Exception)
{
throw;
}
finally
{
returnValue = "def";
}
}
What does this sample return?
You'd think that because of the finally block, it returns "def" but in fact, it returns "abc"? I've stepped through the code and confirmed that the finally block is in fact invoked.
The real answer is that you shouldn't write code like this in the first place but I'm still puzzled as to the behaviour.
Edit: To clarify the flow based on some of the answers.
When you step through the code, the finally is executed before the return.
Duplicate of: What really happens in a try { return x; } finally { x = null; } statement?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
finally
块在return
语句之后有效地运行。 因此,在进入 finally 块之前,您已经返回了abc
的旧值。(这并不完全是在幕后工作的,但对于这里的要点来说已经足够接近了)
The
finally
block effectively runs after thereturn
statement. So you've already returned the old value ofabc
before you go into your finally block.(this isn't exactly how works under the hood, but it's close enough for the point here)
我不是专家,但我不得不猜测这个函数返回,然后然后调用finally。 由于
return returnValue
已经被执行,因此 returnValue 在finally 块中取什么值并不重要。 这种行为是有道理的,因为它应该在finally块之前执行整个try块,而它能做到这一点的唯一方法就是它像它应该的那样从函数返回。I'm no expert, but I would have to guess that this function returns, and then invokes finally. Since
return returnValue
has already been executed, it doesn't really matter what value returnValue takes on in the finally block. This behaviour kind of makes sense, because it is supposed to execute the entire try block before the finally block, and the only way it can do that is if it returns from the function like its supposed to.如果您真的很好奇发生了什么,那么您可以下载并安装 Reflector< /a>. 这是一个很棒的工具,可以放入你的“技巧袋”中。 它会告诉您引擎盖下面发生了什么。
If you're really curious as to what is going on, then you can download and install Reflector. It's a fantastic tool to put into your 'bag o tricks'. It will tell you what is going on underneath the hood.
我猜测您正在确定在 return 语句所在的位置将返回什么(对字符串“abc”的引用)。
因此,finally 稍后将该引用设置为引用不同的字符串这一事实对返回值没有影响。
At a guess I'd say that you are determining what will be returned (a reference to the string "abc") at the point where the return statement is.
So the fact that the finally later sets that reference to refer to a different string has no effect on the returned value.
您的“finally”块正在为 returnValue 分配一个值,而不是实际返回一个值。 在finally 块更改值之前“返回”已经发生,因此返回“abc”。
虽然代码令人困惑,因为您所做的事情没有意义,但它所做的事情是正确的。
Your "finally" block is assigning a value to returnValue and not actually returning a value. The "return" has already occurred before the finally block changes the value and therefore "abc" is returned.
Whilst the code is confusing as what you've done doesn't make sense, what it's doing is correct.
是的,finally 块在函数返回后运行,但这并不重要。 请记住,返回值是按值传递的,因此在返回时会为其创建一个新的临时变量,因此finally 块不会影响实际的返回值。 如果您想支持所需的行为,您可以使用 out 参数,如下所示:
或者,您可以简单地将 return 语句移到 try 块之外,如下所示:
但是,考虑到 finally 块将始终覆盖返回值,这是一个有问题的设计。
Yes, the finally block runs after the function returns, but this doesn't matter. Remember that the return value is passed by value, so a new temporary variable is created for it at return time, thus the finally block does nothing to affect the actual return value. If you want to support the desired behavior you could use an out parameter, like so:
Or, you could simply move the return statement outside of the try block, like so:
However, given that the finally block will always override the return value, this is a questionable design.