I have a test program that implements ManagedClass
with both Dispose
method and a Finalizer.
I'm forcing garbage collection via GC.Collect()
, but Finalizer is only called if an object is created in a separate method. Why is that?
namespace FinalizerTest
{
internal class Program
{
static void Run()
{
ManagedClass mc = new ManagedClass();
mc.StartWriting();
}
static void Main(string[] args)
{
Console.WriteLine("Let's test Finalizers!");
// Test #1: Create object through another method
Console.WriteLine("Test #1");
Run();
GC.Collect();
GC.WaitForPendingFinalizers();
// Test #2: Create object directly in Main
Console.WriteLine("Test #2");
ManagedClass mc1 = new ManagedClass();
mc1.StartWriting();
mc1 = null;
GC.Collect();
GC.WaitForPendingFinalizers();
Console.ReadLine();
}
}
public class ManagedClass : IDisposable
{
private StreamWriter _writer;
public void StartWriting()
{
_writer = new StreamWriter("output.txt");
}
public void Dispose()
{
Console.WriteLine("Disposing");
_writer?.Dispose();
GC.SuppressFinalize(this);
}
~ManagedClass()
{
Console.WriteLine("Finalizing");
_writer?.Dispose();
}
}
}
As I understand it in both scenarios a reference to the object is lost.
First test - reference is lost by exiting the scope of the method
Second test - reference is lost by setting reference variable to
null
However, Finalizer is consistently only ever called after the first test.
According to Microsoft documentation:
The garbage collector then calls the Finalize method automatically under the following conditions:
- After the garbage collector has discovered that an object is inaccessible, unless the object has been exempted from finalization by a call to the GC.SuppressFinalize method.
I'm not calling GCSuppressFinalize
and according to Visual Studio I'm working on .NET 7.0
I tried:
Reassigning a new reference instead of
null
Implementing Finalizer without the
Dispose
methodRunning in Release configuration / building the project and running the application directly through exe file
None of those things called Test #2 Finalizer