Представляет ли ссылка на делегат ссылку на объект (чтобы предотвратить сборку мусора)? - PullRequest
8 голосов
/ 12 ноября 2009

Мне было трудно придумать хороший способ сформулировать этот вопрос, поэтому позвольте мне попытаться объяснить на примере:

Предположим, у меня есть интерфейс. Для простоты я скажу, что интерфейс IRunnable, и он предоставляет один метод, Run. (Это не реально; это только пример.)

Теперь, предположим, у меня есть какой-то ранее существующий класс, назовем его Cheetah, который я не могу изменить. Он существовал до IRunnable; Я не могу заставить реализовать мой интерфейс. Но я хочу использовать его , как будто он реализует IRunnable - предположительно, потому что у него есть метод Run или что-то подобное. Другими словами, я хочу иметь возможность иметь код, который ожидает IRunnable и будет работать с Cheetah.

ОК, так что я всегда мог написать CheetahWrapper сделку. Но позабавьте меня и позвольте мне написать что-нибудь более гибкое - как насчет RunnableAdapter?

Я представляю определение класса примерно так:

public class RunnableAdapter : IRunnable {
    public delegate void RunMethod();

    private RunMethod Runner { get; set; }

    public RunnableAdapter(RunMethod runner) {
        this.Runner = runner;
    }

    public void Run() {
        Runner.Invoke();
    }
}

Достаточно просто, верно? Итак, после этого я смогу сделать звонок вот так:

Cheetah c = new Cheetah();
RunnableAdapter ra = new RunnableAdapter(c.Run);

А теперь, вуаля: у меня есть объект, который реализует IRunner и в его сердцах Cheetah.

Мой вопрос таков: если это мое Cheetah выпадет из области видимости в какой-то момент и достигнет точки, где оно обычно будет собирать мусор ... не так ли? Или это свойство RunnableAdapter объекта Runner представляет собой ссылку на исходный Cheetah, так что оно не будет собрано? Я, конечно, хочу, чтобы эта ссылка оставалась действительной, поэтому в основном мне интересно, достаточно ли приведенного выше определения класса или необходимо будет сохранить ссылку на базовый объект (например, через какое-то частное свойство UnderlyingObject), просто чтобы предотвратить сборка мусора.

Ответы [ 4 ]

9 голосов
/ 12 ноября 2009

Да, эта ссылка остается действительной и может быть получена с помощью свойства Delegate.Target - в вашем коде как ra.Runner.Target.

4 голосов
/ 12 ноября 2009

Как говорили другие, это считается ссылкой. Вы можете найти эту историю интересной. http://asserttrue.blogspot.com/2008/11/garbage-collection-causes-car-crash.html

2 голосов
/ 12 ноября 2009

Да, делегат считается ссылкой. Ваш объект не будет собирать мусор, пока делегат также не будет недоступен.

2 голосов
/ 12 ноября 2009

Если нет, то это похоже на сломанный сборщик мусора.

...