Как избавиться от класса in.net?

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

MyClass.Dispose()

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

20 ответов


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

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

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

внутри процесса .NET существует два вида ресурсов-управляемый и неуправляемый. "Управляемый" означает, что среда выполнения контролирует ресурс, а "неуправляемый" означает, что это ответственность программиста. И на самом деле есть только один вид управляемого ресурса, о котором мы заботимся в .NET сегодня-память. Программист говорит среде выполнения выделить память, и после этого это до runtime, чтобы выяснить, когда память может освободиться. Механизм, который .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 не имеет никакого отношения к сборщику мусора. Если ты ... --3-->сделал хотите убедиться, что память была освобождена, ваш единственный вариант-вызвать GC.Collect() для принудительной сборки мусора.

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

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

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

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

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

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


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

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

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

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

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

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

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

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

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

GC.Collect() is не замена для правильного использования 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 и добавить finaliser.

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

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

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

~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).


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

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


взгляните на это статьи

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

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

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

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

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


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

полное объяснение Джо Даффи на "утилизация, завершение и управление ресурсами":

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


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

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

  1. не пытайтесь управлять своей памятью
  2. Dispose не об управлении памятью, это о неуправляемом управлении ресурсами
  3. финализаторы присуще шаблон Dispose и замедлить освобождая память управляемые объекты (поскольку они должны войти в очередь завершения, если уже не Dispose d)
  4. GC.Собирать плохо, так как это заставляет некоторые недолговечные объекты казаться необходимыми дольше и поэтому замедляет их сбор.

однако, 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

vs

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

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


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


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

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


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


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

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

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

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


@Keith,

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

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

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


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

GC.Collect();

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

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

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


@Keith:

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

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

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

Dispose имеет два рабочих места:

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

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

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


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

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

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

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

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

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

в любом дело using передовая практика.


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

IDisposable на управлял ресурсы.

Finalisers для неуправляемые ресурсы.

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

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

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


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


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

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

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

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

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

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

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

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

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

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

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


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

MyClass.Dispose();

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

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

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