-4

I am bit confused regarding the finally block. I know that finally block gets executed no matter if there is an exception or not.

I have got 2 scenarios :-

1) If there is an exception in try block and I have not written any catch block for this try block, but I have a finally block, then will the finally block gets executed? Does finally block executed if the exception is unhandled?

Below is an example code :-

static void Main(string[] args)
            {
                int x = 0;
                try
                {
                    int divide = 12 / x;
                }
                //catch (Exception ex)
                //{
                //    int divide = 12 / x;
                //    Console.WriteLine(ex.Message);

                //}
                finally
                {
                    Console.WriteLine("I am finally block");
                }
                Console.ReadLine();
            }

2) Will the finally block get executed if there is an exception in catch block? Below is the sample code :-

static void Main(string[] args)
    {
        int x = 0;
        try
        {
            int divide = 12 / x;
        }
        catch (Exception ex)
        {
            int divide = 12 / x;   // this will throw exception in catch block
            Console.WriteLine(ex.Message);

        }
        finally
        {
            Console.WriteLine("I am finally block");
        }
        Console.ReadLine();
    }

I have tried these codes and I don't see the finally block getting executed. Please explain me why the finally block is not executed.

  • 4
    Debug to see... – Antoine V Jul 30 '18 at 17:57
  • 5
    I'm voting to close this question as off-topic because OP basically asks for a tutorial on error handling which could be testes by himself fairly easily. – VDWWD Jul 30 '18 at 18:01
  • @ThierryV : Please read my entire post. I did debug and found that finally block is not getting executed. Wanted to know the reason. – siddharth chakraborty Jul 30 '18 at 18:01
  • 2
    https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/try-finally – chadnt Jul 30 '18 at 18:08
  • 1
    The documentation specifically mentions that if there's no top-level catch block, it's not guaranteed that the `finally` block would execute. https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/try-finally – xxbbcc Jul 30 '18 at 18:18
  • 1
    This is a perfectly valid question (although a duplicate). Please justify your downvotes. If you're not willing to or can't answer, please let others to do so. – Eren Ersönmez Jul 30 '18 at 18:43
  • @siddharthchakraborty thanks for the question. This might help: https://stackoverflow.com/q/1555567/201088 – Eren Ersönmez Jul 30 '18 at 18:45
  • My answer is below and I don't downvote this question – Antoine V Jul 31 '18 at 07:31

2 Answers2

3

In really simple terms, these are what try-catch-finally blocks do:

Try

The place where you'd put potentially problematic code. If an exception is generated, an exception will be thrown.

Catch

Catch is the ONLY block where an exception will be caught. Hence the name. So when an exception is thrown, if you want to ensure the program doesn't 'hang', you must catch the exception.

Finally

Do your cleanup. If, say, you have some array in your try block and you want to clean it up in case of an exception, this is the place to do it.

Try-Finally

The documentation says:

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.

Meaning, if you don't catch your exception, it depends on the situation whether finally is run.

So, with that in mind, let's look at your first code block.

static void Main(string[] args)
{
    int x = 0;
    try
    {
        int divide = 12 / x;
    }
    finally
    {
        Console.WriteLine("I am finally block");
    }
    Console.ReadLine();
}

You're attempting to do a divide by zero which generates an exception. But there's no place for it to be 'caught', so the program hangs:

enter image description here

So if you add a catch block here, now it will allow for smooth sailing and go to your finally as well.

try
{
    int divide = 12 / x;
}
catch (Exception ex)
{
    Console.WriteLine("Oops. Division by Zero.");
}
finally
{
    Console.WriteLine("I am finally block");
}

Now let's take your second code snippet. I'm going to do a small modification and flip the order of two lines of code inside the catch.

static void Main(string[] args)
{
    int x = 0;
    try
    {
        int divide = 12 / x;
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex.Message);
        int divide = 12 / x;
    }
    finally
    {
        Console.WriteLine("I am finally block");
    }
    Console.ReadLine();
}

Now, the catch block catches the exception thrown by the first illegal division and prints a message. But then there's a second illegal division inside the catch, and there's no catch for that thrown exception so the program hangs.

So if you modify it to have a second try-catch inside the first catch like so:

static void Main(string[] args)
{
    int x = 0;
    try
    {
        int divide = 12 / x;
    }
    catch (Exception ex)
    {
        try
        {
            Console.WriteLine(ex.Message);
            int divide = 12 / x;
        }
        catch (Exception ex2)
        {
            Console.WriteLine(ex2.Message);
        }
    }
    finally
    {
        Console.WriteLine("I am finally block");
    }
    Console.ReadLine();
}

Now it will catch both exceptions and you're good to go.

So the idea is, if you have a try you should try to have a catch unless you can justify why you don't want one.

Sach
  • 10,091
  • 8
  • 47
  • 84
0

Following the article MSDN

Within a handled exception, the associated finally block is guaranteed to be run

That means for try catch finally, the code in finally must be executed.

        int x = 0;
        try
        {
            int divide = 12 / x;
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
        finally
        {
            Console.WriteLine("I am finally block");
        }
        Console.ReadLine();

With the output:

Attempted to divide by zero. // catch Console.WriteLine(ex.Message);
I am finally block // finally

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.

That means it depends the exception thrown finally code will be executed or not. If StackOverflowException or an exception i.e ExecutionEngineException, which may invoke to call Environment.FailFast() or Environment.Exit(), your finally code won't be executed because your application has closed before.

In your case 2, there is an exception DivideByZeroException in catch or in try in the case 1 , the code finally in this case will be executed.

int x = 0;
try
{
    int divide = 12 / x;
}
catch (Exception ex)
{
    int divide = 12 / x;   // no handled
    Console.WriteLine(ex.Message);

}
finally
{
    Console.WriteLine("I am finally block");
}
Console.ReadLine();

The output:

I am finally block // finally
Run-time exception (line 16): Attempted to divide by zero. // exception non handled catch by the level plus high that cause crashing the application
Antoine V
  • 6,998
  • 2
  • 11
  • 34