C#: Уведомление перед WeakReference собрано?

Оптимизация последнего вызова состоит в том, где Вы в состоянии постараться не выделять новый стековый фрейм для функции, потому что функция вызова просто возвратит значение, которое это получает от вызванной функции. Наиболее популярный способ использования является хвостовой рекурсией, где рекурсивная функция, записанная для использования в своих интересах оптимизации последнего вызова, может использовать постоянное стековое пространство.

Схема является одним из нескольких языков программирования, которые гарантируют в спецификации, что любая реализация должна обеспечить эту оптимизацию (JavaScript делает также, начиная с ES6) , таким образом, вот два примера функции факториала в Схеме:

(define (fact x)
  (if (= x 0) 1
      (* x (fact (- x 1)))))

(define (fact x)
  (define (fact-tail x accum)
    (if (= x 0) accum
        (fact-tail (- x 1) (* x accum))))
  (fact-tail x 1))

первая функция не является хвостом, рекурсивным, потому что, когда рекурсивный вызов выполняется, функция должна отслеживать умножение, которое это должно сделать с результатом после возвратов вызова. По сути, стек смотрит следующим образом:

(fact 3)
(* 3 (fact 2))
(* 3 (* 2 (fact 1)))
(* 3 (* 2 (* 1 (fact 0))))
(* 3 (* 2 (* 1 1)))
(* 3 (* 2 1))
(* 3 2)
6

Напротив, отслеживание стека для хвоста рекурсивный факториал смотрит следующим образом:

(fact 3)
(fact-tail 3 1)
(fact-tail 2 3)
(fact-tail 1 6)
(fact-tail 0 6)
6

, Как Вы видите, мы только должны отслеживать тот же объем данных для каждого вызова к хвосту факта, потому что мы просто возвращаем значение, в котором мы разбираемся до вершины. Это означает, что, даже если я должен был звонить (факт 1000000), мне нужна только та же сумма пространства как (факт 3). Дело обстоит не так с non-tail-recursive фактом и большими значениями как таковыми может вызвать переполнение стека.

11
задан Robert Fraser 17 July 2009 в 20:29
поделиться

4 ответа

Нет, нет никакого способа реализовать эту функциональность.

После некоторых предположений я не верю, что возможно реализовать функцию таким образом, как вы описываете.

Учтите, что в момент сбора объекта, удерживаемого WeakReference, больше нет ссылок (следовательно, он может быть собран). Чтобы событие могло быть вам полезно, необходимо предоставить объект как часть события. Это означает, что ссылка из собираемой превратилась в несобранную. Ничто не мешает обрабатывающему коду повторить ссылку на этот объект. Следовательно, объект больше не может считаться коллекционным. CLR потребуется второй проход для объекта, чтобы убедиться, что его можно собрать.

Вы можете видеть, что во второй раз событие не могло быть инициировано, потому что это привело бы к необратимым объектам.

Было бы неправильным использовать именование, чтобы утверждать, что это событие было инициировано непосредственно перед сбором объекта. Просто потому, что любой обработчик может предотвратить его сбор, установив новую ссылку на объект. Вместо этого это должно быть «ObjectMaybeAboutToBeCollected». Это, наверное, выиграло ' t дать вам поведение, которое вы ищете.

6
ответ дан 3 December 2019 в 05:13
поделиться

Вы не можете этого сделать. Однако вы можете наблюдать, когда приближается сборщик мусора (в CLR v3.5Sp1 есть новые API сборщика мусора, которые позволяют это делать, GCNotifications)

6
ответ дан 3 December 2019 в 05:13
поделиться

Ваш вопрос не имеет для меня смысла. Где должен находиться код, который будет вызываться? Учитывая, что слабые ссылки будут обнулены до того, как объект, на который указывает ссылка, будет уничтожен, не имеет смысла быть частью класса, который ссылается на объект, который должен быть уничтожен. И в указанном объекте уже есть код, который вызывается до того, как объект будет уничтожен - это деструктор.

Какую реальную проблему проектирования вы хотите решить? Возможно, есть способ получше.

0
ответ дан 3 December 2019 в 05:13
поделиться

Для того, что вы описываете, финализаторы были бы лучшим подходом.

0
ответ дан 3 December 2019 в 05:13
поделиться
Другие вопросы по тегам:

Похожие вопросы: