Как утилизировать класс в .net?

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

MyClass.Dispose()

и освободить все используемое пространство переменными и объектами MyClass?

20 ответов

  1. В ответ на первоначальный вопрос, с информацией, предоставленной до сих пор оригинальным плакатом, он на 100% уверен, что он не знает достаточно о программировании в .NET, чтобы даже получить ответ: используйте GC.Собирать.)( Я бы сказал, что 99,99% вероятности, что ему действительно не нужно использовать GC.Collect() at all, as most posters have pointed out.

    Правильный ответ сводится к » Пусть GC делает свою работу. Период. Тебе есть о чем беспокоиться. Но вы, возможно, захотите рассмотреть, следует ли и когда утилизировать или очищать определенные объекты, и нужно ли реализовать IDisposable и, возможно, завершить в своем классе.’

    Относительно должности Кита и его правила № 4:

    Некоторые плакаты вводят в заблуждение Правило 3 и Правило 4. Правило 4 кита абсолютно правильно, однозначно. Это одно из четырех правил, которое вообще не нуждается в редактировании. Я бы немного перефразировал некоторые из его других правил, чтобы сделать их более ясными, но они по существу правильны, если вы правильно их разбираете и на самом деле читаете весь пост, чтобы увидеть, как он их расширяет.

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

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

      a) немедленно удалить/освободить их в локальном контексте, в котором они были созданы, или…

      b) реализовать IDisposable в шаблоне, рекомендованном в посте кита, или в нескольких тысячах мест в интернете, или буквально в 300 книгах к настоящему времени.

      b.1) Кроме того, если (b), и это неуправляемый ресурс, который был открыт, и IDisposable и Finalize всегда должны быть реализованы, согласно правилу кита № 4.
      В этом контексте Finalize absolutely является сетью безопасности в одном смысле: если кто-то создает экземпляр вашего IDisposable объекта, который использует неуправляемый ресурс, и не вызывает dispose, то Finalize-это последний шанс для вашего объекта закрыть неуправляемый ресурс должным образом.
      (Finalize должен сделать это, вызвав Dispose таким образом, чтобы метод Dispose пропускал освобождение чего-либо, кроме неуправляемого ресурса. В качестве альтернативы, если метод Dispose объекта вызывается должным образом любым экземпляром объекта, то он одновременно передает вызов Dispose всем объектам IDisposable, которые он создал, и освобождает неуправляемые ресурсы должным образом, завершая вызовом для подавления Finalize на объекте, что означает, что влияние использования Finalize уменьшается, если объект расположен должным образом вызывающим. Все эти пункты включены в сообщение кита, кстати.)

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

    Короче говоря, относительно поста кита, он совершенно прав, и этот пост является наиболее правильным и полным ответом, на мой взгляд. Он может использовать некоторые короткие заявления, которые некоторые считают «неправильными» или возражают, но его полный пост расширяется на использование Finalize полностью, и он абсолютно прав. Обязательно прочитайте его пост полностью, прежде чем переходить на одно из правил или предварительных заявлений в его посте.

  2. Если MyClass реализует IDisposable, вы можете это сделать.

    MyClass.Dispose();
    

    Лучшая практика в C# :

    using( MyClass x = new MyClass() ) {
        //do stuff
    }
    

    Как это заворачивает dispose в try-finally и гарантирует, что он никогда не пропустит.

  3. Вы не можете заставить GC очистить объект, когда вы хотите, хотя есть способы заставить его работать, ничто не говорит, что он очищает весь объект, который вы хотите/ожидаете. Лучше всего вызывать dispose в try catch ex, наконец, dispose end try (VB.NET rulz) way. But Dispose is for cleaning up system resources (memory, handles, db connections, etc. выделяется объектом детерминированным способом. Dispose не очищает (и не может) память, используемую самим объектом, только GC может это сделать.

  4. public class MyClass : IDisposable
    {
        public void Dispose()
        {
           // cleanup here
        }
    }
    

    тогда вы можете сделать что-то вроде этого

    MyClass todispose = new MyClass();
    todispose.Dispose(); // instance is disposed right here
    

    или

    using (MyClass instance = new MyClass())
    {
    
    }
    // instance will be disposed right here as it goes out of scope
    
  5. @ Curt Hagenlocher-это задом наперед. Я понятия не имею, почему так много проголосовали за это, когда это неправильно.

    IDisposable is для управляемых ресурсов.

    Финализаторы предназначены для неуправляемых ресурсов.

    Пока вы используете только управляемые ресурсы, @Jon Limjap и я полностью правы.

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

    Избегайте использования GC.Collect-это медленный способ работы с управляемыми ресурсами, и ничего не делает с неуправляемыми, если вы правильно построили свои ~финализаторы.


    Я удалил комментарий модератора из исходного вопроса в соответствии с https://stackoverflow.com/questions/14593/etiquette-for-modifying-posts

  6. @Кит,

    Я согласен со всеми вашими правилами, кроме № 4. Добавление финализатора должно быть сделано только при очень специфических обстоятельствах. Если класс использует неуправляемые ресурсы, они должны быть очищены в функции Dispose(bool). Эта же функция должна очищать управляемые ресурсы только при значении bool true. Добавление финализатора увеличивает стоимость сложности использования объекта, так как каждый раз при создании нового экземпляра он также должен помещаться в очередь завершения, которая проверяется каждый раз, когда GC выполняет цикл сбора. Фактически это означает, что ваш объект выдерживает один цикл / поколение дольше, чем это должно быть, чтобы можно было запустить финализатор. Финализатор не следует рассматривать как»страховочную сетку».

    GC будет выполнять цикл сбора только тогда, когда он определяет, что в куче Gen0 недостаточно доступной памяти для выполнения следующего выделения, если только вы не «поможете» ему, вызвав GC.Collect () для принудительного использования внеполосной коллекции.

    Суть в том, что, несмотря ни на что, GC знает только, как освободить ресурсы, вызвав метод Dispose (и, возможно, финализатор, если он реализован). Именно до этого метода, чтобы «сделать правильную вещь» и очистить любые неуправляемые ресурсы, используемые и проинструктировать любые другие управляемые ресурсы, чтобы вызвать их Dispose метод. Он очень эффективен в том, что он делает, и может самостоятельно оптимизировать в значительной степени, пока ему не помогают внеполосные циклы сбора. Это, как говорится, за исключением вызова GC.Collect явно у вас нет контроля над тем, когда и в каком порядке будут удалены объекты и освобождена память.

  7. IDisposable не имеет ничего общего с освобождением памяти. IDisposable-это шаблон для освобождения неуправляемых ресурсов , а память, безусловно, является управляемым ресурсом.

    Ссылки, указывающие на GC.Collect () являются правильным ответом, хотя использование этой функции, как правило, не рекомендуется в документации Microsoft .NET.

    Edit: заработав значительную сумму кармы за этот ответ, я чувствую определенную ответственность за его разработку, чтобы новичок в управлении ресурсами .NET не получил неверное впечатление.

    В процессе .NET существует два вида ресурсов-управляемый и неуправляемый. «Управляемый «означает, что среда выполнения контролирует ресурс, а» неуправляемый » означает, что это ответственность программиста. И действительно есть только один вид управляемого ресурса, о котором мы заботимся в .NET сегодня-память. Программист говорит среде выполнения выделить память, и после этого это до среды выполнения, чтобы выяснить, когда память может освободить. Механизм, используемый .NET для этой цели называется сборкой мусора и вы можете найти много информации о GC в интернете просто с помощью Google.

    Для других видов ресурсов .NET ничего не знает об их очистке, поэтому он должен полагаться на программиста, чтобы сделать правильную вещь. Для этого платформа предоставляет программисту три инструмента:

    1. Интерфейс IDisposable и оператор» using » в VB и C#
    2. Метод завершения
    3. Шаблон IDisposable, реализованный многими классами BCL

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

    using (DisposableObject tmp = DisposableObject.AcquireResource()) {
        // Do something with tmp
    }
    // At this point, tmp.Dispose() will automatically have been called
    // BUT, tmp may still a perfectly valid object that still takes up memory
    

    Если » AcquireResource «является заводским методом, который (например) открывает файл и» Dispose » автоматически закрывает файл, то этот код не может утечка файлового ресурса. Но память для самого объекта «tmp»вполне может быть выделена. Это потому, что IDisposable интерфейс не имеет абсолютно никакого соединения с сборщиком мусора. Если вы действительно хотите убедиться, что память была освобождена, единственным вариантом будет вызвать GC.Collect()принудительную сборку мусора.

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

    Что происходит, если ресурс используется в течение более длительного периода времени, так что его срок службы пересекает несколько методов? Ясно, что оператор» using «больше не применим, поэтому программисту придется вручную вызывать» Dispose», когда он или она закончит с ресурсом. А что произойдет, если программист забудет? Если резервный вариант отсутствует, то процесс или компьютер может в конечном итоге закончиться из того ресурса, который не был должным образом освобожден.

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

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

    Для большинства ресурсов мы хотим и то, и другое. Мы хотим, чтобы конвенция могла сказать: «мы закончили с этим ресурсом сейчас», и мы хотим убедиться, что есть, по крайней мере, некоторый шанс для очистки произойдет автоматически, если мы забудем сделать это вручную. Вот где» IDisposable » шаблон вступает в игру. Это соглашение, которое позволяет IDispose и финализатор, чтобы играть красиво вместе. Вы можете увидеть, как работает шаблон, посмотрев официальную документацию для IDisposable .

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

  8. Уместно ли также упомянуть, что dispose не всегда ссылается на память? Я размещаю ресурсы такие ссылки на файлы чаще чем на память. СБОРЩИК МУСОРА.Collect () напрямую связан с сборщиком мусора среды CLR и может или не может освободить память (в Диспетчере задач). Это, вероятно, повлияет на ваше приложение отрицательным образом (например, производительность).

    В конце концов, почему вы хотите, чтобы память вернулась немедленно? Если есть давление памяти из других мест, ОС получит вам память в большинстве случаев.

  9. Я написал резюме деструкторов и утилизации и сбора мусора на http://codingcraftsman.wordpress.com/2012/04/25/to-dispose-or-not-to-dispose/

    Чтобы ответить на первоначальный вопрос:

    1. Не пытайтесь управлять своей памятью
    2. Dispose — это не управление памятью, это неуправляемое управление ресурсами
    3. Завершители являются неотъемлемой частью шаблона Dispose и фактически замедляют освобождение памяти управляемых объектов (так как они должны войти в очередь завершения, если уже Dispose d)
    4. СБОРЩИК МУСОРА.Собирать плохо, так как это заставляет некоторые недолговечные объекты казаться необходимыми дольше, и поэтому замедляет их сбор.

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

    Кроме того, есть аргумент в пользу этой модели:

    var myBigObject = new MyBigObject(1);
    // something happens
    myBigObject = new MyBigObject(2);
    // at the above line, there are temporarily two big objects in memory and neither can be collected
    

    против

    myBigObject = null; // so it could now be collected
    myBigObject = new MyBigObject(2);
    

    Но главный ответ заключается в том, что сбор мусора просто работает, если вы не возитесь с ним!

  10. Можно только утилизировать экземпляры, реализующие интерфейс IDisposable.

    Чтобы заставить сборщик мусора немедленно освободить (неуправляемую) память:

    GC.Collect();  
    GC.WaitForPendingFinalizers();
    

    Это обычно плохая практика, но есть, например, ошибка в x64-версии .NET framework, которая заставляет GC вести себя странно в некоторых сценариях, и тогда вы, возможно, захотите сделать это. Я не знаю, если ошибка была решена еще. Кто-нибудь знает?

    Чтобы избавиться от класса, вы делаете это:

    instance.Dispose();
    

    или как это:

    using(MyClass instance = new MyClass())
    {
        // Your cool code.
    }
    

    это будет переводиться во время компиляции на:

    MyClass instance = null;    
    
    try
    {
        instance = new MyClass();        
        // Your cool code.
    }
    finally
    {
        if(instance != null)
            instance.Dispose();
    }
    

    Интерфейс IDisposable можно реализовать следующим образом:

    public class MyClass : IDisposable
    {
        private bool disposed;
    
        /// <summary>
        /// Construction
        /// </summary>
        public MyClass()
        {
        }
    
        /// <summary>
        /// Destructor
        /// </summary>
        ~MyClass()
        {
            this.Dispose(false);
        }
    
        /// <summary>
        /// The dispose method that implements IDisposable.
        /// </summary>
        public void Dispose()
        {
            this.Dispose(true);
            GC.SuppressFinalize(this);
        }
    
        /// <summary>
        /// The virtual dispose method that allows
        /// classes inherithed from this one to dispose their resources.
        /// </summary>
        /// <param name="disposing"></param>
        protected virtual void Dispose(bool disposing)
        {
            if (!disposed)
            {
                if (disposing)
                {
                    // Dispose managed resources here.
                }
    
                // Dispose unmanaged resources here.
            }
    
            disposed = true;
        }
    }
    
  11. Эта статья имеет довольно простое пошаговое руководство. Однако необходимость вызывать GC вместо того, чтобы позволить ему взять свой естественный курс, обычно является признаком плохого дизайна/управления памятью, особенно если не используются никакие ограниченные ресурсы (соединения, дескрипторы, все остальное, что обычно приводит к реализации IDisposable).

    Что заставляет вас делать это?

  12. Взгляните на эту статью

    Реализация шаблона Dispose, IDisposable и / или финализатора не имеет абсолютно никакого отношения к тому, когда память восстанавливается; вместо этого, это имеет все отношение к указанию GC, как восстановить эту память. При вызове Dispose () вы никоим образом не взаимодействуете с GC.

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

    Вы можете позвонить в GC.Collect() but you really shouldn’t until there is a very good reason to (which is almost always «Never»). Когда вы заставляете внеполосный цикл сбора данных, подобный этому, вы фактически заставляете GC делать больше работы и в конечном итоге можете повредить производительности приложений. В течение цикла сбора GC приложение фактически находится в замороженном состоянии…чем больше циклов GC выполняется, тем больше времени приложение проводит в замороженном состоянии.

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

    Вся предпосылка для gargbage собранной среды выполнения заключается в том, что вам не нужно беспокоиться (как много) о том, когда среда выполнения выделяет/освобождает фактическую память; вам нужно только беспокоиться о том, чтобы убедиться, что ваш объект знает, как очистить после себя, когда его спрашивают.

  13. Если вы не хотите (или не можете) реализовать IDisposable в своем классе, вы можете принудительно выполнить сборку мусора, как это (но это медленно) —

    GC.Collect();
    
  14. Интерфейс IDisposable предназначен для классов, содержащих неуправляемые ресурсы. Если класс не содержит неуправляемых ресурсов, зачем освобождать ресурсы до того, как это сделает сборщик мусора? В противном случае просто убедитесь, что экземпляр объекта создан как можно позже и как можно скорее выходит за пределы области видимости.

  15. Конрад Рудольф-да, обычно финалист вообще ничего не делает. Вы не должны реализовывать его, если не имеете дело с неуправляемыми ресурсами.

    Затем при его реализации используется шаблон dispose корпорации Майкрософт (как уже описано)

    • public Dispose() звонкиprotected Dispose(true)-сделки с управляемыми и неуправляемыми ресурсами. Вызов Dispose()должен подавлять завершение.

    • ~Finalize звонкиprotected Dispose(false)-сделки только с неуправляемыми ресурсами. Это предотвращает неуправляемые утечки памяти, если не удается вызвать public Dispose()

    ~Finalize медленный и не должен использоваться, если у вас нет неуправляемых ресурсов для работы.

    Управляемые ресурсы не могут утечка памяти, они могут только тратить ресурсы для текущего приложения и замедлить сбор мусора. Неуправляемые ресурсы могут протекать, и ~Finalizeлучше всего гарантировать, что они этого не делают.

    В любом случае usingэто наилучшая практика.

  16. Детерминированное уничтожение объектов в c++

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

    Для тех, кто публикует IDisposable ответы. Вызов метода Dispose не уничтожает объект, как описывает asker.

  17. @Кит:

    IDisposable предназначен для управляемых ресурсов.

    Финализаторы предназначены для неуправляемых ресурсов.

    Извините, но это неправильно. Обычно финализатор вообще ничего не делает. Однако, если шаблон dispose был правильно реализован, завершитель пытается вызвать Dispose.

    Dispose имеет две работы:

    • Свободные неуправляемые ресурсы, и
    • свободные вложенные управляемые ресурсы.

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

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

  18. Полное объяснение Джо Даффи на » Dispose, Finalization, и управление ресурсами«:

    Ранее в .NET Framework
    продолжительность жизни, финализаторы были последовательно
    упомянутые как деструкторы C#
    программисты. Как мы становимся умнее
    время, мы стараемся прийти к соглашению
    с тем, что метод Dispose
    действительно более эквивалентно C++
    деструктор (детерминированный)
    , в то время как
    финализатор-это нечто полностью
    отдельный (недетерминированный)
    . Факт
    что C# заимствовал деструктор c++
    синтаксис (т. е. ~T ()) наверняка имел по крайней мере
    немного сделать с развитием
    это неправильное название.

  19. Ответы на этот вопрос более чем немного запутались.

    Заголовок спрашивает об утилизации, но затем говорит, что они хотят немедленно вернуть память.

    .Net управляется, что означает, что при написании приложений .Net вам не нужно беспокоиться о памяти напрямую, стоимость заключается в том, что у вас нет прямого контроля над памятью.

    .Net решает, когда лучше очистить и освободить память, а не вы как .Net-кодер.

    DisposeЭто способ сказать .Net, что вы закончили с чем-то, но это не будет на самом деле освободить память, пока это не лучшее время, чтобы сделать это.

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

    В .Net вы можете использоватьGC.Collect(), чтобы заставить его немедленно, но это почти всегда плохая практика. Если .Net еще не очистил его, это означает, что это не особенно хорошее время для этого.

    GC.Collect() подбирает объекты, которые .Net идентифицирует как выполненные. Если объект не удален, .Net может принять решение сохранить его. Это означает, что GC.Collect()это эффективно только в том случае, если вы правильно реализуете свои одноразовые экземпляры.

    GC.Collect() не является заменой для правильного использования IDisposable.

    Таким образом, Dispose и память не связаны напрямую, но они не должны быть. Правильное размещение сделает ваши приложения .Net более эффективными и, следовательно, будет использовать меньше памяти, хотя.


    В 99% случаев в .Net рекомендуется следующее:

    Правило 1: Если вы не имеете дело с чем-либо неуправляемым или что реализуетIDisposable, то не беспокойтесь о Dispose.

    Правило 2: Если у вас есть локальная переменная, которая реализует IDisposable, убедитесь, что вы избавляетесь от нее в текущей области:

    //using is best practice
    using( SqlConnection con = new SqlConnection("my con str" ) )
    {
        //do stuff
    } 
    
    //this is what 'using' actually compiles to:
    SqlConnection con = new SqlConnection("my con str" ) ;
    try
    {
        //do stuff
    }
    finally
    {
        con.Dispose();
    }
    

    Правило 3: Если класс имеет свойство или переменную-член, которая реализует IDisposable, то этот класс должен реализовать IDisposable тоже. В методе Dispose этого класса можно также Удалить Свойства IDisposable:

    //rather basic example
    public sealed MyClass :
       IDisposable
    {   
        //this connection is disposable
        public SqlConnection MyConnection { get; set; }
    
        //make sure this gets rid of it too
        public Dispose() 
        {
            //if we still have a connection dispose it
            if( MyConnection != null )
                MyConnection.Dispose();
    
            //note that the connection might have already been disposed
            //always write disposals so that they can be called again
        }
    }
    

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

    Правило 4: Если класс использует неуправляемый ресурс, то реализуйте IDispose и добавьте завершитель.

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

    Метод Dispose должен работать как с управляемыми, так и с неуправляемыми ресурсами.

    Финализатор-это уловка безопасности — он гарантирует, что если кто-то другой создает и экземпляр вашего класса и не может утилизировать его, «опасные» неуправляемые ресурсы все еще могут быть очищены .Net.

    ~MyClass()
    {
        //calls a protected method 
        //the false tells this method
        //not to bother with managed
        //resources
        this.Dispose(false);
    }
    
    public void Dispose()
    {
        //calls the same method
        //passed true to tell it to
        //clean up managed and unmanaged 
        this.Dispose(true);
    
        //as dispose has been correctly
        //called we don't need the 
    
        //'backup' finaliser
        GC.SuppressFinalize(this);
    }
    

    Наконец, эта перегрузка Dispose, которая принимает логический флаг:

    protected virtual void Dispose(bool disposing)
    {
        //check this hasn't been called already
        //remember that Dispose can be called again
        if (!disposed)
        {
            //this is passed true in the regular Dispose
            if (disposing)
            {
                // Dispose managed resources here.
            }
    
            //both regular Dispose and the finaliser
            //will hit this code
            // Dispose unmanaged resources here.
        }
    
        disposed = true;
    }
    

    Обратите внимание, что после того, как все это будет установлено, другой управляемый код, создающий экземпляр вашего класса, может просто рассматривать его как любой другой IDisposable (правила 2 и 3).

  20. Извините, но выбранный ответ неверен. Как несколько человек заявили впоследствии Dispose и реализация IDisposable не имеет ничего общего с освобождением памяти, связанной с .NET-классом. Она главным образом и традиционно использована для того чтобы освободить неуправляемые ресурсы как ручки ЕТК файла.

    Пока приложение может вызывать GC.Collect () чтобы попытаться принудительно собрать коллекцию сборщиком мусора, это будет действительно иметь влияние только на те элементы, которые находятся на правильном уровне генерации в очереди freachable. Таким образом, возможно, что если вы очистили все ссылки на объект, это все еще может быть несколько вызовов GC.Collect () до освобождения фактической памяти.

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

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