2013-04-16 25 views
5

Giả sử rằng bạn có phương thức C# với câu lệnh return bên trong khối try. Có thể sửa đổi giá trị trả lại trong khối finally không?Có thể thay đổi giá trị trả về trong một mệnh đề cuối cùng trong C# không?

Cách tiếp cận rõ ràng, sử dụng return trong khối finally, sẽ không làm việc:

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

Điều thú vị là, này có thể được thực hiện trong VB: Return bên Finally bị cấm, nhưng chúng ta có thể lạm dụng thực tế là (có lẽ vì lý do tương thích ngược) VB vẫn cho phép giá trị trả về được sửa đổi bằng cách gán nó cho tên phương thức:

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

Ghi chú:

  1. Lưu ý rằng tôi hỏi câu hỏi này thuần túy vì tò mò khoa học; Rõ ràng, mã như vậy là rất dễ bị lỗi và khó hiểu và không bao giờ nên được viết.

  2. Lưu ý rằng tôi là không phải hỏi về try { var x = "A"; return x; } finally { x = "B"; }. Tôi biết rằng điều này không thay đổi giá trị trả về và I understand why this happens. Tôi muốn biết nếu có các cách để thay đổi giá trị trả lại được đặt bên trong khối thử bằng phương tiện của một khối cuối cùng.

+7

Ngừng lạm dụng VB.NET - đã bị lạm dụng đủ rồi! – Oded

+1

Chỉ vì bạn * có thể * làm điều này trong VB không có nghĩa là bạn * nên *! –

+2

Ngừng sử dụng VB.NET - nó đã sử dụng đủ rồi! – PhonicUK

Trả lời

18

Giả sử bạn có phương thức C# với câu lệnh trả về trong khối thử. Có thể sửa đổi giá trị trả về trong khối cuối cùng không?

số

Bạn tuy nhiên có thể thay đổi giá trị trả về ngoài khối finally:

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

Chỉ vì đã có ban đầu là một "return 123" không có nghĩa là phương pháp sẽ trả lại 123, nếu đó là những gì câu hỏi của bạn thực sự nhận được. Phương pháp này trả về 456.

+1

Rất thú vị. Nó xuất hiện quy tắc miễn trừ duy nhất là khi một ngoại lệ được ném bên trong khối 'cuối cùng'. –

+4

@BradM: Bạn đã chính xác. Nói chung hơn: chỉ có ba luồng điều khiển có thể có trong một khối 'cuối cùng': (1) không bao giờ rời khỏi, (2) để lại bình thường, hoặc (3) bỏ qua ngoại lệ ném. Các luồng điều khiển khác như 'return',' goto', 'break',' continue', 'yield return',' yield break' và 'await' là không hợp pháp trong khối cuối cùng, hoặc chỉ được phép nếu chúng nhảy tới một vị trí * trong * khối cuối cùng. –

-1

Bạn có thể làm như sau để tiếp cận tác dụng tương tự:

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

Đọc lại câu hỏi. Câu hỏi bắt đầu "giả sử bạn có câu lệnh trả về trong khối thử". Câu lệnh trả về trong khối thử của bạn ở đâu? –

+1

đọc câu trả lời của tôi một lần nữa .. ".. để tiếp cận hiệu ứng tương tự" .. nó là một thay thế, không phải là một giải pháp, bởi vì nó không phải là có thể. không có lý do để bỏ phiếu .. – Yami

-1

Một loại suy chặt chẽ với các phương pháp VB trích dẫn sẽ được gán một giá trị sửa đổi để biến được sử dụng bởi return (trong đó có lợi ích của việc bảo tồn một điểm duy nhất của trở lại của điều khiển):

string returnResult; 

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

return returnResult; 
+1

Đọc lại câu hỏi. Câu hỏi bắt đầu "giả sử bạn có câu lệnh trả về trong khối thử". Câu lệnh trả về trong khối thử của bạn ở đâu? –

+0

Không có gì sai khi nói với người dùng "Đừng làm như vậy, hãy làm như thế này" - chỉ cần trả lời câu hỏi của họ không phải lúc nào cũng đúng nếu họ đang cố gắng làm là sai. – PhonicUK

+6

Đoạn cuối cùng của câu hỏi cho biết rằng áp phích ban đầu nhận thức được rằng đó là kiểu xấu. –

0

phiên bản VB.NET được lạm dụng một cấu trúc thuộc về tàn tích từ thời VB6 mà bạn trả về một giá trị bằng cách gán giá trị cho tên của hàm .

gì sẽ thực sự thú vị khi biết là nếu có một sự khác biệt trong IL tạo ra khi sử dụng một return tuyên bố tiêu chuẩn như trái ngược với myFunc = "B", như try...catch...finally ngữ nghĩa sẽ dường như ra lệnh rằng nó sẽ không thể thay đổi giá trị trả về theo tuyên bố return.

+1

'MyFunc =" B "' không trả về để IL sẽ không giống nhau –

Các vấn đề liên quan