2009-07-17 62 views
17

Nếu bạn chạy vào mã bên dưới nó thực sự thực thi cuối cùng sau mỗi cuộc gọi đến goto:Tại sao "cuối cùng" này thực thi?

int i = 0; 
Found: 
    i++; 
    try 
    { 
     throw new Exception(); 
    } 
    catch (Exception) 
    { 
     goto Found; 
    } 
    finally 
    { 
     Console.Write("{0}\t", i); 
    } 

Tại sao?

+12

-1 để sử dụng GOTO –

+8

Tôi không làm điều này trong mã sản xuất. Đó chỉ là một tình huống giả định. – Kredns

+1

Lý do chính để bỏ phiếu bầu: Tôi nghĩ loại câu hỏi noob của nó, sau khi kiếm được hơn 4k điểm !!! Tôi xin lỗi ... :) –

Trả lời

28

Tại sao bạn mong đợi nó không thực thi?

Nếu bạn đã thử/bắt/cuối cùng hoặc thử/cuối cùng chặn, cuối cùng khối thực hiện bất kể mã nào bạn có thể có trong khối thử hoặc bắt most of the time.

Thay vì goto, hãy xem xét 'trả lại'.

//imagine this try/catch/finally block is inside a function with return type of bool. 
try 
{ 
    throw new Exception(); 
} 
catch (Exception) 
{ 
    return false; //Let's say you put a return here, finally block still executes. 
} 
finally 
{ 
    Console.WriteLine("I am in finally!"); 
} 
+0

Tôi đoán tôi nghĩ rằng một goto sẽ ghi đè lên điều này. – Kredns

+0

Không có cấu trúc nào có thể ghi đè hành vi này. 'goto'/'return'/bất kỳ cấu trúc nào khác mà bạn có thể tưởng tượng. – SolutionYogi

+2

điều gì sẽ xảy ra nếu bạn có 'trả lại đúng'; trong khối cuối cùng (đối với mã ví dụ ở trên). những gì được trả lại? giả hay đúng? –

2

Đó là theo thiết kế. Trong trình xử lý ngoại lệ, bạn có thể thực hiện một số hành động ngoại lệ cụ thể. Trong khối cuối cùng, bạn nên làm sạch tài nguyên - đó là lý do tại sao khối cuối cùng luôn được thực hiện bất kể mã xử lý ngoại lệ là gì.

3

Có vẻ hợp lý. Một khối finally luôn chạy sau try hoặc catch.

Tương tự

try 
{ 
    // do something 
    return; 
} 
finally 
{ 
    // do something else 
} 

sẽ luôn luôn chạy khối finally. EDIT - nhưng xem bình luận của Eric ở trên.

0

Do tuyên bố finally dự kiến ​​sẽ được thực hiện sau khi rời khỏi try (hoặc catch khi ngoại lệ bị bắt). Điều này bao gồm khi bạn thực hiện cuộc gọi goto của mình.

37

Các văn bản sau đây xuất phát từ C# Language Specification (8.9.3 The goto statement)


Một tuyên bố goto được thực hiện như sau:

  • Nếu lệnh goto thoát một hoặc nhiều khối try với liên kết cuối cùng khối, kiểm soát ban đầu được chuyển giao cho khối cuối cùng của tuyên bố cố gắng trong cùng. Khi và nếu điều khiển đạt đến điểm cuối của khối cuối cùng, điều khiển được chuyển đến khối cuối cùng của câu lệnh thử kèm theo tiếp theo. Quá trình này được lặp lại cho đến khi các khối cuối cùng của tất cả các câu lệnh cố gắng can thiệp đã được thực hiện.
  • Điều khiển được chuyển đến mục tiêu của câu lệnh goto.
+2

+1 để tham khảo thông số kỹ thuật. –

+0

+1 để tham khảo đặc điểm kỹ thuật. –

+0

Chúa ơi! Các spec là khá dài ;-) – Kredns

1

Như mọi người đã đề cập, finally chạy bất kể luồng chương trình. Tất nhiên, khối finally là tùy chọn, vì vậy nếu bạn không cần, đừng sử dụng nó.

12

Ý chính của câu trả lời được đưa ra - khi điều khiển rời khỏi khu vực được bảo vệ bằng bất kỳ phương tiện nào, cho dù "trả lại", "goto", "break", "continue" hoặc "throw", "finally" được thực hiện - đúng. Tuy nhiên, tôi lưu ý rằng hầu hết mọi câu trả lời đều nói rằng "khối cuối cùng luôn chạy". Khối cuối cùng KHÔNG luôn chạy. Có nhiều tình huống trong đó khối cuối cùng không chạy.

Ai muốn thử liệt kê tất cả?

+0

Theo spec "Các báo cáo của một khối cuối cùng luôn luôn được thực hiện khi kiểm soát lá một tuyên bố thử. Điều này là đúng cho dù việc chuyển giao kiểm soát xảy ra như là kết quả của thực hiện bình thường, như là kết quả của việc thực hiện một lệnh break, continue, goto hoặc return, hoặc là kết quả của việc truyền một ngoại lệ ra khỏi câu lệnh try. " Tuy nhiên, tôi muốn nói một StackOverflowException là một, bởi vì không có gì có thể đối phó với nó như xa như tôi có thể nhìn thấy. –

+1

Colin, quả thật vậy, điểm mấu chốt là KHI KIỂM SOÁT LEAVES. Nếu điều khiển không rời khỏi thì khối cuối cùng không thực thi! Ví dụ, khu vực được bảo vệ có thể chứa một vòng lặp vô hạn. –

+0

@Eric: Tôi hoàn toàn nhận được câu hỏi này từ bài đăng blog của bạn. Tôi cũng không nghĩ về một vòng lặp vô hạn trong khối try/catch – Kredns

0

Đó là điểm của khối finally. Nó luôn luôn thực hiện (khá nhiều).

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