17

Suppose I have the following two classes in two different assemblies:

//in assembly A
public class TypeA {
   // Constructor omitted
   public void MethodA
   {
     try {
       //do something
     }
     catch {
        throw;
     }
   }
}
//in assembly B
public class TypeB {
   public void MethodB
   {
     try {
       TypeA a = new TypeA();
       a.MethodA();
     }
     catch (Exception e)
       //Handle exception
     }
   }
}

In this case, the try-catch in MethodA just elevates the exception but doesn't really handle it. Is there any advantage in using try-catch at all in MethodA? In other words, is there a difference between this kind of try-catch block and not using one at all?

JaredPar
  • 733,204
  • 149
  • 1,241
  • 1,454
Leo Nix
  • 2,085
  • 2
  • 24
  • 37
  • It does help with debugging to have the try catch throw... And hopefully you should be throwing to many exceptions when you application is complete any way (The resource problem that has been mentioned) – bytebender Apr 04 '09 at 18:20
  • Does this answer your question? [Why catch and rethrow an exception in C#?](https://stackoverflow.com/questions/881473/why-catch-and-rethrow-an-exception-in-c) – Dour High Arch Dec 30 '20 at 01:01
  • @bytebende How does it help with debugging? It doesn't make any difference if you don't do anything but re-throw the exception. – The incredible Jan Oct 12 '22 at 09:03

11 Answers11

7

In your example, there is no advantage to this. But there are cases where it is desirable to just bubble up a specific exception.

    public void Foo()
    {
        try
        {
            // Some service adapter code

            // A call to the service
        }
        catch (ServiceBoundaryException)
        {
            throw;
        }
        catch (Exception ex)
        {
            throw new AdapterBoundaryException("some message", ex);
        }
    }

This allows you to easily identify which boundary an exception occurred in. In this case, you would need to ensure your boundary exceptions are only thrown for code specific to the boundary.

Mufaka
  • 2,333
  • 1
  • 18
  • 25
  • 1
    ...unless your code is in the hot path or is deeply recursive (so the exception is re-thrown repeatedly), see http://blogs.msdn.com/curth/archive/2008/07/29/stackoverflowexception-and-ironpython.aspx – Anton Tykhyy Apr 04 '09 at 20:27
3

With the code the way you've written it for MethodA, there is no difference. All it will do is eat up processor cycles. However there can be an advantage to writing code this way if there is a resource you must free. For example

Resource r = GetSomeResource();
try {
  // Do Something
} catch { 
  FreeSomeResource();
  throw;
}
FreeSomeResource();

However there is no real point in doing it this way. It would be much better to just use a finally block instead.

JaredPar
  • 733,204
  • 149
  • 1,241
  • 1,454
  • 1
    Better to use the finally block with a boolean flag variable, ugly as it is. CIL actually has fault handlers which do exactly this, but for some unknown reason C# doesn't expose them. – Anton Tykhyy Apr 04 '09 at 17:47
  • That technique is useful if the function was planning on returning the resource. The exception voids that plan, so the function should clean up the resource itself before allowing the exception to propagate. – Rob Kennedy Apr 04 '09 at 18:00
  • 1
    How is this different then using the try...finally? – bendewey Apr 04 '09 at 18:16
  • 1
    It's quite different from try-finally; In this code, FreeSomeResource will ONLY be called for an exception, not under the normal flow of control. – Rob Kennedy Apr 04 '09 at 21:44
  • @Rob Kennedy You were right but just 30 minutes later JaredPar edited his answer and now there's no difference to finally anymore... – The incredible Jan Oct 12 '22 at 09:47
3

Yes there is a difference. When you catch an exception, .NET assumes you are going to handle it in some way, the stack is unwound up to the function that is doing the catch.

If you don't catch it will end up as an unhandled exception, which will invoke some kind of diagnostic (like a debugger or a exception logger), the full stack and its state at the actual point of failure will be available for inspection.

So if you catch then re-throw an exception that isn't handled elsewhere you rob the diagnostic tool of the really useful info about what actually happened.

AnthonyWJones
  • 187,081
  • 35
  • 232
  • 306
  • 1
    Hm, this is subtle. When you rethrow a different exception, the stack trace is lost unless you explicitly preserve it, but if you just rethrow the original exception (`throw;`), the stack trace is preserved. – Anton Tykhyy Apr 04 '09 at 18:00
  • Anthony, I think you're wrong. http://blog.dotnetclr.com/archive/2007/11/05/Re-throwing-an-exception.aspx – Rob Kennedy Apr 04 '09 at 18:13
  • OK, my wording wasn't precise enough: `throw ex;` and `throw;` *are* different, and both could be said to "rethrow the original exception", but I did write `throw;`, and your link agrees with me (right before the end of the linked post). – Anton Tykhyy Apr 04 '09 at 18:49
  • @Anton: Depending on how you re-throw you can maintain the stack trace as its stored in the exception. However the stack itself is unwound and all its current state (which may well include vital clues as what actually went wrong) is lost. – AnthonyWJones Apr 04 '09 at 20:44
  • @Rob: As I indicated to Anton, there is very important difference between a stack _trace_ stored in the exception and the _actual_ stack itself. The stack trace does not preserve the parameter values passed to each method in the stack or the values of local variables. – AnthonyWJones Apr 05 '09 at 07:26
2

Just rethrowing makes no sense - it's the same as if you did not do anything.

However it gets useful when you actually do something - most common thing is to log the exception. You can also change state of your class, whatever.

Rashack
  • 4,667
  • 2
  • 26
  • 35
2

Taken as-is, the first option would seem like a bad (or should that be 'useless'?) idea. However, it is rarely done this way. Exceptions are re-thrown from within a Catch block usually under two conditions :

a. You want to check the exception generated for data and conditionally bubble it up the stack.

try 
{
  //do something
}
catch (Exception ex)
{
  //Check ex for certain conditions.
  if (ex.Message = "Something bad")
    throw ex;
  else
    //Handle the exception here itself.
}

b. An unacceptable condition has occurred within a component and this information needs to be communicated to the calling code (usually by appending some other useful information or wrapping it in another exception type altogether).

try 
{
  //do something
}
catch (StackOverflowException ex)
{
    //Bubble up the exception to calling code 
    //by wrapping it up in a custom exception.
    throw new MyEuphemisticException(ex, "Something not-so-good just happened!");
}
Cerebrus
  • 25,615
  • 8
  • 56
  • 70
1

Never do option A. As Anton says, it eats up the stack trace. JaredPar's example also eats up the stacktrace. A better solution would be:

SomeType* pValue = GetValue();
try {
  // Do Something
} finally {
  delete pValue;
}

If you got something in C# that needs to be released, for instance a FileStream you got the following two choices:

FileStream stream;
try
{
  stream = new FileStream("C:\\afile.txt");
  // do something with the stream
}
finally
{
  // Will always close the stream, even if there are an exception
  stream.Close(); 
}

Or more cleanly:

using (FileStream stream = new FileStream("c:\\afile.txt"))
{
  // do something with the stream
}

Using statement will Dispose (and close) the stream when done or when an exception is closed.

jgauffin
  • 99,844
  • 45
  • 235
  • 372
  • I was talking about stack space, not stack trace. Stack trace is OK in the particular case of rethrowing the original exception. – Anton Tykhyy Apr 04 '09 at 18:06
  • 3
    Jared's code does not destroy the stack trace, either. The stack trace will still show the original source of the exception. You're confusing it with catching an exception with a parameter and throwing the caught exception anew: "catch (Exception e) { throw e; }" -- that trashes the stack trace. – Rob Kennedy Apr 04 '09 at 18:09
1

When you catch and throw, it allows you to set a breakpoint on the throw line.

Rob Kennedy
  • 161,384
  • 21
  • 275
  • 467
  • The debugger can break on an excception. Don't do this just for breakpoints. The code is likely to ship that way. – John Saunders Apr 04 '09 at 18:48
  • Breaking on exception isn't the same as breaking in the procedure where the breakpoint is. Besides, the question didn't ask whether it was a good idea. It asked what the effect was. – Rob Kennedy Apr 04 '09 at 21:48
1

Re-throwing exceptions can be used to encapsulate it into generic exception like... consider following example.

public class XmlException: Exception{
   ....
} 

public class XmlParser{
   public void Parse()
   {
      try{
          ....
      }
      catch(IOException ex)
      {
         throw new XmlException("IO Error while Parsing", ex );
      }
   }
}

This gives benefit over categorizing exceptions. This is how aspx file handlers and many other system code does exception encapsulation which determines their way up to the stack and their flow of logic.

Akash Kava
  • 39,066
  • 20
  • 121
  • 167
1

The assembly A - try catch - block does not make any sense to me. I believe that if you are not going to handle the exception, then why are you catching those exceptions.. It would be anyway thrown to the next level.

But, if you are creating a middle layer API or something like that and handling an exception ( and hence eating up the exception) in that layer does not make sense, then you can throw your own layer ApplicationException. But certainly rethrowing the same exception does not make sense.

123Developer
  • 1,463
  • 3
  • 17
  • 24
1

Since the classes are in 2 different assemblies, you may want o simply catch the exception for logging it and then throw it back out to the caller, so that it can handle it the way it sees fit. A throw instead of a throw ex will preserve contextual information about where the exception originated. This can prove useful when your assembly is an API/framework where in you should never swallow exceptions unless its meaningful to do so but helpful nonetheless in trouble shooting if it's logged for example to the EventLog.

Abhijeet Patel
  • 6,562
  • 8
  • 50
  • 93
0

You can use try{} catch(ex){} block in Method A only if you could catch the specific exception which can be handled in MethodA() (for eg: logging ).

Another option is chain the exception using the InnerException property and pass it to the caller. This idea will not kill the stack trace.

Shan
  • 121
  • 1
  • 5