views:

616

answers:

10

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?

+1  A: 

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
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
@Anton, hah, I read this as a C++ question :)
JaredPar
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
How is this different then using the try...finally?
bendewey
@bendewey, practically it's not (read the last sentence)
JaredPar
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
@Rob, yep, missed the non-error case ;) Fixed
JaredPar
+1  A: 

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
+1  A: 

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
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
Anthony, I think you're wrong. http://blog.dotnetclr.com/archive/2007/11/05/Re-throwing-an-exception.aspx
Rob Kennedy
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
@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
I said Anthony, not Anton.
Rob Kennedy
@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
+1  A: 

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
I was talking about stack space, not stack trace. Stack trace is OK in the particular case of rethrowing the original exception.
Anton Tykhyy
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
+1  A: 

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

Rob Kennedy
The debugger can break on an excception. Don't do this just for breakpoints. The code is likely to ship that way.
John Saunders
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
@Rob: I agree with John, this not a good idea.
AnthonyWJones
+1  A: 

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
The question you've answered is not the one Cullen asked.
Rob Kennedy
+4  A: 

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
...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
+2  A: 

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
"throw ex" is bad - is screws up the stack. Just do "throw"
John Saunders
Can you really catch StackOverflowException? I thought .NET 2.0+ doesn't let you do that.
Anton Tykhyy
Please don't use the message property of an exception for conditional logic as they can be localized.
Matt Ellis
@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.
Cerebrus
+1  A: 

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  A: 

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