Вопрос

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

MyClass.Dispose()

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

Это было полезно?

Решение

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

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

Редактировать: Заработав значительную сумму кармы за этот ответ, я чувствую определенную ответственность подробно остановиться на нем, чтобы у новичка в управлении ресурсами .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», когда он или она закончит работу с ресурсом.А что будет, если программист забудет?Если резервного варианта нет, то в процессе или компьютере может в конечном итоге исчерпаться ресурс, который не освобождается должным образом.

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

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

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

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

Другие советы

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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#.Когда мы становимся умнее со временем, мы пытаемся смириться с тем фактом, что Метод распознавания действительно более эквивалентен деструктору C ++ (детерминированный), в то время Финализатор - это нечто совершенно отдельное (неэнергинистовое).Тот факт, что C# позаимствовал синтаксис деструктора C ++ (т.е.~ T ()), несомненно, немного связано с развитием этого неправильного.

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

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

  1. Не пытайтесь управлять своей памятью
  2. Dispose — это не управление памятью, а управление неуправляемыми ресурсами.
  3. Финализаторы являются встроенной частью шаблона Dispose и фактически замедляют освобождение памяти управляемых объектов (поскольку они должны перейти в очередь финализации, если они еще не Dispose d).
  4. 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);

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

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

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

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

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

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

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

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

@Кит,

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

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

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

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

MyClass.Dispose();

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

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

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

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

GC.Collect();

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

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

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

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

@Кит:

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

IDisposable для удалось Ресурсы.

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

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

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

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


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

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

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

Что касается поста Кита и его правила №4:

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

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

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

    а) немедленно удалить/выпустить их в локальном контексте, в котором они были созданы, ИЛИ...

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

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top