问题
open System
let WeakReferenceExample() =
let mutable obj = new Object();
let weak = new WeakReference(obj);
GC.Collect();
Console.WriteLine("IsAlive: {0}\nobj <> null is {1}\n---", weak.IsAlive, obj <> null);
obj <- null;
GC.Collect();
Console.WriteLine("IsAlive: {0}", weak.IsAlive);
WeakReferenceExample()
Console.ReadKey()
Translated from the Rx In Action book sample. The above when run gives the following output which is different than what I get when I compile it in C# and run it.
IsAlive: True
obj <> null is True
---
IsAlive: True
Why is the weak reference not getting collected?
回答1:
This is one of those cases where the measurement affects the result.
The underlying cause is compiler (reverse?) optimizations for better locals during Debugging.
When you write:
let list1 = [1; 2; 3]
let list2 = [3; 4; 5]
printfn "%b" (list1 = list2)
This elaborates every sub-expression to:
let list1 = [1; 2; 3]
let list2 = [3; 4; 5]
let list1' = list1
let list2' = list2
let is_eq = list1'.Equals(list2')
printfn "%b" (is_eq)
Now you can begin to guess where this is going.
Console.WriteLine("IsAlive: {0}\nobj <> null is {1}\n---", weak.IsAlive, obj <> null);
Elaborates to:
let isAlive = weak.IsAlive
let obj' = obj
let isNotNull = obj' <> null
Console.WriteLine("IsAlive: {0}\nobj <> null is {1}\n---", isAlive, isNotNull);
Now when you do:
obj <- null;
GC.Collect();
note that a reference still exists in obj'
.
So the object won't be collected during the GC pass.
And that's what WeakReference
is showing.
So interestingly enough, if you comment out the first Console.Writeline
, there's no sub-expression elaboration, hence no references, and you get:
IsAlive: False
Or you could just build it in Release mode.
来源:https://stackoverflow.com/questions/60989884/why-does-the-weak-reference-not-get-collected-in-this-simple-f-example