As all of you probably know, catching and re-throwing a exception in c# this way is evil, because it destroys the stack trace:
try
{
if(dummy)
throw new DummyException();
}
catch (DummyException ex)
{
throw ex;
}
The right way to re-throw an exception without loosing the stack trace is this:
try
{
if(dummy)
throw new DummyException();
}
catch (DummyException ex)
{
throw;
}
The only problem with this is that I get a lot of compilation warnings: "The variable 'ex' is declared but never used". If you have a lot of these, a useful warning may be hidden in the garbage. So, that's what I did:
try
{
if(dummy)
throw new DummyException();
}
catch (DummyException)
{
throw;
}
catch(AnotherException ex)
{
//handle it
}
This seems to work, but I'd like to know if there is any downside of re-throwing an exception that is not set to an variable. How does .net threats this?
Thanks in advance
Edit:
I've changed my code a little bit to make clearer what I wanted to do, as some had misunderstood
I'd like to know if there is any downside of re-throwing an exception that is not set to an variable.
No, there's no downside at all. A variable is only needed if you want to reference the exception in your code, but since you don't need to do that with a throw statement, you don't need a variable at all.
And you have exactly the right idea in attempting to eliminate "noisy" compiler warnings. They have a tendency to bury important errors that you do want to fix, and getting a clean build is always important. The best solution is simply to rewrite the code to use a parameterless catch clause.
However, be aware that in 82% of cases that I see*, it's a mistake to write code that uses throw at all. You generally shouldn't catch exceptions that you don't know how to handle and your only intended "handling" strategy is to rethrow them. There are cases where even using throw can reset the call stack, causing you to lose important debugging information. There are also better alternatives for logging exceptions to catching/rethrowing. You can find more information in the answers to these questions:
Main method code entirely inside try/catch: Is it bad practice?
what can lead throw to reset a callstack (I'm using "throw", not "throw ex")
There's absolutely nothing wrong with letting exceptions bubble up and handling them all in a central place. The rule to keep in mind is that you shouldn't use exceptions for flow control. But there's nothing wrong with throwing an exception in low level code, and showing the user an error message higher up the stack in UI code. Read Microsoft's Best Practices for Handling Exceptions for some general tips.
* Slightly more than the percent of statistics that are made up on the spot.
There is no downside to that. You are simply telling the compiler "I plan to catch this exception but I have no need for a reference to the actual exception", it doesn't affect how things are thrown or how exceptions work. Your latter example is the ideal way to do what you want, however if you are merely going to immediately throw; with nothing else whatsoever in the block, then why catch at all?
If you're not doing anything with DummyException in the catch block (which you can't, since you haven't given it an identifier), why not get rid of the try/catch block entirely? E.g., just do this:
throw new DummyException();
Although at that point, I'd probably evaluate what you're trying to accomplish here and rethink your application architecture so as not to not rely on exception propagation in this manner.
Why catch if your simply going to re-throw? Anyway, you may want to take a look at this previous discussion. Though not identical much of what is discussed is relevant:
Throw VS rethrow : same result?
Actually throwing an exception using "throw;" is a .Net best practice, because it preserves exception stack trace.
Throwing exceptions using "throw ex;" is considered a worst practice, because it looses the original stack trace and should be avoided.
Why catch and rethrow like this? Why do people always have to assume they know every case? Answer: Database transactions.
If you have a better way to do this please speak up Dr. Proton, no offense taken. Keep in mind that there are a lot of different database systems in use but most of them support transaction control (begin/commit/rollback) and have C# interfaces.
pseudocode (a simplified case):
try
{
db.beginTrans();
db.doStuff();
db.doOtherStuff();
db.commitTrans();
}
catch
{
db.rollbackTrans();
throw;
}
Now, it is quite annoying to lose the detail of whether doStuff() or doOtherStuff() failed and I don't see any good reason why C# would toss the line number information in this case. But it seems to. Hence the googling and my subsequent arrival. If I am missing something please do tell.
Related
In C#, younger developers use often "throw ex" instead of "throw" to throw exception to parent method.
Example :
try
{
// do stuff that can fail
}
catch (Exception ex)
{
// do stuff
throw ex;
}
"throw ex" is a bad practise because the stack trace is truncated below the method that failed. So it's more difficult to debug code. So the code must be :
try
{
// do stuff that can fail
}
catch (Exception ex)
{
// do stuff
throw;
}
My question is why compilator authorize this (or doesn't display a warning message ?) Is there a case which "throw ex" is useful ?
Is there a case which "throw ex" is useful ?
Sure - sometimes you want to truncate the stack trace - to avoid exposing implementation details, etc. Other times you may want to throw a new exception, which would mean the compiler would have to distinguish from just re-throwing the caught exception and throwing a new exception.
So why would you want the compiler to prevent you form doing something that 1) is not illegal and 2) could be useful?
throw new Exception(); or throw ex; both will use the same language rules to allow throwing an exception object, (whether new or existing). When you want to add some extra information with the exception than that option is helpful.
See: How to: Explicitly Throw Exceptions - MSDN
You can explicitly throw an exception using the throw statement. You
can also throw a caught exception again using the throw statement.
It is good coding practice to add information to an exception that is re-thrown to provide more information when debugging.
Since both, throw new Exception() and throw ex; would require the same language rules, it is not really compiler's job to distinguish those two.
Simply throwing the existing exception without any modification to the exception object would be using the same language construct.
Also as #D Stanley has pointed out in his answer, that truncating the stack trace could be the desired behaviour.
As far as your question about compiler not warning about it is concerned, It is not the job of compiler to warn about bad practices, there are code analysis tools. For example Managed Code Analysis tool will raise the warning for throw ex; CA2200: Rethrow to preserve stack details
While compilers can certainly prevent some obvious programming errors, they cannot possibly watch out for best practices like that without triggering some inevitable false positives along the way.
Programmers could choose to change the content of the exception inside the exception handler, or throw a brand-new exception instead. In both cases a message that warns about throwing an exception from an exception handler would be annoying and useless.
One case when it make sense to change the internal state of an exception happens when you throw an exception from a recursive function. Consider a recursive descent parser reporting an error from several layers down the recursive chain. Each level of invocation could potentially add more useful information to an exception. However, wrapping exceptions of each subsequent layer into a new exception is not practical in this case, because you end up with a recursive data structure representing a flat list. One viable solution for situations like this would be creating a custom exception to which each catcher can add more details before re-throwing it. Since the function (or more precisely, a group of functions) is recursive, the location in code from which the original exception has been thrown is of less importance than the completeness of the context that lead to the exception in the first place.
It does not mean that finding situations like that is entirely useless: code proofing tools, such as ReSharper, can certainly help programmers watch out for issues like this. The compiler, however, is a poor choice for a best practice watchdog, because for the most part the compiler should do what it is told.
I guess I consider catch the culprit when you actually just want something to propagate up the stack. Shouldn't catch be avoided entirely in favor of finally?
bool bSucceeded = false;
try
{
// do stuff that can fail
bSucceeded = true;
}
finally
{
if( !bSucceeded )
// do stuff you need to do only on error. (rare, for me)
// cleanup stuff (you're nearly always doing this anyways right?)
}
I've written many bSucceded's, and don't think I have ever written throw inside catch without wrapping in a new Exception(). (At least since I was first learning Java in '99 or so.)
I'm guessing the massive number of possible ways to deal with this is why they let you do what you want here instead of trying to lock it down.
What is the convention for Try/Catch outside of obviously needed locations(such as getting specific user input)? While code re-use is an important idea behind OOP, is it expected that each (example) array access should have a try/catch? Is it primarily the designer's decision of what can throw an exception, and those parts of the program that should be well regulated enough to never throw an exception?
Ex. An array of playing cards is, and should always be, 52 cards. No try/catch is necessary.
Or since an array out of bounds exception could cause a run-time error, and the deck could be used at a later date with jokers added, then put it in now?
You should only catch exceptions, you can actually handle. I.e. you should not have try/catch statements everywhere.
As for throwing exceptions, you should throw an exception when there's no better option. If you can handle user input meaningfully then there's no reason to throw an exception in that case. Without knowing the specifics I would assume that there's no need for an exception in this case.
Your example is a little off.
Assuming you have an array of 52 elements, the correct way of handling this is to test that your index is within the bounds of the array before even attempting to access it. This is far better than simply wrapping the code in a try .. catch in there.
Try Catch is there to help save us from ourselves. If a given method is coded properly then there is very little reason to use them. By properly I mean that you verify your inputs are within the ranges expected and you've tested enough to know that the code won't "except" out. Of course, an example of "very little" include calls to unmanaged resources such as the SqlConnection object.
Point is, it's a crutch that is a last ditch effort to salvage something usable out of that particular code blocks execution.
If, however, there is literally nothing that can be done about the exception then I'd say your only choices are to ignore it and let it bubble up or catch, log and rethrow.
Trey Nash in his book Accelerated C# recommends (as probably most do) to program in a way that negates use of try/catch branches. Most try/catches that you see can be done away with by better programming. There are instances where you need it, mainly in dealing with file handles, database connections, basically anytime you need to use a using statement (which behind the covers is a try/finaly block) with a type that implements IDisposable. Any use of something in the OS that is beyond your control where something could go wrong use a try catch.
And try not to use the general
try { //some exception thrown }
catch (Exception ex) { }
That's too general, do the best you can to handle the more relevant exceptions that can happen instead of having them all go into a general catch statement.
In general i tend to catch exceptions, log them, rethrow and then ultimately have some application level exception handling that presents a general error to the user.
In specific cases where you might know what is causing the exception (e.g. you catch an exception that indicates thatthe connection to the database server is down) you catch the specific exception and then generate an appropriate error message for the user.
If invalid user input is causing exceptions then you have buggy code and you need to validate your input.
You should avoid using try/catch as it's very expensive. In most scenarios you can implement necessary check to avoid exceptions being thrown.
With regards to collections or arrays you can check how many items you have in the collection to avoid errors.
The valid place where you would use try catch would be when reading file or accessing 3rd party resource.
When you catch exception, log it and try to find a way of avoiding it.
Also when rethrowing exception use code below
try
{
}
catch (Exception ex)
{
throw;
}
Hope that answers your question.
Try/Catch says by itself, that you tried to do something, something happened (in our case no a good thing) and you're trying to catch that exception to do something with that information.
Moral: if you know that there could be an exception, and if you know what you're gonna do in case it happen, use try/catch to develop your exception handling logic.
If not, there is more meaning to have try/finally (for example during IO access for allocated resources disposing logic execution guarantee).
Hope this helps.
I've got a new project. Every time you dealing with somebody else code it's an adventure.
Here is what I found:
try
{
.....
}
catch (InvalidOperationException e) {
throw e;
}
catch (Exception e)
{
throw;
}
Anybody has an idea why?
PS
Thanks everybody.
It really helps.
Here are some good sources that you recommended:
Why catch and rethrow an exception in C#?
http://msdn.microsoft.com/en-us/library/0yd65esw.aspx
http://msdn.microsoft.com/en-us/library/ms229005.aspx
Because whoever has written this doesn't have any understanding of how exceptions work in .NET.
If you don't do anything with an exception, don't catch it.
The code you posted would better be written as:
.....
The real danger of this (other than being completely useless...) is that it modifies the call stack. Others have briefly mentioned it in comments, but it deserves to be called out specifically.
When you have throw ex;, the previous call stack is blown away and replaced with the call stack at the point where throw ex; is called. You almost never want to do this. I will often catch an exception, log it, then rethrow the exception. When doing that, you want to just use throw;. This will preserve the original stack trace.
Makes no sense whatsoever to me, but not for the reason you might think.
Catching an exception is not the same thing as handling it. This try/catch block does no handling at all. I think a better, more honest, less verbose solution would have been to remove the try/catch and let the exceptions bubble up to where they can/should be dealt with.
i guess the application wants the outer method calling this to catch the exception instead but this is not the way it should be done, do check these references as they are somewhat similar
Why catch and rethrow an exception in C#?
http://winterdom.com/2002/09/rethrowingexceptionsinc
It is possible that they wanted to implement different handling for InvalidOperationException and other types of exceptions, so they wrote this code as a stub. But then this idea was abandoned so you see this code artifact.
you can improve this code by adding logging.
after every catch, log the information that you throw.
there are some opensource code available for logging.
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 5 years ago.
Improve this question
Sometimes I do this and I've seen others doing it too:
VB:
Try
DontWannaCatchIt()
Catch
End Try
C#:
try
{
DontWannaCatchIt();
}
catch {}
I know I should catch every important exception that I'm expecting and do something about it, but sometimes it's not important to - or am I doing something wrong?
Is this usage of the try block incorrect, and the requirement of at least one catch or finally block an indication of it?
Update:
Now I understand the reason for this, and it's that I should at least comment on the empty catch block so others understand why it's empty. I should also catch only the exceptions I'm expecting.
Luckily for me I'm coding in VB so I can write it in just one catch:
Catch ex As Exception When TypeOf ex Is IOException _
OrElse TypeOf ex Is ArgumentException _
OrElse TypeOf ex Is NotSupportedException _
OrElse TypeOf ex Is SecurityException _
OrElse TypeOf ex Is UnauthorizedAccessException
'I don't actually care.
End Try
If you don't want to catch it, why are you using try in the first place?
A try statement means that you believe something can go wrong, and the catch says that you can adequately handle that which goes wrong.
So in your estimation:
try
{
//Something that can go wrong
}
catch
{
//An empty catch means I can handle whatever goes wrong. If a meteorite hits the
//datacenter, I can handle it.
}
That catch swallows any exceptions that happen. Are you that confident in your code that you can handle anything that goes wrong gracefully?
The best thing to do (for both yours and your maintenance programmer's sanity) is to explicitly state that which you can handle gracefully:
try
{
//Something that could throw MeteoriteHitDatacenterException
}
catch (MeteoriteHitDatacenterException ex)
{
//Please log when you're just catching something. Especially if the catch statement has side effects. Trust me.
ErrorLog.Log(ex, "Just logging so that I have something to check later on if this happens.")
}
No, you should not catch every important exception. It is okay to catch and ignore exceptions you don't care about, like an I/O error if there's nothing you can do to correct it and you don't want to bother reporting it to the user.
But you need to let exceptions like StackOverflowException and OutOfMemoryException propagate. Or, more commonly, NullReferenceException. These exceptions are typically errors that you did not anticipate, cannot recover from, should not recover from, and should not be suppressed.
If you want to ignore an exception then it is good to explicitly write an empty catch block in the code for that particular exception. This makes it clear exactly what exceptions you're ignoring. Ignoring exceptions very correctly is an opt-in procedure, not an opt-out one. Having an "ignore all exceptions" feature which can then be overridden to not ignore specific types would be a very bad language feature.
How do you know what types of exceptions are important and should not be caught? What if there are exceptions you don't know about? How do you know you won't end up suppressing important errors you're not familiar with?
try
{
}
// I don't care about exceptions.
catch
{
}
// Okay, well, except for system errors like out of memory or stack overflow.
// I need to let those propagate.
catch (SystemException exception)
{
// Unless this is an I/O exception, which I don't care about.
if (exception is IOException)
{
// Ignore.
}
else
{
throw;
}
}
// Or lock recursion exceptions, whatever those are... Probably shouldn't hide those.
catch (LockRecursionException exception)
{
throw;
}
// Or, uh, what else? What am I missing?
catch (???)
{
}
No catch or finally is invalid. Empty catch or finally is valid. Empty catch means you don't care about exceptions, you just try to do something and it doesn't matter if it doesn't work, you just want to go on. Useful in cleanup functions for example.
Also if you haven't to do something about an error maybe you should specify what kind of exception the program has to ignore.
If you have to ignore every exception, I can't see why you can't use try/catch in this way.
It's usually a mistake. Exceptions signal, well, exceptional behavior; when an exception is thrown it should mean that something went wrong. So to continue normal program flow as if nothing went wrong is a way of hiding an error, a form of denial. Instead, think about how your code should handle the exceptional case, and write code to make that happen. An error that propagates because you've covered it up is much harder to debug than one that surfaces immediately.
It's not made easy for you to do because it's considered bad practice by the majority of developers.
What if someone later adds a method call to the body of DontWannaCatchIt() that does throw an exception worth catching, but it gets swallowed by your empty catch block? What if there are some exceptions that you actually would want to catch, but didn't realize it at the time?
If you absolutely must do this, try to be as specific as possible with the type of exception you're going to catch. If not, perhaps logging the exception is an option.
An error exists, has been thrown, and needs to go somewhere. Normal code flow has been aborted and the fan needs cleaned.
No catch block = indeterminate state. Where should the code go? What should it do?
An empty catch block = error handled by ignoring it.
Note: VBA has a vile "On Error Continue"...
The reason I've heard is that if your try fails for ANY reason, giving you control of the error response is highly preferable to giving the Framework control of it, i.e., yellow screen or error 500.
what if you write only code with try
try
{
int j =0;
5/j;
}
this would equivalent to write
int j =0;
5/j;
so writing try does not make any sense , it only increse your count of lines.
now if you write try with empty catch or finally , you are explicitley instructing runtime to behave differently.
so that' why i think empty try block is not possible.
Yes, it is incorrect. It's like goto: one per 100 KLoc is fine, but if you need many of these, you are doing it wrong.
Swallowing exceptions without any reactions is one of the worse things in error handling, and it should at least be explicit:
try
{
DontWannaCatchIt();
}
catch
{
// This exception is ignored based on Spec Ref. 7.2.a,
// the user gets a failure report from the actual results,
// and diagnostic details are available in the event log (as for every exception)
}
The further-away-look:
Error handling is an aspect: in some contexts, an error needs to be thrown and propagate up the call stack (e.g. you copy a file, copy fails).
Calling the same code in a different context might require the error to be tracked, but the operation to continue (e.g. Copying 100 files, with a log indicating which files failed).
Even in this case, an empty catch handler is wrong.
With most languages, there is no other direct implementation than to try+catch within the loop, and build the log in the catch handler. (You could build a mroe flexible mechanism, though: Have a per-call-thread handler that can either throw, or stow away the message. However, interaction with debugging tools suffers without direct language support.)
A sensible use case would be implementing a TryX() from a X(), but that would have to return the exception in question.
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.