ApplicationException cho .NET là gì?


172

Để ném ngoại lệ, tôi thường sử dụng các lớp ngoại lệ tích hợp, ví dụ ArgumentNullExceptionNotSupportedException. Tuy nhiên, đôi khi tôi cần sử dụng một ngoại lệ tùy chỉnh và trong trường hợp đó tôi viết:

class SlippedOnABananaException : Exception { }
class ChokedOnAnAppleException : Exception { }

và như thế. Sau đó, tôi ném và bắt những thứ này trong mã của tôi. Nhưng hôm nay tôi đã đi qua ApplicationExceptionlớp học - tôi có nên sử dụng nó không? Cái này để làm gì?

Có vẻ như không hiệu quả khi có rất nhiều lớp Ngoại lệ giống hệt nhau với các tên khác nhau (tôi thường không cần bất kỳ chức năng riêng lẻ nào). Nhưng tôi không thích ý tưởng bắt một cái chung ApplicationExceptionvà phải sử dụng thêm mã để xác định lỗi là gì.

Trường hợp nên ApplicationExceptionphù hợp với mã của tôi?


35
Câu hỏi tuyệt vời, cũng là +1 cho các trường hợp ngoại lệ mẫu được đặt tên khéo léo
Cody Grey

Câu trả lời:


100

Theo các nhận xét trong msdn:

Các ứng dụng người dùng, không phải thời gian chạy ngôn ngữ chung, đưa ra các ngoại lệ tùy chỉnh xuất phát từ lớp ApplicationException. Lớp ApplicationException phân biệt giữa các ngoại lệ được xác định bởi các ứng dụng so với các ngoại lệ được xác định bởi hệ thống.

Nếu bạn đang thiết kế một ứng dụng cần tạo ngoại lệ của riêng mình, bạn nên rút ra các ngoại lệ tùy chỉnh từ lớp Exception. Ban đầu người ta nghĩ rằng các ngoại lệ tùy chỉnh sẽ xuất phát từ lớp ApplicationException; tuy nhiên trong thực tế điều này đã không được tìm thấy để thêm giá trị quan trọng. Để biết thêm thông tin, hãy xem Thực tiễn Tốt nhất để Xử lý Ngoại lệ.

Xuất phát từ họ Exception. Ngoài ra, tôi không thấy vấn đề gì với việc tạo ra ngoại lệ mới cho các trường hợp của bạn, miễn là nó được bảo hành. Nếu bạn gặp trường hợp đã có ngoại lệ trong khung, hãy sử dụng trường hợp đó, nếu không, hãy tự xử lý.


9
Vì vậy, có vẻ như nó ApplicationExceptionlà vô dụng và chỉ có vì khả năng tương thích ngược?
Beatles1692

Tài liệu MSDN mới, ít nhất 4.7.2, bỏ lỡ nhận xét này. Cảm ơn vì qutoe: D
Alex

147

Câu trả lời ngắn gọn là: hư không.

Đây là một di tích của quá khứ, nơi Microsoft dự định các nhà phát triển kế thừa tất cả các ngoại lệ tùy chỉnh của họ từ ApplicationException. Ngay sau đó, họ đã thay đổi quyết định và khuyên rằng các ngoại lệ tùy chỉnh nên xuất phát từ lớp Exception cơ sở. Xem Thực tiễn tốt nhất để xử lý ngoại lệ trên MSDN.

Một trong những lý do được lưu hành rộng rãi hơn cho điều này xuất phát từ một đoạn trích từ Jeffery Richter trong Nguyên tắc thiết kế khung :

