2009-04-18 31 views

Trả lời

22

Bạn không nên ném bất kỳ ngoại lệ nào được CLR tự động ném do lỗi người dùng. Ví dụ

  • StackOverflowException
  • NullReferenceException
  • AccessViolationException
  • vv ...

Lý do là để làm như vậy sẽ tạo ra sự nhầm lẫn cho người gọi API của bạn. Người dùng có thể phân biệt giữa các ngoại lệ được kích hoạt một cách chủ động bởi một API và các ngoại lệ không được chủ động ném (do CLR đưa ra).

Lý do là tại trường hợp ngoại lệ được gửi tích cực thường đại diện cho một trạng thái đã biết trong API. Nếu tôi gọi một API và nó ném một ArgumentException, tôi có một kỳ vọng hợp lý rằng đối tượng đã cho ở trạng thái tốt. Nó nhận ra một tình huống có khả năng xấu và tích cực chiếm nó. Mặt khác, nếu nó ném ra một NullRefrenceException, đó là một dấu hiệu cho thấy API đã gặp lỗi không xác định và hiện đang ở trạng thái không đáng tin cậy.

Lý do khác thấp hơn là các ngoại lệ này hoạt động khác nhau khi được ném bởi mã người dùng thay vì CLR. Ví dụ, nó có thể bắt một StackOverflowException nếu được ném bởi mã người dùng, nhưng không phải nếu nó được ném bởi CLR.

EDIT Hưởng ứng lời nhận xét của Michael

Bạn cũng không nên ném ngoại lệ, ApplicationException hoặc SystemException trực tiếp. Các loại ngoại lệ này quá chung chung để cung cấp thông tin có ý nghĩa cho mã gọi API của bạn. Đúng, bạn có thể đặt một thông điệp rất mô tả vào thông số tin nhắn. Nhưng nó không thẳng về phía trước hoặc duy trì để bắt một ngoại lệ dựa trên một thông điệp. Nó tốt hơn nhiều để bắt nó dựa trên loại.

FxCop quy tắc về chủ đề này: http://msdn.microsoft.com/en-us/library/ms182338(VS.80).aspx

+0

Tôi đồng ý, ngoại trừ NullReferenceException ... trừ khi nó hoạt động khác nhau, tôi nghĩ rằng nó hợp lệ để ném điều này khi ai đó vượt qua null như một tham số không thể rỗng. – Eddie

+10

@Eddie bạn nên sử dụng ArgumentNullException thay vì NullReferenceException. Và có nó hành vi khác nhau. Nó sẽ có một mã HRESULT khác nhau. – JaredPar

+5

Bạn nên thêm "Ngoại lệ" vào danh sách. Cách duy nhất để bắt nó sẽ là nuốt _all_ ngoại lệ. – Michael

0

có một số ngoại lệ đã được xác định cho bạn. Luôn cố gắng sử dụng các Exceptions này trước khi cuộn

+0

@ downvoters: hãy giải thích downvotes của bạn, hoặc họ vô nghĩa – dfa

9

Hầu hết các lớp ngoại lệ trong khung không được sử dụng lại vì chúng thường được tạo ra để báo hiệu một số lỗi cụ thể của Khung. Giống như những người mentioned by @JaredPar, chúng được sử dụng bởi khuôn khổ để chỉ ra một số tiểu bang trong khuôn khổ.

Có nghĩa là hàng chục, có thể hàng trăm, ngoại lệ trong khuôn khổ, vì vậy IMO sẽ hữu ích hơn nếu liệt kê những thứ mà chúng tôi nên sử dụng.Ở phía trên đầu của tôi, đây là những người tôi chủ động sử dụng:

Đối với điều kiện lỗi khác trong mã người dùng , thực hành tốt nhất là tạo các lớp ngoại lệ của riêng bạn.

+0

Đồng ý. Và trên thực tế, bạn không nên ném một ngoại lệ mà một phương pháp khung sẽ ném nó thay thế. ** I.e. ** Nếu bạn đóng gói một Stack trong một lớp giám sát và có một phương thức gọi 'stack.Pop()', chỉ cần để đối tượng 'System.Collections.Generic.Stack ' ném 'InvalidOperationException'. Đừng tự ném nó sau khi kiểm tra> 0 phần tử. –

2

Microsoft đã từng nói với các lập trình viên không được kế thừa trực tiếp từ Ngoại lệ, mà thay vào đó sử dụng ApplicationException làm lớp cơ sở của họ. Không chắc chắn ý kiến ​​đó vẫn đúng ... Mặc dù ...

Và nếu ngoại lệ được xác định trước đã tồn tại bao gồm điều kiện lỗi chính xác của bạn (như "NullReferenceException" hoặc "InvalidArgumentException", v.v.) ném những thứ đó thay vì phát minh lại chúng bên trong mã của riêng bạn.

Marc

+2

Vâng, lập trường về ApplicationException đã thay đổi. Hiện tại, bạn không nên bắt nguồn từ lớp đó: http://blogs.msdn.com/brada/archive/2004/03/25/96251.aspx – JaredPar

+1

Giữa .NET 2.0 và 3.0 tôi nghĩ. Lời khuyên để lấy được từ ApplicationException trong .NET 2.0 vẫn tồn tại trên MSDN cho 2.0 và trước đó - http://msdn.microsoft.com/en-us/library/system.applicationexception(VS.80).aspx. Đối với phiên bản 3.0 đã thay đổi - http://msdn.microsoft.com/en-us/library/system.applicationexception(VS.85).aspx – BlackWasp

3

@Michael Thực tế là có một tình huống trong đó nó được khuyến khích để ném một NullReferenceException: Nếu tham số đầu tiên (tham số "this") của một phương thức mở rộng là null. Bạn cần làm điều này để các biến null hoạt động như mong đợi.

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