Установка объектов в ноль / ничего после использования в .NET

Если вы установите все объекты на null (Nothing в VB. NET), как только вы закончили с ними?

Я понимаю, что в. NET, необходимо избавиться от любых экземпляров объектов, которые реализуют интерфейс IDisposable, чтобы освободить некоторые ресурсы, хотя объект все еще может быть чем-то после его удаления (следовательно, свойство isDisposed в формах), поэтому я предполагаю, что он все еще может находиться в памяти или хотя бы частично?

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

Итак, учитывая это, установит ли он значение null, чтобы ускорить высвобождение памяти системой, поскольку ей не нужно выяснять, что она больше не находится в области действия, и являются ли они плохими побочными эффектами?

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

вопрос задан 5.08.2008
John
18258 репутация

13 ответов


  • 67 рейтинг

    Карл абсолютно прав, нет необходимости устанавливать объекты в null после использования. Если объект реализует IDisposable, просто убедитесь, что вы вызвали IDisposable.Dispose(), когда закончите с этим объектом (обернутым в try. , finally или блок using()). Но даже если вы не помните, чтобы вызывать Dispose(), метод finalizer объекта должен вызывать для вас Dispose().

    Я думал, что это было хорошее лечение:

    Копание в IDisposable

    и этот

    Понимание IDisposable

    Нет никакого смысла пытаться угадать GC и его стратегии управления, потому что он самонастраивается и непрозрачен. Здесь была хорошая дискуссия о внутренней работе с Джеффри Рихтером на Dot Net Rocks здесь: Джеффри Рихтер на Windows Memory Model и Книга Рихтерса CLR через C # , глава 20 имеет отличную трактовку:

    ответ дан Kev, с репутацией 95664, 5.08.2008
  • 15 рейтинг

    Нет не пустые объекты. Вы можете проверить http: // codebetter. ком / блоги / karlseguin / Архив / 2008/04/27 / фундаменты-оф-программирования-пт-7-назад к основам-памяти. aspx для получения дополнительной информации, но установка нулевого значения ничего не изменит, кроме как испачкать ваш код.

    ответ дан Karl Seguin, с репутацией 16949, 5.08.2008
  • 7 рейтинг

    Также:

    using(SomeObject object = new SomeObject()) 
    {
      // do stuff with the object
    }
    // the object will be disposed of
    
    ответ дан Steve Tranby, с репутацией 5460, 5.08.2008
  • 5 рейтинг

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

    ответ дан Bob, с репутацией 66275, 5.08.2008
  • 1 рейтинг

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

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

    В целом, вы действительно не должны беспокоиться. Пусть компилятор и GC выполнят свою работу, чтобы вы могли выполнять свою.

    ответ дан Patrick, с репутацией 55430, 5.08.2008
  • 0 рейтинг

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

    эл. г.

    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 обычно оптимизирует удаление нуля , поэтому оба бита кода в конечном итоге будут одинаковыми.

    ответ дан Wilka, с репутацией 19943, 15.08.2008
  • 0 рейтинг

    Я полагаю, что по замыслу разработчиков GC вы не можете ускорить GC с аннулированием. Я уверен, что они предпочли бы, чтобы вы не беспокоились о том, как / когда GC работает - относитесь к этому как к вездесущей , защищающей и следящей за вами. , , (склоняет голову, поднимает кулак к небу). , ,

    Лично я часто явно устанавливаю переменные в нуль, когда я заканчиваю с ними как форма самодокументирования. Я не объявляю, использую, затем устанавливаю на нуль позже - я обнуляю сразу после того, как они больше не нужны. Я говорю прямо: «Я официально закончил с тобой. , , уйти , , "

    Нужно ли обнулять в языке GC'd? Нет. Это полезно для GC? Может быть, да, может быть, нет, не знаю наверняка, по своему замыслу я действительно не могу это контролировать, и независимо от сегодняшнего ответа с этой версией или той, будущие реализации GC могут изменить ответ вне моего контроля. Плюс, если / когда обнуление оптимизировано, это немного больше, чем модный комментарий 2823006243 , если хотите.

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

    Я смотрю на это так: языки программирования существуют, чтобы позволить людям дать другим людям представление о намерениях, а компилятор запросить работу, что делать - компилятор преобразует этот запрос в другой язык (иногда несколько) для CPU - - ЦП (ы) могут подсказать, какой язык вы используете, настройки вкладок, комментарии, стилистические акценты, имена переменных и т. д. - Процессор - это все о битовом потоке, который сообщает ему, какие регистры и коды операций, а также места в памяти нужно менять. Многие вещи, написанные в коде, не преобразуются в то, что потребляется процессором в указанной нами последовательности. Наш C, C ++, C #, Lisp, Babel, ассемблер или что-то еще является теорией, а не реальностью, написанной как формулировка работы. То, что вы видите, не то, что вы получаете, да, даже на языке ассемблера.

    Я понимаю, что «ненужные вещи» (например, пустые строки) «не что иное, как шум и загромождение кода. "Это был я в начале своей карьеры; я полностью это понял. На этом этапе я склоняюсь к тому, что делает код более понятным. Это не то, что я добавляю даже 50 строк "шума" в мои программы - это несколько строк здесь или там.

    Есть исключения из любого правила. В сценариях с энергозависимой памятью, статической памятью, состояниями гонки, одиночными событиями, использованием «устаревших» данных и всем этим видом гнили все по-другому: вам нужно управлять собственной памятью, блокируя и обнуляя как, кстати, потому что память не является частью Вселенная GC'd - надеюсь, все это понимают. В остальное время с языками GC это вопрос стиля, а не необходимости или гарантированного повышения производительности.

    В конце дня убедитесь, что вы понимаете, что подходит для GC, а что нет; блокировать, распоряжаться и обнулять соответственно; воск, воск от; вдох-выдох; и для всего остального я говорю: если это хорошо, сделай это. Ваш пробег может отличаться. , , как это должно. , ,

    ответ дан John, с репутацией 137, 10.05.2016
  • 0 рейтинг

    В общем случае нет необходимости устанавливать значение NULL. Но предположим, что у вас есть функция сброса в вашем классе.

    Тогда вы можете это сделать, потому что вы не хотите вызывать dispose дважды, поскольку некоторые из Dispose могут быть реализованы неправильно и вызывать System. ObjectDisposedException.

    private void Reset()
    {
        if(_dataset != null)
        {
           _dataset.Dispose();
           _dataset = null;
        }
        //..More such member variables like oracle connection etc. _oraConnection
     }
    
    ответ дан Munish Goyal, с репутацией 734, 17.04.2012
  • 0 рейтинг

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

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

    this.myField.Dispose();
    // ... at some later time
    this.myField.DoSomething();
    

    Хорошо обнулить поле после его удаления и получить NullPtrEx прямо в строке, где поле используется снова. В противном случае вы можете столкнуться с какой-то загадочной ошибкой (в зависимости от того, что именно делает DoSomething).

    ответ дан dbkk, с репутацией 7518, 9.08.2008
  • 0 рейтинг

    Скорее всего, ваш код недостаточно структурирован, если вам нужно 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
    

    Я считаю, что использование фигурных скобок без каких-либо «заголовков» действительно очищает код и помогает сделать его более понятным.

    ответ дан mbillard, с репутацией 28817, 9.08.2008
  • 0 рейтинг

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

    Да, вы должны ВСЕГДА звонить по телефону .Dispose() или .Close() на все, что есть, когда вы закончите. Будь то файловые дескрипторы, соединения с базой данных или одноразовые объекты.

    Отдельно от этого стоит очень практичный шаблон LazyLoad.

    Скажи, что у меня есть и создан ObjA из class A. Class A имеет публичную собственность под названием PropB class B.

    Внутренне, PropB использует закрытую переменную _B и по умолчанию имеет значение null. Когда используется PropB.Get(), он проверяет, является ли _PropB нулевым, и, если это так, открывает ресурсы, необходимые для создания экземпляра B в _PropB. Затем он возвращает _PropB.

    По моему опыту, это действительно полезный трюк.

    Когда возникает необходимость обнуления, если вы сбрасываете или изменяете A таким образом, чтобы содержимое _PropB было дочерним по отношению к предыдущим значениям A, вам потребуется Dispose AND null out _PropB, чтобы LazyLoad мог выполнить сброс, чтобы получить права значение, если код требует этого.

    Если вы выполняете только _PropB.Dispose() и вскоре после этого ожидаете, что проверка LazyLoad не будет выполнена успешно, она не будет нулевой, и вы будете просматривать устаревшие данные. По сути, вы должны обнулить его после Dispose() просто чтобы быть уверенным.

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

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

    Основная причина, на которую ссылается dbkk, заключается в том, что родительский контейнер (ObjA с PropB) сохраняет экземпляр области _PropB, несмотря на Dispose().

    ответ дан KenF, с репутацией 107, 11.04.2012
  • 0 рейтинг

    Взгляните также на эту статью: http: // www. CodeProject. ком / KB / CS / IDisposable. aspx

    По большей части установка нулевого объекта не имеет никакого эффекта. Единственный раз, когда вы должны быть уверены в этом, это если вы работаете с «большим объектом», размер которого превышает 84 КБ (например, растровые изображения).

    ответ дан Scott Dorman, с репутацией 34290, 17.08.2008
  • -1 рейтинг

    Некоторые объекты предполагают метод .dispose(), который вынуждает ресурс быть удаленным из памяти.

    ответ дан GateKiller, с репутацией 33634, 5.08.2008