Как удалить класс в .net?

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

MyClass.Dispose()

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

Ответ 1

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

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

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

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

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

  • Интерфейс IDisposable и оператор "using" в VB и С#
  • Финализаторы
  • Шаблон 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" - это метод factory, который (например) открывает файл, а "Dispose" автоматически закрывает файл, тогда этот код не может протекать файловый ресурс. Но память для объекта "tmp" сама по себе может быть выделена. Это потому, что интерфейс IDisposable абсолютно не связан с сборщиком мусора. Если вы хотите убедиться, что память была освобождена, единственным вариантом будет вызов GC.Collect() для принудительной сборки мусора.

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

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

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

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

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

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

Ответ 2

Вы можете удалять экземпляры, реализующие интерфейс 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;
    }
}

Ответ 3

Ответы на этот вопрос были немного смущены.

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

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

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

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

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

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

GC.Collect() собирает объекты, которые .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).

Ответ 4

Было бы уместно также упомянуть, что dispose не всегда относится к памяти? Я располагаю ресурсами такие ссылки на файлы чаще, чем память. GC.Collect() напрямую относится к сборщику мусора CLR и может содержать или не освобождать память (в диспетчере задач). Вероятно, это повлияет на ваше приложение отрицательными способами (например, производительность).

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

Ответ 5

Взгляните на статью

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

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

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

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

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

Ответ 6

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

Ответ 7

Полное объяснение Джо Даффи " Dispose, Finalization и Resource Management":

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

Ответ 8

Вы не можете заставить GC очистить объект, если хотите, хотя есть способы заставить его работать, ничто не говорит, что он очищает весь объект, который вы хотите/ожидаете. Лучше всего вызывать dispose в попытке поймать ex, наконец, уничтожить конечную попытку (VB.NET rulz). Но Dispose предназначен для очистки системных ресурсов (память, дескрипторы, db-соединения и т.д., Выделенные объектом детерминированным способом. Dispose не очищает (и не может) память, используемую самим объектом, только GC может сделать это.

Ответ 9

Я написал сводку деструкторов и коллекции Dispose and Garbage на http://codingcraftsman.wordpress.com/2012/04/25/to-dispose-or-not-to-dispose/

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

  • Не пытайтесь управлять своей памятью.
  • Dispose - это не управление памятью, а неуправляемое управление ресурсами.
  • Финализаторы являются врожденной частью шаблона Dispose и фактически замедляют освобождение памяти от управляемых объектов (поскольку они должны войти в очередь завершения, если уже не удалить D)
  • GC.Collect плохой, поскольку он заставляет некоторые непродолжительные объекты казаться требуемыми дольше и таким образом замедляет их от сбора.

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

Кроме того, есть аргумент в пользу этого шаблона:

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);

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

Ответ 10

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

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

Ответ 11

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

Ответ 12

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

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

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

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

Ответ 13

@Keith,

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

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

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

Ответ 14

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

GC.Collect();

Ответ 15

У вас может быть детерминированное уничтожение объекта в С++

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

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

Ответ 16

@Курт Hagenlocher - это на передний план. Я не знаю, почему так многие проголосовали за это, когда это было неправильно.

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

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

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

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

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


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

Ответ 17

@Keith:

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

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

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

Dispose имеет два задания:

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

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

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

Ответ 18

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

Затем, когда вы его реализуете, вы используете Microsoft удалять шаблон (как уже описано)

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

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

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

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

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

Ответ 19

В ответ на исходный вопрос, с информацией, предоставленной до сих пор оригинальным плакатом, на 100% уверен, что он недостаточно знает о программировании в .NET, чтобы даже получить ответ: используйте GC.Collect(), Я бы сказал, что 99,99% вероятно, что он действительно не должен использовать GC.Collect() вообще, как отмечали большинство плакатов.

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

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

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

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

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

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

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

    b.1) Кроме того, если (b), и это неуправляемый ресурс, который был открыт, оба IDisposable AND Finalize ДОЛЖНЫ ВСЕГДА быть реализованы в соответствии с Правилом № 4.
    В этом контексте Finalize абсолютно является защитной сетью в одном смысле: если кто-то создает экземпляр вашего объекта IDisposable, который использует неуправляемый ресурс, и они не могут вызвать dispose, тогда Finalize - это последний шанс для ВАШЕГО объекта правильно закрыть неуправляемый ресурс. < ш > (Finalize должен сделать это, вызвав Dispose таким образом, чтобы метод Dispose пропускал что-либо, кроме неуправляемого ресурса. В качестве альтернативы, если ваш метод Dispose объекта был правильно вызван любым экземпляром вашего объекта, тогда он ОБА проходит по вызову Dispose все объекты IDisposable, которые он создал, AND освобождает неуправляемые ресурсы должным образом, заканчивая вызовом для подавления Finalize на вашем объекте, а это означает, что влияние использования Finalize уменьшается, если ваш объект правильно настроен вызывающим. Все эти точки включены в пост Кейта, BTW.)

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

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

Ответ 20

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

MyClass.Dispose();

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

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

Поскольку это завершает работу в try-finally и гарантирует, что он никогда не пропустит.