Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In .NET, is finally equivalent to try-catch-throw?

Tags:

c#

.net

cil

I am writing a static analysis tool for CIL. Control flow analysis would be simplified if finally blocks could be interpreted as try-catch blocks with a rethrow inside the catch. In C#, I fail to see the difference between

try
{
    // ...
}
finally
{
    // finally code here
}

and

try
{
    // ...
}
catch
{
    // finally code here
    throw;
}

or between

try
{
    // ...
}
catch(Exception e)
{
    // catch code here
}
finally
{
    // finally code here
}

and

try
{
    try
    {
        // ...
    }
    catch (Exception e)
    {
        // catch code here
    }
}
catch
{
    // finally code here
    throw;
}

There are even a finally block and endfinally instructions in the CIL. There must be a difference, is there?

like image 760
Călin Darie Avatar asked Nov 27 '22 17:11

Călin Darie


2 Answers

No - a finally block is executed even if no exception is thrown, and also even if another catch block catches the exception. (That's true whether the catch block then throws an exception itself or not.)

Oh, and a finally block will also be executed if the try block returns from the method.

Basically, if you want code to always execute when execution leaves the statement, finally is what you want. Although in C# I find I rarely write an explicit finally block - a using statement nearly always makes the code simpler.

like image 59
Jon Skeet Avatar answered Dec 06 '22 16:12

Jon Skeet


To add to Jon's -- correct, of course -- answer: you are actually describing a try-fault block. That is, a try-fault block is equivalent to try followed by catch-everything and automatic re-throw.

C# does not support try-fault blocks but CIL does, so if you're ever reading IL and you see a fault block, now you know what it is.

Also, it is correct to say that

try{} 
catch {} 
finally {}

is equivalent to

try 
{ 
    try { } 
    catch { } 
} 
finally { }

And in fact inside the C# compiler that's what it does; all try-catch-finally blocks are rewritten into a nested try-catch inside a try-finally. That is a simplifying assumption that can help when writing a static analyzer.

like image 45
Eric Lippert Avatar answered Dec 06 '22 16:12

Eric Lippert