tags:

views:

453

answers:

8

There are already lots of questions on SO about exceptions, but I can't find one that answers my question. Feel free to point me in the direction of another question if I've missed it.

My question is quite simple: how do other (C#) developers go about choosing the most appropriate type of exception to throw? Earlier I wrote the following code:

    if (Enum.IsDefined(enumType, value))
    {
        return (T)Enum.Parse(enumType, value);
    }
    else
    {
        throw new ArgumentException(string.Format("Parameter for value \"{0}\" is not defined in {1}", value, enumType));
    }

I have since realised that throwing an InvalidEnumArgumentException would probably have been more appropriate had I known of its existence at the time.

Is there an authoritative resource available that helps developers chose exception types, or is it simply a matter of experience?

Edit

I've given the points to Noldorin for providing a range of ideas in a well thought-out answer. The points could have gone to any one of you really - thanks for all the suggestions.

+3  A: 

Common Exception Types and their Explanations

I think this will probably help you find out what the most appropriate exceptions for you to use are. You can also look into the MSDN documentation for more information on the Exception class and all of its types if you need.

TheTXI
Hmm, that article is far from exhaustive. What did developers do before that article existed? I'm searching for a *definitive* resource, thanks.
Paul Suart
thedorko: The MSDN documentation (which I have provided some links now) will give you a much more thorough list of the exception types. But as a later poster said, a lot of it does come down to a mix of experience and good old fashioned intuition. And as Grzenio posted below, developer-defined exception classes don't hurt either, although the time spent creating all the specific exception types you need may not be worth it in the end.
TheTXI
Apologies, didn't mean to be short. As you say, "a mix of experience and good old fashioned intuition" seems to be the answer - which is fine. I felt that I was missing something as I have been using intuition until now but still find it annoying when I discover a more appropriate type I could have used. As Jamie Ide points out, unless you're going to handle each type differently, there's not much point worrying about throwing a specific exception type anyway.
Paul Suart
Correct. If you focus on the obvious ones you'll be safe. If you have to force yourself to dig through the archives for a definition on an esoteric and little-used exception type, you'd be better off using a more common one (even if it won't necessarily be the best fit) or creating your own (where at least then you would be aware of what it is for).
TheTXI
+1  A: 

I usually define my own structure of exceptions, first creating some base exception:

class MyProjectNameException:Exception
{
...constructors, etc
}

and then derived classes for more precise exceptions. In this way you know exactly when to expect which exception, and you know if the exception was thrown by you or by the framework.

Grzenio
Good tip, thanks. Would you never consider throwing one of the standard exception types?
Paul Suart
its not a good practice to create new exception types, just to have your own teams exceptions
Peter Gfader
+1, I agree. Coming from a Java background, this is what I always did although I feel like I use exceptions much less in C# than in Java because of the lack of checked exceptions (something I really miss from the Java world).
Eric Petroelje
+4  A: 

I would say it's just down to experience. There's still new exceptions I discover every so often, and I've been working many aspects of .NET for a while now! What would you want this source to tell you, anyway? Choosing the appropiate exception type would seem highly context-specific, so I'm doubtful over the level of advice it could offer. Listing the more common ones would be at the most it could provide. The names and Intellisense descriptions of the exception types typically explain with good clarity their usage scenarios.

My recommendation is simply to familiarise yourself with all of the fundamental ones (specifically, those in System, System.IO, and any other namespaces you often use), and learn the others along the way. I find that I get generally get away using just a small number. If you accidentally use a more generic exception type when there already exists a more specific one in the BCL, then it's no great crime, and can be changed later easily enough. To be honest, for any error that's particularly specific, you will often need to create your own class inheriting from Exception anyway.

Hope that helps.

Edit: If you want a brief guide to the very common ones, see the Common Exception Classes page on MSDN.

Noldorin
Great, thanks for the advice. I've been writing C# for 5 years or so now, and have often wondered if I was missing something. It's reassuring to know that it genuinely is just a matter of experience :)
Paul Suart
@thedorko: No problem... And yeah, as long as you know the important ones (no more than a dozen perhaps), there's nothing to worry.
Noldorin
+1  A: 

I have most of the common exceptions written on postcards on my desk and use them when people try and interop with me in a way that is exceptional.

This is really good practice for working out which exception fits best...

The one I find myself using mostly is OperationNotSupportedException

ck
Do you throw the postcard at them?
Paul Suart
Haha... like the way to learn/remember stuff
Peter Gfader
+2  A: 

I think the real question is to ask yourself "What type of exception do I want to handle?" If you're not going to have special handling for an InvalidEnumArgumentException or an ArgumentException, then they offer no advantage over a plain old Exception.

I typically either throw Exception or wrap the exception in a custom exception.

Edited to add: At one point, I recall that the guidance from Microsoft was that your application should never throw framework exceptions, rather it should only throw extensions of ApplicationException.

Jamie Ide
Another good point, thanks!
Paul Suart
Since InvalidEnumArgumentException inherits from ArgumentException, catching ArgumentException you can catch both...
Peter Gfader
+8  A: 

Krzysztof Cwalina has a good post on this see chapter "1.1.1 Choosing the Right Type of Exception to Throw"

PS Consider subscribing to his blog. Good reading!

To answer your question: InvalidEnumArgumentException
because throw the most specific (the most derived) exception that makes sense.

AND callers that catch ArgumentException, catch InvalidEnumArgumentException too...

Peter Gfader
Thanks for the link.
Paul Suart
and callers that catch ArgumentException, catch InvalidEnumArgumentException too...
Peter Gfader
That IS a great blog!
RedFilter
+1  A: 

If you find an exception that is a good fit, you can use it.

If in doubt, just use ApplicationException. It's the exception that is intended for code that is not part of a standard library.

If the exception is not intended to be used in a standardised way (like catching the base class IOException to catch any I/O related error), the message that you put in the exception is more useful than the type of the exception.

Guffa
Some good tips here, thanks.
Paul Suart
+3  A: 

If you check out the MSDN article on System.Exception, right at the bottom of the page is a whole list of BCL exception types that inherit Exception. It's not quite a definitive list on what should be used for what - but it does give you a great place to start checking out exception types. Going through each will tell you what they should be used for:

There is also a fairly comprehensive article regarding the .NET Exception Hierarchy found at:

In fact the whole section in the MSDN library about handling and throwing exceptions is pretty good:

BenAlabaster
Thanks for the link.
Paul Suart