2012-04-21 25 views
5

Có vẻ như nó thực hiện theo một số thử nghiệm ban đầu, nhưng điều tôi muốn biết là nếu được bảo đảm để trả lại hoặc nếu trong một số trường hợp không thể trả lại? Điều này là rất quan trọng đối với đơn đăng ký của tôi nhưng tôi chưa tìm thấy trường hợp sử dụng nào mà nó không trả lại.
Tôi muốn có chuyên môn về chủ đề này.Nếu tôi trở lại trong một thử/cuối cùng khối trong C# hiện các mã trong cuối cùng luôn luôn chạy?

+1

Một số trường hợp ngoại lệ không thể bị bắt như một chồng tràn. –

+0

Xem tại đây: http://stackoverflow.com/a/50627/5190 –

+0

Bạn có thể vượt qua kịch bản của mình không? Hãy nhớ rằng một chương trình có thể bị ép buộc. Từ tiêu đề, có vẻ như bạn đang hỏi nếu thử {return; } cuối cùng {// mycode} sẽ chạy mã cuối cùng. Câu trả lời là không. –

Trả lời

10

Mọi thứ trong khối cuối cùng sẽ luôn được thực hiện bất kể điều gì xảy ra bên trong khối thử hoặc nắm bắt. Nó không quan trọng nếu bạn quay trở lại hình thức phương pháp hay không.

Ngoại lệ duy nhất cho điều này là nếu mã trong khối cuối cùng ném một ngoại lệ, thì nó sẽ dừng thực thi giống như bất kỳ khối mã nào khác.

Liên quan đến goto, câu trả lời vẫn là có. Xét đoạn mã sau:

try 
{ 
    Console.WriteLine("Inside the Try"); 
    goto MyLabel; 
} 
finally 
{ 
    Console.WriteLine("Inside the Finally"); 
} 

MyLabel: 
    Console.WriteLine("After the Label"); 

Sản lượng sản xuất là thế này:

Bên trong Cố gắng

Bên trong Cuối cùng

Sau Label

+0

ngay cả khi tôi làm một goto? – zorg

+0

'Thread.Sleep (-1)' :) – Ryan

+0

