Pros and Cons of implementing a generic custom exception - c#

What are the pros and cons of implementing a custom exception as follows:
Create an enum which represents error messages in its descriptions:
public class Enums
{
public enum Errors
{
[Description("This is a test exception")]
TestError,
...
}
}
Create a custom exception class:
public class CustomException : ApplicationException
{
protected Enums.Errors _customError;
public CustomException(Enums.Errors customError)
{
this._customError = customError;
}
public override string Message
{
get
{
return this._customError!= Enums.Errors.Base ? this.customError.GetDescription() : base.Message;
}
}
}
The GetDescription method is an enum extension method which gets the enum description using reflection. This way, I can throw exception like:
throw new customException(enums.Errors.TestError);
And show it to the user in catch block like:
Console.WriteLn(ex.Message);
I've seen this approach recommended by an MVP. What are the benefits of this approach over the followings:
Using generic exception: throw new Exception("Error Message");.
Using Custom Exception: Define custom exceptions for any situation. e.g. (WebServiceException class, AuthenticationException class, etc.)
Here's the link to the recommendation by the MVP.
Thank you.

Personally, i don't think it's a good idea.
You should always throw as specific exceptions as possible. The same goes for catching.
It's easy to decide if we want to catch a WebServiceException or AuthenticationException, but with your Enum-example, we have to parse a string to decide if we want to catch it or not. What happens if this message changes?
I don't think it has any benefits at all. For each error type, you have to create a new Enum member. Why not create a new class instead?

The major advantage of custom exceptions is the language support for differentiation between different exception types. For example
try
{
SomeFunc()
}
catch( CustomException EX)
{
//This is my error that I know how to fix
FixThis()
DoSomeAwesomeStuff()
}
catch( Exception exa)
{
//Somthing else is wrong
WeepLikeBaby();
}
If I use the message Property
try
{
SomeFunc()
}
catch( Exception exa)
{
if(exa.Message == "ErrType 1")
{
DoStuff;
}
if(exa.Message == "ErrType 2")
{
Die();
}
}
Utilizing The Base enum example can still retain this capability. However you give yourself one place to define your messages, but that is solved in a variety of different ways by applications. The enum example would make creating localized messages pretty simple as It will give you A way to define your message strings independently.
Another Advantage is that you can add Cusotm data that makes sense in you application. Say for example you have a customer information system, and the customer ID is almost always going to be important. If you utilize the message property only, every handler will have to know how to parse out that information if needed.
public class MyCustomeEx : Exception
{
int CustID { get; set; }
}
public void Fail()
{
//Awww Customer error
throw new MyCustomeEx () {CustID = 123}
}

Option 1 I would not recommend. You should not be throwing System.Exception at all. You should always throw the most specific exception available for your situation in order to have reasonably structured exception handling in your code.
The major drawback I see in your proposed method (Errors enum) is that there is no way you can decide if you want to handle or not the exception without catching it first. With custom exceptions you can make that decision beforehand.

Please see my (accepted) answer at the following similar Stack Overflow question: Custom exception vs built in exception with very descriptive message. It should prove helpful in providing arguments against frivilous custom exceptions.

The link to the MVP's recommendation was shared in comments.
After looking at the code and the question I think the reason for this is to limit the possible messages in the exception. And maybe help with localizing exception texts, but then there's extra work to do in this example. Anyways, such a method shouldn't be used for creating "Exception sub-types" that are processed differently.

Related

Combining a single custom exception with an enum to easily create several sub-exceptions

