What’s the difference between "throw" and "throw ex"?

Asked

Viewed 2,737 times

18

I saw that the C# allows to do...

try
{
    //algum código
}
catch
{
    throw;
}

also...

try
{
    //algum código
}
catch (Exception ex)
{
    throw ex;
}

and...

try
{
    //algum código
}
catch (Exception)
{
    throw;
}

My doubts are: where is the exception played on throw, what is the difference between the three and if there is any, what is the best situation to use each?

1 answer

22


The first and last examples in practice are identical if you are using only C# as a language in your application. Not specifying what to capture indicates you are capturing Exception. That is, any exception. There is a difference in a case.

If you are using C++ or other language that allows you to launch anything (a string, a number, any data structure) and having C# capture this exception will work in the first example. Since he doesn’t specify what to catch, he’ll take anything. But it will not work in the last example, after all you are specifying that you want exceptions of the type Exception and, of course, all exceptions inherited directly or indirectly from Exception.

C# only allows you to cast exceptions of this type and its derivatives. So a catch without specification will take any exception released by C#, which is the same as a catch (Exception ex).

You should always wear throw;.

When you issue a throw ex; you are stopping the exception there doing some operation (in your case neither this is done but I will consider it is just to be an example) and then launches another exception from then on. He loses the information from where the real exception really came from and throws a new. It is as if a new problem has occurred. There will hardly be a case where this is desirable. In your example you will probably catch a more specific exception and launch a Exception which is the exception you have captured and very general which is not desirable (I reply a lot about this, my most recent answer on the subject is to There is some inconvenience in always capturing Exception and not something more specific?, there’s a link for other answers).

Issuing only the throw; you are going over to same exception forward, then another snippet of the code (where there is a catch) can capture and know what to do with the original exception preserving all necessary information, especially the stack trace.

Every time you make an exception she’ll end up where she found the first catch. Although rare, this may be just in the same method as the exception was thrown, it may be in the calling method, it may be in the previous method, and the previous one to it and so on, until it may be in the Main() and even if you don’t find one catch nowhere will fall on a catch implicit "hidden" by the environment. When you launch a throw can’t be sure where it will be captured unless it is a very small application developed only by you and doesn’t usually add new things to it.

The only place an exception to is a catch (of course a finally is still a catch. I would say that this is valid for any language, at least it is for all I know.

Note that if you use the code presented in the real code question it makes no sense. There’s no reason why you should capture an exception, do nothing with it and forward it to another catch take some action.

I found a example in the OS that helps to better understand:

using System;
using static System.Console;

public class Program {
     public static void Main(string[] args) {
        try {
            ThrowException1(); // line 19
        } catch (Exception x) {
            WriteLine("Exception 1:");
            WriteLine(x.StackTrace);
        }
        try {
            ThrowException2(); // line 25
        } catch (Exception x) {
            WriteLine("Exception 2:");
            WriteLine(x.StackTrace);
        }
    }

    private static void ThrowException1() {
        try {
            DivByZero(); // line 34
        } catch {
            throw; // line 36
        }
    }

    private static void ThrowException2() {
        try {
            DivByZero(); // line 41
        } catch (Exception ex) {
            throw ex; // line 43
        }
    }

    private static void DivByZero() {
        int x = 0;
        int y = 1 / x; // line 49
    }
}

Behold working in the ideone. And in the .NET Fiddle. Also put on the Github for future reference.

The exit would be:

Exception 1:
   at UnitTester.Program.DivByZero() in <snip>\Dev\UnitTester\Program.cs:line 49
   at UnitTester.Program.ThrowException1() in <snip>\Dev\UnitTester\Program.cs:line 36
   at UnitTester.Program.TestExceptions() in <snip>\Dev\UnitTester\Program.cs:line 19

Exception 2:
   at UnitTester.Program.ThrowException2() in <snip>\Dev\UnitTester\Program.cs:line 43
   at UnitTester.Program.TestExceptions() in <snip>\Dev\UnitTester\Program.cs:line 25

Noticed that the second with throw ex; lost important information about where the exception actually occurred? And then you get like a "silly cockroach" trying to find something in a method. Of course it may seem easy to find the error but remember that this is a simple example code, it may be that you miss several levels of method calls, that methods are more complex.

CIL code generated when using a throw ex;:

catch [mscorlib]System.Exception {
    IL_000b:  stloc.0
    IL_000c:  nop
    IL_000d:  ldloc.0
    IL_000e:  throw
}

And with throw;:

 catch [mscorlib]System.Exception {
    IL_000b:  stloc.0
    IL_000c:  nop
    IL_000d:  rethrow
 }

The actual instruction to be executed is quite different. The first code throws an exception in a normal way using as argument what is in the stack and the second makes a completely different operation. Explicitly is relaunching active exception (note that no argument is loaded with the statement ldloc as is done in the previous example).

  • What would this "forward" be? I know that in Java it plays the exception to the method it is calling (throws), would be this here too?

  • 2

    After lunch I will give an improved but this "forward" is more or less what you are saying, although even in Java it does not need to stop in the calling method, it stops when you find a catch, even if it is the catch implicit that every application has "hidden" if you provide no catch in your. Always remember that the only place an exception stops is a catch and it is not always easy to predict where it will end up. So one should not abuse exceptions. It is a goto long and unpredictable.

  • I usually play all exceptions for view, to report to the user from there.

  • It’s usually a good one. If you do it right. To tell you the truth throw; it is rarely necessary to use. It has its usefulness but in general when you catch the exception and do everything you need to do with it, it is not so common to "bubble up" the exception to another catch capture and tantar do something. An exception would be you try to recover, fail and then relaunch the same exception to your view give a final presentation to your users.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.