2012-01-17 15 views
7

thể trùng lặp:
Catching specific vs. generic exceptions in c#Xử lý ngoại lệ C#, mệnh đề nào cần sử dụng?

Dưới đây là một phương pháp dụ

private static void outputDictionaryContentsByDescending(Dictionary<string, int> list) 
{ 
    try 
    { 
     //Outputs entire list in descending order 
     foreach (KeyValuePair<string, int> pair in list.OrderByDescending(key => key.Value)) 
     { 
      Console.WriteLine("{0}, {1}", pair.Key, pair.Value); 
     } 
    } 
    catch (Exception e) 
    { 
     MessageBox.Show(e.Message, "Error detected", MessageBoxButtons.OK, MessageBoxIcon.Error); 
    } 
} 

Tôi muốn biết những gì điều khoản ngoại lệ để sử dụng ngoài chỉ Exception và nếu có một lợi thế trong việc sử dụng các mệnh đề bắt cụ thể hơn.

Edit: O.k nhờ mọi người

Trả lời

2

duy nhất nguyên nhân tiềm năng cho một ngoại lệ mà tôi nhìn thấy trong ví dụ của bạn là nếu list là null. OrderByDescending() phải trả lại số trống IEnumerable<> thay vì tham chiếu null.

Nếu tôi đọc mà chính xác, nó có thể làm cho ý nghĩa hơn để bắt NullReferenceException:

try 
{ 
... 
} catch (NullReferenceException exception) 
{ 
    MessageBox.Show(...); 
} 

Tuy nhiên, điều này thực sự phụ thuộc vào nhu cầu của ứng dụng của bạn. Nếu ý định của bạn chỉ là cảnh báo cho người dùng hoặc đăng nhập tất cả các ngoại lệ, hãy bắt gặp lớp học Exception là tốt. Nếu bạn cần xử lý đặc biệt với nhiều loại khác nhau của ngoại lệ - chẳng hạn như gửi một thông báo qua email thay vì chỉ đăng thông điệp - sau đó nó làm cho tinh thần để sử dụng các loại ngoại lệ cụ thể:

try 
{ 
} 
catch(NullReferenceException e) 
{ 
//... 
} 
catch(StackOverflowException e) 
{ 
//... 
} 
catch(Exception e) 
{ 
/// generic exception handler 
} 
+0

Nếu 'list' là null, 'outputDictionaryContentsByDescending' nên ném 'ArgumentNullException' –

7

Bắt từng loại ngoại lệ trong bản Tuyên Bố của bạn sẽ cho phép bạn để xử lý từng theo một cách khác.

Quy tắc chăn cho Exception có thể hữu ích cho việc ghi nhật ký và khôi phục ngoại lệ, nhưng không phải là cách tốt nhất để xử lý ngoại lệ mà bạn có thể khôi phục.

try 
{ 
    // open a file specified by the user 
} 
catch(FileNotFoundException ex) 
{ 
    // notify user and re-prompt for file 
} 
catch(UnauthorizedAccessException ex) 
{ 
    // inform user they don't have access, either re-prompt or close dialog 
} 
catch(Exception ex) 
{ 
    Logger.LogException(ex); 
    throw; 
} 
4

Bạn nên chỉ thực sự bắt ngoại lệ mà bạn đang mong đợi mã có thể ném. Bằng cách đó, nếu nó ném một cái gì đó bạn không mong đợi, nó có thể là một cái gì đó quan trọng; một cái gì đó mà nên làm bong bóng ngăn xếp cuộc gọi và có thể làm hỏng ứng dụng; hoặc một cái gì đó bạn đã không nghĩ đến.

Ví dụ: bạn có thể muốn xử lý IOException s được ném bởi mã I/O để bạn có thể chuyển tiếp sự cố lại cho người dùng. Tuy nhiên, các hoạt động tương tự có thể ném thứ gì đó quan trọng hơn như là AccessViolationException. Trong trường hợp này, bạn có thể muốn chương trình chấm dứt hoặc xử lý vấn đề theo cách khác.

Xử lý ngoại lệ chung chỉ nên sử dụng thực sự được sử dụng trong trường hợp bạn không quan tâm đến lỗi nào và sau đó không muốn ảnh hưởng đến phần còn lại của quá trình.

1

Vì bạn đang đối phó với một từ điển .. sau đó bạn muốn xem xét những trường hợp ngoại lệ 2

  • Mấu chốt của KeyValuePair là một tham chiếu null (Không có gì trong Visual Basic).

  • ArgumentException Một phần tử có cùng khóa đã tồn tại trong Từ điển (TKey, TValue).

    KekValuePair Exception này được lấy từ các trang web MSDN

+0

Oh cảm ơn vì điều đó không biết nó được liệt kê excpetions thể trên MSDN – Elliot678

0

Sử dụng các loại ngoại lệ mà bạn có thể mong đợi nhưng vẫn không thể ngăn chặn và rằng bạn có thể xử lý thỏa đáng. Hãy để bất cứ điều gì khác bong bóng lên đến một nơi nào đó mà có thể mong đợi nó hoặc có thể xử lý nó.

Trong trường hợp của bạn ở đây, tôi có thể mong đợi rằng tôi sẽ chạy vào một số NullReferenceException nếu từ điển rỗng. Nhưng tôi sẽ không bắt được nó. Đây là điều mà tôi có thể xác nhận đối với thay

if (dictionary != null) 

Vì vậy, không có lý do để cho phép một ngoại lệ cho dù xảy ra. Không bao giờ sử dụng ngoại lệ cho luồng điều khiển và xác thực các nguyên nhân đã biết.

