Почему слабая ссылка не собирается в этом простом примере F #? - PullRequest
1 голос
/ 02 апреля 2020
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()

Перевод с Rx In Action *1003* книжный образец. Приведенное выше при запуске дает следующий вывод, который отличается от того, что я получаю, когда я компилирую его в C# и запускаю его.

IsAlive: True
obj <> null is True
---
IsAlive: True

Почему слабая ссылка не собирается?

1 Ответ

2 голосов
/ 02 апреля 2020

Это один из тех случаев, когда измерение влияет на результат.

Основной причиной является оптимизация компилятором (обратная?) Для улучшения локальных параметров во время отладки.

Когда вы пишете:

let list1 = [1; 2; 3]
let list2 = [3; 4; 5]
printfn "%b" (list1 = list2)

Это уточняет каждое подвыражение:

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)

Теперь вы можете начать догадываться, куда это идет.

 Console.WriteLine("IsAlive: {0}\nobj <> null is {1}\n---", weak.IsAlive, obj <> null);

Уточняется:

    let isAlive = weak.IsAlive
    let obj' = obj
    let isNotNull = obj' <> null
    Console.WriteLine("IsAlive: {0}\nobj <> null is {1}\n---", isAlive, isNotNull);

Теперь, когда вы сделаете:

    obj <- null;
    GC.Collect();

обратите внимание, что ссылка все еще существует в obj'.

Таким образом, объект не будет собран во время прохода G C. И это то, что показывает WeakReference.

Достаточно интересно, что если вы закомментируете первое Console.Writeline, нет никакой детализации подвыражения, следовательно, нет ссылок, и вы получите:

IsAlive: False

Или вы можете просто построить его в режиме Release .

...