Подтвердить что ты не робот

Любой смысл устанавливать obj = null (Nothing) в Dispose()?

Есть ли смысл устанавливать пользовательский объект в null (Nothing в VB.NET) в методе Dispose()? Может ли это предотвратить утечку памяти или бесполезно?!

Рассмотрим два примера:

public class Foo : IDisposable
{
    private Bar bar; // standard custom .NET object

    public Foo(Bar bar) {
        this.bar = bar;
    }
    public void Dispose() {
        bar = null; // any sense?
    }
}

public class Foo : RichTextBox
{
    // this could be also: GDI+, TCP socket, SQl Connection, other "heavy" object
    private Bitmap backImage; 

    public Foo(Bitmap backImage) {
        this.backImage = backImage;
    }

    protected override void Dispose(bool disposing) {
        if (disposing) {
            backImage = null;  // any sense?
        }
    }
}
4b9b3361

Ответ 1

Цель Dispose() - очистить ресурсы, которые не обрабатываются сборщиком мусора. Объекты обслуживаются GC, поэтому на самом деле нет необходимости устанавливать ссылку на null при нормальных обстоятельствах.

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

Ответ 2

Лично я склонен; по двум причинам:

  • это означает, что если кто-то забыл выпустить Foo (возможно, из какого-либо события), все последующие объекты (a Bitmap в этом случае) могут быть собраны (в какой-то момент в будущем - всякий раз, когда GC чувствует нравится); вполне вероятно, что это всего лишь мелкая обертка вокруг неуправляемого ресурса, но каждый помогает.
    • Мне действительно не нравится случайное хранение всего графика объектов, зависающего только потому, что пользователь забыл отцепить одно событие; IDisposable - удобный переключатель "почти убить" - почему бы не отсоединить все доступное?
  • Что еще более важно, я могу нахально использовать это поле для проверки (в методах и т.д.) для удаления, выбрасывая ObjectDisposedException, если это null

Ответ 3

Это просто бесполезно. Я полагаю, что установка в NULL обратно в старые дни COM/VB уменьшит ваш счетчик ссылок.

Это неверно с .NET. Когда вы устанавливаете бар равным нулю, вы не уничтожаете и не отпускаете что-либо. Вы просто меняете ссылку, на которую указывает балл, от вашего объекта до "null". Ваш объект все еще существует (хотя теперь, поскольку ничто не ссылается на него, в конечном итоге он будет собран мусором). За некоторыми исключениями, и в большинстве случаев это то же самое, что и произошло бы, если бы вы просто не сделали Foo IDisposable в первую очередь.

Основная цель IDisposable - разрешить вам освобождать неуправляемые ресурсы, такие как TCP-сокеты или SQL-соединения, или что-то еще. Обычно это делается путем вызова любой функции очистки, которую предоставляет неуправляемый ресурс, а не путем установки ссылки на "null".

Ответ 4

Это может иметь смысл, если вы хотите каким-то образом предотвратить повторное использование удаленного экземпляра.

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

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

Это может не иметь смысла для вас, если все объекты IDisposable имеют свойство IsDisposed и/или throw ObjectDisposedException, если они используются после их удаления - некоторые могут нарушать этот принцип и устанавливать их в null может предотвратить появление нежелательных эффектов.

Ответ 5

В настройке С# объект с нулевым значением просто освобождает ссылку на объект.

Итак, теоретически лучше высвободить ссылку на управляемые объекты в Dispose-Method в С#, но только для возможности GC для сбора объекта, на который ссылается, до того, как собранный объект будет собран. Поскольку и то, и другое, скорее всего, будет собрано в одном и том же забеге, GC будет наиболее вероятно распознавать, что ссылочный объект ссылается только на расположенный тип, поэтому оба могут быть собраны.

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

Ответ 6

В VB.NET там есть смысл, чтобы установить Nothing объявленные объекты Private WithEvents.

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

Ответ 7

Цель dispose() - очистка неуправляемых ресурсов. TCP-соединения, соединения с базой данных и другие объекты базы данных и множество таких неуправляемых ресурсов должны быть освобождены разработчиком в методе удаления. Так что это действительно имеет смысл.

Ответ 8

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

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

private void Reset()
{
    if(_dataset != null)
    {
       _dataset.Dispose();
       _dataset = null;
    }
    //..More such member variables like oracle connection etc. _oraConnection
 }