The difference between try/catch/throw and try/catch(e)/throw e - c#

What is the difference between
try { }
catch
{ throw; }
and
try { }
catch(Exception e)
{ throw e;}
?
And when should I use one or the other?

The constructions
try { ... }
catch () { ... } /* You can even omit the () here */
try { ... }
catch (Exception e) { ... }
are similar in that both will catch every exception thrown inside the try block (and, unless you are simply using this to log the exceptions, should be avoided). Now look at these:
try { ... }
catch ()
{
/* ... */
throw;
}
try { ... }
catch (Exception e)
{
/* ... */
throw;
}
try { ... }
catch (Exception e)
{
/* ... */
throw e;
}
The first and second try-catch blocks are EXACTLY the same thing, they simply rethrow the current exception, and that exception will keep its "source" and the stack trace.
The third try-catch block is different. When it throws the exception, it will change the source and the stack trace, so that it will appear that the exception has been thrown from this method, from that very line throw e on the method containing that try-catch block.
Which one should you use? It really depends on each case.
Let's say you have a Person class with a .Save() method that will persist it into a database. Let's say that your application executes the Person.Save() method somewhere. If your DB refuses to save the Person, then .Save() will throw an exception. Should you use throw or throw e in this case? Well, it depends.
What I prefer is doing:
try {
/* ... */
person.Save();
}
catch(DBException e) {
throw new InvalidPersonException(
"The person has an invalid state and could not be saved!",
e);
}
This should put the DBException as the "Inner Exception" of the newer exception being throw. So when you inspect this InvalidPersonException, the stack trace will contain info back to the Save method (that might be sufficient for you to solve the problem), but you still have access to the original exception if you need it.
As a final remark, when you are expecting an exception, you should really catch that one specific exception, and not a general Exception, ie, if you are expecting an InvalidPersonException you should prefer:
try { ... }
catch (InvalidPersonException e) { ... }
to
try { ... }
catch (Exception e) { ... }

The first preserves the stack trace while the second resets it. This means that if you use the second approach the stack trace of the exception will always start from this method and you will lose the original exception trace which could be disastrous for someone reading exception logs as he will never find out the original cause of the exception.
The second approach might be useful when you want to add additional information to the stack trace but it is used like this:
try
{
// do something
}
catch (Exception ex)
{
throw new Exception("Additional information...", ex);
}
There's a blog post discussing the differences.

You should use
try { }
catch(Exception e)
{ throw }
if you want to do something with the exception before re-throwing it (logging for example). The lonely throw preserves stack trace.

The difference between a parameterless catch and a catch(Exception e) is that you get a reference to the exception. From framework version 2 unmanaged exceptions are wrapped in a managed exception, so the parameterless exception is no longer useful for anything.
The difference between throw; and throw e; is that the first one is used to rethrow exceptions and the second one is used to throw a newly created exception. If you use the second one to rethrow an exception, it will treat it like a new exception and replace all stack information from where it was originally thrown.
So, you shold not use either of the alternatives in the question. You should not use the parameterless catch, and you should use throw; to rethrow an exception.
Also, in most cases you should use a more specific exception class than the base class for all exceptions. You should only catch the exceptions that you anticipate.
try {
...
} catch (IOException e) {
...
throw;
}
If you want to add any information when rethrowing the exception, you create a new exception with the original exception as an inner exception to preservere all information:
try {
...
} catch (IOException e) {
...
throw new ApplicationException("Some informative error message", e);
}

Related

C# How to rethrow an exception from an outer catch

