I'm trying to learn how finalization and destructor works in C#, I tried to run the code in the System.Object.Finalize
example(code copy-pasted, no changes made), but the output is not the same as expected, it shows that the destructor is never called.
The code is:
using System;
using System.Diagnostics;
public class ExampleClass
{
Stopwatch sw;
public ExampleClass()
{
sw = Stopwatch.StartNew();
Console.WriteLine("Instantiated object");
}
public void ShowDuration()
{
Console.WriteLine("This instance of {0} has been in existence for {1}",
this, sw.Elapsed);
}
~ExampleClass()
{
Console.WriteLine("Finalizing object");
sw.Stop();
Console.WriteLine("This instance of {0} has been in existence for {1}",
this, sw.Elapsed);
}
}
public class Demo
{
public static void Main()
{
ExampleClass ex = new ExampleClass();
ex.ShowDuration();
}
}
Update:
When I use visual studio and .net framework 4.5, the code works as expected: Output same as example:
The example displays output like the following: Instantiated object This instance of ExampleClass has been in existence for 00:00:00.0011060 Finalizing object This instance of ExampleClass has been in existence for 00:00:00.0036294
When I use dotnet core app, the code does not work: The actual output is:
PS C:\ws\test> dotnet run Instantiated object This instance of ExampleClass has been in existence for 00:00:00.0056874
So why this is different in .NET Core?
Finalization won't occur until the garbage collector runs. Garbage collection doesn't run unless it needs to (e.g. you're low on memory), or if you force it to run.
Try adding
to your code and see if the finalizer runs in that situation.
Putting together information from comments by Peter Duniho and Henk Holterman and expanding on it further:
This behavior is in violation of the C# 5.0 spec from Microsoft and the current draft of the C# 6.0 spec from Microsoft, which say:
But it's not a bug, .Net Core intentionally diverged from the .Net Framework behavior, as explained in a corefx issue:
Presumably due to this, the C# 5.0 spec from ECMA weakened this requirement, so .Net Core does not violate this version of the spec: