Reputation: 739
I want to write a method that handle exceptions and that will be called inside a catch
block. Depending on the type of the exception passed, the exception is either passed as an inner exception of a new exception or simply re-thrown. How to preserve stack trace in the second case ?
Example :
public void TestMethod()
{
try
{
// can throw an exception specific to the project or a .Net exception
SomeWorkMethod()
}
catch(Exception ex)
{
HandleException(ex);
}
}
private void HandleException(Exception ex)
{
if(ex is SpecificException)
throw ex; //will not preserve stack trace...
else
throw new SpecificException(ex);
}
What I would not like to do is, because the pattern is repeated in many places and there will be no factorization :
try
{
SomeWorkMethod();
}
catch(Exception ex)
{
if(ex is SpecificException)
throw;
else
throw new SpecificException(ex);
}
Upvotes: 3
Views: 783
Reputation: 14007
You need to use throw
without specifying the exception to preserve stack trace. This can only be done inside the catch
block. What you can do is return from HandleException
without throwing the original exception and then use throw
right afterwards:
public void TestMethod()
{
try
{
// can throw an exception specific to the project or a .Net exception
SomeWorkMethod()
}
catch(Exception ex)
{
HandleException(ex);
throw;
}
}
private void HandleException(Exception ex)
{
if(ex is SpecificException)
return;
else
throw new SpecificException(ex);
}
As long as you only use is
to categorize the exception, the preferred way is two catch blocks:
public void TestMethod()
{
try
{
// can throw an exception specific to the project or a .Net exception
SomeWorkMethod()
}
catch (SpecificException)
{
throw;
}
catch(Exception ex)
{
throw new SpecificException(ex);
}
}
With C# 6.0 you can also use when
to let the exception fall through:
public void TestMethod()
{
try
{
// can throw an exception specific to the project or a .Net exception
SomeWorkMethod()
}
catch(Exception ex) when (!(ex is SpecificException))
{
throw new SpecificException(ex);
}
}
Upvotes: 6
Reputation: 120450
Actually, there's a really nice way of doing this in .Net4.5 using System.Runtime.ExceptionServices.ExceptionDispatchInfo.Capture
:
void Main()
{
try
{
throw new Exception(); //appears to be thrown from here
}
catch(Exception ex)
{
ThrowEx(ex);
}
}
public void ThrowEx(Exception ex)
{
if(someCondition)
{
//we're in the scope of a `catch` and the exception
//is "active", so the exception with original stack-trace
//can be re-thrown with
ExceptionDispatchInfo.Capture(ex).Throw();
//the following line is unreachable, but the compiler doesn't realise
//so we can "tell" the compiler that this branch ends in an exception
//and avoid having to return anything in the non-void case
throw new Exception();
}
}
Upvotes: 3
Reputation: 1
Maybe you can try this.
if(ex.Gettype() == typeof(SpecificException))
Upvotes: -2