As a follow-up to this question, I have the following code:
using System;
using System.Runtime.InteropServices;
namespace ConsoleApplication1
{
class Program
{
class Child
{
public override string ToString()
{
return "I am a child!";
}
~Child()
{
Console.WriteLine("~Child called");
}
}
class Test
{
readonly object _child;
readonly WeakReference _ref;
readonly GCHandle _gch; // GCHandle is a value type, so it's safe
public Test()
{
_child = new Child();
_ref = new WeakReference(_child);
_gch = GCHandle.Alloc(_child);
}
// ...
public void DoTest()
{
lock (_child)
{
Console.WriteLine("DoTest called, child: " + _child.ToString() + ", is alive: " + _ref.IsAlive);
}
}
~Test()
{
Console.WriteLine("~Test starts");
DoTest();
_gch.Free();
Console.WriteLine("~Test ends");
}
}
static void Main(string[] args)
{
var test = new Test();
test.DoTest();
test = null;
GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced);
System.Threading.Thread.Sleep(1000);
GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced);
Console.ReadLine();
}
}
}
The output:
DoTest called, child: I am a child!, is alive: True ~Test starts DoTest called, child: I am a child!, is alive: False ~Test ends ~Child called
The question: why does WeakReference.IsAlive
for _child
become false
inside ~Test()
, while the _child
object is still pinned down with GCHandle.Alloc
?