2010-11-16 25 views
6

tôi đang có sự nhầm lẫn lớn với thứ tự thử, bắt và cuối cùng là thực thi khối.thứ tự thực hiện cố gắng nắm bắt và cuối cùng là chặn

tôi cũng muốn biết khi nào tôi nên sử dụng khối try catch và những gì tôi nên đặt trong khối try catch, tôi cũng muốn biết nếu một số ngoại lệ đến trong khối thử sau đó nếu một hành động được thực hiện tương ứng để thử khối sau đó cái nào được thực thi đầu tiên hoặc cuối cùng (là luôn luôn được thực hiện), và sau khi thực hiện hai điều này không kiểm soát trở lại để thử khối hoặc nó từ bỏ nó mãi mãi.

+0

Hãy học cách sử dụng dấu chấm ('.') và dấu hỏi ('?') một cách thích hợp. Tôi không thể hiểu được câu hỏi của bạn vì nó hiện đang đứng. – BoltClock

Trả lời

6

Nếu bạn có (lưu ý: đây không phải là hợp lệ C#, xem dưới đây cho một ví dụ hợp lệ):

try { 
    // ... some code: A 
} catch(...) { 
    // ... exception code: B 
} finally { 
    // finally code: C 
} 

Code A sẽ được thực thi. Nếu mọi thứ suôn sẻ (nghĩa là không có ngoại lệ nào bị ném trong khi A đang thực hiện), nó sẽ đi đến cuối cùng, vì vậy mã C sẽ được thực hiện. Nếu một ngoại lệ được ném trong khi A được thực hiện, sau đó nó sẽ đi đến B và cuối cùng là C.

Như một ví dụ, đây là một C# code block hiệu lực kể từ http://msdn.microsoft.com/en-us/library/dszsf989.aspx:

public class EHClass 
{ 
    void ReadFile(int index) 
    { 
     // To run this code, substitute a valid path from your local machine 
     string path = @"c:\users\public\test.txt"; 
     System.IO.StreamReader file = new System.IO.StreamReader(path); 
     char[] buffer = new char[10]; 
     try 
     { 
      file.ReadBlock(buffer, index, buffer.Length); 
     } 
     catch (System.IO.IOException e) 
     { 
      Console.WriteLine("Error reading from {0}. Message = {1}", path, e.Message); 
     } 
     finally 
     { 
      if (file != null) 
      { 
       file.Close(); 
      } 
     } 
     // Do something with buffer... 
    } 
} 

Lý do để sử dụng cố gắng/bắt/cuối cùng là để ngăn chặn chương trình của bạn thất bại nếu có một lỗi trong một số mã (A trong ví dụ trên). Nếu có sự cố, bạn có thể sử dụng phần catch để bắt vấn đề và thực hiện điều gì đó hữu ích, chẳng hạn như thông báo cho người dùng, đăng nhập ngoại lệ vào tệp nhật ký, thử lại hoặc thử một thứ khác mà bạn cho rằng có thể hoạt động thay vì những gì bạn đã thử ban đầu.

finally được sử dụng để đảm bảo rằng một số dọn dẹp được thực hiện. Ví dụ. trong A bạn có thể thử mở một tập tin và đọc nó. Nếu mở thành công, nhưng đọc không thành công, bạn sẽ có một tập tin mở đang treo lơ lửng. Những gì bạn muốn trong trường hợp đó là phải đóng nó, mà bạn sẽ làm trong khối finally - khối này luôn được thực hiện, đảm bảo việc đóng tệp.

Hãy xem ở đây để biết thêm:

+0

Thưa bạn, ý nghĩa của các trường hợp ngoại lệ được ném vào "điều kiện do người dùng xác định" là gì? – NoviceToDotNet

+0

Không chắc chắn tôi hiểu ý bạn là gì bởi "điều kiện do người dùng xác định" - nếu bạn muốn nói đến ngoại lệ do người dùng xác định, hãy xem tại đây: http://msdn.microsoft.com/en-us/library/87cdya3t.aspx. Các ngoại lệ do người dùng định nghĩa được sử dụng khi không có ngoại lệ nào được hệ thống xác định cho bạn một lời giải thích phù hợp về lỗi mà bạn muốn báo hiệu. –

+0

-1: bạn đã thông báo cho người đọc để làm chính xác điều sai. Nếu có lỗi trong mã, thì chương trình đã thất bại (và do đó có lập trình viên). Ý tưởng tốt hơn là cho phép chương trình "thất bại", cho phép người dùng phàn nàn về nó, và sau đó cho phép vấn đề thực sự được sửa chữa, không che giấu sự bất công của bạn sau mệnh đề bắt và "thông báo cho người dùng". –

5

Bạn hầu như không bao giờ nên dùng thử/nắm bắt.

Bạn chỉ nên catch ngoại lệ mà bạn thực sự có thể sửa và chỉ khi bạn đang mong đợi. Nếu không, hãy để người gọi xử lý ngoại lệ - hay không.

Nếu được sử dụng, bất kỳ mệnh đề catch nào được thực hiện trước tiên - chỉ một trong số chúng.

Sau đó, finally được "thực thi" cuối cùng.


Điều này đã được nêu rõ hơn ở nhiều nơi, nhưng tôi sẽ thử. Mã sau:

try 
{ 
    // Do something here 
} 
catch (Exception ex) 
{ 
    MessageBox.Show("Friendly error message"); 
} 

không khắc phục ngoại lệ. Nó ẩn ngoại lệ để vấn đề sẽ không bao giờ được sửa. Mã đó không có ý tưởng ngoại lệ được ném ra, bởi vì nó sẽ bắt tất cả chúng, và nó không có gì để sửa vấn đề - nó chỉ nói cho người dùng một tiểu thuyết lịch sự.

Thực tế của vấn đề là các mã trên nên được thay thế bằng những điều sau đây:

// Do something here 

Bằng cách này, nếu người gọi của phương pháp này biết làm thế nào để khắc phục vấn đề đặc biệt, sau đó người gọi có thể khắc phục chúng . Bạn sẽ không xóa tùy chọn đó khỏi người gọi.

Nếu người gọi không biết cách khắc phục sự cố, thì người gọi cũng không nên bắt ngoại lệ.


Đây là ví dụ (từ MSDN) về sử dụng ngoại lệ một cách hợp lý. Đó là một dạng sửa đổi của ví dụ trong tài liệu của SmtpFailedRecipientsException Class.

public static void RetryIfBusy(string server) 
{ 
    MailAddress from = new MailAddress("[email protected]"); 
    MailAddress to = new MailAddress("[email protected]"); 
    using (
     MailMessage message = new MailMessage(from, to) 
            { 
             Subject = "Using the SmtpClient class.", 
             Body = 
              @"Using this feature, you can send an e-mail message from an application very easily." 
            }) 
    { 
     message.CC.Add(new MailAddress("[email protected]")); 
     using (SmtpClient client = new SmtpClient(server) {Credentials = CredentialCache.DefaultNetworkCredentials}) 
     { 
      Console.WriteLine("Sending an e-mail message to {0} using the SMTP host {1}.", to.Address, client.Host); 
      try 
      { 
       client.Send(message); 
      } 
      catch (SmtpFailedRecipientsException ex) 
      { 
       foreach (var t in ex.InnerExceptions) 
       { 
        var status = t.StatusCode; 
        if (status == SmtpStatusCode.MailboxBusy || status == SmtpStatusCode.MailboxUnavailable) 
        { 
         Console.WriteLine("Delivery failed - retrying in 5 seconds."); 
         System.Threading.Thread.Sleep(5000); // Use better retry logic than this! 
         client.Send(message); 
        } 
        else 
        { 
         Console.WriteLine("Failed to deliver message to {0}", t.FailedRecipient); 
          // Do something better to log the exception 
        } 
       } 
      } 
      catch (SmtpException ex) 
      { 
       // Here, if you know what to do about particular SMTP status codes, 
       // you can look in ex.StatusCode to decide how to handle this exception 
       // Otherwise, in here, you at least know there was an email problem 
      } 
      // Note that no other, less specific exceptions are caught here, since we don't know 
      // what do do about them 
     } 
    } 
} 

Lưu ý rằng mã này sử dụng try/catch để bao quanh một đoạn mã nhỏ. Trong khối try/catch đó, nếu một SmtpException hoặc SmtpFailedRecipientsException được ném ra, chúng ta biết phải làm gì với nó. Ví dụ, nếu chúng ta bắt được IOException, chúng ta sẽ không biết nó có ý nghĩa gì, hoặc phải làm gì với nó. Bất kỳ trường hợp ngoại lệ nào bạn không thực sự biết cách sửa lỗi sẽ không bị bắt, ngoại trừ có thể thêm thông tin vào ngoại lệ, đăng nhập và truy cập lại.

+0

bây giờ tôi đang bối rối hơn, tại sao tôi không nên sử dụng khối try catch? và nếu trước tôi biết nơi ngoại lệ sẽ đến thì tôi sẽ sửa nó. Ngoài ra ý nghĩa của câu lệnh này là "để người gọi xử lý ngoại lệ - hay không." – NoviceToDotNet

+0

Nếu bạn không hiểu mình đang làm gì, hãy thử nghe. Không sử dụng nó. Chỉ để lại ngoại lệ một mình. Nếu mã của bạn là ném một ngoại lệ mà nó không nên, sau đó sửa mã của bạn. Có rất ít lý do để bao giờ bắt ngoại lệ, đối với hầu hết các nhà phát triển. –

4

Một khối try ... catch được sử dụng để bắt ngoại lệ. Trong khối try bạn đặt mã mà bạn mong đợi có thể làm tăng ngoại lệ.

Nếu không có ngoại lệ xảy ra thì mã trong khối try hoàn thành như mong đợi. Nếu có khối finally thì điều đó sẽ thực thi tiếp theo.

Nếu xảy ra ngoại lệ thì thực thi sẽ nhảy đến đầu khối catch khớp thứ nhất. Khi mã đó hoàn thành khối cuối cùng (nếu nó tồn tại) được thực hiện. Việc thực hiện không trở lại khối try.

1

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

try 
{ 
    someFunctionThatWorks(); 

    functionThatThrowsAnException(); // As soon as this function throws an exception we are taken to the catch block 

    anotherFunction(); // <-- This line will never get executed 
} 
catch(Exception e) 
{ 
    // Here you can handle the exception, if you don't know how to handle it you should not be catching it 
    // After this you will not be taken back to the try block, you will go right to the finally block 
} 
finally 
{ 
    // Code here is always executed at the very end, regardless of whether an exception was thrown or not 
} 
+0

và thưa ông, nếu cuối cùng chính nó ném một số ngoại lệ thì điều gì sẽ xảy ra? – NoviceToDotNet

+0

Nếu một ngoại lệ khác được ném vào khối cuối cùng, bạn có thể bắt nó bằng cách lồng một lần thử khác ... bắt ... cuối cùng, nếu không nó sẽ hoạt động như bất kỳ ngoại lệ không được xử lý nào khác. Xem http://stackoverflow.com/questions/481446/throws-exception-in-finally-blocks này – tbridge

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