1

For a long time I thought that it allows me to free up all the resources in the finally block and I thought that if an exception happens in the try block, then the resources will still be free up in the finally block. But that seems not to be the case.

I have the following piece of code:

using System;

public sealed class Program
{

    public static void Main()
    {
        try {
            int zero = 0;
            int i = 1/zero;
        } finally {
            Console.WriteLine("divide by zero"); //the line is never called
        }
    }
}

I never reach the line which prints to the console. That means that I will not be able to free up resource in finally block in this case on the exception being thrown inside the try block.

So, I believe there are two things: either I am missing something or the try + finally combination has no use cases in the C#. The second statement makes sense, because I will get the same functionality as is produced by the above code with the code below:

using System;

public sealed class Program
{

    public static void Main()
    {
            int zero = 0;
            int i = 1/zero;

            Console.WriteLine("divide by zero"); //the line is never called
    }
}

But I am afraid that I might be missing something here. So, could someone confirm that the combination is useless or prove that it is not, please?

UPDATE

After the comment which is able to call the finally block in its fiddle, I checked once more in the VS Code, and still I see no output.

enter image description here

Alexei Levenkov
  • 98,904
  • 14
  • 127
  • 179
qqqqqqq
  • 1,831
  • 1
  • 18
  • 48
  • 1
    @MichaelRandall Try with the .NET Core compiler: https://dotnetfiddle.net/8hLq8h – Johnathan Barclay Feb 10 '20 at 20:58
  • @JohnathanBarclay, oh. You are my saver. That is due to the .NET Core transition, while I am used to the .NET Framework. Thank you a lot. – qqqqqqq Feb 10 '20 at 20:59
  • @JohnathanBarclay, I believe your comment is the answer I was looking for. Could you, please, add it as an answer? – qqqqqqq Feb 10 '20 at 21:02
  • Does this answer your question? [C# try catch confusion](https://stackoverflow.com/questions/19970397/c-sharp-try-catch-confusion) – T.S. Feb 10 '20 at 21:03
  • @T.S., no. What answers my questions is the fiddle by **Johnathan Barclay**. – qqqqqqq Feb 10 '20 at 21:04
  • 1
    @qqqqqqq The answer by Michael Randall explains the actual reason. My fiddle was just an observation. – Johnathan Barclay Feb 10 '20 at 21:06
  • @JohnathanBarclay, I can not infer from the answer what is so different about the .NET Core from the .NET Framework that led to such a behavior. That is crucial for my question. – qqqqqqq Feb 10 '20 at 21:08
  • I've rewrote very broad/opinion based title - if you feel that the edit does not reflect what you are asking (also it is exactly what is being answered/accepted) than feel free to [edit] more, but don't revert to "What are all possible use cases …" style of title. – Alexei Levenkov Feb 10 '20 at 21:11
  • @JohnathanBarclay, could you, please, let me know what was your deduction path that you decided to check the .NET Core? Was it a random decision? – qqqqqqq Feb 10 '20 at 21:13
  • No thought process; I generally test everything in. NET Core now and I observed the same behaviour as yourself. – Johnathan Barclay Feb 10 '20 at 22:07

3 Answers3

9

You're assumptions are incorrect (sometimes) https://dotnetfiddle.net/hjqmOS

try-finally (C# Reference)

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.

There are cases when it doesn't run though

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.

Here is the important part

Usually, when an unhandled exception ends an application, whether or not the finally block is run is not important. However, if you have statements in a finally block that must be run even in that situation, one solution is to add a catch block to the try-finally statement. Alternatively, you can catch the exception that might be thrown in the try block of a try-finally statement higher up the call stack.

TheHans255
  • 2,059
  • 1
  • 19
  • 36
TheGeneral
  • 79,002
  • 9
  • 103
  • 141
  • 1
    Wow.. had no idea about the caveat in the last quote. Seems a little counterintuitive... but then again I don't think I've ever actually needed to read the docs for try/catch (or so I thought!). – Broots Waymb Feb 10 '20 at 21:04
  • 3
    @BrootsWaymb its surprising whats buried in those pesky documentations :) – TheGeneral Feb 10 '20 at 21:06
  • @MichaelRandall, does it mean that the last documentation quote is supported by the .NET Core, but not by the .NET Framework? – qqqqqqq Feb 10 '20 at 21:11
  • @qqqqqqq in short, use a `catch-finally` to handle the exceptions to try an ensure something is run. Don't depend on the environment – TheGeneral Feb 10 '20 at 21:16
  • @MichaelRandall, got it. Thank you. Could you, please, also let me know what does the `exception unwind operation triggering` means? I was not able to find anything explaining this in the documentation. – qqqqqqq Feb 10 '20 at 21:32
  • @MichaelRandall, one more thing I find confusing it that we have the [using](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/using-statement) in C#. The `using` mimics the try + finally. So, is it naturally to expect the same kind of problems from the using? (I am not expecting you to know the answer, probably someone else will be able to answer it). Thank you once more. – qqqqqqq Feb 10 '20 at 21:39
  • @qqqqqqq hrm "*guessing*" its dependent on the operating system and how it unwinds the stack. Though maybe someone with a bit more knowledge of the internals can answer this one. This is most likely another question, and an interesting one at that, which might draw in the likes of someone with a bit more knowledge – TheGeneral Feb 10 '20 at 21:39
  • @MichaelRandall, [thank you](https://stackoverflow.com/questions/60158924/are-there-guarantees-in-c-sharp-that-the-using-statement-wont-inherit-the-try). – qqqqqqq Feb 10 '20 at 21:44
1

try/catch/finally has nothing to do with freeing up resources. This is strictly application flow and error handling construct. You live in the managed code and garbage collector frees up resources. This construct does the following

try
{
    int zero = 0;
    int i = 1/zero;
}
catch (DividedByZeroException ex)
{
    Console.WriteLine(Exception handled);
    throw; // propagate ex to caller
}
finally
{
    Console.WriteLine("Method ended execution"); // called with or without exception
}
T.S.
  • 18,195
  • 11
  • 58
  • 78
1

I believe this is because you have VS to break on unhandled errors and thus VS steps in displaying the exception. If you compile it and run it manually on the command line I believe you will see "divide by zero". Also, instead of changing your VS settings, you can 'handle' the error and then should see the behavior you expect.

Example:

using System;

public sealed class Program
{

public static void Main()
{
    try
    {
        int zero = 0;
        int i = 1 / zero;
    }
    catch
    {

    }
    finally
    {
        Console.WriteLine("divide by zero"); 
    }
}
}
Tim
  • 606
  • 4
  • 7