Делегат, который не поддерживает цель - PullRequest
0 голосов
/ 19 июня 2019

Есть ли способ, чтобы делегат не мог сохранить цель живым?

Если у меня есть Action a = someObj.DoSomething, то делегат сохранит в живых someObj.

Если яиметь WeakReference<Action> a = new WeakReference<Action>((Action)someObj.DoSomething), someObj делегат по-прежнему будет поддерживать работу, но сам делегат будет собран GC, а затем цель может быть собрана.

Ответы [ 2 ]

1 голос
/ 19 июня 2019

Вы просто хотите иметь делегата, который использует слабую ссылку, а не слабую ссылку на делегат.

WeakReference<YourObjectType> someObjReference = new WeakReference<YourObjectType>(someObj);
Action a = () =>
{
    if (someObjReference.TryGetTarget(out YourObjectType someObjValue))
        someObjValue.DoSomething();
};
0 голосов
/ 19 июня 2019

Я думаю, что вы сделали правильно, и что-то еще удерживает ваш объект.

Я тестировал с

    class Program
    {
        public class YourObjectType {
            public void DoSomething() { }
        }
        public class WeakReferences {
            public WeakReference<Action> a;
            public WeakReference<YourObjectType> o;
        }

        static WeakReferences createReferences() {
            var someObj = new YourObjectType();

            return new WeakReferences() { a = new WeakReference<Action>((Action)someObj.DoSomething), o = new WeakReference<YourObjectType>(someObj) };
        }

        static void Main(string[] args)
        {
            WeakReferences wr = createReferences();
            YourObjectType o = null;
            wr.o.TryGetTarget(out o); //comment this line to collect it instead
            GC.Collect();
            Action a = null;

            Console.WriteLine(wr.a.TryGetTarget(out a));
            Console.WriteLine(wr.o.TryGetTarget(out o));
            Console.ReadLine();
        }
    }

, и действительно, если вы избежите первого TryGetTarget, он исчезнет..

...