C # Действие, Закрытие и Сборка мусора - PullRequest
15 голосов
/ 17 ноября 2011

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

Меня меньше волнует, когда оба класса должны иметь почти одинаковую продолжительность жизни. Мой вопрос более уместен, когда продолжительность жизни Class1 намного больше, чем Class2, или когда продолжительность жизни Class2 намного больше, чем 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();
    }
}

Ответы [ 4 ]

18 голосов
/ 17 ноября 2011

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

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

Меня меньше волнует, когда оба класса должны иметь почти одинаковую продолжительность жизни. Мой вопрос более уместен, когда продолжительность жизни Class1 намного больше, чем Class2, или когда продолжительность жизни Class2 намного больше, чем 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;
    }
}

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

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

4 голосов
/ 17 ноября 2011

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

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

0 голосов
/ 17 ноября 2011

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

0 голосов
/ 17 ноября 2011

Нет, нет.Сборщик мусора справится с этим.

...