[英]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 在返回之前執行。
您的“最終”塊正在為 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.