Here I have declared two types A,and B,and they have reference to each other
public class A
{
public B B { get; set; }
~A()
{
Console.WriteLine( "destructing A..." );
}
}
public class B
{
public A A { get; set; }
~B()
{
Console.WriteLine( "destructing B..." );
}
}
in Main method,
var b = new B();
var a = new A();
a.B = b;
b.A = a;
a = null;
b = null;
GC.Collect();
the output shows that the destruction order is exactly as their definition order,I'm wondering why is that?
There is no guaranteed order for finalizers:
The finalizers of two objects are not guaranteed to run in any specific order, even if one object refers to the other. That is, if Object A has a reference to Object B and both have finalizers, Object B might have already been finalized when the finalizer of Object A starts. Object.Finalize
With an exception for critical finalizers:
In addition, the CLR establishes a weak ordering among normal and critical finalizers: for objects reclaimed by garbage collection at the same time, all the noncritical finalizers are called before any of the critical finalizers. CriticalFinalizerObject
Garbage Collection in .NET is non-deterministic (as you have observed since you are calling GC.Collect). There is no guarantee regarding the order of finalization whatsoever.
Yes, this means that referenced objects can be finalized before objects referencing them. That's one of the reasons writing a finalizer is very hard. You might work on "deinitialized" state.
Try not to use finalizers at all. It is extremely rare to need them.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With