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
Failed to Serialize the Response in Web API
Is It Necessary to Manually Close and Dispose of SQLdatareader
Excel to Datatable Using Epplus - Excel Locked for Editing
Linq to SQL Using Group by and Count(Distinct)
Cannot Access a Disposed Object in ASP.NET Core When Injecting Dbcontext
How to Hide a Column (Gridview) But Still Access Its Value
Will the Dynamic Keyword in C#4 Support Extension Methods
Is Inaccessible Due to Its Protection Level
C# "Internal" Access Modifier When Doing Unit Testing
Creating Wcf Channelfactory<T>
How to Specify Proxy Credentials in Your Web.Config
Cannot Set Some Http Headers When Using System.Net.Webrequest
Performance of Calling Delegates VS Methods
Why Do We Need the New Keyword and Why Is the Default Behavior to Hide and Not Override
Scope of Static Variable in Multi-User ASP.NET Web Application