Установка объектов в Null / Nothing после использования in.NET
если вы установите все объекты в null
(Nothing
in VB.NET) как только вы закончите с ними?
Я понимаю, что в .NET необходимо утилизировать любые экземпляры объектов, которые реализуют IDisposable
интерфейс для освобождения некоторых ресурсов, хотя объект все еще может быть чем-то после его удаления (отсюда isDisposed
собственность в формы), поэтому я предполагаю, что он все еще может находиться в памяти или по крайней мере частично?
Я также знаю, что когда объект выходит затем он помечается для сбора, готового к следующему проходу сборщика мусора (хотя это может занять некоторое время).
так что с этим в виду будет установка его в null
ускорить систему, освобождающую память, поскольку она не должна работать, что она больше не находится в области действия, и являются ли они плохими побочными эффектами?
статьи MSDN никогда не делают этого в примерах, и в настоящее время я делаю это, как я не могу смотрите, какой вред. Однако я столкнулся со смесью мнений, поэтому любые комментарии очень полезный.
13 ответов:
Карл абсолютно прав, нет необходимости устанавливать объекты в null после использования. Если объект реализует
IDisposable
, просто убедитесь, что вы называетеIDisposable.Dispose()
когда вы закончите с этим объектом (завернутый вtry
..finally
илиusing()
блок). Но даже если вы не помните, чтобы позвонитьDispose()
, метод финализатора на объекте должен вызыватьDispose()
для вас.Я думал, что это было хорошее лечение:
и
нет никакого смысла пытаться угадать GC и его стратегии управления, потому что он самонастраивается и непрозрачен. Здесь была хорошая дискуссия о внутренней работе с Джеффри Рихтером на Dot Net Rocks:Джеффри Рихтер на модели памяти Windows и Книга Рихтера CLR через C# Глава 20 имеет большое лечение:
еще одна причина, чтобы избежать установки объектов в null, когда вы закончите с ними, заключается в том, что он может фактически поддерживать их жизнь дольше.
например
void foo() { var someType = new SomeType(); someType.DoSomething(); // someType is now eligible for garbage collection // ... rest of method not using 'someType' ... }
позволит объекту, на который ссылается someType, быть GC'D после вызова "DoSomething", но
void foo() { var someType = new SomeType(); someType.DoSomething(); // someType is NOT eligible for garbage collection yet // because that variable is used at the end of the method // ... rest of method not using 'someType' ... someType = null; }
иногда может поддерживать объект живым до конца метода. Элемент JIT обычно оптимизирует назначение до null, так что оба бита кода в конечном итоге являются тот же.
нет не null объектов. Вы можете проверить http://codebetter.com/blogs/karlseguin/archive/2008/04/27/foundations-of-programming-pt-7-back-to-basics-memory.aspx для получения дополнительной информации, но установка вещей в null ничего не сделает, кроме грязного кода.
также:
using(SomeObject object = new SomeObject()) { // do stuff with the object } // the object will be disposed of
В общем, нет необходимости обнулять объекты после использования, но в некоторых случаях я считаю, что это хорошая практика.
Если объект реализует IDisposable и хранится в поле, я думаю, что это хорошо, чтобы обнулить его, просто чтобы избежать использования утилизированного объекта. Ошибки следующего рода могут быть болезненными:
this.myField.Dispose(); // ... at some later time this.myField.DoSomething();
хорошо обнулить поле после его удаления и получить NullPtrEx прямо в строке, где поле используется снова. В противном случае, вы можете столкнуться с некоторыми загадками ошибка вниз по линии (в зависимости от того, что именно делает DoSomething).
скорее всего, ваш код не структурирован достаточно плотно, если вы чувствуете необходимость
null
переменные.существует несколько способов ограничить область действия переменной:
как отметил Стив Транби
using(SomeObject object = new SomeObject()) { // do stuff with the object } // the object will be disposed of
аналогично, вы можете просто использовать фигурные скобки:
{ // Declare the variable and use it SomeObject object = new SomeObject() } // The variable is no longer available
Я считаю, что с помощью фигурных скобок без каких-либо" заголовок", чтобы действительно очистить код и помочь сделать его больше понятный.
единственный раз, когда вы должны установить переменную в null, это когда переменная не выходит из области видимости, и вам больше не нужны данные, связанные с ней. Иначе в этом нет необходимости.
В общем случае не нужно устанавливать значение null. Но предположим, что у вас есть функция сброса в вашем классе.
тогда вы можете сделать, потому что вы не хотите вызывать dispose дважды, так как некоторые из Dispose могут быть реализованы неправильно и бросить систему.Исключение ObjectDisposed.
private void Reset() { if(_dataset != null) { _dataset.Dispose(); _dataset = null; } //..More such member variables like oracle connection etc. _oraConnection }
этот вид "нет необходимости устанавливать объекты в null после использования" не совсем точен. Иногда вам нужно обнулить переменную после ее удаления.
Да, вы всегда должны звонить
.Dispose()
или.Close()
на все, что имеет его, когда вы закончите. Будь то дескрипторы файлов, соединения с базами данных или одноразовые объекты.отдельно от этого очень практически картина LazyLoad.
скажем, у меня есть и экземпляр
ObjA
наclass A
.Class A
имеет публичное свойство под названиемPropB
наclass B
.внутри
PropB
использует закрытую переменную_B
и по умолчанию null. Когда он проверяет, чтобы увидеть, если_PropB
null и если это так, открывает ресурсы, необходимые для созданияB
на_PropB
. Затем он возвращает_PropB
.по моему опыту, это очень полезный трюк.
где возникает необходимость в нуле, Если вы сбросите или измените A каким-то образом, что содержание
_PropB
были дочерними от предыдущих значенийA
, вам нужно будет избавиться и обнулить_PropB
так LazyLoad может сбросить, чтобы получить правильное значение, если код требует его.если вы только делаете
_PropB.Dispose()
и вскоре после того, как ожидайте, что нулевая проверка LazyLoad будет успешной, она не будет нулевой, и вы будете смотреть на устаревшие данные. По сути, вы должны обнулить его послеDispose()
просто чтобы быть уверенным.я уверен, что это было бы иначе, но у меня есть правильный код теперь демонстрируя такое поведение после
Dispose()
на_PropB
и вне вызывающей функции, которая сделала Dispose (и, таким образом, почти вне области действия), частная опора все еще не равна нулю, и устаревшие данные все еще там.в конце концов, удаленное свойство будет обнулено, но это было недетерминированным с моей точки зрения.
основная причина, как намекает dbkk, заключается в том, что родительский контейнер (
ObjA
СPropB
) сохраняет экземпляр_PropB
в рамках, несмотря наDispose()
.
есть некоторые случаи, когда имеет смысл обнулить ссылки. Например, когда вы пишете коллекцию-например, очередь приоритетов-и по вашему контракту вы не должны поддерживать эти объекты для клиента после того, как клиент удалил их из очереди.
но такие вещи имеют значение только в долгоживущих коллекциях. Если очередь не переживет конец функции, в которой она была создана, то это имеет гораздо меньшее значение.
в целом, тебе действительно не стоит беспокоиться. Пусть компилятор и GC делают свою работу, чтобы вы могли делать свою.
взгляните и на эту статью:http://www.codeproject.com/KB/cs/idisposable.aspx
по большей части, установка объекта в null не имеет никакого эффекта. Единственный раз, когда вы должны быть уверены, чтобы сделать это, если вы работаете с "большим объектом", который является одним больше, чем 84K в размере (например, растровые изображения).
Я считаю, что по дизайну разработчиков GC вы не можете скорость GC с обнулением. Я уверен, что они предпочли бы, чтобы вы не беспокоились о том, как/когда GC работает-относитесь к этому так вездесуще будучи защита и наблюдение за вами...(склоняет голову, поднимает кулак к небу)...
лично я часто явно устанавливаю переменные в null, когда я заканчиваю с ними как с формой самостоятельной документации. Я не объявляю, не использую, а затем устанавливаю значение null позже -- Я обнуляю сразу после того, как они больше не нужны. Я прямо говорю: "я официально закончил you...be ушел..."
- Это сводит на нет необходимости в GC бы язык? Нет. Это полезно для GC? Может быть, да, может быть, нет, не знаю наверняка, по дизайну я действительно не могу его контролировать, и независимо от сегодняшнего ответа с этой версией или той, будущие реализации GC могут изменить ответ вне моего контроля. Плюс, если / когда обнуление оптимизировано, это немного больше, чем фантазия комментарий если вы будете.
Я думаю, если это делает мои намерения яснее для следующего бедного дурака, который следует по моим стопам, и если это "может" потенциально помогает GC иногда,тогда это стоит того. В основном это заставляет меня чувствовать себя опрятным и ясным, а Монго любит чувствовать себя опрятным и ясным. :)
Я смотрю на это так: языки программирования существуют, чтобы позволить людям дать другим людям представление о намерениях и компилятор запрос задания о том, что делать -- компилятор преобразует этот запрос в другой язык (иногда несколько) для процессора-процессор(Ы) может дать гудок, какой язык вы использовали, настройки вкладки, комментарии, стилистические акценты, имена переменных и т. д. -- процессор-это все о битовом потоке, который говорит ему, какие регистры и опкоды и ячейки памяти нужно крутить. Многие вещи, написанные в коде, не преобразуются в то, что потребляется процессором в указанной нами последовательности. Наш C, C++, C#, Lisp, Babel, ассемблер или что-то еще скорее теория чем реальность, написанная как изложение работы. То, что вы видите, это не то, что вы получаете, да, даже на языке ассемблера.
Я понимаю, что мышление " ненужных вещей "(например, пустые строки) " не что иное, как шум и беспорядок кода."Это был я раньше в моей карьере; я полностью понимаю это. В этот момент я склоняюсь к тому, что делает код более ясным. Это не похоже на то, что я добавляю даже 50 строк "шума" в свои программы-это несколько строк здесь или там.
есть исключения из любого правила. В сценариях с изменчивой памятью, статической памятью, условиями гонки, синглетами, использованием "устаревших" данных и всем этим видом гнили, это другое: вам нужно управлять своей собственной памятью, блокируя и обнуляя ее, потому что память не является частью Вселенной GC'D-надеюсь, все это понимают. В остальное время с языками GC'D это вопрос стиля, а не необходимости или гарантированного повышения производительности.
В конце дня сделать конечно, вы понимаете, что подходит для GC, а что нет; заблокировать, утилизировать и аннулировать соответствующим образом; воск, воск; вдох, выдох; и для всего остального я говорю: если это хорошо, сделайте это. Ваш пробег может варьироваться...как надо...