views:

210

answers:

6

I would assume that most User-defined Exceptions are for Business Logic level exceptions, but what are some good reasons to use a User-Defined Exception and what are some good examples?

Is a user-defined exception's only advantage that you can define a consistent Error Message?

What logic can be written inside exceptions to make them truly more useful?

After all, can't you just do this: throw new Exception("Some Error Message");

+1  A: 

No, they are not only for messages. You can look for User defined ones in the exception list of a catch block.

catch(UserDefinedException){}
catch(Exception){}

You can use User Defined Exceptions anytime you want to look for something specific that occurs. Maybe a Client ID is out of a specified range and you want to look for that specifically. Instead of having to parse the error message (which can be a pain, and is prone to errors, like if the message changes later down the road), you have an exception you use and you know that somewhere else in the code is specifically telling you "Hey this happened. You need to be aware of it."

Kevin
Good point. Yeah, I know you can use multiple catch blocks. My main thrust before was that I usually had the same handling, but a different error message.
Atømix
@Atomiton you can do that to. Have a new exception auto populate the error message. That is another use for it.
Kevin
+1  A: 

You should create very few user-defined exceptions. They should only be used if someone is going to catch the exception and do something specific with it. If throwing your exception instead of InvalidOperationException is not going to make the code behave differently, then throw InvalidOperationException.

John Saunders
-1 Don't agree, I do use `InvalidOperation`, when the operation that is being performed is invalid. However there is no reason you shouldn't create your own custom exceptions to better describe the problem that has occured. If everything just threw InvalidOperationException then you'd be back at "what if everything just threw Exception".
Sekhat
@Sekhat: you're mistaken. You should "describe" exceptions in the message. The _type_ of the exception should be used for programatically distinguishing between exceptions. If your custom exception means "something specific is invalid in the current state", then throw `InvalidOperationException` _unless some code needs to take a different path_ specific to your exception.
John Saunders
That makes sense, John. It's all about how you're going to handle it. If a `UserDefinedException` logs the error msg to errors.log and `InvalidOperationException` does the same thing, then you're not handling the errors differently anyhow... so distinguish the difference in the message.
Atømix
@Atomiton: I hope you don't mean that you have the exception classes doing logging?
John Saunders
@John: Nope... Error logging done in the catch block.
Atømix
@Atomiton: good.
John Saunders
+1  A: 

User defined exceptions can be used within a component to allow consumers of the component the ability to catch them with a greater level of granularity then the catch (Exception) block. This will provide the component consumer with the ability to perform different tasks, based on which exception has been thrown. User defined exceptions should only really be created when there is a real expectation that consumers will use them to differentiate in this way.

Daniel Dyson
+1  A: 

You can also add properties to store additional meta-data with a user-defined exception, such as an error code (for example when calling an unmanaged API). This is more user-friendly than simply putting stuff into the Data property of the Exception object.

Mark Heath
But of course, any extra data doesn't matter if nobody catches the specific exception, and the extra data is of no value unless someone uses the extra data.
John Saunders
+3  A: 

Having user-defined exceptions is useful because it allows you to handle different kinds of errors in specific ways. Why does .NET define so many different types of exceptions if they could just throw all exceptions as System.Exception with a different text message? The reason that there are different types of exceptions in .NET is that you can catch individual types of errors and handle them differently. That's the same reason you would define your own user exceptions - so that you can provide a different response based on the type of exception that occurred.

You can also create user-defined exceptions that include additional data. For example, you could define a severity level based on an enum, an integer error code or anything else that might be useful to the calling program to identify what went wrong. As for logic to include in exceptions, I generally just try to report what went wrong and leave the logic (what to do about the error) to the calling program. In some cases, I have the exception code automatically write the error to a log file if it has exceeded a certain severity level (e.g. warnings are thrown but only critical errors are written to the log file).

TLiebe
But .NET is a framework, with a huge variety of callers, with a huge variety of needs. In the context of a single application, this is not true, and it's possible to more narrowly define the requirements. In particular, it's possible to know whether any code cares about whether you've thrown your custom exception or some other.
John Saunders
I agree that there is no sense in throwing specific exceptions that nobody is going to catch anyway but one option you might not be considering is to inherit from existing .NET exception types. For example, you can define your own exception that inherits from InvalidOperationException. That way, a user of your class/library can either catch an InvalidOperationException or the more specific exception that you created (assuming the custom invalid operation exception is caught first in the catch block). The more specific error (presumably with better info) is available for those that need it.
TLiebe
Good answer. Any common examples of Standard UserDefined Exceptions? So, for example, you could log UserErrors in a different location. So, for example a DiscountExceededException could be logged differently as the end user ( Finance Department ) will care about that, whereas standard Application Exceptions may just be logged to a txt file for the admin?
Atømix
@TLiebe: yet my point remains. If nobody is going to catch your derived exception, then why derive it? Just use the base exception type that you would have derived from. Add your "better info" to the Message property, where someone will see it.
John Saunders
@Atomiton: If they're to be logged differently, then that's a case where the code will be different based on the exception type, and it would make sense to wrap those exceptions in a user-defined exception type.
John Saunders
@John Saunders: if the code is properly documented then the person using the class/library should know what type of exceptions are going to be thrown. At that point, it's up to them to make the decision whether to catch a generic error or a more specific one. I think most programmers would want to catch the derived exception to handle the error in the best way.
TLiebe
@TLiebe: it seems a waste of time to create the derived exception because someone _might_ use it. I'd wait until there was an actual requirement to catch the derived exception.
John Saunders
+2  A: 

There are quite a lot of Exceptions already in the .NET framework, which you should use if you can find one that could be used for your exceptional circumstance.

For example, in my configuration classes (which are normally wrappers around the ConfigurationManager) I throw ConfigurationErrorsException when ever a value can't be parsed correctly.

When parsing custom values from text or something else that requires a specfic format and the parsing fails, I throw a FormatException

However if my BankAccount object doesn't have enough money in it for me to withdraw £10 then I'll write and throw InsufficentFundsException because then that way I can handle that specific error case, if it ever occurs.

Hope this (somewhat) helps.

Sekhat
@Sekhat: if the handling of `InsufficientFundsException` is different from the handling of `InvalidOperationException`, then this is a good choice. If the handling is the same, then it's not.
John Saunders