Подтвердить что ты не робот

С# Действие, закрытие и сбор мусора

Нужно ли устанавливать MyAction в значение null, чтобы сбор мусора мог работать с любым из этих классов?

Я менее обеспокоен тем, что оба класса должны иметь почти одну и ту же продолжительность жизни. Мой вопрос более подходит, когда срок службы Class1s намного длиннее Class2 или когда срок службы Class2s намного длиннее Class1.

Код здесь убирается. Предположим, что и Class1, и Class2 содержат другие элементы и методы, которые могут повлиять на их продолжительность жизни.

public class Class1 : IDisposable
{
    public Action<string> MyAction { get; set; }

    // Is this necessary?
    public void Dispose()
    {
        MyAction = null;
    }
}

public class Class2
{
    string _result = string.Empty;

    public void DoSomething()
    {
        Class1 myClass1 = new Class1();
        myClass1.MyAction = s => _result = s;
        myClass1.Dispose();
    }
}
4b9b3361

Ответ 1

Нужно ли устанавливать MyAction в null, чтобы сбор мусора мог работать с любым из этих классов?

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

Я менее обеспокоен тем, что оба класса должны иметь почти одну и ту же продолжительность жизни. Мой вопрос более подходит, когда срок службы Class1s намного длиннее Class2 или когда срок службы Class2s намного длиннее Class1.

Вопрос не имеет никакого смысла; классы не имеют жизней. Места хранения имеют срок службы.. С какими местами хранения вы беспокоитесь? Вы можете уточнить вопрос?

Замечу, что есть очень серьезные опасения по поводу продления времени жизни замкнутых переменных посредством замыканий; ваш вопрос, однако, настолько расплывчатый, что трудно понять, сталкиваетесь ли вы с такой ситуацией. Позвольте мне продемонстрировать:

class Expensive
{
    public byte[] huge = MakeHugeByteArray();
}

class Cheap
{
    public int tiny;
}

class C
{
    public static Func<Cheap> longLived;
    public static void M()
    { 
        Expensive expensiveLocal = new Expensive();
        Cheap cheapLocal = new Cheap();
        Func<Expensive> shortLived = ()=>expensiveLocal ;
        C.longLived = ()=>cheapLocal;
    }
}

Какова продолжительность жизни локальной переменной дорогостоящаяLocal? Время жизни локальной переменной обычно коротки; обычно локальные переменные живут не дольше, чем активация метода. Однако , находящийся в замыкании, продлевает время жизни локальной переменной сколь угодно долго, до времени жизни замыкания. В этом конкретном случае оба лямбда разделяют замыкание, а это означает, что время жизни локальной переменной дорогойLocal, по крайней мере, дольше, чем время жизни локальной переменной cheapLocal, которая имеет бесконечно длинный срок службы, потому что ссылка на закрытие только что хранилась в статическом поле, которое живет вечно. Этот большой массив байтов никогда не будет восстановлен, хотя единственное, что, похоже, ссылается на него, было собрано давно; закрытие является скрытой ссылкой.

У многих языков есть эта проблема; С#, VB, JScript и т.д. Все имеют лексические замыкания, которые не разбиваются на групповые переменные по времени жизни. Мы рассматриваем возможность изменения С# и VB на лучшее управление жизненным циклом для закрытий, но это далеко вперед в будущем, поэтому никаких гарантий.

Ответ 2

Нет. Нет необходимости устанавливать ссылку на null.

Dispose() предназначен для очистки неуправляемых ресурсов. Action<string> является управляемым ресурсом и будет надлежащим образом обрабатываться CLR, когда экземпляр Class1 выпадает из области видимости в конце DoSomething().

Ответ 3

Нет, нет. Сборщик мусора будет обрабатывать его.

Ответ 4

Когда возвращается DoSomething, myCLass1 является кандидатом на сбор мусора. Когда класс собирает мусор, все его члены также собираются, если нет выдающихся ссылок. Поэтому вам не нужно делать то, что вы делаете.