Должны ли вы установить все объекты null
( Nothing
в VB.NET), как только закончите с ними?
Я понимаю, что в .NET важно избавляться от любых экземпляров объектов, которые реализуют IDisposable
интерфейс, чтобы высвободить некоторые ресурсы, хотя объект все еще может быть чем-то после его удаления (отсюда и isDisposed
свойство в формах), поэтому я предполагаю, что он все еще может находиться в памяти или хотя бы частично?
Я также знаю, что когда объект выходит из области видимости, он помечается для сбора, готового к следующему проходу сборщика мусора (хотя это может занять некоторое время).
Таким образом, имея это в виду, будет ли установка для null
ускорения высвобождения памяти системой, поскольку не нужно выяснять, что она больше не находится в области действия и являются ли они плохими побочными эффектами?
Статьи MSDN никогда не делают этого в примерах, и в настоящее время я делаю это, потому что не вижу вреда. Однако я натолкнулся на смесь мнений, поэтому любые комментарии полезны.
Ответы:
Карл абсолютно прав, нет необходимости устанавливать объекты в null после использования. Если объект реализуется
IDisposable
, просто убедитесь, что вы вызываете,IDisposable.Dispose()
когда закончите с этим объектом (обернутым вtry
..finally
или, вusing()
блок). Но даже если вы не помните, чтобы вызыватьDispose()
, метод finaliser для объекта должен вызыватьDispose()
вас.Я думал, что это было хорошее лечение:
и это
Нет никакого смысла пытаться угадать GC и его стратегии управления, потому что он самонастраивается и непрозрачен. Здесь была хорошая дискуссия о внутренней работе с Джеффри Рихтером в Dot Net Rocks: Джеффри Рихтер о модели памяти Windows и книга Рихтерса CLR через C # глава 20 отлично справились:
источник
Еще одна причина, по которой вы не можете устанавливать объекты в null, когда вы закончите с ними, заключается в том, что они могут фактически поддерживать их живыми дольше.
например
позволит объекту, на который ссылается someType, быть GC'd после вызова DoSomething, но
иногда может поддерживать объект в живых до конца метода. JIT обычно оптимизируется прочь присваивание нуля , так как биты конца кода вверх является одинаковым.
источник
GC.KeepAlive(someType);
См. Ericlippert.com/2013/06/10/construction-destructionНет, не обнуляйте объекты. Вы можете проверить http://codebetter.com/blogs/karlseguin/archive/2008/04/27/foundations-of-programming-pt-7-back-to-basics-memory.aspx для получения дополнительной информации, но настройки вещей к нулю не будет ничего делать, кроме грязного вашего кода.
источник
Также:
источник
В общем, нет необходимости обнулять объекты после использования, но в некоторых случаях я считаю, что это хорошая практика.
Если объект реализует IDisposable и хранится в поле, я думаю, это хорошо, чтобы обнулить его, просто чтобы избежать использования удаленного объекта. Ошибки следующего вида могут быть болезненными:
Хорошо обнулить поле после его удаления и получить NullPtrEx прямо в строке, где поле используется снова. В противном случае вы можете столкнуться с какой-то загадочной ошибкой (в зависимости от того, что именно делает DoSomething).
источник
.Dispose()
. Если вы найдете его, вы не используете IDisposable правильно. Единственное использование для одноразового предмета должно быть в пределах блока использования. А после использования блока у вас даже нет доступа к немуmyField
. А в блоке using установка значенияnull
не обязательна, блок using выберет объект для вас.Скорее всего, ваш код недостаточно структурирован, если вам нужны
null
переменные.Есть несколько способов ограничить область действия переменной:
Как упомянуто Стивом Транби
Точно так же вы можете просто использовать фигурные скобки:
Я считаю, что использование фигурных скобок без каких-либо «заголовков» действительно очищает код и помогает сделать его более понятным.
источник
Единственный раз, когда вы должны установить переменную в null, это когда переменная не выходит из области видимости, и вам больше не нужны связанные с ней данные. Иначе в этом нет необходимости.
источник
В общем случае нет необходимости устанавливать значение NULL. Но предположим, что у вас есть функция сброса в вашем классе.
Тогда вы можете это сделать, потому что вы не хотите вызывать dispose дважды, поскольку некоторые из Dispose могут быть реализованы неправильно и вызывать исключение System.ObjectDisposed.
источник
этот вид «нет необходимости устанавливать объекты равными нулю после использования» не совсем точен. Есть моменты, когда вам нужно обнулять переменную после ее удаления.
Да, вы должны ВСЕГДА звонить
.Dispose()
или.Close()
на все, что есть, когда вы закончите. Будь то файловые дескрипторы, соединения с базой данных или одноразовые объекты.Отдельно от этого очень практичный шаблон LazyLoad.
Скажем , у меня есть и экземпляры
ObjA
изclass A
.Class A
имеет общественное свойствоPropB
изclass B
.Внутренне
PropB
использует закрытую переменную_B
и по умолчанию имеет значение null. КогдаPropB.Get()
используется, он проверяет,_PropB
является ли значение null, и если это так, открывает ресурсы, необходимые для создания экземпляраB
в_PropB
. Затем он возвращается_PropB
.По моему опыту, это действительно полезный трюк.
Когда возникает необходимость в нулевом
_PropB
значенииA
, если вы сбрасываете или изменяете A таким образом, чтобы содержимое было дочерним по отношению к предыдущим значениям , вам нужно будет удалить и удалить нулевое значение,_PropB
чтобы LazyLoad мог сбросить для получения правильного значения, ЕСЛИ код требует этого.Если вы только
_PropB.Dispose()
и вскоре после этого ожидаете, что проверка LazyLoad на ноль будет успешной, она не будет нулевой, и вы будете просматривать устаревшие данные. По сути, вы должны обнулить его послеDispose()
чтобы быть уверенным.Я уверен , что бы это было иначе, но у меня есть код прямо сейчас , проявляющий это поведение после того, как
Dispose()
на_PropB
и за пределами вызывающей функции , что сделал в Dispose (и , таким образом , почти из области видимости), частный проп еще не равно нулю, и устаревшие данные все еще там.В конце концов, свойство disposed будет недействительным, но это было недетерминировано с моей точки зрения.
Основная причина, на которую ссылается dbkk, заключается в том, что родительский контейнер (
ObjA
сPropB
) сохраняет экземпляр_PropB
в области видимости, несмотря наDispose()
.источник
В некоторых случаях имеет смысл обнулить ссылки. Например, когда вы пишете коллекцию - например, очередь с приоритетами - и по вашему контракту вы не должны оставлять эти объекты живыми для клиента после того, как клиент удалил их из очереди.
Но такого рода вещи имеют значение только в долгоживущих коллекциях. Если очередь не переживет конец функции, в которой она была создана, то это будет иметь гораздо меньшее значение.
В общем, вы действительно не должны беспокоиться. Пусть компилятор и GC выполнят свою работу, чтобы вы могли выполнять свою.
источник
Взгляните также на эту статью: http://www.codeproject.com/KB/cs/idisposable.aspx
По большей части установка нулевого объекта не имеет никакого эффекта. Единственный раз, когда вы должны быть уверены в этом, это если вы работаете с «большим объектом», размер которого превышает 84 КБ (например, растровые изображения).
источник
Стивен Клири очень хорошо объясняет в этом посте: Должен ли я установить переменные в Null, чтобы помочь в сборке мусора?
Говорит:
Важной вещью, которую мы должны рассмотреть, являются Статические поля .
Вывод:
источник
Я верю, что разработчики GC не смогут ускорить GC с помощью аннулирования. Я уверен, что они предпочли бы, чтобы вы не беспокоились о том, как / когда GC работает - относитесь к этому как к этому вездесущему существу. защищает и наблюдает за вами ... (склоняет голову, поднимает кулак в небо) .. ,
Лично я часто явно устанавливаю переменные в null, когда я заканчиваю с ними как форму самодокументирования. Я не объявляю, использую, затем устанавливаю на ноль позже - я обнуляю сразу после того, как они больше не нужны. Я говорю прямо: «Я официально закончил с тобой ... уйди ...»
Нужно ли обнулять в языке GC'd? Нет. Это полезно для GC? Может быть, да, может, нет, не знаю наверняка, по своей структуре я действительно не могу это контролировать, и независимо от сегодняшнего ответа с этой версией или той, будущие реализации GC могут изменить ответ вне моего контроля. Плюс, если / когда обнуление оптимизировано, это немного больше, чем модный комментарий если хотите.
Я полагаю, если это прояснит мои намерения следующему бедному дураку, который пойдет по моим стопам, и если это «может» потенциально помочь ГК иногда, то оно того стоит для меня. В основном это заставляет меня чувствовать себя опрятным и ясным, а Монго любит чувствовать себя опрятным и чистым. :)
Я смотрю на это так: языки программирования существуют, чтобы позволить людям дать другим людям представление о намерениях, а компилятор запросить работу, что делать - компилятор преобразует этот запрос в другой язык (иногда несколько) для CPU - Процессор (ы) может дать подсказку, какой язык вы использовали, настройки вашей вкладки, комментарии, стилистические акценты, имена переменных и т. д. - Процессор - это все о битовом потоке, который сообщает ему, какие регистры и коды операций и места в памяти можно менять. Многие вещи, написанные в коде, не преобразуются в то, что потребляется процессором в указанной нами последовательности. Наш C, C ++, C #, Lisp, Babel, ассемблер или что-то еще является теорией, а не реальностью, написанной как констатация работы. То, что вы видите, не то, что вы получаете, да, даже на языке ассемблера.
Я понимаю, что «ненужные вещи» (например, пустые строки) «не что иное, как шум и загромождение кода». Это был я ранее в моей карьере; Я полностью понимаю это. На этом этапе я склоняюсь к тому, что делает код более понятным. Это не то, что я добавляю даже 50 строк "шума" в мои программы - это несколько строк здесь или там.
Есть исключения из любого правила. В сценариях с энергозависимой памятью, статической памятью, состояниями гонки, одиночными событиями, использованием «устаревших» данных и всем этим видом гнили все по-другому: вам нужно управлять собственной памятью, блокируя и обнуляя как, кстати, потому что память не является частью Вселенная GC'd - надеюсь, все это понимают. В остальное время с языками GC это вопрос стиля, а не необходимости или гарантированного повышения производительности.
В конце дня убедитесь, что вы понимаете, что подходит для GC, а что нет; блокировать, распоряжаться и обнулять соответственно; воск, воск от; вдох-выдох; и для всего остального я говорю: если это хорошо, сделай это. Ваш пробег может меняться ... как следует ...
источник
Я думаю, что установить что-то обратно на ноль это грязно. Представьте себе сценарий, в котором выставляемый элемент выставляется, скажем, через свойство. Теперь, когда какой-то фрагмент кода случайно использует это свойство после удаления элемента, вы получите исключение нулевой ссылки, которое требует некоторого исследования, чтобы точно выяснить, что происходит.
Я полагаю, что одноразовые рамки позволят создать исключение ObjectDisposedException, которое является более значимым По этой причине лучше не устанавливать их обратно в ноль.
источник
Некоторые объекты предполагают
.dispose()
метод, который вынуждает ресурс быть удаленным из памяти.источник