Reputation:
If all I want to do is throw the exception up a level when it occurs?
private void TryCatch()
{
try
{
foo();
}
catch (Exception ex)
{
throw;
}
}
private void NoTryCatch()
{
foo();
}
Aren't these two methods the same?
If an exception occurs in TryCatch it will be thrown up a level and if an exception occurs in NoTryCatch, the exception will also be thrown up a level.
This question came about after using ReSharper and noticing that it suggested to remove the try/catch block as it was redundant.
Upvotes: 9
Views: 5452
Reputation: 3694
They really are not the same. Throw
on its own or throw ex
mess with the stack trace information and can make debugging harder.
The best reason to catch an exception is to add context to the stack trace, like:
try {
Foo();
}
catch (Exception e) {
throw new BetterException("I did something slightly silly", e);
}
Upvotes: 1
Reputation: 743
Something I thought about, but I wasn't sure 100% so I went to check. I was right, sometimes.
Apparently, if you re-throw the exception, which is what your code is doing, you could end up changing the stack-trace. First of all, if you were to write throw ex;
that would reset the stack-trace. Second, even when writing throw;
there can also be cases where information is missing. See this article and some user comments following up on it.
Of course, most of these issues are related to the stack-trace and line-numbers, which are important, but I thought it would also affect performance, not just because of inlining (or the lack thereof), but also because of the whole exception catching and throwing overhead, but I didn't find anything concrete on this.
Upvotes: 1
Reputation: 1502686
Yes, those methods are pretty much (*) the same. The only difference is that it's easy to put a breakpoint in the first one. I'd always go with the second unless I really needed to break there and only there (as opposed to immediately any exceptions of that type were thrown, which would be easy). Even if I ever used the first, I'd put it back to the second form before committing the code.
(*) There may well be some differences in terms of how the JIT handles them. The first will end up with more IL, which will affect opportunities for inlining etc.
EDIT: I can't resist a bit of micro-benchmarking. It looks like try/catch/throw has nastier effects on performance than just disabling inlining:
using System;
using System.Diagnostics;
using System.Runtime.CompilerServices;
public class Test
{
const int Iterations = 1000000000;
static void Main()
{
Stopwatch sw;
sw = Stopwatch.StartNew();
for (int i=0; i < Iterations; i++)
{
SimpleMethod();
}
sw.Stop();
Console.WriteLine("Simple method: {0}", sw.ElapsedMilliseconds);
sw = Stopwatch.StartNew();
for (int i=0; i < Iterations; i++)
{
NoInlining();
}
sw.Stop();
Console.WriteLine("No inlining: {0}", sw.ElapsedMilliseconds);
sw = Stopwatch.StartNew();
for (int i=0; i < Iterations; i++)
{
TryCatchThrow();
}
sw.Stop();
Console.WriteLine("try/catch/throw: {0}", sw.ElapsedMilliseconds);
}
static void SimpleMethod()
{
Foo();
}
[MethodImpl(MethodImplOptions.NoInlining)]
static void NoInlining()
{
}
static void TryCatchThrow()
{
try
{
Foo();
}
catch (Exception)
{
throw;
}
}
static void Foo() {}
}
Compile with /o+ /debug-
Results (three runs):
Simple method: 504, 495, 489
No inlining: 2977, 3060, 3019
try/catch/throw: 5274, 4543, 5145
Upvotes: 19
Reputation: 116471
If all you do is rethrow the exception you don't need the try/catch block. Generally you should only catch exceptions when you can handle them. Otherwise let them propagate upwards.
Upvotes: 0
Reputation: 7553
Yes, the try catch block is redundant. The stack will just be unwound until a try/catch is found to handle the exception.
Upvotes: 0
Reputation: 189505
ReSharper is correct. Unless you actually intend to catch and do something about an exception there is no point including a try..catch block.
Upvotes: 0
Reputation: 14084
No, you do not need the try catch. The only reason you would want to use the first function is if you wanted to do some logging or release resources before handling the function further up.
Upvotes: 3
Reputation: 74290
These two methods are essentially the same. In this case ReSharper was correct with its suggestion.
Upvotes: 1