I think I am need of writing one or more custom exceptions in C# 5.0. I am probably not, but it seems that the .NET provided exceptions belong to a too-systemic and too-generic domain of exceptions - very much specific to situation of "having a running program on the CLR supporting file I/O". This IS exactly what I have, at least, of course. Still, when trying to develop an application in C# or any other OO-language, a subset (or all) of the new types that you create, should in most circumstances originate from an ontology of concepts, which is nowhere close to such a systemic domain as the CLR or the .NET Framework. That's how I see the "authoring" part of OO development - but that's an entire different question really.
So, on the "problem" of creating custom exceptions, I wanted to hear if the following solution have any drawbacks.
Let's say I create this enum and custom exception:
public enum MyCustomExceptionKind
{
MyCustomInitializationException,
MyCustomStartException,
MyCustomStopException,
MyCustomFatalException
}
public class MyCustomException: Exception
{
private MyCustomExceptionKind? m_exceptionKind = null;
public MyCustomExceptionKind ExceptionKind
{
// return the value of the nullable type:
get { return m_exceptionKind.Value; }
}
// let's support only the most-exclicit instance constructor for now:
public EmployeeListNotFoundException(
MyCustomExceptionKind myCustomExceptionkind,
string message,
Exception inner): base(message, inner)
{
m_exceptionKind = myCustomExceptionkind;
}
}
The idea here, is the use of a built-in enumeration type. Instead of creating many new exception, I have chosen to use an enum for encoding the sub-type on an exception. Note that I also take use of a nullable enum-type by using the question-mark.
Handling such an exception would then behave something like this:
public class SomeType
{
public void StartUniverse(int num)
{
if (num != 42)
{
throw new MyCustomException(
MyCustomExceptionKind.AttemptToStart,
"It was not possible start the damn thing ...",
null);
}
}
public bool TryStart(int num)
{
tryOK = true;
try
{
StartUniverse(num);
}
catch (MyCustomException ex)
{
// set the overall state-bool to false:
tryOK = false;
// use a switch case for handling sub-types of this exception:
switch (MyCustomException.ExceptionKind)
{
case MyCustomExceptionKind.MyCustomStartException:
Trace.TraceError("oh dear - could not start");
break;
}
}
return tryOK;
}
static public Main(string[] args)
{
var myObj = new SomeType();
myObj.TryStart(199); // <-- 199 != 42
}
}
Anything to be aware of in such an implementation? Pros and cons? From where I stand, I see only good things. That's usually an illusion though.
Keep in mind that writing several different exception classes is effort you pay once; handling the different exception scenarios may come up many times. So try to focus on making this easier for the client that's going to handle these exceptions.
Compare the boilerplate of catching the general exception, peeking inside to check if it's actually relevant, and rethrowing otherwise, versus just catching a specialized exception type that you know you care about. The facilities to catch specific exception types and to derive new exception types work together to make it easier to just use specialized exception types than to use general exception types otherwise marked with special values. Don't work against the grain of the language.
If you anticipate your client wanting to catch all of your custom exceptions at the same site, you can make your custom exceptions inherit from a common MyCustomException class. This is essentially a superset of your enum solution; if someone catches the general MyCustomException class and then for whatever reason needs to know the specific type, they can just say (ex is MyCustomInitializationException). But you've still given your users the option to catch MyCustomInitializationException in the first place if that's what they care about.
Your approch is okay, as long as all ExceptionKinds are on the same level: all exception can be handled on the same layer and will result in the same handling (like showing a message box or stopping a task).
But for instance, when MyCustomFatalException should result in a program termination, then your approach is not the best, cause you would need to catch it twice
void DoStuff()
{
try
{
...
}
catch(MyCustomException inner)
{
if (inner.ExceptionKind == MyCustomExceptionKind.MyCustomFatalException)
throw;
// handle inner, show message box
}
}
void DoStuffTwice()
{
DoStuff();
DoStuff();
}
void Main()
{
try
{
DoStuffTwice();
}
catch(MyCustomException inner)
{
if (inner.ExceptionKind == MyCustomExceptionKind.MyCustomFatalException)
return;
// now what??
}
}
this does not look like a big deal, but on heavy load that may introduce a problem, because catching exceptions costs time, and catching an exception without the need of handling it, and just of the purpose of rethrowing it, can slow down your application.
BTW: I don't understand why you choose to make the ExceptionKindproperty return nullable value, since it can never be null.
If the exceptions are really the same thing with a different code (Like HttpStatus), then it makes sense. Otherwise I would create different Exception classes.

Should I catch exceptions in my method for "purely documenting" purposes?

