为什么我的finally 块在C# 中不起作用?

发布于 2024-07-16 11:17:16 字数 803 浏览 8 评论 0原文

我一直在帮助一位同事调试他们代码中的一些奇怪行为。 以下示例说明了这一点:

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 会在返回之前执行。

重复: try { return x; 中到底发生了什么? } 最后 { x = null; } 声明?

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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

风向决定发型 2024-07-23 11:17:17

finally 块在 return 语句之后有效地运行。 因此,在进入 finally 块之前,您已经返回了 abc 的旧值。

(这并不完全是在幕后工作的,但对于这里的要点来说已经足够接近了)

The finally block effectively runs after the return statement. So you've already returned the old value of abc 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)

夜司空 2024-07-23 11:17:17

我不是专家,但我不得不猜测这个函数返回,然后然后调用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.

一身骄傲 2024-07-23 11:17:17

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.

醉生梦死 2024-07-23 11:17:17

我猜测您正在确定在 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.

箜明 2024-07-23 11:17:16

您的“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.

命硬 2024-07-23 11:17:16

是的,finally 块在函数返回后运行,但这并不重要。 请记住,返回值是按值传递的,因此在返回时会为其创建一个新的临时变量,因此finally 块不会影响实际的返回值。 如果您想支持所需的行为,您可以使用 out 参数,如下所示:

static void Main(string[] args)
{
    string answer;
    Sample(out answer);
    Console.WriteLine(answer);
}

public static void Sample(out string answer)
{

    try
    {
        answer = "abc";
        return;
    }

    catch (Exception)
    {
        throw;
    }

    finally
    {
        answer = "def";
    }
}

或者,您可以简单地将 return 语句移到 try 块之外,如下所示:

static void Main(string[] args)
{
    string answer = Sample();
    Console.WriteLine(answer);
}

public static string Sample()
{
    string returnValue;
    try
    {
        returnValue = "abc";
    }

    catch (Exception)
    {
        throw;
    }

    finally
    {
        returnValue = "def";
    }

    return returnValue;
}

但是,考虑到 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:

static void Main(string[] args)
{
    string answer;
    Sample(out answer);
    Console.WriteLine(answer);
}

public static void Sample(out string answer)
{

    try
    {
        answer = "abc";
        return;
    }

    catch (Exception)
    {
        throw;
    }

    finally
    {
        answer = "def";
    }
}

Or, you could simply move the return statement outside of the try block, like so:

static void Main(string[] args)
{
    string answer = Sample();
    Console.WriteLine(answer);
}

public static string Sample()
{
    string returnValue;
    try
    {
        returnValue = "abc";
    }

    catch (Exception)
    {
        throw;
    }

    finally
    {
        returnValue = "def";
    }

    return returnValue;
}

However, given that the finally block will always override the return value, this is a questionable design.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文