Try/Catch in every method of every class? - c#

When we wrap a bunch of statements in a try/catch and one of these issues an exception, within the catch we have no way of knowing which of the statements caused the exception (the ex.stacktrace shows our current method (doit), its caller, its caller's caller, etc. but neither do1 or do2):
function doit() {
try {
do1();
do2();
[...]
}
catch (Exception ex) {
// what failed?
}
}
generally I've taken to wrapping all statements and rethrowing, sort of like:
private void do1() {
try {
// do whatever
} catch(Exception e) {
// write to my error log
throw new Exception("do1: " + e.Message, e.InnerException);
}
}
which leaves a trail of breadcrumbs in my log and makes the chain available for the upstream. The problem, of course, is that I have to wrap every method I write with this kind of code.
something tells me I'm being dumb about it. what is the right approach?

Ok, this is hard to get right because exception handling is a really really touchy subject and in the past people have fought religious wars over how to do this right.
First off: neither use an empty catch (try { ... } catch { ... }), nor catch(Exception ex).
The sole purpose of Exception-derived classes is to give you rich information about the kind of exception which occured so you can do something meaningful in your exception handler (if a thread crashed restart it, if a db connection failed non-permanently try again, then fail, etc).
People tend to use a catch-all handler for the outermost part of their code to log uncaught exceptions and this is kind of OK, but in any case you should either prompt the user or rethrow the exception (using throw, not throw ex - there is a ton of discussion about this as well).
Basically you do not programmatically care about where the Exception occured at all.
You can either handle it or you can't. If you can't handle it then you don't catch it.
Addendum: The most important reason for this "if you can do something about it, do so, otherwise dont you dare touch that exception" philosophy is that silently caught exceptions (whether logged or not) can lead to really hard-to-find bugs. Just pushing them out to a logfile might not be enough because in a live system you may not get the fully annotated stack trace (with line numbers and everything).
Addendum 2: Take for instance a textbox which expects an integer input. If the user supplies a string you cannot meaningfully process the input, maybe a conversion exception gets thrown, you catch that specific exception and reset the textbox to its old value and maybe inform the user about the erroneous input. Alternatively your program might either just die with an exception (bad design, you could recover from that exception) or silently go on showing the erroneous input, but still using the old value (bad design, the program is misleading).

If you are really sold on doing this (others have stated why this is bad already), use an Aspect Oriented Programming approach. This will make your life significantly easier and reduce the amount of code you end up writing and maintaining.
Take a look at PostSharp, it gives you a framework that allows you to decorate methods, classes, or namespaces with attributes that will generate this boilerplate error handling for you.

#Branko nailed it in the comments: the exception's stack trace shows the point where the exception was thrown, not where it was caught.
+1 for #ChaosPandion's comment: this is a very, very, very bad idea.

try and catch seem to me to be probably the single worst designed modern programming mechanism. We no longer have the ability to handle errors as we go; we must fail the entire procedure if a single exception occurs, unless we do something horrifying like try every statement individually. There is no longer the option of recovering, only failing as gracefully as possible.
The best pattern for this I have found so far is to wrap every user event in a try/catch (using a method, not an explicit try every time). Ex:
public static class Defines
{
public static bool TryAction(Action pAction)
{
try { pAction(); return true; }
catch(Exception exception) { PostException(exception); return false; }
}
}
...
private void DoSomething(int pValue)
{
...
}
private void MyControl_MyEvent(object pSender, MyEventArgs pEventArgs)
{
Defines.TryAction(() => DoSomething(pEventArgs.Data));
}
Beyond that, just try to write exception-less code. Only use explicit trys when you are very likely to get an exception and want to do a little more than just fail gracefully.

Related

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.

usage of try catch

Which is best: Code Snippet 1 or Code Snippet 2 ? And Why?
/* Code Snippet 1
*
* Write try-catch in function definition
*/
void Main(string[] args)
{
AddMe();
}
void AddMe()
{
try
{
// Do operations...
}
catch(Exception e)
{
}
}
/* Code Snippet 2
*
* Write try-catch where we call the function.
*/
void Main(string[] args)
{
try
{
AddMe();
}
catch (Exception e)
{
}
}
void AddMe()
{
// Do operations...
}
The real question to ask is "What is AddMe's contract to the rest of the world?" If AddMe represents the be-all do-all of an interface and correctly handles any exception that encounters in the appropriate way, then sure - let it catch it. If AddMe doesn't or can't know what to do with an exception, then it should throw and defer the handling to the calling code.
It depends, as usual.
In Snippet #1, the error handling is reusable. In Snippet #2, it is not, but that is better in cases where you want to use different error handling in different places.
Other than that, they are identical.
they will operate the same however Most would prefer to catch the logic inside the method if thats where it will be thrown from. Just a best practice though.
There's not best universal way. It depends on how you're going to handle your exceptions.
Do you plan on using a global logger in your main application? The you should have a try/catch block in your main method, and log exceptions there.
You can still try/catch in internal methods if you need to do other stuff with the exceptions, but remember to rethrow them, or else the logger in the main method won't have anything to log.
And remember, to rethrow correctly, use:
throw;
and not:
throw e;
Because the former keeps all the stack trace, while the latter doesn't.
IMHO, allow methods to throw exceptions. Don't attempt to hide when things go wrong. When they do it is up to the client to decide how they'd like to handle the exception. The reasoning for this is because each application may want to do something different with the exception.
TL,DR; Catch exceptions when you can do something about the exception, otherwise let them flow up the call stack until something else will handle them. If the exception cannot be handled by any particular part of your application, your application error event method should handle all the logging for you. Your logging functionality will be your final net for dealing with exceptions.
I've worked with a few shops that require try catch logic on EVERY method, and I learned that the Exception object does a better job watching your call stack than you can.
My other rule of thumb is notify the user of exceptions on user trigger events. So event based or command based captures would be a great place to catch, notify, then re-throw the same exception. (IE throw; NOT throw ex;)
There are already good answers to this question, coming ultimately down to "it depends", but I want to add a thought that I believe greatly influences which method is better for any given situation.
In your code snippet examples, but of your catches are catch (Exception e) {} as opposed to, say, catch (IOException e) or catch (NullReferenceException, or some other narrower exception type. The kind(s) of exception(s) you expect from the code in the try block will make a difference in the way you want to handle it. Especially if you have more than one type to consider, as could be the case if you handle exceptions outside of the subroutine - a large enough upper-level try block could have several different types of exceptions to handle, and start to run the risk of making the code messy.
My general rule of thumb, overall, is that if the exception is a non-critical error (especially if caused by invalid user input), I can handle it in the subroutine and keep the system running. On the other hand, if the exception means the program needs to close, I handle it higher up.

Throw a C# exception of the same type as that caught?

why (if at all) is this a bad idea ?
class Program
{
static void Main(string[] args)
{
try
{
throw new NotImplementedException("Oh dear");
}
catch (Exception ex)
{
throw NewException("Whoops", ex);
}
}
// This function is the salient bit here
public static Exception NewException(String message, Exception innerException)
{
return Activator.CreateInstance(innerException.GetType(), message, innerException) as Exception;
}
}
The important bit here is that the function creates an exception of the same type as the "innerException".
I'm thinking... "Oh... an exception has occurred. I can't actually handle it here, but I can add some additional information, and re-throw. Maybe another handler, higher up the call chain can handle it."
A case in point might be some sort of SQL error. I might not be able to handle the exception at the point of calling, but might wish to add some additional "context" information like "I was calling this, and passing that".
It seems like it might be useful to pass back up the call chain an exception of the type that was originally raised, as opposed to "Exception" or "ApplicationException". I know I could create my own custom exception classes, but it seems that it adds nothing much when you already have a nice specific exception.
Of course, I might be wrong. It might be a very useful thing to do... but a little voice is suggesting not.
----- edit -----
For the sake of debate, consider the effects of the following two functions (using the code above):
This... seen all too often:
static int SalesTotal(int customerNumber)
{
try
{
throw new DivideByZeroException(); // something you didn't expect
}
catch (Exception ex)
{
throw new ApplicationException("Unable to calculate sales for customer " + customerNumber, ex);
}
}
versus this...
static int SalesTotal(int customerNumber)
{
try
{
throw new DivideByZeroException(); // something you didn't expect
}
catch (Exception ex)
{
throw NewException("Unable to calculate sales for customer " + customerNumber, ex);
}
}
all exceptions have a Data property that you can add additional data to. There is no need to create a new exception. Just catch the existing exception and add your information and then just rethrow the exception.
This way you get your cake and eat it too. :)
http://msdn.microsoft.com/en-us/library/system.exception_members(v=VS.90).aspx
Creating a new exception type isn't a good option for a general method like this, since existing code will be unable to react to a specific error. (Translation exceptions at API boundaries cane be useful, though).
Creating a new exception of the same type seems perilous. Does the CreateInstance overload you're using copy all fields from the innerException to your new outer exception? What if an exception handler higher up the stack depends on parsing the Message property? What if the exception constructor has side effects?
IMHO, what you're really doing is logging, and you'd probably be better off actually doing logging and a re-throw.
I think you should create your own custom exception type. What kind of information are you going to add? How is the catcher of the exception going to know it has extra information? If you use a custom type, they will have extra properties/methods to view or call.
Don't catch it at all and just let it bubble up - there's no point reinventing the wheel.
Not only is your method not intuitive for somebody else coming in, but you're also going to lose the original stack trace from the first exception.
It can make sense in some cases. If you consider MyClass.MyFunction the public "outside" of the assembly, then what happens inside it is a black box to calling code. It can therefore be more reasonable to have that as the point that the exception happened as far as the calling code goes, and the most reasonable type of exception could happen to be the same type as that caught.
I would be cautious though. In most cases of this happening, either you should have been able to catch that the exception was going to happen, and thrown pre-emptively (if you are going to throw, the sooner the better) or else the exception you are throwing isn't really the right type (if your code doesn't find a file it needs that's a FileNotFoundException to you, but if the files are an implementation detail, then it's not a FileNotFoundException to the calling code), or else the original exception will make perfect sense and it should just be allowed to call through or rethrown with throw;.
So, not always a bad idea, but bad often enough that it's always a suspicious thing to see.
IMHO, it would probably be good to have a few custom exception types, with one hierarchy for exceptions which say "This operation failed, but the system state is as though it had never been attempted", another for exceptions that say "The operation failed, and the system state has been disturbed, but it can probably be unwound", and another for "The operation failed, and unwinding failed; the system state cannot be trusted." In some contexts, one class of exception may be caught and rethrown as another (e.g. if an operation which was supposed to finish restoring system state fails, even if from the point of view of that operation nothing was disturbed, the failure to restore the state may leave it disturbed; conversely, if an operation left a system state disturbed but a catch handler restored the state, it could rethrow as an "operation failed but system state is undisturbed".
I dislike very much the idea of trying to create exception instances that blindly match thrown exception types, since the thrown exceptions may have fields which handlers will expect to be populated. I'm not sure why Microsoft made exceptions "almost" immutable. It would be much nicer if exceptions were required to be immutable and support cloning with whatever semantics conveyed immutability.
Only catch exceptions that you handle, for instance you do not want a SqlException to be thrown from your data layer to your business layer (catch it, try ot handle it and throw a DataLayerException or something like that instead).

How to structure code with 2 methods, one after another, which throw the same two exceptions?

I have two methods, one called straight after another, which both throw the exact same 2 exceptions (IF an erroneous condition occurs, not stating that I'm getting exceptions).
For this, should I write seperate try and catch blocks with the one statement in each try block and catch both exceptions (Both of which I can handle as I checked MSDN class library reference and there is something I can do, eg, re-open SqlConnection or run a query and not a stored proc which does not exist). So code like this:
try
{
obj.Open();
}
catch (SqlException)
{
// Take action here.
}
catch (InvalidOperationException)
{
// Take action here.
}
And likewise for the other method I call straight after. This seems like a very messy way of coding. The other way is to code with the exception variable (that is ommited as I am using AOP to log the exception details, using a class-level attribute). Doing this, this could aid me in finding out which method caused an exception and then taking action accordingly. Is this the best approach or is there another best practise altogether?
I also assume that, as only these two methods are thrown, I do not need to catch Exception as that would be for an exception I cannot handle (causes way out of my control).
Thanks
You shouldn't catch an exception unless you can handle it in a sensible way and recover from the error. With that in mind, you should either choose not to catch these exceptions, or else you should catch them and do something useful and continue.
Assuming that you are trying to do the latter: handle the error and continue, does it really makes sense to do the same thing no matter which of the two statements fails? Assume you have this:
try {
f1();
f2();
} catch (FooException) {
// Recover from error and continue
}
f3();
In this case if f1() fails and you recover from the error, f2() will never be executed - it goes straight to f3(). Is that really what you want? Maybe it is sometimes... but not usually.
More likely, after the error from f1() you either want to quit completely with an error or to recover and then go on to execute f2(). If so then you would need two separate try/catch blocks.
If you're not interested in recovery but just logging the exceptions then the simplest way is to let them propagate and catch them at a higher level (but before your program crashes or becomes unusable) and log the message and stack trace. This ensures that you will log all exceptions and saves you having to insert try/catch and logging code in every method that could throw.
You're right that you shouldn't be catching Exception.
Generally you need as many catch clauses as you have different recovery approaches. If the recovery behavior is different for these two methods, I see nothing wrong with using a try/catch for each.
Especially consider whether you'd run the second method after successfully recovering the first. If so, you definitely don't want to put the second method in the same try block where it will be skipped by the exception.
You could create a method that accepts an Action parameter:
void trySomething(Action mightThrow)
{
try
{
mightThrow();
}
catch(SqlException)
{
}
catch(InvalidOperationException)
{
}
}
Then you can get the name of the method that threw by mightThrow.Method.Name.

Is it ok to catch all exception types if you rethrow them wrapped another exception?

I know you're not suppose to write code that caches all exception types like this.
try
{
//code that can throw an exception
}
catch
{
//what? I don't see no
}
Instead you're suppose to do something more like the code below allowing any other exception that you didn't expect to bubble up.
try
{
//code that can throw an exception
}
catch(TypeAException)
{
//TypeA specific code
}
catch(TypeBException)
{
//TypeB specific code
}
But is it ok to catch all exception types if you are wrapping them with another exception?
Consider this Save() method below I am writing as part of a Catalog class. Is there anything wrong with me catching all exception types and returning a single custom CatalogIOException with the original exception as the inner exception?
Basically I don't want any calling code to have to know anything about all the specific exceptions that could be thrown inside of the Save() method. They only need to know if they tried to save a read only catalog (CatalogReadOnlyException), the catalog could not be serialized (CatalogSerializationException), or if there was some problem writing to the file (CatalogIOException).
Is this a good or bad way to handle exceptions?
/// <summary>
/// Saves the catalog
/// </summary>
/// <exception cref="CatalogReadOnlyException"></exception>
/// <exception cref="CatalogIOException"></exception>
/// <exception cref="CatalogSerializingExeption"></exception>
public void Save()
{
if (!this.ReadOnly)
{
try
{
System.Xml.Serialization.XmlSerializer serializer = new XmlSerializer(typeof(Catalog));
this._catfileStream.SetLength(0); //clears the file stream
serializer.Serialize(this._catfileStream, this);
}
catch (InvalidOperationException exp)
{
throw new CatalogSerializationException("There was a problem serializing the catalog", exp);
}
catch (Exception exp)
{
throw new CatalogIOException("There was a problem accessing the catalog file", exp);
}
}
else
{
throw new CatalogReadOnlyException();
}
}
Update 1
Thanks for all the responses so far. It sounds like the consensus is I shouldn't be doing this, and I should only be catching exceptions if I actually have something to do with them. In the case of this Save() method there really isn't any exception that may be thrown that I want to handle in the Save() method itself. Mostly I just want to notify the user why they were not able to save.
I think my real problem is I'm using exceptions as a way to notify the user of problems, and I'm letting this inform how I am creating and handling exceptions a little too much. So instead should it sounds like it would be better to not catch any exceptions and let the UI layer figure out how to notify the user, and or crash. Is this correct? Consider the Save Menu event handler below.
private void saveCatalogToolStripMenuItem_Click(object sender, EventArgs e)
{
//Check if the catalog is read only
if (this.Catalog.ReadOnly)
{
MessageBox.Show("The currently opened catalog is readonly and can not be saved");
return;
}
//attempts to save
try
{
//Save method doesn't catch anything it can't deal with directly
this.Catalog.Save();
}
catch (System.IO.FileNotFoundException)
{
MessageBox.Show("The catalog file could not be found");
}
catch (InvalidOperationException exp)
{
MessageBox.Show("There was a problem serializing the catalog for saving: " + exp.Message);
}
catch (System.IO.IOException exp)
{
MessageBox.Show("There was a problem accessing the catalog file: " + exp.Message);
}
catch (Exception exp)
{
MessageBox.Show("There was a problem saving the catalog:" + exp.Message);
}
}
Update 2
One more thing. Would the answer change at all if the Save() method was part of a public API vs internal code? For example if it was part of a public API then I'd have to figure out and document all the possible exceptions that Save() may throw. This would be a lot easier if knew that Save() could only possibly throw one of my three custom exceptions.
Also if Save() was part of a public API wouldn't security also be a concern? Maybe I would want to let the consumer of the API know that the save wasn't successful, but I don't want expose anything about how Save() works by letting them get at the exceptions that may have been generated.
Doing a generic catch-all and rethrowing as a new type of exception does not really solve your problem and does not give you anything.
What you really need to do is to catch the exceptions that you can handle and then handle them (at the appropriate level - this is where rethrowing may be useful). All other exceptions either need to be logged so you can debug why they happened, or shouldn't be happening in the first place (for example - make sure you validate user input, etc.). If you catch all exceptions, you'll never really know why you're getting the exceptions you're getting and, thus, cannot fix them.
Updated Response
In response to the update of your question (particularly in how you want to handle the save case), my question to you would be - why are you using exceptions as a means of determine the path your program takes? For example, let's take the "FileNotFoundException." Obviously that can happen at times. But, instead of letting a problem happen and notifying the user about it, before saving (or doing whatever) with the file, why not check first that the file can be found. You still get the same effect, but you aren't using exceptions to control program flow.
I hope this all makes sense. Let me know if you have any additional questions.
When you re-throw with the original exception as inner exception, you lose the original stack trace, which is valuable debugging information.
I will sometimes do what you are suggesting, but I always log the original exception first to preserve the stack trace.
I don't see a problem with what you are doing. The reason for wrapping exceptions in a custom exception types is to create an abstraction between layers of code -- to translate lower-level errors into a higher-level context. Doing this relieves the calling code from having to know too much the implementation details of what Save does.
Your update #1 is an example of the calling code having to know way too much about the implementation details of Save(). In response to your second update, I agree 100%
PS
I'm not saying to do this in every scenario where you encounter exceptions. Only when the benefit outweighs the cost (usually at module boundaries).
Example scenarios for when this is especially useful: you are wrapping a 3rd party library, you don't yet know all the underlying exceptions that might be thrown, you don't have the source code or any documentation, and so on.
Also, he is wrapping the underlying exception and no information is lost. The exception can still be logged appropriately (though you'll need to recursion your way through the InnerExceptions).
I favor wrapping exceptions, from the standpoint that a custom exception hierarchy can divide exceptions into much more useful classifications than the default hierarchy. Suppose one tries to open a document and gets an ArgumentException or an InvalidOperationException. Does the type of the exception really contain any useful information whatsoever? Suppose, however, one instead got a CodecNotFoundException, a PrerenderFingFailureException, or a FontLoadFailureException. One can imagine the system catching some of those exceptions and attempting to do something about it (e.g. allow the user to search for a CODEC, retry rendering with lower-resolution settings, or allow substitution of fonts after warning the user). Much more useful than the default exceptions, many of which say nothing about what's really wrong or what can be done about it.
From a hierarchical standpoint, what's really needed is a means of distinguishing exceptions which indicate that the method throwing the exception was unable to perform its task, but the system state is similar to what it was before the method was started, and those which indicate that the system state is corrupt in a fashion beyond that implied by the method's failure. The normal exception hierarchy is completely useless for that; if one wraps exceptions one may be able to improve the situation slightly (though not as well as if the hierarchy were better designed to start with). An exception which forces a transaction to be unwound is not nearly as bad as one which occurs while committing or unwinding a transaction. In the former case, the state of the system is known; in the latter case, it isn't.
While one should probably avoid catching certain really bad exceptions (StackOverflowException, OutOfMemoryException, ThreadAbortException) I'm not sure it really matters. If the system is going to crash and burn, it's going to do so whether one catches the exception or not. In vb.net, it may be worthwhile to "Catch Ex As Exception When IsNotHorribleException(Ex)" but C# has no such construct, nor even a way to exclude certain exceptions from being caught.
Parting note: in some cases, one operation may generate multiple exceptions that are worthy of logging. Only by wrapping exceptions in a custom exception which holds a list of other exceptions can that really be accomplished.
I don't think its a good idea.
You should only add you own type of exception, if you have anything to add.
And furthermore, you should only catch exceptions that you expect, and that you are able to handle - all other exceptions should be allowed to bubble up.
As a developer I must say, I get angry if you try to "hide" exceptions from me, by swallowing or wrapping them.
For some more info on why catch(exception) is bad check out this article: http://blogs.msdn.com/clrteam/archive/2009/02/19/why-catch-exception-empty-catch-is-bad.aspx
Essentially catching 'Exception' is like saying 'if anything goes wrong I dont care carry on' and catching 'Exception' and wrapping it is like saying 'if anything goes wrong treat them as if they all went wrong for the exact same reason'.
This cannot be correct either you handle it because you semi-expected it or you totally don't think it should ever happen EVER (or didn't know it would). In this case you'd want some kind of app level logging to point you to an issue that you had never expected - not just a one size fits all solution.
My own rule of thumb is to catch and wrap Exception only if I have some useful context I can add, like the file name I was trying to access, or the connection string, etc. If an InvalidOperationException pops up in your UI with no other information attached, you're going to have a hell of a time tracking down the bug.
I catch specific exception types only if the context or message I want to add can be made more useful for that exception compared to what I would say for Exception generally.
Otherwise, I let the exception bubble up to another method that might have something useful to add. What I don't want to do is tie myself in knots trying to catch and declare and handle every possible exception type, especially since you never know when the runtime might throw a sneaky ThreadAbortException or OutOfMemoryException.
So, in your example, I would do something like this:
try
{
System.Xml.Serialization.XmlSerializer serializer =
new XmlSerializer(typeof(Catalog));
this._catfileStream.SetLength(0); //clears the file stream
serializer.Serialize(this._catfileStream, this);
}
// catch (InvalidOperationException exp)
// Don't catch this because I have nothing specific to add that
// I wouldn't also say for all exceptions.
catch (Exception exp)
{
throw new CatalogIOException(
string.Format("There was a problem accessing catalog file '{0}'. ({1})",
_catfileStream.Name, exp.Message), exp);
}
Consider adding the inner exception's message to your wrapper exception so that if a user just sends you a screenshot of the error dialog, you at least have all the messages, not just the top one; and if you can, write the whole ex.ToString() to a log file somewhere.
In this particular case exceptions should be rare enough that wrapping it shouldn't be a useful thing and will likely just get in the way of error handling down the line. There are plenty of examples within the .Net framework where a specific exception that I can handle is wrapped in a more general one and it makes it much more difficult (though not impossible) for me to handle the specific case.
I have written an article on this very topic before. In it I reiterate the importance of capturing as much data about the exception as is possible. Here's the URL to the article:
http://it.toolbox.com/blogs/paytonbyrd/improve-exception-handling-with-reflection-and-generics-8718
What benefit does the user get from being told "There was a problem serializing the catalog"? I suppose your problem domain might be an extraordinary case, but every group of users I've ever programmed for would respond the same way when reading that message: "The program blew up. Something about the catalog."
I don't mean to be condescending towards my users; I'm not. It's just that generally speaking my users have better things to do with their attention than squander it constructing a fine-grained mental model of what's going on inside my software. There have been times when my users have had to build that kind of an understanding in order to use a program I've written, and I can tell you that the experience was not salutary for them or for me.
I think your time would be much better spent on figuring out how to reliably log exceptions and relevant application state in a form that you can access when your users tell you that something broke than in coming up with an elaborate structure for producing error messages that people are unlikely to understand.
To answer this question, you need to understand why catching System.Exception is a bad idea, and understand your own motivations for doing what your propose.
It's a bad idea because it makes the statement that anything that could have gone wrong is okay, and that the application is in a good state to keep running afterwards. That's a very bold statement to make.
So the question is: Is what you are proposing equivalent to catching System.Exception? Does it give the consumer of your API any more knowledge to make a better judgement? Does it simply encourage them to catch YourWrappedException, which is then the moral equivalent of catching System.Exception, except for not triggering FXCop warnings?
In most cases, if you know there's a rule against doing something, and want to know if something similar is "okay", you should start with understanding the rationale for the original rule.
This is a standard practice in .NET and how exceptions should be handled, especially for exceptions that are recoverable from.
Edit: I really have no idea why I'm being downvoted perhaps I read more into the authors intent than everyone else. But the way I read the code the fact he is wrapping those exceptions into his custom exception implies that the consumer of this method is equiped to handle those exceptions and that it is a responsibility of the consumer to deal with the error processing.
Not a single person that DV'd actually left any form of actual dispute. I stand by my answer that this is perfectly acceptable because the consumer should be aware of the potential exceptions this could throw and be equipped to handle them which is shown by the explicit wrapping of the exception. This also preserves the original exception so the stack trace is available and underlying exception accessible.

Categories

Resources