Как зайти в Даркнет?!
25th January, 01:11
6
0
Как в tkinter из поля ввода Entry получить значение в одну переменную и обновить строку кнопкой, затем получить ещё одно введённое значение и затем сложить их. Ниже пример кода
21st July, 19:00
895
0
Программа, которая создает фейковые сервера в поиске игровых серверов CS 1.6 Steam
21st March, 17:43
948
0
Очень долго работает Update запрос Oracle
27th January, 09:58
914
0
не могу запустить сервер на tomcat HTTP Status 404 – Not Found
21st January, 18:02
906
0
Где можно найти фрилансера для выполнения поступающих задач, на постоянной основе?
2nd December, 09:48
938
0
Разработка мобильной кроссплатформенной военной игры
16th July, 17:57
1724
0
период по дням
25th October, 10:44
3955
0
Пишу скрипты для BAS только на запросах
16th September, 02:42
3720
0
Некорректный скрипт для закрытия блока
14th April, 18:33
4613
0
прокидывать exception в блоках try-catch JAVA
11th March, 21:11
4381
0
Помогите пожалуйста решить задачи
24th November, 23:53
6086
0
Не понимаю почему не открывается детальное описание продукта
11th November, 11:51
4351
0
Нужно решить задачу по программированию на массивы
27th October, 18:01
4396
0
Метода Крамера С++
23rd October, 11:55
4309
0
помогите решить задачу на C++
22nd October, 17:31
4002
0
Помогите решить задачу на python с codeforces
22nd October, 11:11
4492
0
Python с нуля: полное руководство для начинающих
18th June, 13:58
2599
0
Как избавиться от класса в .net?
Сборщик мусора .NET в конечном итоге освободит память, но что делать, если вы хотите, чтобы эта память немедленно вернулась? Какой код нужно использовать в классе MyClass для вызова
MyClass.Dispose()
и освободить все используемое пространство переменными и объектами в MyClass ?
IDisposable не имеет никакого отношения к освобождению памяти. IDisposable-это шаблон для освобождения неуправляемых ресурсов , а память, безусловно, является управляемым ресурсом.
Ссылки, указывающие на GC.Collect(), являются правильным ответом, хотя использование этой функции обычно не рекомендуется документацией Microsoft .NET.
Edit: заработав значительную сумму кармы за этот ответ, я чувствую определенную ответственность за его разработку, чтобы новичок в управлении ресурсами .NET не получил неверного впечатления.
Внутри процесса .NET существует два вида ресурсов-управляемые и неуправляемые. "Managed" означает, что среда выполнения контролирует ресурс, в то время как "unmanaged" означает, что это ответственность программиста. И на самом деле есть только один вид управляемого ресурса, который мы сегодня заботимся в .NET-память. Программист говорит среде выполнения выделить память, и после этого она должна выяснить, когда память может быть освобождена. Механизм, который использует .NET для этой цели, называется сборкой мусора , и вы можете найти много информации о GC в интернете, просто используя Google.
Что касается других видов ресурсов, то .NET ничего не знает об их очистке, поэтому ему приходится полагаться на программиста, чтобы сделать правильный выбор. Для этого платформа предоставляет программисту три инструмента:
- Интерфейс IDisposable и оператор "using" в VB и C#
- Метод завершения
- Шаблон 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 обещает , что-прежде чем освободить память для любого объекта этого типа - он сначала даст финализатору шанс сделать некоторую очистку.
Таким образом, в случае файла нам теоретически не нужно закрывать файл вручную вообще. Мы можем просто подождать, пока сборщик мусора доберется до него, а затем позволить финализатору сделать работу. К сожалению, это не работает хорошо на практике, потому что сборщик мусора работает недетерминированно. Файл может оставаться открытым значительно дольше, чем ожидает программист. И если достаточное количество файлов остается открытым, система может потерпеть неудачу при попытке открыть дополнительный файл.
Для большинства ресурсов мы хотим получить и то, и другое. Мы хотим, чтобы соглашение было в состоянии сказать "we're done with this resource now", и мы хотим убедиться, что есть по крайней мере некоторый шанс для очистки произойдет автоматически, если мы забудем сделать это вручную. Вот где в игру вступает паттерн "IDisposable". Это соглашение, которое позволяет IDispose и финализатору хорошо играть вместе. Вы можете увидеть, как работает шаблон, взглянув на официальную документацию для IDisposable .
Итог: Если вы действительно хотите просто убедиться, что память освобождена, то IDisposable и финализаторы вам не помогут. Но интерфейс IDisposable является частью чрезвычайно важного паттерна, который должны понимать все программисты .NET.
Вы можете утилизировать только экземпляры, реализующие интерфейс IDisposable.
Чтобы заставить сборщик мусора немедленно освободить (неуправляемую) память:
GC.Collect();
GC.WaitForPendingFinalizers();
Обычно это плохая практика, но есть, например, ошибка в x64-версии фреймворка .NET, которая заставляет 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() не является заменой для правильного использования 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 должен работать как с управляемыми , так и с неуправляемыми ресурсами.
Завершитель является предохранителем-он гарантирует, что если кто-то другой создаст экземпляр вашего класса и не сможет его утилизировать, то неуправляемые ресурсы 'dangerous' все еще могут быть очищены с помощью файла .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).
Уместно ли также упомянуть, что dispose не всегда относится к памяти? Я располагаю ресурсами таких ссылок на файлы чаще, чем на память. GC.Collect() непосредственно относится к сборщику мусора CLR и может или не может освободить память (в Диспетчере задач). Это, скорее всего, негативно повлияет на ваше приложение (например, производительность).
В конце концов, почему вы хотите, чтобы память вернулась немедленно? Если есть давление памяти из другого места, то OS в большинстве случаев даст вам память.
Взгляните на эту статью
Реализация шаблона Dispose, IDisposable и / или финализатора не имеет абсолютно никакого отношения к тому, когда память восстанавливается; вместо этого она имеет все отношение к указанию GC, как восстановить эту память. Когда вы вызываете Dispose(), вы никоим образом не взаимодействуете с GC.
GC будет работать только тогда, когда он определит необходимость (называемую давлением памяти), а затем (и только тогда) он освободит память для неиспользуемых объектов и сократит объем памяти.
Вы можете позвонить GC.Collect(), но вам действительно не следует этого делать, если нет очень веской причины (которая почти всегда "Never"). Когда вы заставляете out-of-band цикл сбора данных, подобный этому, вы фактически заставляете GC выполнять больше работы и в конечном итоге можете повредить производительность ваших приложений. На протяжении цикла сбора данных GC ваше приложение фактически находится в замороженном состоянии state...the чем больше циклов GC выполняется, тем больше времени ваше приложение проводит в замороженном состоянии.
Есть также некоторые собственные вызовы Win32 API, которые вы можете сделать, чтобы освободить свой рабочий набор, но даже их следует избегать, если нет очень веской причины для этого.
Вся предпосылка, лежащая в основе среды выполнения gargbage collected, заключается в том, что вам не нужно беспокоиться (так же сильно) о том, когда среда выполнения выделяет/освобождает фактическую память; вам нужно только беспокоиться о том, чтобы убедиться, что ваш объект знает, как убирать за собой, когда его спрашивают.
public class MyClass : IDisposable
{
public void Dispose()
{
// cleanup here
}
}
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-х годов время жизни, финализаторы были последовательно упоминается как деструкторы по C# программисты. По мере того как мы становимся умнее над время, мы пытаемся прийти к соглашению с тем, что метод Dispose действительно более эквивалентно a C++ деструктор (детерминированный), в то время как финализатор - это нечто совершенно другое отдельный (недетерминированный) . Факт что C# позаимствовал деструктор C++ синтаксис (т. е. ~T()) наверняка имел по крайней мере немного связано с развитием это неправильное название.
Я написал краткое описание деструкторов и Dispose и сборки мусора на http://codingcraftsman.wordpress.com/2012/04/25/to-dispose-or-not-to-dispose/
Чтобы ответить на первоначальный вопрос:
- Не пытайтесь управлять своей памятью
- 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);
Но главный ответ заключается в том, что сбор мусора просто работает, если вы не возитесь с ним!
Вы не можете действительно заставить GC очистить объект, когда вы хотите, хотя есть способы заставить его работать, ничто не говорит, что это очистить весь объект, который вы want/expect. лучше всего вызвать dispose в try catch ex finally dispose end try (VB.NET rulz) способ. Но Dispose предназначен для очистки системных ресурсов (памяти, дескрипторов, соединений с БД и т. д.). выделяется объектом детерминированным образом. Dispose не очищает (и не может) память, используемую самим объектом, только GC может это сделать.
В этой статье есть довольно простое пошаговое руководство. Однако необходимость вызывать GC вместо того, чтобы позволить ему идти своим естественным путем, как правило, является признаком плохого проектирования/управления памятью, особенно если не используются никакие ограниченные ресурсы (соединения, дескрипторы, все остальное, что обычно приводит к реализации IDisposable).
Чем это вызвано вам нужно сделать для этого?
Извините, но выбранный здесь ответ неверен. Как несколько человек впоследствии заявили, Dispose и реализация IDisposable не имеет ничего общего с освобождением памяти, связанной с классом .NET. Он в основном и традиционно используется для освобождения неуправляемых ресурсов, таких как дескрипторы файлов и т. д.
Хотя ваше приложение может вызвать GC.Collect(), чтобы попытаться принудительно собрать коллекцию сборщиком мусора, это действительно окажет влияние только на те элементы, которые находятся на правильном уровне генерации в очереди freachable. Таким образом, вполне возможно, что если вы очистили все ссылки на объект, то все еще может быть пара вызовов GC.Collect(), прежде чем фактическая память будет освобождена.
Вы не говорите в своем вопросе WHY, что чувствуете необходимость немедленно освободить память. Я понимаю, что иногда могут быть необычные обстоятельства, но серьезно, в управляемом коде почти всегда лучше всего позволить среде выполнения заниматься управлением памятью.
Вероятно, лучший совет, если вы считаете, что ваш код использует память быстрее, чем GC освобождает ее, то вам следует проверить свой код, чтобы убедиться, что никакие объекты, которые больше не нужны, не упоминаются в каких-либо структурах данных, которые у вас лежат в статических членах и т. д. Также старайтесь избегать ситуаций, когда у вас есть циклические ссылки на объекты, поскольку возможно, что они также не будут освобождены.
@Keith,
Я согласен со всеми вашими правилами, за исключением #4. добавление финализатора должно быть сделано только при очень специфических обстоятельствах. Если класс использует неуправляемые ресурсы, они должны быть очищены в вашей функции Dispose(bool). Эта же функция должна очищать управляемые ресурсы только в том случае, если bool имеет значение true. Добавление финализатора увеличивает сложность использования объекта, так как каждый раз при создании нового экземпляра он также должен быть помещен в очередь завершения, которая проверяется каждый раз, когда GC выполняет цикл сбора данных. Фактически это означает, что ваш объект переживает один цикл/поколение дольше, чем это должно быть, чтобы можно было запустить финализатор. Финализатор не следует рассматривать как "safety net".
GC будет выполнять цикл сбора только тогда, когда он определит, что в куче Gen0 недостаточно доступной памяти для выполнения следующего выделения, если только вы не сделаете это с помощью вызова GC.Collect() для принудительного сбора out-of-band.
Суть в том, что, несмотря ни на что, GC знает только, как освободить ресурсы, вызвав метод Dispose (и, возможно, финализатор, если он реализован). Это зависит от этого метода, чтобы "do the right thing" и очистить любые неуправляемые ресурсы, используемые и поручить любые другие управляемые ресурсы, чтобы вызвать их Dispose метод. Он очень эффективен в том, что он делает, и может самооптимизировать в значительной степени, если ему не помогают циклы сбора out-of-band. Тем не менее, за исключением явного вызова GC.Collect, вы не можете контролировать, когда и в каком порядке будут удалены объекты и освобождена память.
Вы можете иметь детерминированное уничтожение объекта в c++
Вы никогда не хотите вызывать GC.Collect, это мешает самонастройке сборщика мусора, чтобы обнаружить давление памяти и в некоторых случаях не делать ничего, кроме увеличения текущего поколения каждого объекта в куче.
Для тех, кто публикует ответы IDisposable. Вызов метода Dispose не приводит к уничтожению объекта, как это описано в методе asker.
IDisposable интерфейс действительно предназначен для классов, содержащих неуправляемые ресурсы. Если ваш класс не содержит неуправляемых ресурсов, то почему вы должны освободить ресурсы до того, как это сделает сборщик мусора? В противном случае просто убедитесь, что ваш объект создается как можно позже и как можно скорее выходит из области видимости.
@Curt Хагенлохер - это задом наперед. Я понятия не имею, почему так много людей проголосовали за это, когда это неправильно.
IDisposable - для управляемых ресурсов.
Финализаторы предназначены для неуправляемых ресурсов.
Пока вы используете только управляемые ресурсы, и @Jon Limjap, и я полностью правы.
Для классов, которые используют неуправляемые ресурсы (и имейте в виду, что подавляющее большинство классов .Net этого не делают), ответ Патрика является исчерпывающим и наилучшим.
Избегайте использования GC.Collect - это медленный способ работы с управляемыми ресурсами и ничего не делает с неуправляемыми, если вы правильно построили свой ~Finalizers.
Я удалил комментарий модератора из исходного вопроса в соответствии с https://stackoverflow.com/questions/14593/etiquette-for-modifying-posts
@Keith:
IDisposable - для управляемых ресурсов.
Финализаторы предназначены для неуправляемых ресурсов.
Извините, но это просто неправильно. Обычно финализатор вообще ничего не делает. Однако, если шаблон dispose был правильно реализован, финализатор пытается вызвать Dispose .
Dispose имеет два рабочих места:
- Свободные неуправляемые ресурсы, а также
- свободные вложенные управляемые ресурсы.
И здесь ваше утверждение вступает в игру, потому что верно, что при завершении объект никогда не должен пытаться освободить вложенные управляемые ресурсы, поскольку они, возможно, уже были освобождены. Однако он все равно должен освободить неуправляемые ресурсы.
Тем не менее, у завершителей нет другой задачи, кроме вызова Dispose и указания ему не трогать управляемые объекты. Dispose, вызванный вручную (или через Using ), освобождает все неуправляемые ресурсы и передает сообщение Dispose вложенным объектам (и методам базового класса), но это никогда не освободит никакой (управляемой) памяти.
Конрад Рудольф-ага, обычно финализатор вообще ничего не делает. Вы не должны реализовывать его, если не имеете дело с неуправляемыми ресурсами.
Затем, когда вы его реализуете, вы используете шаблон dispose корпорации Майкрософт (как уже описано)
public Dispose()вызовыprotected Dispose(true)-работа как с управляемыми, так и с неуправляемыми ресурсами. ВызовDispose()должен подавлять завершение процесса.~Finalizeвызываетprotected Dispose(false)-работает только с неуправляемыми ресурсами. Это предотвращает утечку неуправляемой памяти, если не удается вызватьpublic Dispose()
~Finalize работает медленно, и его не следует использовать, если у вас нет неуправляемых ресурсов для работы.
Управляемые ресурсы не могут пропускать память, они могут только тратить ресурсы для текущего приложения и замедлять его сборку мусора. Неуправляемые ресурсы могут протекать, и ~Finalize -это наилучшая практика, чтобы гарантировать, что они этого не делают.
В любом случае using -это наилучшая практика.
В ответе на первоначальный вопрос, с информацией, предоставленной до сих пор оригинальным плакатом, 100% уверен, что он не знает достаточно о программировании в .NET, чтобы даже получить ответ: используйте GC.Collect(). Я бы сказал, что это 99.99% вероятно, что ему действительно не нужно использовать GC.Collect() вообще, как указывало большинство плакатов.
Правильный ответ сводится к следующему: "пусть GC делает свою работу. Период. У тебя есть и другие причины для беспокойства. Но вы, возможно, захотите рассмотреть, следует ли и когда вы должны избавиться или очистить определенные объекты, и нужно ли вам реализовать IDisposable и, возможно, завершить работу в своем классе.'
Относительно должности Кита и его правления #4:
Некоторые плакаты путают Правило 3 и Правило 4. Правило 4 кита абсолютно верно, однозначно. Это единственное правило из четырех, которое вообще не нуждается в редактировании. Я бы немного перефразировал некоторые из его других правил, чтобы сделать их более ясными, но они по существу правильны, если вы их правильно проанализируете и фактически прочитаете весь пост, чтобы увидеть, как он их расширяет.
Если ваш класс не использует неуправляемый ресурс AND, он также никогда не создает экземпляр другого объекта класса, который сам использует, непосредственно или в конечном счете, неуправляемый объект (т. е. класс, реализующий IDisposable), то вашему классу не нужно будет ни реализовывать IDisposable, ни даже вызывать .dispose на что-либо. (В таком случае глупо думать, что вы на самом деле NEED, чтобы немедленно освободить память с принудительным GC, так или иначе.)
Если ваш класс использует неуправляемый ресурс, OR создает экземпляр другого объекта, который сам реализует IDisposable, то ваш класс должен либо:
а) немедленно утилизируйте / освободите их в локальном контексте, в котором они были созданы, OR...
б) реализовать IDisposable в шаблоне, рекомендованном в посте кита, или в нескольких тысячах мест в интернете, или буквально в 300 книгах к настоящему времени.
b.1) кроме того, если (b), и это неуправляемый ресурс, который был открыт, и IDisposable, и Finalize всегда должны быть реализованы, согласно правилу кита #4.
В этом контексте Finalize абсолютно IS защитная сетка в одном смысле: если кто-то создает экземпляр вашего объекта IDisposable, который использует неуправляемый ресурс, и они не могут вызвать dispose, то Finalize-это последний шанс для объекта YOUR закрыть неуправляемый ресурс должным образом.
(Finalize должен сделать это, вызвав Dispose таким образом, чтобы метод Dispose пропускал освобождение чего-либо BUT неуправляемого ресурса. Кроме того, если метод Dispose вашего объекта IS правильно вызван любым экземпляром вашего объекта, то он BOTH передает вызов Dispose всем объектам IDisposable, которые он создал, AND освобождает неуправляемые ресурсы должным образом, заканчивая вызовом подавления Finalize на вашем объекте, что означает, что влияние использования Finalize уменьшается, если ваш объект правильно расположен вызывающим. Все эти пункты включены в сообщение кита, BTW.)b.2) IF ваш класс реализует только IDisposable, потому что он должен по существу передать Dispose объекту IDisposable, который он создал, а затем не реализовывать метод Finalize в вашем классе в этом случае. Finalize предназначен для обработки случая, когда оба Dispose никогда не вызывались любым экземпляром вашего объекта, AND был использован неуправляемый ресурс, который все еще не выпущен.
Короче говоря, что касается поста кита, то он совершенно прав, и этот пост, на мой взгляд, является самым правильным и полным ответом. Он может использовать некоторые краткие высказывания, которые некоторые находят 'wrong' или возражают против этого, но его полный пост расширяет использование Finalize полностью, и он абсолютно прав. Обязательно прочитайте его пост полностью, прежде чем перейти к одному из правил или предварительных утверждений в его посте.