0

Một số lớp/phương pháp sẽ ném các ngoại lệ khác nhau, tùy thuộc vào lỗi. Ví dụ, bạn có thể đang sử dụng lớp File để ghi dữ liệu vào một tập tin. Bạn có thể viết nhiều câu lệnh Catch cho các kiểu ngoại lệ mà bạn có thể phục hồi, và một ngoại lệ chung bắt giữ để ghi lại và bong bóng lên bất cứ thứ gì không thể phục hồi được.

0

Bằng cách sử dụng Ngoại lệ, bạn bắt tất cả ngoại lệ. Của bạn sử dụng IOException hoặc StackOverflowException bạn sẽ chỉ bắt lỗi của loại đó.

một StackOverflowException đánh bắt bởi một ngoại lệ vẫn giữ cùng một thông điệp, Stack Trace, vv

1

Bạn nên luôn luôn bắt ngoại lệ với một càng cụ thể lớp càng tốt.

Nếu bạn biết phải làm gì nếu tệp bị khóa, nhưng bạn coi tất cả các lỗi khác là không mong muốn và không thể xử lý, bạn nên bắt số System.IO.IOException và xử lý lỗi. Bạn chỉ nên bắt được Exception (hoặc chỉ catch {) để thoát ra một cách duyên dáng.

2

Ngoại lệ nào để sử dụng thực sự phụ thuộc vào mã trong khối thử. Nói chung, bạn muốn nắm bắt các ngoại lệ mà bạn có thể làm điều gì đó và cho phép ngoại lệ bạn không có quyền chuyển sang các cấp cao của mã của bạn, nơi bạn có thể thực hiện một số hành động tạo ra từ đó. Một trong những sai lầm phổ biến nhất mà tôi thấy mọi người mắc phải là cố gắng bắt lỗi mà họ không có khả năng xử lý.

ví dụ

Void ChoseFile() 
{ 
    try 
    { 
     string FileName = GetInputFile() 
    }  
    catch(InvalidFileSelectedException ex) 
    { 
     //In this case we have some application specific exception 
     //There may be a business logic failure we have some ability 
     //to infomr the user or do an action that makes sense 
    } 
    catch(FileNotFoundException exfilenot found) 
    { 
     //In this case we can do somthing different the the above 
    } 
    catch(Exception) 
    { 
     //Normal I would not use this case we have an error we don't know what to do 
     //with. We may not have a usefull action. At best we can log this exception        
     // and rethrow it to a higher level of the application that can inform the user 
     // fail the attempted action. Catching here would only suppress the failure. 
     } 

} 
0

ngoại lệ xử lý triết lý tôi chắc chắn bạn có thể tìm thấy nhiều triết lý khác

Mã việc phòng thủ. Bắt ngoại lệ là tốn kém hơn so với ngăn chặn các lỗi ở nơi đầu tiên.

Không bắt ngoại lệ và chôn nó bằng cách không xử lý. Bạn có thể dành nhiều giờ cố gắng tìm một lỗi đã bị chặn.

Làm các lỗi nhật ký mà bạn nắm bắt. Điều này giúp phân tích vấn đề.Bạn có thể kiểm tra xem nhiều hơn một người dùng có cùng một vấn đề không. Tôi thích một cơ sở dữ liệu để ghi nhật ký, nhưng một tệp phẳng hoặc nhật ký sự kiện cũng phù hợp. Giải pháp cơ sở dữ liệu dễ nhất để phân tích nhưng có thể đưa ra các lỗi bổ sung.

Nếu lỗi do dữ liệu xấu do người dùng nhập, hãy thông báo cho người dùng về sự cố và cho phép họ thử lại. Luôn cho phép tuyến đường thoát hiểm nếu chúng không thể khắc phục được sự cố.

Bắt lỗi gần nguồn nhất có thể Đây có thể là quy trình cơ sở dữ liệu, phương pháp trong lớp truy cập dữ liệu (DAL) hoặc một số vị trí khác.

Xử lý ngoại lệ khác với việc bắt nó. Bạn có thể cần phải tính lại ngoại lệ để nó có thể được xử lý cao hơn trong ngăn xếp hoặc trong giao diện người dùng.

Làm lại ngoại lệ có thể được thực hiện theo ít nhất hai cách. tự ném không làm thay đổi ngăn xếp. throw ex không thay đổi hoặc thêm vào stack mà không có lợi ích.

Đôi khi tốt nhất là không bắt ngoại lệ, nhưng thay vào đó hãy để nó phát sáng.

Nếu bạn đang viết dịch vụ (web hoặc cửa sổ) không có giao diện người dùng (UI) thì bạn nên luôn ghi nhật ký lỗi. Một lần nữa, điều này là để ai đó có thể phân tích nhật ký hoặc tệp cơ sở dữ liệu để xác định điều gì đang xảy ra.

Bạn luôn muốn ai đó biết rằng đã xảy ra lỗi.

Có rất nhiều câu lệnh bắt cho khối thử có thể làm cho mã của bạn khó bảo trì hơn, đặc biệt nếu logic trong khối catch của bạn phức tạp. Thay vào đó, mã phòng thủ.

Hãy nhớ rằng bạn có thể thử bắt các khối trong khối catch.

Ngoài ra, đừng quên sử dụng khối cuối cùng khi thích hợp. Ví dụ, đóng kết nối cơ sở dữ liệu, hoặc xử lý tập tin, vv

HTH Harv