Сборка мусора в случае динамического объекта - PullRequest
2 голосов
/ 19 декабря 2011
Foo a;

try
{
 // some work with a;
}
finally
{
 a = null;
}

В этом примере мы помечаем объект a для сборки мусора.

Теперь предположим, что мы модифицируем код следующим образом.

public  xyz()
{
 return new Foo();
}

Теперь в этом примере у вновь созданного объекта нет имени, поэтому когда он будет помечен для сбора? Или GC автоматически определит, что он бесполезен, и попытается восстановить его?

РЕДАКТИРОВАТЬ:

Прочитав ответ, я добавляю еще одну ситуацию.

Foo a;

try
{     
  return a;
}
finally
{
 a = null;
}

Что теперь будет?

Ответы [ 5 ]

4 голосов
/ 19 декабря 2011

Это никогда"помечено для сбора мусора" ... это объект и существует - , которого достаточно для GC, чтобы рассмотреть его. Присвоение полей и переменных влияет только на то, когда оно может быть успешно собрано.

В отношении второго примера:

  • если оно находится в стеке как значение (как возвращение из xyz()), оно не будет собрано
  • если он хранится в локальной переменной, он не будет собран (возможно, в зависимости от того, будет ли эта переменная когда-либо читать снова, в зависимости от реализации GC)
  • если оно хранится где-то как поле на достижимом (не подлежащем сбору) объекте, оно не будет собрано
2 голосов
/ 19 декабря 2011

В этом примере мы помечаем объект a для сборки мусора.

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

Установка ссылки на null никак не влияет на сборщик мусора, если только вы не используете переменную позже в коде.

Foo a = new A();

try {
  // some work with a;
  // at this point a is no longer used, so it can be collected
} finally {
  // this has no effect on garbage collection:
  a = null;
}

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

Единственные объекты, которые требуют специальной обработки, - это объекты, реализующие интерфейс IDisposable. Вы должны вызвать метод Dispose для этих объектов, когда закончите с ними, или поместить их в блок using, который автоматически вызовет Dispose.

Edit:

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

2 голосов
/ 19 декабря 2011

если вызывающий xyz назначает результат чему-либо, то он останется без присмотра, в противном случае это будет GC'd в конечном итоге. Просто нужно что-то удерживать для ссылки на объект, чтобы выжить в ГК.

1 голос
/ 19 декабря 2011

Вот интересная статья в MSDN о времени жизни объекта C #.

Фрагмент:

сборщик мусора отслеживает ссылки на объекты и идентифицирует объекты, которые не могутболее длинный доступ к нему выполняется с помощью кода

В нем явно сказано, что он не использует подсчет ссылок, а является альтернативой, когда он сканирует, если объекты имеют какие-либо доступные ссылки.Если код не может получить доступ к объекту, он помечается для сбора.

0 голосов
/ 19 декабря 2011

когда вы пишете Foo a;, вы создаете только память для ссылки на объект типа Foo в стеке.

когда вы пишете new Foo();, тогда вы создаете только объект типа Foo в Heap без ссылки.

и когда вы пишете Foo a = new Foo();, вы делаете a для ссылки на объект Foo в куче, как показано

enter image description here

когда вы устанавливаете a = null;, вы просто удаляете ссылку на объект Foo в Heap и больше не ссылаетесь.

GC будет собирать любые такие объекты, на которые больше нет ссылок.

То же самое, когда вы создаете объект внутри метода и возвращаетесь из метода.
Ссылка, которую вы создаете как a внутри метода, будет очищена из стека при возврате, и объект, который вы создали внутри метода, больше не будет ссылаться (если ссылка не возвращена). GC собирает его.

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