Когда .net object = null игра для сборки мусора? Имеет ли значение сфера? - PullRequest
4 голосов
/ 11 января 2011

Folks,

Если я установлю для большого объекта значение .net, равное нулю, в середине долгого метода (не обязательно интенсивного использования процессора ... просто длительного), это сразу игра для мусораcollection ИЛИ должен ли метод завершиться до того, как объект будет готов к сборке мусора?

Ответы [ 3 ]

7 голосов
/ 11 января 2011

Метод не нужно завершать, но вам также не нужно устанавливать переменную в null, если GC может сказать, что вы не собираетесь читать его снова.Например:

public void Foo()
{
    SomeObject x = new SomeObject();
    // Code which uses x

    Console.WriteLine("Eligible for collection");

    // Code which doesn't use x.
}

Объект имеет право на сбор в указанной точке - при условии, конечно, что ничто не сохранило ссылку на него.Важно то, сможет ли что-нибудь снова прочитать это значение.Вы даже можете присвоить переменной другое значение, а затем прочитать ее, при условии, что GC знает, что больше не увидит оригинальное значение, которое не будет действовать как корень GC.Например:

using System;

class Bomb
{
    readonly string name;

    public Bomb(string name)
    {
        this.name = name;
    }

    ~Bomb()
    {
        Console.WriteLine(name + " - going boom!");
    }    

    public override string ToString()
    {
        return name;
    }
}

class Test
{
    static void Main()
    {
        Bomb b = new Bomb("First bomb");
        Console.WriteLine("Using bomb...");
        Console.WriteLine(b);
        Console.WriteLine("Not using it any more");

        GC.Collect();
        GC.WaitForPendingFinalizers();

        Console.WriteLine("Creating second bomb...");
        b = new Bomb("Second bomb");
        Console.WriteLine("Using second bomb...");
        Console.WriteLine(b);
        Console.WriteLine("End of main");
    }
}

Вывод:

Using bomb...
First bomb
Not using it any more
First bomb - going boom!
Creating second bomb...
Using second bomb...
Second bomb
End of main
Second bomb - going boom!

Фактически, это может стать более экстремальным: объект может иметь право на сборку мусора , даже если методзапуск "in" it до тех пор, пока GC может обнаружить, что ничто не может снова прочитать поле.Вот короткий, но полный пример:

using System;

class Bomb
{
    int x = 10;

    ~Bomb()
    {
        Console.WriteLine("Boom!");
    }

    public void GoBang()
    {
        Console.WriteLine("Start of GoBang");
        GC.Collect();
        GC.WaitForPendingFinalizers();

        Console.WriteLine("x={0}", x);
        Console.WriteLine("No more reads of x");
        GC.Collect();
        GC.WaitForPendingFinalizers();

        Console.WriteLine("Returning");
    }
}

class Test
{
    static void Main()
    {
        Bomb b = new Bomb();
        b.GoBang();
        Console.WriteLine("Still in Main");
    }
}

Вывод:

Start of GoBang
x=10
No more reads of x
Boom!
Returning
Still in Main

(Запустите этот не в отладчике - отладчик задерживает сборку мусора, чтобы вы могливсе еще смотрите переменные.)

Одно замечание: ваш вопрос говорит об установке объекта в ноль ... этого понятия не существует.Вы только когда-либо устанавливали переменную в ноль.Это стоит различать.

7 голосов
/ 11 января 2011

См. Статью Рэймонда Чена Когда объект станет доступен для сбора мусора? . По сути, он может иметь право на сбор практически в любое время, в том числе даже до того, как вы установите для этой ссылки значение null.

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

1 голос
/ 11 января 2011

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

...