System.ApplicationException là một lớp không phải là một phần của .NET Framework. Ý tưởng ban đầu là các lớp xuất phát từ SystemException sẽ chỉ ra các ngoại lệ được ném từ chính CLR (hoặc hệ thống), trong khi các ngoại lệ không phải CLR sẽ được lấy từ ApplicationException . Tuy nhiên, rất nhiều lớp ngoại lệ không theo mô hình này. Ví dụ: TargetInvocationException (được CLR ném) có nguồn gốc từ ApplicationException . Vì vậy, lớp ApplicationException mất hết ý nghĩa. Lý do để xuất phát từ lớp cơ sở này là cho phép một số mã cao hơn trong ngăn xếp cuộc gọi để bắt lớp cơ sở. Nó không còn có thể bắt tất cả các ngoại lệ ứng dụng.

Vì vậy, có bạn có nó. Tóm tắt điều hành là ApplicationException không có hại , chỉ là vô dụng .


2
Có ai biết tại sao lại như vậy không? Có vẻ như nó sẽ có ý nghĩa để bạn có thể hiển thị các ngoại lệ của Ứng dụng nhưng không ngoại lệ "lập trình viên".
Josh Kodroff

9
BTW, có vẻ như từ lời giải thích này rằng đây không phải là một thiết kế tồi cho mỗi lần mà MSFT đã làm hỏng việc thực hiện. Có ai khác đọc điều này tương tự?
Josh Kodroff

8
@JoshKodroff: Tôi nghĩ vấn đề là nếu ứng dụng Whizbangquyết định rằng nó muốn có tất cả các ngoại lệ theo một hệ thống phân cấp chung nào đó, sử dụng ApplicationExceptioncho mục đích đó thực sự sẽ không có lợi thế gì khi sử dụng WhizbangExceptionlớp cơ sở tùy chỉnh . Tuy nhiên, vấn đề nghiêm trọng hơn trong hệ thống phân cấp ngoại lệ của .net là không xảy ra ApplicationException, nhưng với việc không tách các ngoại lệ thành các danh mục có thể gây tử vong cho ứng dụng, có thể gây tử vong và liên quan đến vấn đề cục bộ, cùng với việc không thể có ngoại lệ "tổng hợp" có ý nghĩa.
supercat

@JoshKodroff: Trong một khuôn khổ ngoại lệ đúng thiết kế, IMHO, nếu một ngoại lệ được ném trong finallykhối trong khi ngoại lệ khác đang chờ, catchkhối tiếp tục lên các cuộc gọi stack nên được kích hoạt nếu chúng phù hợp bất kỳ ngoại lệ lồng nhau, nhưng để lại ngoại lệ khác cấp phát để thoát một catchkhối sẽ tiến tới một catchkhối khác trong cùng một trykhối (nếu có phù hợp) và thoát khỏi một finallykhối có bất kỳ ngoại lệ nào đang chờ xử lý sẽ chuyển sang bên ngoài tiếp theo catchhoặc finally.
supercat

2
@JoshKodroff Có một điều nữa khiến tôi ngạc nhiên không được chú ý nhiều hơn. Một "ứng dụng" thực sự là gì? Thư viện bên thứ ba thì sao? Vì đây không phải là một phần của khung .Net, nên theo nguyên tắc ban đầu, chúng sẽ được kế thừa từ ApplicationException. Bây giờ khi bạn sử dụng thư viện đó trong ứng dụng của mình và cũng tạo cho bạn ApplicationExceptions, bạn không còn có thể nhận ra các ngoại lệ của riêng bạn khỏi ngoại lệ của thư viện dựa trên điều đó. Vì vậy, nó vô dụng. Thay vào đó, mỗi thành phần chỉ cần xác định loại cơ sở ngoại lệ của riêng mình, như supercat mô tả.
Oskar Berggren

22

Trong thiết kế ban đầu, trong .NET 1.0, đã có kế hoạch rằng chính khung công tác sẽ ném SystemExceptionvà xuất phát; trong khi các ứng dụng người dùng - sẽ ném ApplicationExceptionvà dẫn xuất.

Nhưng sau đó, trong .NET 2.0, điều đó đã bị loại bỏ.

Do đó xuất phát từ Exception.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.