@zorg: [Vâng, ngay cả khi bạn làm một 'goto'.] (Http://ideone.com/a8LUJ) – Ryan

1

Trong trường hợp ngoại lệ chết người mà chấm dứt ứng dụng Cuối cùng khối sẽ không b e gọi. Bao gồm tràn ngăn xếp, ngoại lệ trong JIT của các phương thức để gọi, các ngoại lệ gây tử vong insisde CLR runtime.

Khi @mintech chỉ ra nếu ứng dụng bị treo bên trong khối, nó đơn giản sẽ không đến được khối cuối cùng. Điều này bao gồm chờ đợi cho các đối tượng đồng bộ hóa, deadlocks vòng lặp vô hạn hoặc thậm chí giao diện người dùng mà không có một cách để đóng nó.

28

Có một số điểm không chính xác trong các câu trả lời khác.

Điều khiển được chuyển đến khối cuối cùng khi điều khiển rời khối thử thông thường - tức là, bằng cách quay lại, goto, ngắt, tiếp tục hoặc đơn giản là rơi xuống cuối. Điều khiển được chuyển đến khối cuối cùng khi điều khiển rời khối thử thông qua ngoại lệ đã bị chặn bởi khối catch kèm theo.

Trong mọi trường hợp khác, không có bảo đảm rằng mã trong khối cuối cùng sẽ được gọi. Cụ thể:

  • Nếu mã khối thử đi vào vòng lặp vô hạn hoặc luồng bị đóng băng và không bao giờ bị đóng băng, thì mã khối cuối cùng sẽ không bao giờ được gọi.

  • Nếu quá trình được tạm dừng trong trình gỡ lỗi và sau đó bị tiêu diệt mạnh thì khối cuối cùng sẽ không bao giờ được gọi. Nếu quá trình thực hiện không nhanh thì khối cuối cùng sẽ không bao giờ được gọi.

  • Nếu dây nguồn được kéo ra khỏi tường thì khối cuối cùng sẽ không bao giờ được gọi.

  • Nếu có một ngoại lệ ném mà không có một khối catch tương ứng thì liệu khối finally chạy hay không là một chi tiết thi hành runtime. Thời gian chạy có thể chọn bất kỳ hành vi nào khi có ngoại lệ không bị bắt buộc. Cả hai "không chạy các khối cuối cùng" và "chạy các khối cuối cùng" là các ví dụ về "bất kỳ hành vi nào", do đó, hoặc là có thể được chọn. Thông thường những gì thời gian chạy không là yêu cầu người dùng nếu họ muốn đính kèm một trình gỡ lỗi trước khi các khối cuối cùng chạy; nếu người dùng nói không thì các khối cuối cùng sẽ chạy. Nhưng một lần nữa: thời gian chạy không phải là yêu cầu để thực hiện điều đó. Nó có thể thất bại nhanh chóng.

Bạn không thể dựa vào các khối cuối cùng luôn được gọi. Nếu bạn yêu cầu bảo đảm mạnh mẽ về việc thực thi mã thì bạn không nên viết thử cuối cùng, bạn nên viết một vùng thực thi hạn chế . Viết CER đúng là một trong những nhiệm vụ khó khăn nhất trong lập trình C#, vì vậy hãy nghiên cứu kỹ tài liệu trước khi bạn cố gắng viết mã.

Ngẫu nhiên, một "sự thật thú vị" về gotos cuối cùng bị chặn là:

try { goto X; } finally { throw y; } 
X : Console.WriteLine("X"); 

X là một nhãn unreachable nhắm mục tiêu bởi một thể truy cập goto! Vì vậy, lần tới khi bạn ở một bữa tiệc, bạn có thể giống như "mọi người, mọi người có thể tạo một chương trình C# có nhãn không thể truy cập được nhắm đến bởi một goto có thể truy cập không?" và bạn sẽ thấy ai trong nhóm đã đọc thông số kỹ thuật khả năng hiển thị và ai chưa biết!

+0

Tôi sẽ thêm lỗi: trong thời gian chạy, hệ điều hành, trình điều khiển, phần cứng, vv gây ra BSOD hoặc PC treo cứng. –

+0

@EricLippert Nếu ngoại lệ outofMemory xảy ra trong khối thử tôi nghĩ Cuối cùng sẽ không được thực hiện. Tôi có đúng trong giả định không? Làm ơn cho tôi biết. – Sandeep

+3

Vì vậy, đạo đức của câu chuyện là: Không bao giờ mời Eric Lippert cho các bên của bạn;) – Tergiver

4

Dưới đây là một số ví dụ:

Environment.FailFast()

 try 
     { 
      Console.WriteLine("Try"); 
      Environment.FailFast("Test Fail"); 

     } 
     catch (Exception) 
     { 
      Console.WriteLine("catch"); 
     } 
     finally 
     { 
      Console.WriteLine("finally"); 
     } 

Kết quả chỉ là "Thử"

Stackoverflow

 try 
     { 
      Console.WriteLine("Try"); 
      Rec(); 
     } 
     catch (Exception) 
     { 
      Console.WriteLine("catch"); 
     } 
     finally 
     { 
      Console.WriteLine("finally"); 
     } 

Nơi Rec là:

private static void Rec() 
    { 
     Rec(); 
    } 

Đầu ra chỉ là "Thử" và quá trình chấm dứt do StackOverflow.

Unhanded ngoại lệ

 try 
     { 
      Console.WriteLine("Try"); 
      throw new Exception(); 
     } 
     finally 
     { 
      Console.WriteLine("finally"); 
     } 
Các vấn đề liên quan