Friday, April 29, 2011

In C#, are there any built-in exceptions I shouldn't use?

I was just wondering - are there any Exceptions defined in the .NET Framework that I shouldn't throw in my own code, or that it is bad practice to? Should I write my own?

From stackoverflow
  • You shouldn't throw any exception that is automatically thrown by the CLR due to user errors. For instance

    • StackOverflowException
    • NullReferenceException
    • AccessViolationException
    • etc ...

    The reason being is to do so creates confusion for people calling your API. Users should be able to distinguish between actively thrown exceptions by an API and exceptions that are not actively thrown (thrown by CLR).

    The reason is that at actively thrown exception generally represents a known state in an API. If I call an API and it throwns an ArgumentException, I have a reasonable expectation that the given object is in a good state. It recognized a potentially bad situation and actively accounted for it. On the other hand if it throwns a NullRefrenceException, that is an indication that the API encountered an unknown error and is now in an unreliable state.

    Another lesser reason is that these exceptions behave differently when thrown by user code as opposed to the CLR. For instance it's possible to catch a StackOverflowException if thrown by user code, but not if it's thrown by the CLR.

    EDIT Responding to Michael's comment

    You also should not throw Exception, ApplicationException or SystemException directly. These exceptions types are too general to provide meaningful information to the code which calls your API. True you can put a very descriptive message into the message parameter. But it's not straight forward or maintainable to catch an exception based on a message. It's much better to catch it based on the type.

    FxCop rule on this subject: http://msdn.microsoft.com/en-us/library/ms182338(VS.80).aspx

    Eddie : I agree, except for NullReferenceException ... unless it behaves differently, I think it's valid to throw this when someone passes null as a parameter that cannot be null.
    JaredPar : @Eddie you should use ArgumentNullException instead of NullReferenceException. And yes it does behavior differently. It will have a different HRESULT code.
    Michael : You should add "Exception" to the list. The only way to catch it would be to swallow _all_ exceptions.
    Eddie : Ah, then I withdraw my comment. :) And some C# code I inherited may have to be changed.
    JaredPar : @Michael, I corrected that and added a few more that is along those lines.
  • there are several exception already defined for you. Always try to use these Exceptions before roll your own

    dfa : @downvoters: please explain your downvotes, or they're pointless
  • Most exception classes in the framework are not meant for reuse since they usually are crafted to signal some Framework specific error. Like those mentioned by @JaredPar, they are used by the framework to indicate certain states in the framework.

    There are literally tens, maybe hundreds, exceptions in the framework, so IMO it is more useful to list those that we should use. At the top of my head, these are those I actively use:

    For other error conditions in user code, best practice is to create your own exception classes.

  • Microsoft was at one point telling programmers not to inherit directly from Exception, but instead to use ApplicationException as their base class. Not sure if that opinion still holds true, though...

    And if a pre-defined exception already exists that covers your exact error condition (like "NullReferenceException", or "InvalidArgumentException" etc.) - by all means, throw those instead of re-inventing them inside your own code.

    Marc

    JaredPar : Yeah, the stance on ApplicationException changed. It is now recommended to not derive from that class: http://blogs.msdn.com/brada/archive/2004/03/25/96251.aspx
    BlackWasp : Between .NET 2.0 and 3.0 I think. The advice to derive from ApplicationException in .NET 2.0 still exists on MSDN for 2.0 and earlier - http://msdn.microsoft.com/en-us/library/system.applicationexception(VS.80).aspx. For 3.0 it changed - http://msdn.microsoft.com/en-us/library/system.applicationexception(VS.85).aspx
  • The online Design Guidelines for Exceptions contains the principle advice (see specifically this page).

    The book "Framework Design Guidelines: Conventions, Idioms, and Patterns for Reusable .NET Libraries, 2nd Edition" has more details and more discussion on this topic.

  • @Michael There is actually one situation in which it is recommended to throw a NullReferenceException: If the first parameter (the "this" parameter) of an extension method is null. You need to do this in order that null variables behave as expected.

0 comments:

Post a Comment