2011-12-31 24 views
17

Tôi có câu hỏi: "Bạn thích gì, xử lý ngoại lệ hoặc nếu điều kiện"nếu điều kiện vs xử lý ngoại lệ

để phỏng vấn. Câu trả lời của tôi là xử lý ngoại lệ được ưa thích chỉ cho các trường hợp đặc biệt như một lỗi đĩa cho phép trên ghi tập tin. Người phỏng vấn dường như đang chờ đợi một số câu trả lời khác. Câu trả lời đúng là gì?

EDIT: Bất kỳ ví dụ cụ thể nào về xử lý ngoại lệ thường được sử dụng khi điều kiện if sẽ phù hợp hơn?

+5

'Người phỏng vấn dường như đang chờ đợi một số câu trả lời khác' - vậy tại sao bạn không hỏi anh ấy? Tôi càng bị ấn tượng bởi câu hỏi hơn là trả lời khi phỏng vấn ... –

Trả lời

23

Vì câu hỏi này được gắn thẻ "C#", chúng tôi có thể tham khảo Nguyên tắc thiết kế .NET Framework như một điểm khởi đầu tốt để trả lời các loại câu hỏi này. Đây là hướng dẫn được cung cấp trên MSDN theo số "Exception Throwing":

Không sử dụng ngoại lệ cho luồng kiểm soát thông thường, nếu có thể. Ngoại trừ cho lỗi hệ thống và hoạt động với điều kiện cuộc đua tiềm năng, nhà thiết kế khung phải thiết kế API để người dùng có thể viết mã không loại trừ ngoại lệ. Ví dụ: bạn có thể cung cấp cách để kiểm tra điều kiện tiên quyết trước khi gọi điện cho thành viên để người dùng có thể viết mã số không loại trừ ngoại lệ.

Dưới đây là một ví dụ về một thực hành xấu nơi một ngoại lệ được xử lý nhưng có thể gần như luôn luôn phải tránh:

public int? GetItem(int index) 
{ 
    int? value = null; 
    try 
    { 
     value = this.array[index]; 
    } 
    catch (IndexOutOfRangeException) 
    { 
    } 

    return value; 
} 

này dường như contrived nhưng tôi thấy mã như thế này khá thường xuyên từ các lập trình viên mới. Giả sử đồng bộ hóa thích hợp xung quanh lần đọc và ghi vào array, ngoại lệ này có thể tránh được 100% xác định. Do đó, cách tốt hơn để viết mã đó sẽ như sau:

public int? GetItem(int index) 
{ 
    int? value = null; 

    // Ensure the index is within range in the first place! 
    if (index >= 0 && index < this.array.Length) 
    { 
     value = this.array[index]; 
    } 

    return value; 
} 

Có những trường hợp khác mà bạn không thể tránh hợp lý ngoại lệ và chỉ cần xử lý chúng. Điều này thường gặp nhất khi bạn phải xử lý các tài nguyên bên ngoài như tệp hoặc kết nối mạng mà bạn có khả năng mất quyền truy cập hoặc liên hệ với bất kỳ lúc nào. Ví dụ từ WCF:

public void Close() 
{ 
    // Attempt to avoid exception by doing initial state check 
    if (this.channel.State == CommunicationState.Opened) 
    { 
     try 
     { 
      // Now we must do a (potentially) remote call; 
      // this could always throw. 
      this.channel.Close(); 
     } 
     catch (CommunicationException) 
     { 
     } 
     catch (TimeoutException) 
     { 
     } 
    } 

    // If Close failed, we might need to do final cleanup here. 
    if (this.channel.State == CommunicationState.Faulted) 
    { 
     // local cleanup -- never throws (aside from catastrophic situations) 
     this.channel.Abort(); 
    } 
} 

Ngay cả trong ví dụ trên, rất tốt để kiểm tra xem các hoạt động bạn sẽ phải làm ít nhất có một cơ hội của thành công. Vì vậy, vẫn có kiểm tra if(), theo sau là logic xử lý ngoại lệ thích hợp.

+0

