The difference between re-throwing parameter-less catch and not doing anything?
Asked Answered
A

11

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?

Adan answered 4/4, 2009 at 17:42 Comment(3)
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)Hoisch
Does this answer your question? Why catch and rethrow an exception in C#?Conias
@bytebende How does it help with debugging? It doesn't make any difference if you don't do anything but re-throw the exception.Hodgkinson
B
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.

Brisesoleil answered 4/4, 2009 at 18:14 Comment(1)
...unless your code is in the hot path or is deeply recursive (so the exception is re-thrown repeatedly), see blogs.msdn.com/curth/archive/2008/07/29/…Bondie
H
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.

Hung answered 4/4, 2009 at 17:46 Comment(5)
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.Bondie
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.Keefer
How is this different then using the try...finally?Burberry
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.Keefer
@Rob Kennedy You were right but just 30 minutes later JaredPar edited his answer and now there's no difference to finally anymore...Hodgkinson
T
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.

Tezel answered 4/4, 2009 at 17:51 Comment(5)
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.Bondie
Anthony, I think you're wrong. blog.dotnetclr.com/archive/2007/11/05/…Keefer
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).Bondie
@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.Tezel
@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.Tezel
J
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.

Jolson answered 4/4, 2009 at 17:48 Comment(0)
H
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!");
}
Heighttopaper answered 4/4, 2009 at 18:15 Comment(6)
"throw ex" is bad - is screws up the stack. Just do "throw"Viridi
Can you really catch StackOverflowException? I thought .NET 2.0+ doesn't let you do that.Bondie
Please don't use the message property of an exception for conditional logic as they can be localized.Fluidextract
@Matt: It is an example that illustrates the conditions in which you might rethrow exceptions. I'm not suggesting that you should evaluate the message property of an exception for conditional logic.Heighttopaper
I know this is really late, but doesn't ex.Message = "Something bad" do an assignment, not a comparison?Kolodgie
@Kolodgie It does. Unfortunately "Suggested edit queue is full".Hodgkinson
A
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.

Antisyphilitic answered 4/4, 2009 at 17:55 Comment(2)
I was talking about stack space, not stack trace. Stack trace is OK in the particular case of rethrowing the original exception.Bondie
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.Keefer
K
1

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

Keefer answered 4/4, 2009 at 17:58 Comment(2)
The debugger can break on an excception. Don't do this just for breakpoints. The code is likely to ship that way.Viridi
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.Keefer
S
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.

Snuggery answered 4/4, 2009 at 17:58 Comment(1)
The question you've answered is not the one Cullen asked.Keefer
R
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.

Rottenstone answered 4/4, 2009 at 19:47 Comment(0)
O
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.

Octavie answered 4/4, 2009 at 21:58 Comment(0)
A
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.

Annapolis answered 5/2, 2016 at 9:10 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.