24

In a follow-up to a previous question regarding exceptions, what are best practices for creating a custom exception in .NET?

More specifically should you inherit from System.Exception, System.ApplicationException or some other base exception?

Community
  • 1
  • 1
mattruma
  • 16,589
  • 32
  • 107
  • 171

5 Answers5

26

In the C# IDE, type 'exception' and hit TAB. This will expand to get you started in writing a new exception type. There are comments withs links to some discussion of exception practices.

Personally, I'm a big fan of creating lots of small classes, at that extends to exception types. For example, in writing the Foo class, I can choose between:

  1. throw new Exception("Bar happened in Foo");
  2. throw new FooException("Bar happened");
  3. throw new FooBarException();

where

class FooException : Exception 
{
    public FooException(string message) ... 
}

and

class FooBarException : FooException 
{
    public FooBarException() 
        : base ("Bar happened") 
    {
    }
}

I prefer the 3rd option, because I see it as being an OO solution.

Jay Bazuzi
  • 45,157
  • 15
  • 111
  • 168
16

Inherit from System.Exception. System.ApplicationException is useless and the design guidelines say "Do not throw or derive from System.ApplicationException."

See http://blogs.msdn.com/kcwalina/archive/2006/06/23/644822.aspx

Patrick D'Souza
  • 3,491
  • 2
  • 22
  • 39
Mark Cidade
  • 98,437
  • 31
  • 224
  • 236
  • 5
    According to Jeffrey Richter, the original idea was that classes derived from SystemException would indicate exceptions thrown from the CLR (or system) itself, whereas non-CLR exceptions would be derived from ApplicationException. But since a lot of of exception classes thrown by the CLR didn’t follow this pattern, the ApplicationException class lost all meaning. The reason to derive from this base class is to allow some code higher up the call stack to catch the base class but it's impossible to catch all application exceptions since some CLR exceptions inherit from ApplicationException. – Mark Cidade Jan 07 '11 at 19:44
  • @MarkCidade: The fact that some CLR exceptions inherit from `ApplicationException` might actually be a good thing if there were a consistent distinction in the hierarchy between exceptions which mean "The operation couldn't succeed, but the attempt didn't do anything; if you're prepared for that, great", versus "Something has gone so horribly wrong that almost everything should be presumed corrupt; the only reasons not to shut things down instantly would be if one wants to capture diagnostic information or trigger an automatic relaunch, first." Too bad there's no such distinction. – supercat May 17 '13 at 15:01
  • @supercat It might be the case that the context of the application determines whether doing nothing is recoverable or is a reason to fail fast (e.g., almost-real-time systems where something HAS to be successfully attempted all the time). – Mark Cidade May 19 '13 at 16:01
  • @MarkCidade: In some situations, such as when deserializing an object, explicitly accounting for all the things that might go wrong would greatly complicate code. In many cases, if a data stream cannot be deserialized to yield a valid object, one really doesn't care *why*. What one does care about is whether the attempt to load the datastream causes or indicates any problem *beyond* "document could not be opened". If 99% of the exceptions which could occur while deserializing a document should have those same semantics, it would be nice to be able to... – supercat May 19 '13 at 18:00
  • @MarkCidade: ...catch those 99% of exceptions without having to identify them all, and yet still not catch and swallow the 1% which indicate deeper problems. It's too bad neither vb.net nor C# offers fault blocks, since the proper behavior if an unexpected exception might leave an object in an invalid state would be to invalidate the object so most future actions will throw immediate exceptions. If the object is abandoned, its corruption will be a non-issue. If it's critical to operation, its invalidation will force a shutdown. – supercat May 19 '13 at 18:03
  • A well-designed library can use a single base exception for "document could not be opened", similar to `ArgumentException` vs. `ArgumentNullException`,`ArgumentOutOfRangeException`, etc., but whether that's a critical thing or can be re-tried, or ignored, is still completely up to the application that uses that library. – Mark Cidade May 20 '13 at 01:59
5

There is a code snippet for it. Use that. Plus, check your code analysis afterwards; the snippet leaves out one of the constructors you should implement.

1

I think the single most important thing to remember when dealing with exceptions at any level (making custom, throwing, catching) is that exceptions are only for exceptional conditions.

Thomas Owens
  • 114,398
  • 98
  • 311
  • 431
1

The base exception from where all other exceptions inherit from is System.Exception, and that is what you should inherit, unless of course you have a use for things like, say, default messages of a more specific exception.

Jon Limjap
  • 94,284
  • 15
  • 101
  • 152