3

I am working with this code as an example:

var p = new person("Amir");
var zp = new person("Amiraa");
GC.Collect();
GC.WaitForPendingFinalizers();

class person
{
    public person(string nName)
    {
        Console.WriteLine("New");
        string name = nName;
    }

    ~person()
    {
        Console.WriteLine("Garbage collected");
    }
}

But the resault on the console only shows "New", not "Garbage collected". so why is the gc not working?

Good Night Nerd Pride
  • 8,245
  • 4
  • 49
  • 65
ILovePizza
  • 141
  • 1
  • 8
  • Bear in mind that a) garbage collection *does* work in .NET and b) it's intended to let you *not have to think about when objects are collected*. – Damien_The_Unbeliever Jan 12 '22 at 09:28
  • Destructor in c# are very non deterministic. See this answer from Eric Lippert: https://stackoverflow.com/questions/44573392/c-sharp-my-destructor-isnt-being-called – Federico Alterio Jan 13 '22 at 01:18

1 Answers1

6

Play around, and you'll notice that your code works as expected in Release, but not necessarily Debug.

This is because the variables p and zp are still in scope at the point that you call GC.Collect(). They still refer to the person instances.

In Release, the GC will happily collect objects referenced by variables which are still in scope, so long as they are not used again. In Debug, the debugger needs to let you view the contents of all variables which are in scope, so the GC can't collect them.

If you do:

var p = new person("Amir");
var zp = new person("Amiraa");

p = null;
zp = null;

GC.Collect();
GC.WaitForPendingFinalizers();

You'll see the output you expect, even in Debug. Note that the tiered compilation introduced in .NET 6 affects this, and the above test might not work as expected.

If you introduce a separate method, so the lifetimes of p and zp are explicitly scoped, you should see the expected behaviour even on .NET 6 in Debug:

Test();
GC.Collect();
GC.WaitForPendingFinalizers();

void Test()
{
    var p = new person("Amir");
    var zp = new person("Amiraa");
}
canton7
  • 37,633
  • 3
  • 64
  • 77
  • Hey, Yes I thought about that - but still it is not working, I am not getting the GB. (still console only shows new). – ILovePizza Jan 12 '22 at 09:25
  • See the links in my answer - they show the output I describe. If you're seeing something different, then I'm afraid I can't reproduce it. Make sure you can reproduce what you're seeing on a site such as https://sharplab.io or https://dotnetfiddle.net – canton7 Jan 12 '22 at 09:26
  • The link you send also only write "new" to the console. it does not show the output from the ~(person) – ILovePizza Jan 12 '22 at 09:32
  • See the "Release" link. Interestingly the output from the `p = null` seems to have changed... – canton7 Jan 12 '22 at 09:41
  • Yes I see your point. but for some reason it does not show on .vs 2022 – ILovePizza Jan 12 '22 at 09:46
  • If memory services, the tiered compilation in .NET 6 gets in the way here, and might be why we're seeing changing results on SharpLab. See my latest edit – canton7 Jan 12 '22 at 09:54