Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can I throw an exception after a return statement? [duplicate]

The code below will complain

try
{
    session.Save(obj);
    return true;
}
catch (Exception e)
{
    throw e;
    return false;  // this will be flagged as unreachable code
}

whereas this will not:

try
{
    session.Save(obj);
    return true;
}
catch (Exception e)
{
    return false;
    throw e;
}

I dont get it...I thought my csc101 told me that return statements should always be the last statement in a function and that it exits the function and return control to the calling code. Why does this defy my professor's logic, and why does only one of these generate a warning?

like image 427
sirbombay Avatar asked Sep 26 '13 10:09

sirbombay


People also ask

Can you throw an exception and return something?

It's not possible to both throw an exception and return a value from a single function call. Perhaps it does something like returning false if there's an error, but throwing an exception if the input is invalid.

What happens if both a catch and a finally block define return statement?

If both catch and finally return, the receiving method will get the returned value from the finally block.

Do you need to return after throwing an exception?

After throwing an exception, you do not need to return because throw returns for you. Throwing will bubble up the call stack to the next exception handler so returning is not required.

What causes an exception to be thrown?

Exceptions are used to indicate that an error has occurred while running the program. Exception objects that describe an error are created and then thrown with the throw keyword.


3 Answers

return will exit the method; throw will also exit the method, assuming it is not inside the try. It can only exit once!

So regardless of the order - the first of the throw / return effectively end the method.

As more general feedback, though: if the intent is to return false upon failure, all you need is:

try
{
    session.Save(obj);
    return true;
}
catch
{
    return false;
}

Personally, I would say that this is bad code - it hides the actual problem from the caller, making it very hard to debug. It tells us nothing of why it failed. I would say that the better approach is simply to let the exception bubble. In that case, there is no point returning true, because we would never return false - and there is no point catching an exception just to re-throw it. So the entire method becomes:

session.Save(obj);

(nothing else required whatsoever)


If your question is "why does only one of these generate a warning": a fair question, but the compiler isn't required to spot either of them for you. Perhaps it should spot it. I suspect that gmcs would spot this and warn about it - the compiler in mono is far more willing to point out stupidity.


Edit: as expected, [g]mcs outputs:

Program.cs(15,13): warning CS0162: Unreachable code detected

Program.cs(28,13): warning CS0162: Unreachable code detected

for the code below - so it does indeed report both uses as warnings:

class Program
{
    static void Main() { }
    static void DoSomething() { }
    bool ReturnFirst()
    {
        try
        {
            DoSomething();
            return true;
        }
        catch
        {
            return false;
            throw; // line 15
        }
    }
    bool ThrowFirst()
    {
        try
        {
            DoSomething();
            return true;
        }
        catch
        {
            throw;
            return false; // line 28
        }
    }
}
like image 178
Marc Gravell Avatar answered Nov 03 '22 23:11

Marc Gravell


You are wrong: both your examples raise the Dead code compiler error because both throw and return mark the exit point of a method and no further code is allowed beyond that point.

However, whether the compiler allows it or not, the code below either the throw or the return is still dead and will never get a chance to execute.

(NOTE: this question was initially tagged as Java and my first sentence pertains to Java compiler semantics)

like image 33
Marko Topolnik Avatar answered Nov 04 '22 00:11

Marko Topolnik


Because any code after the return statement within a code block will be unreachable.

like image 34
Juned Ahsan Avatar answered Nov 04 '22 00:11

Juned Ahsan