Should I catch exceptions in my method for "purely documenting" purposes, thus encapsulating the error-documentation inside the method itself, or is that responsibility of the caller?
Suppose I call numerous other methods in my EncryptPackage() method, including the framework ones, which potentially throw numerous exceptions. I wrap everything in using blocks, so no need to catch exceptions for cleanup (or I use try/finally for cleanup). Should I catch the exception anyway, and provide the details about the context of that method, or is it the responsibility of caller method?
Here is the case one:
[Serializable]
class TestClassException : Exception
{
public TestClassException() : base() { }
public TestClassException(string message) : base(message) { }
public TestClassException(string message, Exception innerException) : base(message, innerException) { }
}
class TestClass
{
public TestClass() { }
public void EncryptPackage()
{
try
{
DoSomething();
DoAnotherThing();
}
catch (Exception ex)
{
throw new TestClassException("Error occurred during package encryption", ex);
}
}
}
class ConsumerExample
{
public ConsumerExample() { }
public void DoSomeStuff()
{
TestClass testClass = new TestClass();
try
{
testClass.EncryptPackage();
}
catch (TestClassException ex)
{
System.Windows.Forms.MessageBox.Show(ex.ToString());
}
}
}
In this code, notice how the EncryptPackage() method catches all possible exceptions, just to "decorate the error text", with a "Error occurred during package encryption" text. EncryptPackage() here encapsulates the error-description logic.
And here is another technique:
class TestClass2
{
public TestClass2() { }
public void EncryptPackage()
{
DoSomething();
DoAnotherThing();
}
}
class ConsumerExample2
{
public ConsumerExample2() { }
public void DoSomeStuff()
{
TestClass testClass = new TestClass();
try
{
testClass.EncryptPackage();
}
catch (Exception ex)
{
System.Windows.Forms.MessageBox.Show("Error occurred during package encryption.\r\n\r\n" + ex.ToString());
}
}
}
In this example, EncryptPackage() does not catch anything, because the caller documents the error case anyway with "Error occurred during package encryption.\r\n\r\n" message.
Please note that this is a very simplified example, in real world there will be numerous hierarchical classes, and exceptions will be propagating through the long call stack, so which method of catching exceptions is preferred? Second approach seems "cleaner", because the exception is handled in a layer where some "actual handling" (e.g. displaying to user) is going to take place. Call stack information would be preserved in exception object, so technically it will be possible to find out where exactly the exception was thrown. But... that does not seem as "well-documenting" as the first approach, where each level of abstraction adds its own description to the error, preserving the previous exception in an innerException member. In this case, when the execution leaves the TestClass layer, it already contains detailed description of the error that happened within this class. So this feels to be the better encapsulation of error-handling logic.
Which one to use?
There is a chapter on this in Effective Java:
Higher layers should catch lower-level exceptions and, in their place,
throw exceptions that can be explained in terms of the higher-level
abstraction. This idiom is known as exception translation.
I prefer your second example, mainly because it can signicantly reduce the amount of error handling code you have to write, especially if you are writing custom exceptions - with the first example you could end up with a lot of custom exception classes which do not give much benefit (you already have the call stack to tell you where the exception came from).
You might think it is nice to have a more descriptive error message, but who benefits from this? The end-user? Should you even be displaying exception messages to your user (and what language are you going to use)? A lot of the time the user just needs to know that there has been an internal error, and they should give up (restart), or try again. Do you the developer benefit? You are probably going to end up examining the call stack anyway with the source code in front of you, so you don't really need a more descriptive message, you can see for yourself what the code is doing at that point.
This is not a hard and fast rule. Most of the time I only catch exceptions at the top level, where I log them and report an error to the user. If you are reporting the exception directly to the user, then often the original exception does not benefit from translation, e.g., if you try to open a non-existent file, then the System.IO.FileNotFoundException is descriptive enough so why translate it to something else? Do you really want to make the same judgement call ("I know better than the library author so I am going to translate their carefully crafted exceptions") for all of the gazillions of exceptions out there? I only catch exceptions lower down if I want to recover from them (generally not possible), or, very rarely, I want to translate them to a more descriptive exception.
In a layered architecture, it can make sense to translate exceptions between the layers, e.g., catch exceptions coming out of the data access layer to a form suitable for the application layer, and similarly between the application layer and the user interface, but I don't know if you are working on that type of system.
If you want to document your exceptions, you should use the exception tag in the xml documentation for the method. This can then be used to general help files from the documentation, e.g., using SandCastle.
As per #Sjoerd above, translate exceptions so they are in the same level of abstraction. In your case EncryptPackage should translate any lower-level exceptions itself, NOT the caller.
Say the lower-level exceptions were from a DB layer (say DBException). Would the caller expect to understand DBException? The answer is NO: the caller wants to encrpt a package, not a DBException. The lower-level exceptions should be chained INSIDE the higher-level exception for debugging purposes.
Finally, I know TestClassException is an example, but make sure the exception class describes the problem clearly: I, personally, don't like bland, generic exception classes (except to make a common base-class for other exceptions).
You should try/catch in few, easily distinguished situations:
any method that can be invoked "externally", such as your app's entry point, UI events, multi-threaded calls and others. Put some log output or message on each and every catch you have. This will prevent your app from crashing (for the most part) as well as provide you or the user with some feedback on how to fix the problem.
when you can really handle the exception. This means your app can, for example, opt for a secondary database or server URL, apply a different processing etc.
when you want to prevent something optional from ruining the main workflow, for example failing to delete your temp file shouldn't cause your process to fail.
there are probably some other places where you'll need a try/catch but these should be rare
Always combine error handling with a decent way of logging and/or messaging the user, don't let any exceptions info disappear because that's how you get apps and don't behave well for "no apparent reason" - at least the reason should be made apparent.
Also - don't use exceptions to control your workflow. There really shouldn't be any "throw"s unless there's absolutely no other way of doing something.

