2010-09-15 18 views

Trả lời

45

Có, khối finally được thực thi tuy nhiên luồng sẽ rời khỏi khối try - cho dù bằng cách kết thúc, trả lại hoặc ném ngoại lệ.

Từ C# 4 spec, phần 8,10:

Các báo cáo của một khối finally luôn thực hiện khi kiểm soát lại một thử tuyên bố. Điều này đúng cho dù việc chuyển giao kiểm soát xảy ra do kết quả thực hiện thông thường là , do thực hiện lệnh ngắt, tiếp tục, goto hoặc trả lại hoặc kết quả là tuyên bố một ngoại lệ trong tuyên bố thử.

(Mục 8.10 có chi tiết hơn rất nhiều về điều này, tất nhiên.)

Lưu ý rằng giá trị trả được xác định trước khối cuối cùng được thực hiện mặc dù, vì vậy nếu bạn đã làm điều này:

int Test() 
{ 
    int result = 4; 
    try 
    { 
     return result; 
    } 
    finally 
    { 
     // Attempt to subvert the result 
     result = 1; 
    } 
} 

... giá trị 4 sẽ vẫn được trả về, chứ không phải 1 - nhiệm vụ trong khối finally sẽ không có hiệu lực.

+0

Cảm ơn câu trả lời của bạn! – Liu

+0

không phải là nó thực sự có ý nghĩa thực tế nhiều nhưng khối cuối cùng không được thực hiện nếu một StackOverflowException xảy ra hoặc nếu bạn gọi System.Environment.FailFast (...) –

+0

Tất nhiên, điều khiển không trả về người gọi ở tất cả trong những trường hợp đó. Bạn có thể nói rằng dòng chảy * kết thúc * thay vì rời khỏi khối, để tuyên bố của Skeet vẫn giữ. –

6

Một khối finally sẽ luôn được thực thi và điều này sẽ xảy ra trước khi trở về từ phương pháp này, vì vậy bạn có thể an toàn viết mã như thế này:

try { 
    return "foo"; 
} finally { 
    // This will always be invoked 
} 

hoặc nếu bạn đang làm việc với các tài nguyên dùng một lần:

using (var foo = GetFoo()) 
{ 
    // foo is guaranteed to be disposed even if an exception is thrown 
    return foo.Bar(); 
} 
+0

Cảm ơn câu trả lời của bạn! – Liu

2

Cuối cùng các khối sẽ được thực thi nếu trở về từ các khối thử hoặc bắt trong C-Sharp?

YES

Nếu nó sẽ, Trước khi trở về hoặc sau?

TRƯỚC

3

Với xử lý ngoại lệ hai vượt qua, mà .NET thừa hưởng từ các cửa sổ, bạn có thể không chính xác nói rằng khối cuối cùng thực hiện trước khi điều khiển đi lại cho người gọi.

Khối cuối cùng sẽ thực thi sau khi khối cuối cùng trong nhiều khung cuộc gọi lồng nhau, và trước khi khối cuối cùng và khối catch trong khung cuộc gọi ít lồng nhau, nhất quán với khối cuối cùng đang chạy trước khi trở về. Nhưng tất cả các bộ lọc ngoại lệ giữa điểm ném và điểm bắt sẽ chạy trước bất kỳ khối cuối cùng nào, có nghĩa là trong trường hợp ngoại lệ, một số mã người gọi có thể chạy trước khối cuối cùng.

Khi điều khiển rời khỏi khối bình thường (không có ngoại lệ ném), sau đó cuối cùng chạy trước khi kiểm soát trở về người gọi.

+0

+1 vì bộ lọc ngoại lệ đáng nhắc đến ... nhưng ngay cả với bộ lọc ngoại lệ, chắc chắn khối cuối cùng đang chạy trước khi điều khiển chuyển lại cho người gọi. Nó chỉ là bộ lọc ngoại lệ có thể chạy ngay cả trước đó. –

+0

Vâng, kiểm soát chuyển đến bộ lọc ngoại lệ của người gọi, sau đó đến khối cuối cùng, sau đó đến trình xử lý ngoại lệ của người gọi. Vì vậy, kiểm soát chuyển cho người gọi cả trước và sau khối cuối cùng. –

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