c# – How and when to use Finally after a Try?

Question:

First I would like to know why using the finally

What are your advantages? Does it really only work when there is an exit from within the scope of a try-catch , such as when there is a return or goto inside?

Answer:

Other answers have already answered the most important thing about the question. In addition, the most common use for finally is resource cleanup.

When you use a variable declaration with using are actually using a try-finally

So when does:

using (Font font1 = new Font("Arial", 10.0f)) {
    byte charset = font1.GdiCharSet;
}

It is the same as:

{
  Font font1 = new Font("Arial", 10.0f);
  try {
    byte charset = font1.GdiCharSet;
  }
  finally {
    if (font1 != null)
      ((IDisposable)font1).Dispose();
  }
}

In fact it's just syntax sugar . The compiler actually swaps the using for the second construct.

The catch is used to catch exceptions and only, the finally is always executed after the end of a block of code inside the try or catch , if there is one, with an exception or not. The finally will be executed anyway, even if before it there is a return or goto trying to avoid it. It is not possible to exit the code block started by the try without going through the finally (at least not under normal C# conditions, as Omni remembers, there are catastrophic situations where the CLR may not guarantee the execution of the finally , moreover, in theory it is possible to change the IL to avoid it, but this is something wrong to do).

There is no way to use a return or goto inside a finally . Either you use it in try or catch or put it after the finally . Remembering that if it is after the finally block, it may not be executed, as the last code of Lucas Nunes' response demonstrates.

I found this an excellent answer (see also Jon Skeet's answer ) showing how the return works in the block protected by the try . This code:

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

Compile for CIL:

.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
}

Which would be the same as:

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

The return is executed at the end, but the expression contained in it is executed where the return would be in the original code.

I put it on GitHub for future reference .

Scroll to Top