Customize .NET framework generated exception messages?

I was wondering if there was a reasonable way to customize messages on exceptions that are thrown by the .NET framework? Below is a chunk of code that I write often, in many different scenarios to achieve the effect of providing reasonable exception messages to my users.
public string GetMetadata(string metaDataKey)
{
// As you can see, I am doing what the dictionary itself will normally do, but my exception message has some context, and is therefore more descriptive of the actual problem.
if (!_Metadata.ContainsKey(metaDataKey))
{
throw new KeyNotFoundException(string.Format("There is no metadata that contains the key '{0}'!", metaDataKey));
}
// This will throw a 'KeyNotFoundException' in normal cases, which I want, but the message "The key is not present in the dictionary" is not very informative. This is the exception who's message I wish to alter.
string val = _Metadata[metaDataKey].TrimEnd();
return val;
}
As you can see, I am essentially producing duplicate code just to use a different (better) message.
Edit:
What I am looking for, essentially is something like this:
KeyNotFoundException.SetMessage("this is my custom message!")
{
// OK, now this will send off the message I want when the exception appears!
// Now I can avoid all of that silly boilerplate!
string val = _Metadata[metaDataKey].TrimEnd();
}
At any rate, i don't think that such a feature exists, but if it did I would be very pleased indeed. Has anyone tackled this type of problem before? It's looking like I am going to wind up needed some type of extension method in the end...
Unless I'm missing something in your question, this is exactly what you're supposed to be doing. I'm pretty sure every exception includes an overload that takes string message as a parameter. If you want to provide information above and beyond the "default" provided by .NET, you need to set the specific message.
You seem to be doing this the right way to begin with. I would however change the way you check for exceptions:
public string GetMetadata(string metaDataKey)
{
try
{
string val = _Metadata[metaDataKey].TrimEnd();
return val;
}
catch (KeyNotFoundException ex)
{
// or your own custom MetaDataNotFoundException or some such, ie:
// throw new MetaDataNotFoundException(metaDatakey);
throw new KeyNotFoundException(string.Format("There is no metadata that contains the key '{0}'!", metaDataKey));
}
}
Just inherit from the KeyNotFoundException class and override the Message property to generate a more meaningful message and then use your own exception class with a proper constructor. This is exactly what inheritance was meant for, adding value. i.e.
throw new MetaDataKeyNotFoundException(string metaDataKey);
The Exception class already supports adding custom user data associated to a specific occurrence or scenario in which the error occurred through the use of the property Exception.Data.
From MSDN entry for that property, emphasis is mine:
Gets a collection of key/value pairs that provide additional user-defined information about the exception.
I know that you were looking to override the Message property, but using Data you can achieve the same by just making sure that the exception handler knows how to deal with this additional data.
An exception is an object. As with most objects, you can't control how the creator creates the object, whether or not the creator is the .NET Framework.
How would you even tell the .NET Framework what message to create under which circumstances? You would want one message on a KeyNotFoundException in the case you posted, and another message in a different circumstance. How would you distinguish the two situations?
KeyNotFoundException.SetMessage("this
is my custom message!");
There is no such feature (apart from messing with internals or resources maybe). But how should it work anyway. You would be changing the message for every piece of code that uses the exception - to some of which your new message would make no sense at all.
Consider some arbitrary use of the Dictionary class, or even some totally different code, that follows the "best practice" of reusing existing exception types, all of them would suddenly use your (very much) custom error message.
Here is a solution that I came up with, but I would like to note that it is more of a patch than anything. It does work, but probably isn't suitable for all applications. I couldn't even think of a good name for it either.
public class ContextDictionary<TKey, TValue> : Dictionary<TKey, TValue>
{
public TValue this[TKey key, string context]
{
get
{
if (!this.ContainsKey(key))
{
throw new KeyNotFoundException(string.Format("There is no {0} that contains the key '{1}'!", context, key));
}
return this[key];
}
set { this[key] = value; }
}
}
So now I can say something like this, and get the more descriptive exception message that I really want.
var _MetaData = new ContextDictionary<string,string>();
string val = _Metadata[metaDataKey, "metadata"].TrimEnd();

.net exceptions

When should I create my own custom exception class rather than using a one provided by .Net?
Which base exception class should I derive from and why?
Why create your own exception?
You create your own exception so that when you throw them, you can have specific catches and hence differentiate them from system thrown (unhandled) exceptions.
What class should you derive it from?
Earlier, it was standard practice for custom exceptions to be derived from ApplicationException class but over time, MS recommendations have changed encouraging developers to derive from System.Exception itself rather than ApplicationException
This may seem a bit obvious but you should create an exception when no built in exceptions make sense. Typically I will define a base exception for a library I am working on.
public class MyLibraryException : Exception
{
// .....
}
Then I will create an exception for situations that may arise when using the library.
public class SomethingHorribleException : MyLibraryException
{
// .....
}
Then the client can always know that my library will throw something that inherits MyLibraryException.
The goal of exception handling should be to create a clear understanding of what went wrong. Therefore, you should define your own exception any time the provided exceptions do not provide that clear understanding.
For example, I'm writing an application which converts Arabic Numerals to Roman Numerals. One of the constraints in this application is that Roman Numerals must fall within the range 0 < x < 4000.
private string ToRoman(int number)
{
if (number > 0 && number < 4000)
{
//ConvertHere
}
else
{
//Custom exception used for readability purposes.
throw new NumeralOutOfRangeException();
}
}
As for which base class to use, Microsoft recommends that user defined exceptions subclass Exception. (http://msdn.microsoft.com/en-us/library/seyhszts.aspx)
One reason to create your own exception is to be able to isolate them for catching. For example:
try {
// do stuff
} catch (MyCustomException e) {
// handle this known exception
}
All other exceptions can bubble up and be handled at another level.
The answers so far all look good, but I would also add:
To hide implementation details that might otherwise be exposed because you need to handle those exceptions.
E.g. You don't want your UI to catch SQLException. You should throw your own exceptions out of your data access code and let your UI deal with those. If you changed to a non database provider for data storage (e.g. XML, file system, etc), you would not need to change your UI code.
However, I would only do that if I was handling them in my UI code explicitly.
I'd create my own excpetion class if i wanted to add other properties to it such as variables, location, user name, num returned records etc.
essentially i'd create a class that would narrow down what the error was and how to re-create it.
edit
oh and you could add validation errors to an exception class that can be passed to the front end to show the errors.

Exception throws: encapsulate them or not?

Once I read an MSDN article that encouraged the following programming paradigm (its not 100% true... see edit):
public class MyClass
{
public void Method1()
{
NewCustomException();
}
public void Method2()
{
NewCustomException();
}
void NewCustomException()
{
throw new CustomException("Exception message");
}
}
Do you think this paradigm makes sense? Wouldn't it be enough to store the exception message in a static const field and then pass it to the exception's constructor, instead of encapsulating the whole exception throw?
EDIT:
Use exception builder methods. It is
common for a class to throw the same
exception from different places in its
implementation. To avoid excessive
code, use helper methods that create
the exception and return it.
I just noticed (see citation), that the article tells to return an exception:
public class MyClass
{
public void Method1()
{
throw NewCustomException();
}
public void Method2()
{
throw NewCustomException();
}
CustomException NewCustomException()
{
return new CustomException("Exception message");
}
}
What do you think about this?
My understanding is that passing an exception instance around is a faux pas if for no other reason than you lose the stack trace associated with the exception. Calling another method would change the stack trace and thereby make it effectively useless. I'd recommend at a minimum getting the stack trace off the exception and passing it as an argument to some helper if that's the road you're going to go down.
That's a refactor too far in my book. You have to go back up a line in the stack trace to see exactly where the problem occured. If your custom exception is always using the same message, put it in the CustomException class. If it's only the same within the code you've quoted, then yes, put it in a const field (you can't have static const - it's implicitly static).
Another problem you get doing that is that there will be lots of places where you wont even be able to throw an exception because the compiler wont allow it. Consider these two methods added to your class:
public string GetFoo1(bool bar)
{
if (bar)
return "";
else
NewCustomException();
}
public string GetFoo2(bool bar)
{
if (bar)
return "";
else
throw new CustomException("Exception message");
}
GetFoo1 will not compile while GetFoo2 will.
I would have a method that builds an Exception, rather than one that throws it. As in the sample below. I seem to remember seeing a Microsoft guideline that recommended this, but I can't remember where.
With this technique, if you want to change the exception type for any reason, you only need to do so in one place (e.g. a change from ConfigurationException to ConfigurationErrorsException when upgrading from .NET 1.x to .NET 2.0).
Also you respect the DRY principle by having a single copy of the code that builds the exception with its message and any other data included in the exception.
You obviously wouldn't do this in trivial cases (e.g. you wouldn't replace throw new ArgumentNullException("myParamName") by throw BuildArgumentNullException("myParamName"))
private static Exception BuildSomeException(... parameters with info to include in the exception ...)
{
string message = String.Format(...);
return new SomeException(message, ...);
}
...
throw BuildSomeException(...);
I don't see the point of making a method that simply throws an exception. But, I do think trowing custom exceptions has value. If all of the exceptions you throw are children of a custom exception, it allows you to quickly see if the thrown exception is one you are accounting for or something you have not handled yet. Also, you can then catch MyBaseException and it is not as bad as catching Exception.
It is handy to do this if you don't know how you plan to handle exceptions, exactly. Do you want to just throw it? Or perhaps later you are going to log the exception somewhere then throw it? Or maybe pass some arguments (i.e. method name, etc.) that get bundled in with the exception?
In this case, creating a separate method that handles the exception situation is convenient when you want to change it.
I don't usually bother with this - instead, just figure out upfront how you are going to handle exceptions (i.e. what string information you are going to putin the message).
I generally prefer to store exception messages as resources. That serves several purposes:
If the requirement comes down to localize exception messages, it's a no-brainer.
Exception messages tend to be more standardized across developers since it's extra work to create a new, but only slightly different message.
If you ensure that messages are referenced by an identifier, and include the identifier with the exception when it's thrown, then tracing a message to the code that threw it is easier.
Downside is it does require (just) slightly more effort up front than hard-coding the messages.

Categories

Resources