views:

770

answers:

9

What are the guidelines for when to create a new exception type instead of using one of the built-in exceptions in .Net?

The problem that got me thinking is this. I have a WCF service, which is a basic input-output service. If the service is unable to create an output, because the input is invalid, I want to throw an exception, but which one?

Right now I'm just throwing system.Exception, but this doesn't feel right to me, I don't know why, it just feels wrong. One thing that bugs me, if I test it with a unit test and I expect the system.Exception to be thrown. The exception could as well be thrown by the framework or other code and not by the code I excepted to throw. The test would then pass, as I get the expected exception, but it should have failed.

What do you recommend?

+13  A: 

Avoid throwing System.Exception or System.ApplicationException yourself, as they are too general.

For WCF services there are Fault Contracts - a generic exception that you can tell subscibers to handle.

Flag the interface with:

[FaultContract( typeof( LogInFault ) )]
void LogIn( string userName, string password, bool auditLogin );

Then if there is an exception you can throw this specific fault:

throw new FaultException<LogInFault>( new LogInFault(), "message" );

Use the [DataContract] serialisation on your fault - this saves you from having to handle all the serialisation stuff exceptions normally require.

Keith
@Keith- this is good. To make it even better provide an example of LoginFault.
RichardOD
+5  A: 

Definitely avoid throwing System.Exception for anything other than throwaway code.

If an argument to a method is invalid, throw ArgumentException (or some derived, more specific exception). Consult the docs for existing exceptions before creating your own - but it can often be useful to do so. (You can derive your own type of exception from ArgumentException, of course - if you've got some particular type of condition which you want to indicate from multiple places, creating a new type gives more information than just putting it in the error message.)

Now error handling in WCF may well be different to error handling within the "normal" framework - I suggest you refer to WCF-specific docs/books for that.

Jon Skeet
When using WCF, you usually want to distinguish exceptions that are due to client (sender) input from those due to a server problem/bug. ArgumentException is too general - better to use a FaultContract.
Joe
A: 

Always create a new exception type (or use a standard type if it suits you).

In that case you can handle the exceptions as a group.

Gamecat
+2  A: 

It's not a good idea to throw System.Exception. The biggest reason for this is the effect it has on the calling code. How should they handle the exception? If the calling code is going to handle the exception, then they have to catch every exception, which is probably not the best thing for them to do.

If a circumstance isn't covered by one of the standard exceptions, then you should create a new Exception object if the exception is something that calling code would be expected to handle as a special case.

Jeffrey L Whitledge
+2  A: 

System.Exception should only be used as a base class for Exceptions, never be thrown directly.

The Framework offers already a lot of valid Exception classes like ArgumentException, ArgumentNullException, InvalidOperationException, FormatException, OverflowException, etc...

You say you are doing I/O stuff, so a good idea is to look at similar operations in the framework (like int.Parse) and throw the same exceptions for similar errors.

Or derive your own exception class from an existing exception class if none of them really fits your needs.

Fionn
+1  A: 

What are the guidelines for when to create a new exception type instead of using one of the built-in exceptions in .Net?

When there is no suitable predefined exception class.
.NET FW is very rich, often you can find predefined exception.

If the service is unable to create an output, because the input is invalid

ArgumentException Class (System)

The exception that is thrown when one of the arguments provided to a method is not valid.

aku
A: 

As previous posters have stated, you shouldn't be throwing System.Exception. In fact, if you ran FxCop on your code, it would flag that as a rule violation.

I recommend having a look at Chapter 18 of Applied .NET Framework Programming, or chapter 19 of the more recent CLR via C# (2nd edition) for detailed guidance. Richter does an excellent job of correcting the misconceptions that a lot of developers hold about exceptions.

Both books contain a list of the exceptions defined by the Framework Class Library. Look at the list and figure out the most specific exceptions possible that your code can throw. If you can recover from an exception, do so in that catch block. If you have need of multiple catch blocks, organize them from the most specific to the least specific. Create a custom exception if you can't find one in the existing list that suits the situation.

Scott A. Lawrence
A: 

Thanks for the answers guys.

Some are suggesting that I use ArgumentException, I agree that would be a better choice than Exception. But it's still a very general exception, that could be thrown by other code than I intended to throw the exception. Giving me a false test result. But perhaps the chance is so small, that I shouldn't worry about it?

There is no try-catch block around the code that would be able to handle the exception.

I see no other solution that making a custom exception, if I want safe unit tests. But this leads me down a path, where I would be creating custom exceptions that would only be used for the unit test, which seems bad? I could also compare the exception message, but this would force me to make a string comparison. The test would then fail if I changed the exception message, giving me less robust tests.

Karsten
Fionn offered a pretty long list of more specific exceptions: ArgumentNullException, InvalidOperationException, FormatException, OverflowException. I think it's likely that one of these is appropriate for your case.
Scott A. Lawrence
+2  A: 

If you throw System.Exception, then the caller must catch System.Exception. Both sides of this are a no-no, since it leaves us telling the user "that didn't work", rather than something more useful.

An ArgumentException is useful if the caller passed in an invalid argument. If your function has an int parameter that you need to be an even number, then you would throw and ArgumentException telling the caller what parameter was invalid and why. However, if all arguments were valid but there is still a problem, you'll probably need a custom exception. This way the caller can tell the user excatly what went wrong.

The test for me is really on the calling side. If I would have a dozen catches that all did the same thing, then I really only needed one exception. However, if I had one catch and would have a statement telling the user one of three things went wrong, then I really needed three unique exceptions.

Jon B