Что происходит с переменной в конце блока в управляемом коде - PullRequest
1 голос
/ 14 мая 2011

После окончания блока

{
}

Что происходит с переменной, которая находится в блоке?

{
    int a;
    a=2;
    int b = 3;
}

//What happened now???

и что происходит после этого блока

{
    int a=2;
    int b = 3;
}
GC.Collect();

Это понятно?Если теги, которые я выбрал, неверны, пожалуйста, отредактируйте их или если вы можете отредактировать мой вопрос, чтобы он был понятен, отредактируйте его.

Ответы [ 3 ]

4 голосов
/ 14 мая 2011

В конце блока все переменные, объявленные внутри, просто «выходят из области видимости».

Скорее всего, они вытолкнуты из стека, но детали оптимизатора (ов).

И поскольку все ваши примеры переменных int s (ValueTypes), они не имеют ничего общего с сборкой мусора.

Если мы изменим последний пример на:

{
  int a=2;
  var b = new StringBuilder();
  ...
}
GC.Collect();

Тогда память для StringBuilder будет собрана в GC.Collect (). Обратите внимание, что обычной программе никогда не нужно вызывать GC.Collect ().

4 голосов
/ 14 мая 2011

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

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

Вызов GC.Collect(); просто заставляет GC работать, хотя сбор не уверен. В большинстве случаев это не требуется.

2 голосов
/ 14 мая 2011

В конце блока переменные, объявленные внутри блока, выходят из области видимости. Если они являются типами значений (например, int), они просто выталкиваются из стека. Если они являются ссылочными типами (как и большинство других объектов, например, StringBuilder), то на них больше не будут ссылаться (если вы не передали их чему-либо за пределами блока, который все еще находится в области видимости), и сборщик мусора получит его через некоторое время .

Если у вас есть объекты, которые обращаются к дефицитным ресурсам, например, к различным классам на основе Stream (или к чему-либо, что реализует IDisposable), то вы должны поместить это в оператор using, например:

using (Stream s = GetStream())
{
    // Do something with the stream.
}

В конце блока using вызывается метод Dispose и освобождаются все ресурсы (такие как обработчики файлов, соединения с базой данных, большие куски памяти и т. Д.)

Как правило, вам не нужно понимать, когда именно сборщик мусора будет работать или освобождать память. Когда я перешел из C ++ в .NET в 2002 году, мне было очень трудно понять, когда я перешел с C ++ просто потому, что я привык вызывать delete для любого объекта, который я создал в куче.

Вам больше не нужно беспокоиться об этом. Даже если вы забудете вызвать dispose, сборщик мусора рано или поздно доберется до него (хотя, вероятно, вы не захотите хранить этот дескриптор файла дольше, чем необходимо, поэтому IDisposable)

...