簡體   English   中英

為什么我的 finally 塊在 C# 中不起作用?

[英]Why is my finally block not working in 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 在返回之前執行。

重復: 在 try { return x; 中真正發生了什么 } 最后 { x = null; } 陳述?

您的“最終”塊正在為 returnValue 分配一個值,而不是實際返回一個值。 “返回”在 finally 塊更改值之前已經發生,因此返回“abc”。

雖然代碼令人困惑,因為您所做的沒有意義,但它所做的卻是正確的。

finally塊在return語句之后有效地運行。 因此,您已經將 go 之前的abc的舊值返回到 finally 塊中。

(這並不完全是引擎蓋下的工作方式,但對於這里的觀點來說已經足夠接近了)

是的,finally 塊在 function 返回后運行,但這並不重要。 請記住,返回值是按值傳遞的,因此在返回時會為其創建一個新的臨時變量,因此 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 塊將始終覆蓋返回值,這是一個有問題的設計。

前段時間找到了這個鏈接來處理這個問題。 他不厭其煩地展示了 IL 代碼,該代碼確切地說明了正在發生的事情。

我不是專家,但我不得不猜測這個 function 返回,然后最終調用。 由於return returnValue已經被執行,所以 returnValue 在 finally 塊中取什么值並不重要。 這種行為是有道理的,因為應該在 finally 塊之前執行整個 try 塊,並且它可以做到這一點的唯一方法是如果它像它應該的那樣從 function 返回。

如果你真的很好奇發生了什么,那么你可以下載並安裝Reflector 這是一個很棒的工具,可以放入您的“包 o 技巧”。 它會告訴你引擎蓋下發生了什么。

猜測一下,我會說您正在確定在 return 語句所在的位置將返回什么(對字符串“abc”的引用)。

因此,finally 稍后將該引用設置為引用不同的字符串這一事實對返回值沒有影響。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM