2013-04-16 49 views
5

假設您在try塊中擁有一個使用return語句的C#方法。是否可以修改finally塊中的返回值?是否有可能在C#中的finally子句中更改返回值?

最明顯的方法,在finally塊使用return,將無法正常工作:

String Foo() 
{ 
    try 
    { 
     return "A"; 
    } 
    finally 
    { 
     // Does not compile: "Control cannot leave the body of a finally clause" 
     return "B"; 
    } 
} 

有趣的是,這可以可以在VB中完成:ReturnFinally是被禁止的,但我們可以濫用事實上(可能出於向後兼容的原因)VB仍允許通過將返回值分配給方法名稱來修改返回值:

Function Foo() As String ' Returns "B", really! 
    Try 
     Return "A" 
    Finally 
     Foo = "B" 
    End Try 
End Function 

注:

  1. 注意,我問這個問題純粹出來的科學的好奇心;顯然,這樣的代碼非常容易出錯並且令人困惑,而且絕不應該被寫入。

  2. 請注意,我是而不是詢問約try { var x = "A"; return x; } finally { x = "B"; }。我知道這不會改變返回值和I understand why this happens。我想知道是否有通過finally塊更改try塊內設置的返回值的方法。

+7

停止濫用VB.NET - 它已經被濫用了! – Oded

+1

僅僅因爲你*可以*在VB中這樣做並不意味着你*應該*! –

+2

停止使用VB.NET - 它已經夠用了! – PhonicUK

回答

18

假設你有一個try塊內return語句一個C#方法。是否有可能修改finally塊中的返回值?

但是,您可以修改外的返回值finally塊

static int M() 
{ 
    try 
    { 
     try 
     { 
      return 123; 
     } 
     finally 
     { 
      throw new Exception(); 
     } 
    } 
    catch 
    { 
     return 456; 
    } 
} 

只是因爲這裏原是一個「返回123」並不意味着該方法將返回123,如果這是你的問題實際上得到的。該方法返回456

+1

非常有趣。看起來唯一的豁免規則是在'finally'塊內引發異常。 –

+4

@BradM:你說的沒錯。更一般地說:'finally'塊中只有三種可能的控制流:(1)永不離開,(2)正常離開,或者(3)通過拋出的異常離開。其他控制流如'return','goto','break','continue','yield return','yield break'和'await'在finally塊中是不合法的,或者只有跳轉到*在finally塊中的位置*。 –

-1

你可以做以下的接近同樣的效果:

private string myFunction() 
{ 
    string result = String.Empty; 
    try 
    { 
     //.. 
     result = "something"; 
    } 
    finally 
    { 
     result = "something else"; 
    } 
    return result; 
} 
+5

再次閱讀問題。問題開始「假設你在try塊中有return語句」。你的try塊中的return語句在哪裏? –

+1

再次閱讀我的答案..「接近同一效果」..這是一個替代方案,而不是一個解決方案,因爲這是不可能的。沒有理由投下來.. – Yami

-1

與引用VB的做法很相似會被分配修正值由return使用的變量(其中有節約控制的回報)的單點好處:

string returnResult; 

try 
{ 
    returnResult = "A"; 
} 
finally 
{ 
    returnResult = "B"; 
} 

return returnResult; 
+1

再次閱讀問題。問題開始「假設你在try塊中有return語句」。你的try塊中的return語句在哪裏? –

+0

在告訴用戶「不要這樣做,像這樣做,而不是這樣做」的SO上沒有任何錯誤 - 只要給他們回答他們的問題並不總是正確的做法,如果他們試圖做錯了。 – PhonicUK

+6

問題的最後一段表示原始海報意識到這是不好的風格。 –

0

的VB.NET版本濫用從VB6時代殘留結構中,您可以通過值分配給函數的名稱返回一個值。

什麼是真正有趣知道的是,如果在IL使用標準return語句時,而不是myFunc = "B",作爲try...catch...finally語義似乎決定了它不可能改變返回值產生差異通過return聲明。

+1

'MyFunc =「B」'不會返回,因此IL不會相同 –

相關問題