2011-01-04 36 views
140

Cái nào:try/catch + sử dụng, đúng cú pháp

using (var myObject = new MyClass()) 
{ 
    try 
    { 
     // something here... 
    } 
    catch(Exception ex) 
    { 
     // Handle exception 
    } 
} 

HOẶC

try 
{ 
    using (var myObject = new MyClass()) 
    { 
     // something here... 
    } 
} 
catch(Exception ex) 
{ 
    // Handle exception 
} 
+6

Chỉ cần một lưu ý: nên cẩn thận để ngoại lệ ngại duy nhất mà thực sự có thể được _handled_ (điều chỉnh), trừ trường hợp khai thác gỗ, hoặc gói chúng. –

+1

Hãy ghi nhớ rằng '}' cuối cùng của câu lệnh 'using' có thể ném một ngoại lệ [như được nhắc tới ở đây] (https://msdn.microsoft.com/en-us/library/aa355056%28v=vs. 110% 29.aspx). –

+0

TIL rằng trình gỡ rối (trong VS) sẽ không gọi phương thức vứt bỏ nếu bạn sử dụng khối mã đầu tiên. Bởi vì bản thân câu lệnh sử dụng có thể ném một ngoại lệ, nó giúp tôi sử dụng khối thứ hai để đảm bảo 'cuối cùng' được gọi là phương thức vứt bỏ. – ShooShoSha

Trả lời

70

tôi thích thứ hai. Có thể cũng bẫy lỗi liên quan đến việc tạo ra các đối tượng là tốt.

+10

Tôi không đồng ý với lời khuyên này. Nếu bạn đang mong đợi việc tạo đối tượng để ném một lỗi, thì bất kỳ xử lý ngoại lệ nào * phải * đi ra ngoài. Nếu có một số câu hỏi về nơi xử lý nên đi, thì ngoại lệ được mong đợi phải là thứ gì đó khác - trừ khi bạn đang ủng hộ việc bắt bất kỳ ngoại lệ ngẫu nhiên nào có thể hoặc không thể dự đoán được, đó là một mẫu chống cổ điển (bên ngoài quá trình xử lý ngoại lệ không xử lý). –

+1

@ Jeffrey: Cách tiếp cận tôi mô tả đã phục vụ tôi tốt và tôi đã làm điều này một thời gian dài. Không ai nói bất cứ điều gì về * mong đợi * tạo đối tượng thất bại. Nhưng bằng cách gói một hoạt động có thể * có khả năng * thất bại trong một khối 'try', cho phép bạn bật một thông báo lỗi nếu có điều gì đó không thành công, chương trình hiện có khả năng khôi phục và thông báo cho người dùng. –

+0

Câu trả lời của bạn là chính xác nhưng vẫn tiếp tục gợi ý rằng try/catch _has_ sẽ ở đó (ngay lập tức) mọi lúc. –

8

Cả hai đều là cú pháp hợp lệ. Nó thực sự đi xuống đến những gì bạn muốn làm: nếu bạn muốn bắt lỗi liên quan đến việc tạo ra/xử lý các đối tượng, sử dụng thứ hai. Nếu không, hãy sử dụng đầu tiên.

6

Có một điều quan trọng mà tôi sẽ gọi ở đây: Đầu tiên sẽ không bắt bất kỳ ngoại lệ nào phát sinh từ việc gọi hàm tạo MyClass.

27

Từ một khối sử dụng chỉ là một việc đơn giản hóa cú pháp của một thử/cuối cùng (MSDN), cá nhân tôi muốn đi với những điều sau đây, mặc dù tôi nghi ngờ nó khác với tùy chọn thứ hai của bạn đáng kể:

MyClass myObject = null; 
try { 
    myObject = new MyClass(); 
    //important stuff 
} catch (Exception ex) { 
    //handle exception 
} finally { 
    if(myObject is IDisposable) myObject.Dispose(); 
} 
+3

Tại sao bạn nghĩ rằng việc thêm một khối 'cuối cùng' thích hợp hơn với câu lệnh' using'? –

+7

Việc thêm một khối 'cuối cùng' để xử lý một đối tượng IDisposable là một câu lệnh' using'. Cá nhân, tôi thích điều này thay vì khối 'using' được nhúng bởi vì tôi nghĩ nó rõ ràng hơn khi mọi thứ đang diễn ra, và tất cả đều ở cùng một cấp độ. Tôi cũng thích điều này hơn một số khối 'sử dụng' được nhúng ... nhưng tất cả chỉ là sở thích của tôi. – chezy525

+4

Nếu bạn thực hiện nhiều xử lý ngoại lệ, bạn phải thực sự thích gõ! Từ khóa "sử dụng" đó đã tồn tại một thời gian và ý nghĩa của nó khá rõ ràng đối với tôi. Và sử dụng nó giúp làm cho phần còn lại của mã của tôi rõ ràng hơn bằng cách giữ số lượng lộn xộn ở mức tối thiểu. –

17

Nó phụ thuộc. Nếu bạn đang sử dụng Windows Communication Foundation (WCF), using(...) { try... } sẽ không hoạt động chính xác nếu proxy trong câu lệnh using ở trạng thái ngoại lệ, tức là việc loại bỏ proxy này sẽ gây ra một ngoại lệ khác.

Cá nhân, tôi tin vào phương pháp xử lý tối thiểu, tức là xử lý ngoại lệ duy nhất bạn biết tại thời điểm thực hiện. Nói cách khác, nếu bạn biết rằng việc khởi tạo một biến trong using có thể ném một ngoại lệ cụ thể, tôi quấn nó với try-catch. Tương tự, nếu trong phạm vi using, nội dung nào đó có thể xảy ra, không liên quan trực tiếp đến biến số trong using, sau đó tôi kết hợp nó với một số khác try cho ngoại lệ cụ thể đó. Tôi hiếm khi sử dụng Exception trong số catch es của mình.

Nhưng tôi thích IDisposableusing mặc dù vậy tôi có thể thiên vị.

16

Nếu câu lệnh bắt của bạn cần truy cập biến được khai báo trong câu lệnh sử dụng, thì bên trong là tùy chọn duy nhất của bạn.

Nếu câu lệnh bắt của bạn cần đối tượng được tham chiếu trong quá trình sử dụng trước khi nó được xử lý, thì bên trong là lựa chọn duy nhất của bạn.

Nếu câu lệnh bắt của bạn có hành động không xác định, như hiển thị thông báo cho người dùng và bạn muốn vứt bỏ tài nguyên trước khi điều đó xảy ra, thì bên ngoài là lựa chọn tốt nhất của bạn.

Bất cứ khi nào tôi có một scenerio tương tự như vậy, khối try-catch thường là trong một phương pháp khác tiếp tục lên ngăn xếp cuộc gọi từ việc sử dụng. Nó không phải là điển hình cho một phương pháp để biết cách xử lý các ngoại lệ xảy ra bên trong nó như thế này.

Vì vậy, đề xuất chung của tôi ở bên ngoài — cách bên ngoài.

private void saveButton_Click(object sender, EventArgs args) 
{ 
    try 
    { 
     SaveFile(myFile); // The using statement will appear somewhere in here. 
    } 
    catch (IOException ex) 
    { 
     MessageBox.Show(ex.Message); 
    } 
} 
1

Nếu đối tượng bạn đang khởi tạo trong khối Sử dụng() có thể ném bất kỳ ngoại lệ nào thì bạn nên sử dụng cú pháp thứ hai nếu không thì cả hai đều hợp lệ.Trong kịch bản của tôi, tôi đã phải mở một tập tin và tôi đã đi qua filePath trong constructor của đối tượng mà tôi đã khởi tạo trong khối Using() và nó có thể ném ngoại lệ nếu filePath là sai/rỗng. Vì vậy, trong trường hợp này, cú pháp thứ hai có ý nghĩa.

mẫu My mã: -

try 
{ 
    using (var obj= new MyClass("fileName.extension")) 
    { 

    } 
} 
catch(Exception ex) 
{ 
    //Take actions according to the exception. 
} 
Các vấn đề liên quan