Trong ví dụ 'GetItem' của bạn, người gọi không thể xác định nếu một 'index' không hợp lệ được cung cấp, hoặc nếu' array [index] 'chứa một giá trị' null'. Vì vậy, câu hỏi vẫn còn những gì là tốt hơn. Bạn có nên ném ngoại lệ nếu sử dụng chỉ mục không hợp lệ không? Hoặc bạn sẽ chỉ trả về giá trị 'null' mà không có bất kỳ dấu hiệu nào cho thấy có lỗi xảy ra? Sử dụng một chỉ mục không hợp lệ trên một mảng cũng sẽ gây ra một ngoại lệ, nó sẽ không trả về giá trị mặc định của kiểu mảng! – comecme

+2

@comecme: Trong ví dụ này, bạn có thể giả sử 'mảng' được khai báo là' int [] ', vì vậy' null' chỉ có thể có nghĩa là giá trị không tồn tại (ngoài hoặc phạm vi). Có, người gọi sẽ không biết, nhưng người thực hiện * sẽ * biết và không nên sử dụng các ngoại lệ như luồng điều khiển là điểm của ví dụ. Nó là hợp lệ để trả về một giá trị mặc định mà không cần ném một ngoại lệ, mặc dù mô hình này thường được dự kiến ​​sẽ được thể hiện trong phương thức 'TryXxx', như được thảo luận ở đây: http://msdn.microsoft.com/vi-us/library/ms229009.aspx – bobbymcr

10

Xử lý ngoại lệ là một hoạt động nặng và tốn kém khi có liên quan đến hiệu suất. Nếu bạn có thể tránh bắt ngoại lệ bằng cách sử dụng đúng cách nếu có thể tăng hiệu suất của ứng dụng

Mặt khác, nếu khối khác có ý nghĩa hơn đối với trình đọc mã. Chúng rất dễ hiểu và duy trì so với khối catch cố định đặc biệt. Họ mô tả dòng chảy chương trình theo cách thanh lịch hơn

Và cuối cùng như bạn nói xử lý ngoại lệ nên cho các tình huống không chắc chắn hoặc đối với trường hợp đặc biệt nó không nên là sự lựa chọn mặc định

Sửa

Một xấu chung thực hành tôi đã thấy ở một số địa điểm này là

try 
{ 
    string str = "Some String" 
    int i = Convert.ToInt32(str); 
} 
catch (Exception ex) 
{ 
     MessageBox.Show("Invalid input");   
} 

Bây giờ, bạn có thể dễ dàng tránh bắt được vỏ này bằng cách sử dụng nếu khác

string str = "Some String" 
    int i; 
    if(!int.TryParse(str, out i)) 
    { 
     MessageBox.Show("Invalid input");   
    } 
+1

Thông thường, lớp chuyển đổi chuỗi sẽ không phải là lớp hiển thị thông báo lỗi. Đó là lý do tại sao ngoại lệ tồn tại: chúng có thể bị bắt ở mức cao hơn. – comecme

4

Câu trả lời đúng chỉ là câu trả lời bạn đã cung cấp.

Để có độ đặc hiệu cao hơn, bạn nên nói điều gì đó về hiệu quả của "Tôi sử dụng nếu câu lệnh bất cứ khi nào có thể do chi phí bắt và ném ngoại lệ".

0

Nếu bạn biết chính xác đăng nhập của chương trình và biết lỗi có thể xảy ra thì bạn có thể viết câu lệnh if-else hoặc trong trường hợp khác bạn có thể để mọi thứ thử nắm bắt xử lý ngoại lệ.

2

Tôi thường sử dụng một số giá trị đặc biệt không xác định (ví dụ: null cho đối tượng) để cho biết rằng một số tính toán không thể tạo kết quả hợp lệ do đầu vào không hợp lệ. Điều này có nghĩa là mã của tôi có thể xác định thành công và báo cáo rằng dữ liệu đầu vào không hợp lệ và không có kết quả có ý nghĩa nào có thể được tạo ra.

Tôi thích sử dụng ngoại lệ khi mã của tôi không thể hoàn thành việc tính toán được yêu cầu, ví dụ: nếu một tệp có chứa một số dữ liệu bắt buộc không tồn tại, nếu nó không thể kết nối với cơ sở dữ liệu.

Vì vậy, khái niệm:

  • Không xác định kết quả (cộng thêm nếu điều kiện): Chương trình xác định thành công mà không có kết quả hợp lệ cho đầu vào nhất định.
  • Ngoại lệ (cộng với try-catch): chương trình không thể hoàn thành tính toán do một số lỗi trong ứng dụng không liên quan đến đầu vào.