FAQ: What exception should I throw instead of the reserved exceptions that DoNotRaiseReservedExceptionTypes warns against?


Throwing a general exception type such as System.Exception or System.SystemException in a library or Framework forces consumers to catch all exceptions, including unknown exceptions that they do not know how to handle (see FAQ: Why does FxCop warn against catch(Exception)? for reasons as to why this is bad).


Instead, either throw a more derived type that already exists in the Framework, or create your own type that derives from Exception.


The following list examples of when you should throw specific exceptions:


When validating a parameter (including the value parameter in the set accessor of a property) that:



is a null reference (Nothing in Visual Basic) 
    throw System.ArgumentNullException


is outside of the allowable range of values (such as an index for a Collection/List)
    throw System.ArgumentOutOfRangeException (DO NOT throw System.IndexOutOfRangeException)


is outside the allowable values for a enum
    throw System.ComponentModel.InvalidEnumArgumentException


contains a format that not meet the parameter specifications of a method (such as the format string for ToString(String))
    throw System.FormatException


is otherwise invalid (such as an empty string)
    throw System.ArgumentException


When an operation is invalid for an object’s current state:
    throw System.InvalidOperationException


When an operation is performed on an object that has been disposed:
    throw System.ObjectDisposedException


When an operation is not supported (such as in an overridden Stream.Write in a Stream opened for reading):
    throw System.NotSupportedException (DO NOT throw System.NotImplementedException)


When a conversion would result in an overflow (such as in a explicit cast operator overload):
    throw System.OverflowException


For all other situations, consider creating your own type that derives from Exception and throwing that.


Note: Exceptions that derive from ArgumentException (including ArgumentNullException, ArgumentException, ArgumentOutOfRangeException and InvalidEnumArgumentException), InvalidOperationException (including ObjectDisposedException) and NotSupportedException should only be thrown in situations that are avoidable (such as passing a null argument) and if thrown, would indicate a bug in the calling code. The Path class is not a good example of this, it incorrect throws ArgumentException to indicate that a path is incorrectly formed, however, it does not expose any methods that can help prevent this from occurring.

Comments (14)

  1. PeterI says:

    Hmm I’m not sure I understand the IndexOutOfRange one, it seems like a perfect match (or is this a case where matching the rest of the framework is better)

  2. Jarle Nygård says:

    Nice! Thnx for this! :)

  3. davkean says:

    IndexOutOfRangeException is an exception that should be only thrown by the runtime when an index used to access an element is outside of the bounds of the array. To be consistent with the other .NET Framework classes (such as ArrayList, List<T>, Collection<T>, etc), you should throw ArgumentOutOfRangeException.

  4. Jeff Stong says:

    Wondering which exception type to throw rather than the too general System.Exception? Find some…

  5. PeterI says:

    Thanks for that, perhaps you should kick the MSDN doc folks and get that stuck on the documentation page.

  6. davkean says:

    Peter,

    Thanks for the suggestion. We’re working at the moment on making the docs better – expect to see information such as above, included for Orcas.

    Regards

    David

  7. Kevin Westhead says:

    Shouldn’t it be ArgumentOutOfRangeException for enums as well? This was mentioned in the comments of an earlier Enum design guideline (see http://blogs.msdn.com/kcwalina/archive/2004/05/18/134208.aspx), but perhaps best practice has changed since then? It certainly seems like most APIs outside of Windows Forms use ArgumentOutOfRangeException.

  8. davkean says:

    Kevin,

    Good spotting. However, if you look at Brad’s annotation further down the page you will see that he is throwing an InvalidEnumArgumentException.

    I’ve actually explained the reason behind these contradictions in a Community content block at the bottom of the docs on InvalidEnumArgumentException, which I will re-post here:

    Unfortunately, as InvalidEnumArgumentException is defined in System.dll and not mscorlib.dll, the later does not throw it when an invalid enum argument is passed to a member, but instead throws ArgumentException or ArgumentOutOfRangeException. This inconsistancy however, usually does not present a problem, as this exception, when thrown, typically indicates a bug in the caller and is rarely caught within a catch clause.

  9. .NET 2.0 says:

    The Confusing "Cannot implicitly convert type ‘string’ to ‘System.Web.UI.WebControls.TextBox’" Compilation

  10. Krzysztof Cwalina, owner of the Framework Design Guidelines , has written a great post on How to Design

  11. Since I started monitoring traffic on this blog a little more closely about a week ago, I had the unexpected