Можно ли написать C #, чтобы объекты собирали мусор, когда они выпадают из области видимости? - PullRequest
6 голосов
/ 28 января 2010

Например, в приведенном ниже коде будет создан объект 'image', а затем в будущем будет собираться мусор в неизвестном месте

void MyFunction() {

    Bitmap image = RetrieveImage();
    DoSomething(image);
}

Как насчет

void MyFunction() {

    DoSomething(RetrieveImage());

}

В этом случае мусор объекта собирается после того, как он выходит из области видимости, т.е. после завершения MyFunction. Если нет, то где-нибудь, чтобы обеспечить это?

Ответы [ 4 ]

19 голосов
/ 28 января 2010

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

То, что вы делаете хотите, - это своевременно распоряжаться неуправляемыми ресурсами - вот где приходит IDisposable вместе с оператором using:

void MyFunction()
{
    using (Bitmap image = RetrieveImage())
    {
        DoSomething(image);
    }
}

Это вызовет image.Dispose() при выходе из оператора using, вне зависимости от того, выдало ли DoSomething исключение.

Вы должны использовать дополнительную переменную, хотя - если вы не измените DoSomething вместо Func<Bitmap>, вместо:

void DoSomething(Bitmap image)
{
    // Code here
}
...
DoSomething(RetrieveImage());

у вас будет:

void DoSomething(Func<Bitmap> imageProvider)
{
    using (Bitmap image = imageProvider())
    {
        // Code here
    }
}
...
DoSomething(() => RetrieveImage());

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

РЕДАКТИРОВАТЬ: Как указал в своих комментариях mbeckish, здесь не так уж много пользы от простого использования растрового изображения в RetrieveImage. Вот вариант на схеме:

public void ApplyToEachLineInFile(string file, Action<string> action)
{
    using (TextReader reader = File.OpenText(file))
    {
        string line;
        while ((line = reader.ReadLine()) != null)
        {
            action(line);
        }
    }
}

Здесь логика «получения и утилизации» инкапсулирована, и вызывающий ее не беспокоится об этом, но вызывающий может все же быть очень гибким с точки зрения сложности логики, которую они передают.

4 голосов
/ 28 января 2010

Сборка мусора не происходит, когда объект выпадает из области видимости. Скорее, это функция автоматического управления памятью из фреймворка.

http://msdn.microsoft.com/en-us/magazine/bb985010.aspx

Вы можете заставить .Net собирать мусор, но если у вас нет серьезных проблем с памятью, я бы не рекомендовал вам идти по этому пути.

3 голосов
/ 28 января 2010

ПРИМЕЧАНИЕ : Вы не хотите этого делать. Сборщик мусора .NET «умнее», чем вы (или я, или Джон Скит, или кто-либо еще).

try
{
    Bitmap image = RetrieveImage();
    DoSomething(image);
}
finally
{
    GC.Collect();
}

(предполагается, что ни один из объектов, выпадающих из области видимости, не реализует IDisposable)

0 голосов
/ 28 января 2010

Вы можете включить сборщик мусора с помощью:

System.GC.Collect ()

после правильной утилизации (см. Ответ Джонс для использования () {} - Синтаксис).

Не забывайте (как я только что сделал)

System.GC.WaitForPendingFinalizers ();

впоследствии.

Хотя это и не рекомендуется - как сказал Джон.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...