I've read How to rethrow InnerException without losing stack trace in C#? and the answer here may be the same; on the other hand my situation is sufficiently different that someone might be able to suggest a better approach.
My simplified structure is
try {
something();
} catch (MyException e1) {
try {
somethingElse();
} catch (MyException e2) {
throw e1;
}
}
That is to say, calling somethingElse() is an attempt to recover from the original exception, and if the recovery attempt fails, I want to throw the original exception, not the one that arose from the recovery attempt.
I get a warning from the compiler about rethrowing exceptions losing the stack trace (and of course, I don't like leaving my code with warning conditions). But what should I do about it? My IDE (Rider) suggests changing the throw e1; to throw;, but that would presumably rethrow e2.
Are there any solutions short of the convoluted ideas proposed in the cited question for inner exceptions?
To be honest, I don't really care about the imperfect stack trace - I just want to get rid of the warnings.
There is no way to rethrow an exception from an outer catch block inside an inner catch block. The best way to achieve this pattern is to note whether or not the inner operation succeeded :
try {
something();
} catch (MyException e1) {
bool recovered=false;
try {
somethingElse();
recovered=true;
} catch {
}
if (!recovered) {
throw;
}
}
There is the ExceptionDispatchInfo class.
This lets you capture an exception and re-throw it without changing the stack-trace:
public static void Method()
{
try
{
Something();
}
catch (MyException e1)
{
try
{
SomethingElse();
}
catch (MyException)
{
//throw e1;
ExceptionDispatchInfo.Capture(e1).Throw();
throw;
}
}
}
A regular throw; after the .Throw() line is because the compiler won't know that .Throw() always throws an exception. throw; will never be called as a result, but at least the compiler won't complain if your method requires a return object or is an async function.
Original post Link

Rethrowing an exception in C# [duplicate]

This question already has answers here:
Why catch and rethrow an exception in C#?
(17 answers)
Closed 6 years ago.
I have some code which catches the exception, rolls back the transaction and then rethrow the exception.
catch ( Exception exSys ) {
bqBusinessQuery.RollBackTransaction();
throw exSys ;
}
If I use this code, VS Code analysis throws warning saying
Use 'throw' without an argument instead, in order to preserve the stack location where the exception was initially raised.
If I use the code
catch ( Exception exSys ) {
bqBusinessQuery.RollBackTransaction();
throw;
}
then I get a warning saying
The variable 'exSys' is declared but never used
How should I solve this problem?
Edit
I tried this method, but it doesn't work. system.exception class requires an extra message, along with inner exception. If I do that, it will throw a new message overriding the message from the original exception. I don't want to get the new exception, I want to throw the same exception with same message.
catch (System.Exception ex)
{
throw new System.Exception(ex);
}
Edit
catch (System.Exception ex)
{
throw new System.Exception("Test",ex);
}
Tried this method. And then manually caused an exception using throw new Exception("From inside");. Now, ex.Message returns "Test" instead of "From inside". I want to keep that "From inside" message as is. This suggested change will cause problem with error display code everywhere. :/
You do not have to bind a variable to the exception:
try
{
...
}
catch (Exception)
{
bqBusinessQuery.RollBackTransaction();
throw;
}
Actually, in your case, as you catch any exception, you do not have to even name the exception type:
try
{
...
}
catch
{
bqBusinessQuery.RollBackTransaction();
throw;
}
Or (as suggested #Zohar Peled) throw a new exception, using the caught exception as an inner exception. This way you both preserve the stack and give the exception more context.
try
{
...
}
catch (Exception e)
{
throw new Exception("Transaction failed", e);
}
If you actually want to use the exception for some processing (e.g. log it), but want to rethrow it intact, declare the variable, but use a plain throw:
try
{
...
}
catch (Exception e)
{
Console.WriteLine(e.Message);
throw;
}
catch (Exception)
{
bqBusinessQuery.RollBackTransaction();
throw;
}
If you don't plan on using the exception (e.g. passing the message somewhere) then you don't need to pull it out into a variable. You can simply catch, do custom thing and throw.

C# : Is it possible to initialize exception of the same type when some instance of exception is passed in?

I want to prevent all exceptions thrown by referenced libraries from escaping my library. I am doing this by filtering all functions through try catch which wraps exceptions if they are not MyException type. The problem that I have is that in my wrap function if the exception is MyException type I end up loosing my original stack trace since I end up re-throwing the same exception from a new place and don't embed the exception that was originally thrown, since the stack trace gets recorded from a new place where exception is re-thrown the stack trace of original throw is lost.
public static Exception Wrap(Exception exception)
{
Exception exceptionToReturn;
if (exception is MyException)
{
exceptionToReturn = exception;
}
else
{
exceptionToReturn = new MyException("Referenced library exception wrapped", exception);
}
return exception;
}
What I am trying to do is to re-throw the same type of exceptions that derived from MyException to keep the original stack trace. However I do not want to check for every child of MyException with code like:
(exception is ChildOfMyException)
exceptionToReturn = new ChildOfMyException(exception.Message, exception);
If I use generics. I cannot specify an explicit constructor.
public static Exception Wrap<TException>(TException exception)
where TException : Exception, new()
{
Exception exc;
if (exception is MyException)
{
exc = new TException();
}
else
{
exc = new MyException("Referenced library exception wrapped", exception);
}
return exc;
}
Is there some way that I am missing or will I have to use reflection to modify _innerException field.
First of all, if your want to rethrow an exception, use:
throw;
and not
throw ex;
The last statement will overwrite your stack trace, the first statement will preserve it.
You can only rethrow an exception inside the catch-block, but not inside anoother method. You could try something like this:
try
{
// Any code
}
catch(MyException ex)
{
throw;
}
catch(Exception ex)
{
throw Wrap(ex);
}
Where your Wrap method only wraps the the exceptions that must be wrapped. In essence it becomes this:
try
{
// Any code
}
catch(MyException ex)
{
throw;
}
catch(Exception ex)
{
throw new MyException("Referenced library exception wrapped", ex);
}
If this does not work for you (because try-catch blocks get repeated over and over), you also could take a look at AOP which might do it for you. Using postsharp, your method could become a bit like:
[ExceptionPolicy(bla bla)]
void MyMethod()
{
// Any code
}
Read more at: http://www.postsharp.net/
If you want to save the original stacktrace and rethrow the original exception you have to throw instead of throw ex. So your wrap function needs to return a boolean which will indicate a throw or rethrow, along with the new exception if there is any.
Something like this:
public static bool Wrap(ref Exception exception) {
if (exception is MyException) {
// false indicates a rethrow of the original exception
return false;
}
exception = new MyException("Referenced library exception wrapped", exception);
return true;
}
// Calling code
try {
// Something
} catch (Exception ex) {
if (SomeClass.Wrap(ref ex))
throw ex;
throw;
}

Change catch (COMException ce) to catch (COMException)

I have the following code:
try
{
retval = axNTLXRemote.IsUnitPresent(_servers[0].IPAddress, 1, _servers[0].RemotePort, _servers[0].CommFailDelay * 1000);
}
catch (COMException ce)
{
throw ce;
}
Which gives me the followig warning which I want to get rid of:
CA2200 : Microsoft.Usage : 'Connect()' rethrows a caught exception and specifies it explicitly as an argument. Use 'throw' without an argument instead, in order to preserve the stack location where the exception was initially raised.
I have read the following The difference between try/catch/throw and try/catch(e)/throw e and I understand that the 'throw ce; will reset the stack trace and make it appear as if the exception was thrown from that function.
I want to simply change it to a 'throw' instead of a 'throw ce' which will get rid of the warning.
What is the difference in the following catches:
catch (COMException ce)
{
throw;
}
and
catch (COMException)
{
throw;
}
Do I only need to have 'COMException ce' if I wish to somehow use the ce variable?
Also, when I perform a 'throw' or 'throw ce', is it the calling function that will handle or catch it?? I'm a little unclear about this.
The only difference is that with catch (COMException ce), you are assigning the exception to a variable, thereby letting you access it within the catch block. Other than that, it is in every way identical.
I'm not sure what the question is here. If you want to access the exception object, you must give it a variable name in the catch clause.
No matter how or where an exception is thrown, the exception will bubble up through the call stack to the closest catch block that matches.
Here's an example.
void Method1()
{
try
{
Method2();
}
catch // this will catch *any* exception
{
}
}
void Method2()
{
try
{
Method3();
}
catch (COMException ex) // this will catch only COMExceptions and exceptions that derive from COMException
{
}
}
void Method3()
{
// if this code were here, it would be caught in Method2
throw new COMException();
// if this code were here, it would be caught in Method1
throw new ApplicationException();
}
I'm sure someone will jump in with an uber-technical answer, but in my experience the answer to your first two questions is that there is no difference, and as you stated you'd only include ce if you intended to use it to write the stack trace to a log or display the message to the user or similar.
The throw will send the exception up the chain. That may be the calling method or, if your method has several nested try/catch blocks, it will send the exception to the next try/catch block that the current try/catch block is nested within.
Here are a couple good resources to check out if you want to read further on the subject:
Exception Handling
Design Guidelines for Exceptions
There is no difference in both cases, but only when exception variable should be used for stack/message etc.
So:
catch(ComException);
and
catch(ComException ex);
statements will produce similar MSIL, except local variable for ComException object:
.locals init ([0] class [mscorlib]System.Exception ex)

Exception handling problem

I'm trying to write some code that catches a particular exception and throw a more useful one for something higher up the call stack to deal with but also catch more general exceptions and handle them.
The code is something like this:
try
{
// Do stuff
}
catch (SomeException e)
{
throw new SomeExceptionWithContextInfo();
}
catch (Exception e)
{
// Handle unexpected exception gracefully
}
The problem I'm having is that the general exception is catching my new exception. is there a way to avoid this?
My current solution involves checking the type of the exception and throwing it again if it's type is what I just created.
The code you've posted should work, as shown in this test app:
using System;
class OtherException : Exception {}
class Test
{
static void Main(string[] args)
{
try
{
Foo();
}
catch (OtherException)
{
Console.WriteLine("Caught OtherException");
}
}
static void Foo()
{
try
{
string x = null;
int y = x.Length;
}
catch (NullReferenceException)
{
throw new OtherException();
}
catch (Exception)
{
Console.WriteLine("Caught plain Exception");
}
}
}
This just prints "Caught OtherException" not "Caught plain Exception". Are you sure you don't have a nested try block in your real code? Could you post a short but complete example which shows your problem?
Do you really need to catch Exception in your method though? That's very rarely a good idea.
You're doing it right. The general exception will not catch the specific one.
The code you posted is the way to do it (catch for more specific exception must appear first).
I suggest looking again at the code, as either they are not in that order, or the code isn't actually throwing that exception type.
Here is a link on msdn about try-catch: http://msdn.microsoft.com/en-us/library/0yd65esw(VS.80).aspx
Don't catch general exceptions might be the answer? Find out which Exceptions that can be thrown and catch them separately.
try { // Outer try/catch
DoSomething();
try {
/* */
} catch(NotGeneralException e) {
/* */
} catch(AnotherNotGeneralException e) {
throw new SomeOtherException("Exception message");
}
} catch(SomeOtherException e) {
/* */
}
Alternatively only catch a general exception and rethrow SomeOtherExcepion
try {
} catch(Exception e) {
throw new SomeOtherException("Exception message");
}

Categories