简体   繁体   中英

Does throwing an Exception have side effects beyond just constructing the exception?

I've got it in my head that throwing an exception has side effects (like collecting stack information), but I'm realizing it might not. Is there a difference between the following two versions of GetException ?

public Exception GetException() {
    try {
        throw new Exception("Bummer");
    }
    catch (Exception e) {
        return e;
    }
}

public Exception GetException() {
    return new Exception("Bummer");
}

When an exception is thrown, the stack trace is "inserted" into the exception (that is what you can get through the StackTrace property). So yes, there is a side-effect in throwing an exception object.

A problem of rethrowing an exception (even with

throw;

is that the stack trace is mangled (or even overwritten, if you use throw ex; ))

Note that throw; is better than throw ex; , because the first one will only mangle a little the line numbers, while the later will reset totally the stack trace.

There are some persons that don't trust... Look at https://dotnetfiddle.net/RXicN9 and check the line numbers. They are different.

a more complete example that shows that only the method with the two try... catch... has its line numbers mangled: https://dotnetfiddle.net/jJyYWB

See Incorrect stacktrace by rethrow for an explanation. Note that this is a special case, that happens only if an exception is thrown twice in the same method.

Yes, the two are different. The throw will modify the stack trace information in the Exception object - so your second example will still produce an exception, but without the stack trace information.

Exception -derived classes are classes as any other - all the "magic" happens with the throw keyword.

This is also the reason why it's a bad idea to rethrow the exception by doing throw ex; - you either want to use throw; (although careful about the issue of rethrowing in the same method that Xanatos pointed out), or you want to wrap the inner exception (ie. throw new MyException(ex) ). In both cases, there's still some minor changes that can complicate debugging, but if you're well prepared, it helps a lot.

This behaviour is actually quite useful. For one, it means that you can have helper methods that construct exceptions for you to throw (this is used all over the place in .NET code itself). Two, it allows the runtime to actually throw exceptions like StackOverflowException and OutOfMemoryException - both have their instances created when the application starts, and when the issue occurs, they only throw - a new would fail, of course.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM