What Really Happens in a Try { Return X; } Finally { X = Null; } Statement

What really happens in a try { return x; } finally { x = null; } statement?

No - at the IL level you can't return from inside an exception-handled block. It essentially stores it in a variable and returns afterwards

i.e. similar to:

int tmp;
try {
tmp = ...
} finally {
...
}
return tmp;

for example (using reflector):

static int Test() {
try {
return SomeNumber();
} finally {
Foo();
}
}

compiles to:

.method private hidebysig static int32 Test() cil managed
{
.maxstack 1
.locals init (
[0] int32 CS$1$0000)
L_0000: call int32 Program::SomeNumber()
L_0005: stloc.0
L_0006: leave.s L_000e
L_0008: call void Program::Foo()
L_000d: endfinally
L_000e: ldloc.0
L_000f: ret
.try L_0000 to L_0008 finally handler L_0008 to L_000e
}

This basically declares a local variable (CS$1$0000), places the value into the variable (inside the handled block), then after exiting the block loads the variable, then returns it. Reflector renders this as:

private static int Test()
{
int CS$1$0000;
try
{
CS$1$0000 = SomeNumber();
}
finally
{
Foo();
}
return CS$1$0000;
}

Will code in a Finally statement fire if I return a value in a Try block?

Simple answer: Yes.

If I return out of a try/finally block in C# does the code in the finally always run?

Under normal conditions, code in a finally block will be executed regardless of what happens inside the try or catch blocks. It doesn't matter if you return from the method or not.

There are cases where this is not true. For example if the code in the finally block throws an exception, then it will stop executing like any other block of code.

Eric Lippert has written a much more comprehensive answer that outlines additional cases: https://stackoverflow.com/a/10260233/53777

In regards to goto, the answer is still yes. Consider the following code:

try
{
Console.WriteLine("Inside the Try");
goto MyLabel;
}
finally
{
Console.WriteLine("Inside the Finally");
}

MyLabel:
Console.WriteLine("After the Label");

The output produced is this:

Inside the Try

Inside the Finally

After the Label

why is my return statement unreachable after try-finally?

You have no catch, so if there's an exception in your try it will just be thrown. Your method either succeeds and returns true, or an exception is thrown.

If you add a catch block, the warning will go away because that path is now accessible.

You should be able to swallow the exception (if that's what you want) by simply adding catch {} before the finally.

Looking at your code more closely, you likely want to replace the finally with a catch anyways- it's unlikely you wish to log that the delete had failed no matter the outcome.

return statement before finally

From MSDN

By using a finally block, you can clean up any resources that are allocated in a try block, and you can run code even if an exception occurs in the try block. Typically, the statements of a finally block run when control leaves a try statement. The transfer of control can occur as a result of normal execution, of execution of a break, continue, goto, or return statement, or of propagation of an exception out of the try statement.

Within a handled exception, the associated finally block is guaranteed to be run. However, if the exception is unhandled, execution of the finally block is dependent on how the exception unwind operation is triggered. That, in turn, is dependent on how your computer is set up. For more information, see Unhandled Exception Processing in the CLR.

Return in the Finally Block... Why not?

It's illegal because when you reach the Finally block, the value to return is already defined ("OK" if everything went well, "NOK" if an exception was caught). If you were able to return a different value from the Finally block, this value would always be returned, whatever the outcome of the instructions above. It just wouldn't make sense...

return in try-catch's finally block in java. Is there any good point in this example?

Is there really any point in adding a finally block here?

The answer to this is a resounding "no": putting a return statement in the finally block is a very bad idea.

I just add the return null inside the catch block, which would execute the same behavior, or am I wrong?

It wouldn't match the original behavior, but that's a good thing, because it would fix it. Rather than returning null unconditionally the way the original code does, the code with the return inside the catch block would return null only on errors. In other words, the value returned in the try branch would be returned to the caller unless there is an exception.

Moreover, if you add return null after the catch block, you would see the correct effect of returning null on exception. I would go even further, and put a single return in the method, like this:

response or = null;
try {
or = //gives it a value
log.info(or.toString());
} catch ( Exception e) {
e.printStackTrace();
}
return or;

try/finally without catch and return value

From the JLS (emphasis mine):

If execution of the try block completes abruptly because of a throw of
a value V, then there is a choice:

[...]

If the run-time type of V is not assignment compatible with a catchable exception class of any catch clause of the try statement, then the finally
block is executed. Then there is a choice:

  • If the finally block completes normally, then the try statement completes abruptly because of a throw of the value V.

  • If the finally block completes abruptly for reason S, then the try statement completes abruptly for reason S (and the throw of value V is
    discarded and forgotten
    ).

This means if you return within the finally block, the method returns without throwing an exception.

Besides return, there are other statementes that can cause the finally block to complete abruptly and forget about the exception. They are defined in the JLS Section 14.1. Basically, it is break, continue, return or an exception (either thrown or caused by a statement/method). The complete try/catch/finally block then completes with this reason.

There are a few more cases ín the specification of try/catch/finally, especially if there is no exception or a matching catch clause exists. It comes down to finally beats catch beats try.

Is it possible to change the return value in a finally clause in C#?

Assume that you have a C# method with a return statement inside a try block. Is it possible to modify the return value in the finally block?

No.

You can however modify the return value outside the finally block:

static int M()
{
try
{
try
{
return 123;
}
finally
{
throw new Exception();
}
}
catch
{
return 456;
}
}

Just because there was originally a "return 123" does not mean that the method will return 123, if that's what your question is actually getting at. This method returns 456.

java: try finally blocks execution

When you return from try block, the return value is stored on the stack frame for that method. After that the finally block is executed.

Changing the value in the finally block will not change the value already on the stack. However if you return again from the finally block, the return value on the stack will be overwritten, and the new x will be returned.

If you print the value of x in finally block, you will get to know that it is executed, and the value of x will get printed.

static int test(){
int x = 1;
try{
return x;
}
finally{
x = x + 1;
System.out.println(x); // Prints new value of x
}
}

Note: In case of a reference value being returned, the value of reference is stored on the stack. In that case, you can change the value of object, using that reference.

StringBuilder builder = new StringBuilder("");
try {
builder.append("Rohit ");
return builder;

} finally {
// Here you are changing the object pointed to by the reference
builder.append("Jain"); // Return value will be `Rohit Jain`

// However this will not nullify the return value.
// The value returned will still be `Rohit Jain`
builder = null;
}

Suggested Read:

  • JVM Specs - Frames


Related Topics



Leave a reply



Submit