Я знаю, что от чтения в документации Microsoft, что "основной" в пользование интерфейс IDisposable-это для очистки неуправляемых ресурсов.
Для меня "неуправляемый" и означает такие вещи, как соединения с базами данных, розетки, оконные ручки и т. д. Но, я'вэ видел код, где `метод Dispose () метод реализуется на бесплатной managed ресурсов, что представляется излишним для меня, так как сборщик мусора должен заботиться об этом для вас.
Например:
public class MyCollection : IDisposable
{
private List<String> _theList = new List<String>();
private Dictionary<String, Point> _theDict = new Dictionary<String, Point>();
// Die, clear it up! (free unmanaged resources)
public void Dispose()
{
_theList.clear();
_theDict.clear();
_theList = null;
_theDict = null;
}
Мой вопрос, ли это сделать бесплатно сборщик мусора память, используемая коллекции
быстрее, чем обычно?
редактировать: пока люди выложили несколько хороших примеров с использованием метода IDisposable для очистки неуправляемых ресурсов, таких как соединения с базой данных и растровых изображений. Но предположим, что _theList
в приведенном выше коде содержится миллион строк, а вы хотели бесплатно, что теперь памяти, не дожидаясь сборщика мусора. Бы приведенный выше код это сделать?
Точки распоряжаться является, чтобы освободить неуправляемые ресурсы. Это должно быть сделано в определенный момент, иначе они никогда не будут очищены. Сборщик мусора не'т знаю, как называть DeleteHandle () на переменную типа указателя IntPtr
, это не'т знаю, **** ли или не он должен называть DeleteHandle()`.
примечание: что такое неуправляемый ресурс? Если вы нашли его в Microsoft .Чистая рамки: он's не удалось. Если вы пошли ковыряться в MSDN себя, это'ы неуправляемым. Все, что вы'вэ используется П/Invoke вызовы, чтобы выйти на улицу в хорошем удобном мире все доступно для вас на .Framework является неуправляемым – и вы'вновь теперь несет ответственность за ее очистку. Объект, который вы'вэ, созданных должен подставлять некоторые* способ, что внешний мир может вызвать, в целях очистки неуправляемых ресурсов. Метод можно назвать как угодно:
public void Cleanup()
или
public void Shutdown()
Зато есть стандартизированный название этого метода:
public void Dispose()
Там даже интерфейс создан, интерфейс IDisposable
, что есть только один способ:
public interface IDisposable
{
void Dispose()
}
Так вы сделаете свой объект разоблачить интерфейс IDisposable
, и таким образом вы обещаю, что вы'вэ написано, что один способ для очистки неуправляемых ресурсов:
public void Dispose()
{
Win32.DestroyHandle(this.CursorFileBitmapIconServiceHandle);
}
Что делать, если ваш объект уже выделено 250 МБ [система.Чертеж.Растровое изображение][1] (т. е. .Net управляемого класса Bitmap) в качестве своего рода буфера? Конечно, это удалось .Чистый объект, и сборщик мусора освободит его. Но вы действительно хотите оставить 250МБ памяти просто сидит – ждет сборщик мусора в конце концов прийти и освободить его? Что, если там'ы [открыть подключение к базе данных][2]? Конечно, мы не'т хотим, чтобы связь сидела открыта, ждем ГК, чтобы завершить объект.
Если пользователь называемый метод Dispose()
(что означает, что они не планируют использовать объект) почему бы не избавиться от этих расточительных растровые изображения и подключения к базам данных?
Так что теперь мы будем:
public void Dispose()
{
//Free unmanaged resources
Win32.DestroyHandle(this.CursorFileBitmapIconServiceHandle);
//Free managed resources too
if (this.databaseConnection != null)
{
this.databaseConnection.Dispose();
this.databaseConnection = null;
}
if (this.frameBufferImage != null)
{
this.frameBufferImage.Dispose();
this.frameBufferImage = null;
}
}
Что если человек забыл называть метод Dispose () на ваш объект? Потом они просочились неуправляемые ресурсы!
Примечание: они выиграли'т утечка управлял ресурсов, потому что в конечном итоге сборщик мусора будет выполняться в фоновом потоке, и освободить память, связанную с любой неиспользуемых объектов. Это будет включать в себя ваш объект, и любые управляемые объекты можно использовать (например растровые " и " соединение с БД
). Если человек забыл позвонить
метод Dispose(), мы *еще* спасти свою шкуру! Мы все еще называем это *для* них: когда сборщик мусора наконец-то добралась до освобождения (т. е. завершение) наш объект. **Примечание:** сборщик мусора в конечном итоге бесплатно все управляемые объекты. когда он делает, он называет **
доработать** метод на объекте. ГК не'т знаю, или внимательность, о *вашем* **утилизация** способ. это было просто имя, которое мы выбрали для метод мы называем, когда мы хотим получить избавиться от неуправляемых вещей. Уничтожением объекта сборщиком мусора-это *идеальный* время освободить этих надоедливых неуправляемые ресурсы. Мы делаем это путем переопределения
завершение () метод. Примечание: В C#, вы не'т явно переопределитьзавершить()
метод. вы пишете метод, который похоже на деструкторов C++ и компилятор берет, чтобы быть вашей реализации `завершение () метод:
~MyObject()
{
//we're being finalized (i.e. destroyed), call Dispose in case the user forgot to
Dispose(); //<--Warning: subtle bug! Keep reading!
}
Но там'ы ошибка в этом коде. Вы видите, как сборщик мусора работает на фоновый поток; вы не'т знать порядок, в котором были уничтожены два объекта. Вполне возможно, что в вашем метод Dispose()
код, на управлял объект вы'вновь пытается избавиться (потому что хотел быть полезным) уже нет:
public void Dispose()
{
//Free unmanaged resources
Win32.DestroyHandle(this.gdiCursorBitmapStreamFileHandle);
//Free managed resources too
if (this.databaseConnection != null)
{
this.databaseConnection.Dispose(); //<-- crash, GC already destroyed it
this.databaseConnection = null;
}
if (this.frameBufferImage != null)
{
this.frameBufferImage.Dispose(); //<-- crash, GC already destroyed it
this.frameBufferImage = null;
}
}
Так что вам нужно, это способ для finalize () и
рассказать метод Dispose ()
, что она должна не успел ресурсов (потому что они не может быть больше), в то же время освобождение неуправляемых ресурсов.
Стандартный шаблон, чтобы сделать это, чтобы завершить()и
метод Dispose()как назвать **Третий**(!) способ, где вы проходите логическое высказывание, Если вы'вновь зовет его метод Dispose()
(в противоположность завершить()
), означает, что она's, можно бесплатно управляемые ресурсы.
Этот внутреннюю метод можно быть дано какое-то произвольное имя, как-то ", или "MyInternalDispose на" CoreDispose", У;, но традиция называть его метод Dispose(boolean) с`:
protected void Dispose(Boolean disposing)
Но более полезной название параметра может быть:
protected void Dispose(Boolean itIsSafeToAlsoFreeManagedObjects)
{
//Free unmanaged resources
Win32.DestroyHandle(this.CursorFileBitmapIconServiceHandle);
//Free managed resources too, but only if I'm being called from Dispose
//(If I'm being called from Finalize then the objects might not exist
//anymore
if (itIsSafeToAlsoFreeManagedObjects)
{
if (this.databaseConnection != null)
{
this.databaseConnection.Dispose();
this.databaseConnection = null;
}
if (this.frameBufferImage != null)
{
this.frameBufferImage.Dispose();
this.frameBufferImage = null;
}
}
}
И вы измените свое реализации интерфейса IDisposable.Метод Dispose () на:
public void Dispose()
{
Dispose(true); //I am calling you from Dispose, it's safe
}
и ваш финализатора:
~MyObject()
{
Dispose(false); //I am *not* calling you from Dispose, it's *not* safe
}
Примечание: Если ваш объект спускается с объектом, который реализует
распоряжаться
, затем Дон'т забудьте назвать их базовый метод Dispose, когда вы переопределяете распоряжаться:
public override void Dispose()
{
try
{
Dispose(true); //true: safe to free managed resources
}
finally
{
base.Dispose();
}
}
Если пользователь вызывает метод Dispose () на ваш объект, тогда все были очищены. Позже, когда сборщик мусора приходит и требует доработки, он будет затем вызвать распоряжаться
снова.
Это не только расточительно, но если ваш объект имеет ненужных ссылок на объекты, которые вы уже избавились от Последний в метод Dispose(), вы'МР попробовать снова распоряжаться им! Вы'МР обратите внимание на мой код, я был достаточно осторожен, чтобы удалить ссылки на объекты, что я'вэ утилизировать, так что я не'т попробуйте позвонить
избавлятьсяот нежелательной ссылка на объект. Но это'т остановить неуловимую ошибку из вкрадываться. Когда пользователь вызывает метод Dispose()
: ручка CursorFileBitmapIconServiceHandle разрушен. Позже, когда сборщик мусора работает, он будет пытаться уничтожить ту же ручку.
protected void Dispose(Boolean iAmBeingCalledFromDisposeAndNotFinalize)
{
//Free unmanaged resources
Win32.DestroyHandle(this.CursorFileBitmapIconServiceHandle); //<--double destroy
...
}
Как вы исправить это сказать сборщику мусора, что он не'т нужно беспокоиться о доработке объекта – его ресурсы были уже очищены, и больше не будете. Вы делаете это путем вызова `ГХ.SuppressFinalize () в метод Dispose () метод:
public void Dispose()
{
Dispose(true); //I am calling you from Dispose, it's safe
GC.SuppressFinalize(this); //Hey, GC: don't bother calling finalize later
}
Теперь, когда пользователь называемый метод Dispose()
, мы имеем:
Документации для объекта .Завершить
говорит:
метод finalize используется для выполнения операций очистки неуправляемых ресурсов, находящихся в ведении текущего объекта до объекта. Но в документации MSDN говорит также, для [
IDisposable.Dispose
](https://msdn.microsoft.com/en-us/library/system.idisposable.dispose(v=vs. 110).aspx): выполняет определяемые приложением задачи, связанные с высвобождением или сбросом неуправляемых ресурсов. Так что это? Где места для меня очистка неуправляемых ресурсов? Ответ: Это's ваш выбор! Но выбратьраспорядиться
. Вы, безусловно, можете разместить ваш неуправляемый очистки в финализатор:
~MyObject()
{
//Free unmanaged resources
Win32.DestroyHandle(this.CursorFileBitmapIconServiceHandle);
//A C# destructor automatically calls the destructor of its base class.
}
Проблема в том, что вы понятия не имеете, когда сборщик мусора будет вокруг, чтобы завершить ваш объект. Ваш ООН-управляемым, ненужные, ООН-использовать собственные ресурсы будет придерживаться вокруг, пока сборщик мусора в конце концов работает. Затем вызвать метод финализации; очистка неуправляемых ресурсов. Документация объекта.Доработать ввернуто:
точное время, когда финализатор выполняется неопределено. Чтобы обеспечить детерминированное освобождение ресурсов для экземпляров класса, реализовать закрыть метод или обеспечить [
интерфейс IDisposable.Распоряжаться
][3] реализации. Это добродетель, используяраспоряжаться
для очистки неуправляемых ресурсов; вы узнаете, а Управления, когда неуправляемые ресурсы очищаются. Их уничтожение то"детерминированные и".Чтобы ответить на ваш исходный вопрос: почему бы не освободить память сейчас, а не когда сборщик мусора решит сделать это? У меня есть программа распознавания лиц, что должен чтобы избавиться от 530 МБ встроенной изображений сейчас, поскольку они'вновь больше не нужны. Когда мы Дон'т: машина скрежещет к остановке перекачки. Бонус Для Чтения
Для тех, кто любит стиль этого ответа (объяснения почему так как становится очевидным), я предлагаю вам прочитать главу не поле'ы основные com:
- Прямая ссылка: Глава 1 образец Пирсон издание
Магнит: 84bf0b960936d677190a2be355858e80ef7542c0 В 35 страницах он объясняет проблемы использования двоичных объектов, и придумывает com перед вашими глазами. Как только вы понимаете, почему ком, остальные 300 страниц очевидны, и просто деталь от Microsoft'ы реализации. Я думаю, что каждый программист, который хоть раз связывался с объектами или COM должны, по крайней мере, читайте первую главу. Это лучшее объяснение что-нибудь. Дополнительный Бонус Чтение
Когда все вы знаете, является неправильным Эрик Липперт поэтому очень трудно на самом деле писать правильно финализатор, > и лучший совет, который я могу дать вам не попробовать. [3]: https://msdn.microsoft.com/en-us/library/system.idisposable.dispose(в=против 110).аспн
Интерфейс IDisposable
часто используется, чтобы использовать использование
заявление и предлагают простой способ сделать детерминированной очистки управляемых объектов.
public class LoggingContext : IDisposable {
public Finicky(string name) {
Log.Write("Entering Log Context {0}", name);
Log.Indent();
}
public void Dispose() {
Log.Outdent();
}
public static void Main() {
Log.Write("Some initial stuff.");
try {
using(new LoggingContext()) {
Log.Write("Some stuff inside the context.");
throw new Exception();
}
} catch {
Log.Write("Man, that was a heavy exception caught from inside a child logging context!");
} finally {
Log.Write("Some final stuff.");
}
}
}
Цель шаблон Dispose-обеспечить механизм, чтобы очистить как управляемые, так и неуправляемые ресурсы, и когда это происходит, зависит от того, как метод Dispose вызывается. В вашем примере, использование Dispose не на самом деле делает что-нибудь связанное распоряжаться, поскольку очистка списка не имеет никакого влияния на то, что коллекции были уничтожены. Кроме того, призывы установить переменные к нулю и не влияет на ГК.
Вы можете посмотреть на этой статье для получения более подробной информации о том, как реализовать метод Dispose паттерна, но в основном он выглядит так:
public class SimpleCleanup : IDisposable
{
// some fields that require cleanup
private SafeHandle handle;
private bool disposed = false; // to detect redundant calls
public SimpleCleanup()
{
this.handle = /*...*/;
}
protected virtual void Dispose(bool disposing)
{
if (!disposed)
{
if (disposing)
{
// Dispose managed resources.
if (handle != null)
{
handle.Dispose();
}
}
// Dispose unmanaged managed resources.
disposed = true;
}
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
}
Метод, который является наиболее важным здесь является утилизация(типа bool), который фактически работает в двух различных обстоятельствах:
Проблема с просто сдача ГК позаботиться о выполнении очистки заключается в том, что у вас нет реального контроля над тем, когда сборщик мусора будет работать в режиме (вы можете позвонить в ГК.Собрать(), но вы действительно должны'т), так что ресурсы могут остаться здесь дольше, чем нужно. Помните, что вызов метода Dispose() не'т причинить коллекция цикл или каким-либо образом вызвать сборщик мусора, чтобы собрать/освободить объект; он просто предоставляет средства для более deterministicly очистки используемых ресурсов и скажите вещества, которые эту уборку уже выполняется.
Весь смысл IDisposable и шаблон Dispose это'Т О немедленно освободив память. Единственный раз, когда вызов метода Dispose будет даже иметь шанс немедленно освободить память, когда она занимается утилизацией == лживым сценарием и управление неуправляемые ресурсы. Для управляемого кода, памяти выиграл'т действительно быть возвращены до тех пор, пока GC выполняется в цикле сбора, который вы действительно не имеете никакого контроля над (не называя ГК.Собрать(), который я'ве уже упоминалось, не является хорошей идеей).
Ваш сценарий-это'т действительно действует, так как строки в .Чистый Дон'т использовать любые ресурсы unamanged и Дон'т реализовать IDisposable, нет никакого способа, чтобы заставить их быть "подчистили.&и"
Не должно быть никаких дальнейших вызовов на объект'ы методов после вызова Dispose был вызван на это (хотя объект должен и дальше терпеть вызовы Dispose). Поэтому пример в вопрос глупый. Если метод Dispose вызывается, то сам объект может быть удален. Так что пользователю нужно просто отбросить все ссылки на этот объект (установить их в NULL) и все связанные объекты внутренние, автоматически очищаются.
Что касается общего вопроса об управляемых/неуправляемых и обсуждения в других ответов, я думаю, что любой ответ на этот вопрос следует начать с определения неуправляемый ресурс.
Что это сводится к тому, что есть функция, вы можете позвонить, чтобы перевести систему в состояние, и там'с другой функции вы можете позвонить, чтобы вернуть его из этого состояния. Сейчас, в типичном примере, первое может быть функция, которая возвращает дескриптор файла, а вторая может быть вызов CloseHandle
.
Но - и это ключ - они могут быть любой пары функций. Кто-то строит государство, другой слезы вниз. Если бы государство было построено, но еще не снесены, то экземпляр ресурсе существует. Вы должны организовать для демонтажа, чтобы это произошло в нужное время - ресурс не управляемой средой CLR. Только автоматически управляемый тип ресурса-памяти. Есть два вида: ГХ, и стек. Типы значений управляемых с помощью стека (или ловить попутку внутри ссылочных типов), и ссылочные типы управляемых ГК.
Эти функции может вызвать изменения состояния, которые могут свободно чередуются, либо должны быть идеально размещены. Изменения состояния может быть ориентирован на многопотоковое исполнение, или они не могли.
Посмотрите на примере в справедливости'ы вопрос. Изменения в лог-файл'ы отступ должен быть идеально вложенные, или все идет не так. Также они вряд ли будут ориентированы на многопотоковое исполнение.
Можно подвезти со сборщиком мусора, чтобы получить ваши неуправляемые ресурсы очищаются. Но только если государственные функции изменения ориентированы на многопотоковое исполнение и два государства могут иметь жизней, которые пересекаются в любом случае. Поэтому справедливость'ы например, ресурс не должен иметь завершения! Он просто не'т помочь любому.
Для тех видов ресурсов, вы можете просто реализовать интерфейс IDisposable
, без финализатора. Финализатор-это совершенно необязательно - он должен быть. Это умалчивается или даже не упоминается во многих книгах.
Затем вы должны использовать использование
заявление, чтобы иметь шанс сделать распоряжаться
называется. Это по сути как ловил машину со стеком (так как финализатор-это ГК, используя
находится в стеке).
Недостающая часть является то, что вам придется вручную писать распоряжаться и сделать его звать на свои поля и свой базовый класс. В C++/CLI и программистов Дон'т придется сделать это. Компилятор пишет это для них в большинстве случаев.
Есть альтернатива, которую я предпочитаю для государств, которые гнездятся прекрасно и не ориентирована на многопотоковое исполнение (помимо всего прочего, избегая IDisposable, который избавляет вас от необходимости спорить с кем-то, кто может'т сопротивляться добавить финализатор, чтобы каждый класс, который реализует интерфейс IDisposable).
Вместо того, чтобы писать класс, вы пишете функцию. Функция принимает делегат перезвонить по:
public static void Indented(this Log log, Action action)
{
log.Indent();
try
{
action();
}
finally
{
log.Outdent();
}
}
И тогда простым примером может быть:
Log.Write("Message at the top");
Log.Indented(() =>
{
Log.Write("And this is indented");
Log.Indented(() =>
{
Log.Write("This is even more indented");
});
});
Log.Write("Back at the outermost level again");
Лямбда передают в служит блок кода, так что's, как вы делаете вашу собственную структуру управления, чтобы служить той же цели, Через
, за исключением того, что у вас больше нет никакой опасности звонящего злоупотребляя этим. Там's не так, как они могут не убирать ресурсе.
Этот метод менее полезен, если ресурс является видом, который, возможно, пересекающихся жизней, потому что тогда вы хотите быть в состоянии построить ресурса, то ресурс B, а затем убить ресурс и потом убить ресурса В. Вы можете'т сделать это, если вы'вэ заставила пользователей прекрасно гнездиться такой. Но тогда вы должны использовать метод IDisposable
(но все равно без финализатора, если вы не реализовали threadsafety, что это'т бесплатный).
Сценарии я использую метод IDisposable: очистки неуправляемых ресурсов, отписаться на события, тесные связи
Идиома, которую я использую для реализации IDisposable (не ориентирована на многопотоковое исполнение):
class MyClass : IDisposable {
// ...
#region IDisposable Members and Helpers
private bool disposed = false;
public void Dispose() {
Dispose(true);
GC.SuppressFinalize(this);
}
private void Dispose(bool disposing) {
if (!this.disposed) {
if (disposing) {
// cleanup code goes here
}
disposed = true;
}
}
~MyClass() {
Dispose(false);
}
#endregion
}
Да, этот код является совершенно излишним и ненужным, и это не'т сделать сборщик мусора ничего делать не'т сделать иначе (как только экземпляр mycollection выходит из области видимости, то есть.) Особенно `.Очистить () звонки.
Ответ на ваш редактирование: рода. Если я делаю это:
public void WasteMemory()
{
var instance = new MyCollection(); // this one has no Dispose() method
instance.FillItWithAMillionStrings();
}
// 1 million strings are in memory, but marked for reclamation by the GC
Это'ы функционально идентичен этому для целей управления памятью:
public void WasteMemory()
{
var instance = new MyCollection(); // this one has your Dispose()
instance.FillItWithAMillionStrings();
instance.Dispose();
}
// 1 million strings are in memory, but marked for reclamation by the GC
Если вы действительно действительно действительно нужно, чтобы освободить память, это самое мгновение, называть ГК.Сбор()`. Там's нет причин, чтобы делать это здесь. Память будет освобождена, когда она'ы нужны.
Если коллекции
будет собран "мусор" в любом случае, тогда вы должны'т нужно утилизировать. Это будет только сбивать ЦП больше, чем нужно, и даже может отменить некоторые заранее просчитанной анализ, что сборщик мусора уже выполнил.
Я использую метод IDisposable`, чтобы сделать вещи, как обеспечить потоки правильно утилизировать, наряду с неуправляемыми ресурсами.
Редактировать в ответ на Скотта'с комментарием:
библиотеки только время влияет на показатели производительности ГХ-это когда называют [так в оригинале] ГК.Сбор() производится на"_
Концептуально, ГК сохраняет вид объекта ссылочного графа, и все ссылки на него из кадров стека потоков. Эта куча может быть довольно большой и охватывает много страниц памяти. В качестве оптимизации, ГК кэширует его анализ страниц, которые вряд ли будут часто меняться, чтобы избежать повторное сканирование страницы без надобности. ГК получает уведомление от системы, когда данные изменения страницы, поэтому он знает, что страница пачкается и требует повторного сканирования. Если коллекция в Gen0 потом он'ы вероятно, что другие вещи на странице слишком меняется, но это менее вероятно, в Gen1 и Gen2. Занимательно, что эти крючки не были доступны в Mac ОС X для команды, которая портирована ГК на Mac для того, чтобы получить плагин Silverlight работает на этой платформе.
Еще один момент против ненужных утилизации ресурсов: представьте себе ситуацию, когда процесс разгрузки. Представим также, что процесс был запущен в течение некоторого времени. Есть вероятность, что многие из этого процесса'страницы памяти были заменены на диск. По крайней мере, они'вновь больше не в L1 или L2 кэша. В такой ситуации нет смысла для приложения, что'ы выгрузки в своп все эти данные и код страниц назад в память 'освобождение' ресурсы, которые будут выпущены в операционной системе, в любом случае, когда процесс завершается. Это относится к управляемым и даже некоторые неуправляемые ресурсы. Должны утилизироваться только ресурсы, которые держат не фоновых потоков живы, иначе процесс останется жив.
Сейчас, во время обычной работы есть эфемерные ресурсы, которые должны быть очищены правильно (как @fezmonkey указывает, database соединения, розетки, окна handles), чтобы избежать утечек памяти. Это те вещи, которые должны быть утилизированы. Если вы создаете класс, который владеет какой-нить (и владеет я имею в виду, что он его создал, и, следовательно, несет ответственность за обеспечение его останавливает, по крайней мере на мой стиль кодирования), то этому классу скорее всего должен реализовать интерфейс IDisposable и снести ветку в
распорядиться`.
Интернет .Чистая Framework использует интерфейс IDisposable
как сигнал, даже предупреждение, для разработчиков, что этот класс должна быть утилизированы. Я могу'т думаю, что любого вида в рамках, которые реализуют `интерфейс IDisposable (без явной реализации интерфейса), где распоряжение не является обязательным.
Если вы хотите удалить использовать памяти.
См.:
В пример вы выложили, это еще не'т "и освободить память сейчас". Все памяти сборщиком мусора, но это может привести к памяти, которая будет собрана в более ранней поколение. Вы'd должны провести несколько тестов, чтобы быть уверенным.
Основными принципами проектирования являются принципы, а не правила. Они скажут вам, что этот интерфейс предназначен в первую очередь для, Когда использовать его, как использовать его, и когда не использовать его.
Я когда-то читал, что код был простой откат() на отказ, используя метод IDisposable. На MiniTx класс ниже будет проверять флаг на Dispose() и если обязательства
звонка не произошло бы затем вызвать откат
на себя. Она добавила слой делает код намного легче понять и поддержать. Результат выглядел примерно так:
using( MiniTx tx = new MiniTx() )
{
// code that might not work.
tx.Commit();
}
Я'ве также видели сроки / код лесозаготовки сделать то же самое. В этом случае метод Dispose (), остановил таймер и регистрируется, что блок завершен.
using( LogTimer log = new LogTimer("MyCategory", "Some message") )
{
// code to time...
}
Так вот пара конкретных примеров, что Дон'т сделать любой очистки неуправляемых ресурсов, но успешно используется интерфейс IDisposable, чтобы создать более чистый код.
Я выиграл'т повторять обычные вещи об использовании или освобождая ООН-управляемые ресурсы, которые все были покрыты. Но я хотел бы указать на то, что, кажется, распространенное заблуждение.<БР> Учитывая следующий код<БР> в <предварительно> LargeStuff Открытый Класс Реализует IDisposable Частная _Large как строка()
'странный код, что означает _Large теперь содержит несколько миллионов длинных строк.
Государственные Суб Метод Dispose() Реализует IDisposable.Распоряжаться _Large=Ничего Конец Подпрограммы </пред> Я понимаю, что одноразовые реализация не следовать существующим нормативам, но, надеюсь, вы все поняли идею.<БР> Теперь, когда Dispose вызывается, сколько памяти освобождается? <БР><БР> Ответ: Нет.<БР> Вызов метода Dispose может освободить неуправляемые ресурсы, он не может вернуть управляемой памяти, только GC может сделать это. Это не сказать, что совсем't хорошая идея, следующим выше шаблон все еще хорошая идея, на самом деле. После утилизации была запущена, ничто не мешает ГХ вновь претендующий на этот памяти, используется _Large, хотя экземпляр LargeStuff еще может быть в области. Струны в _Large также может быть в ген 0, но экземпляр LargeStuff может быть 2-го поколения, так опять же, память будет вновь утверждал раньше.<БР> Есть в добавление к вызову метода показано выше, хотя распоряжаться finaliser нет смысла. Это будет просто отложить повторный запрос памяти для того, чтобы finaliser бежать.
Кроме своего основного использования как способ управления пожизненная от Система ресурсов (полностью покрыта удивительный ответ Яна, спасибо!), в интерфейс IDisposable/через комбо может также использоваться для объем изменение состояния (критического) Глобальные ресурсы: в консоль, в темы, в процесс, ни глобальный объект как экземпляр приложения.
Я'вэ написал статью об этой схеме: http://pragmateek.com/c-scope-your-global-state-changes-with-idisposable-and-the-using-statement/
Это показывает, как вы можете защитить некоторые часто используемые глобальное состояние в многоразовые и чтения образ: цвет консоли текущие тема культуры, свойства объекта application для Excel...
Если что, я'd и жду код, который должен быть less эффективным, чем при выходе его из.
Называя очистить() методы не нужны, и ГК, наверное, не'т сделать это, если метод Dispose не'т сделать это...
Одна из проблем большинства дискуссий на "неуправляемые ресурсы" это то, что они не'т действительно определить срок, но, похоже, подразумевают, что это как-то связано с неуправляемым кодом. Хотя это правда, что многие виды неуправляемые ресурсы взаимодействия с неуправляемым кодом, думая о неуправляемых ресурсов в таких условиях, разве'т полезная.
Вместо этого, следует признать, что все управляемые ресурсы имеют общую черту: все они влекут за собой объект, задавая некоторые внешние 'что' сделать что-нибудь от его имени, в ущерб какой-то другой 'все' и другой объект согласившись сделать это до дальнейшего уведомления. Если объект был отказаться и исчезнуть без следа, ничто не могло сказать, что за пределами 'что' что больше нет необходимости изменять свое поведение на имени объекта, который не существует; следовательно, 'что'ы полезность будет постоянно уменьшатся.
Неуправляемый ресурс, значит, представляет собой соглашение с какой-либо внешней 'что' чтобы изменить его поведение на имени объекта, который бы бесполезно снизить полезность, что снаружи 'что', если объект был заброшен и перестал существовать. Управляемый ресурс-это объект, который является бенефициаром такого договора, но которые подписались на получение уведомлений, если она заброшена, и которая будет использовать уведомления, чтобы положить свои дела в порядок, прежде чем он будет уничтожен.
Есть вещи, что метод Dispose()работа не в пример код, который *может* иметь эффект, который не будет происходить за счет нормальной ГЖХ
коллекции` объекта.
Если объекты, на которые ссылается _theList " или " _theDict
относятся к другим объектам, то, что список<>или
словарь<>` объект не может быть предметом коллекции, но вдруг нет содержания. Если нет распоряжения (операции), как в Примере, эти коллекции будут еще содержать их содержание.
Конечно, если бы это была ситуация, которую я бы назвал это сломанный дизайн - я'м просто указываю (педантично, я полагаю), что метод Dispose()операция не может быть совершенно излишним, в зависимости от того, есть и другие применения
список<>или
словарь<>` которые не показаны в фрагменте.
Интерфейс IDisposable
хорошо для отписки от событий.
Первые определения. Для меня, неуправляемого ресурса означает некоторый класс, который реализует интерфейс IDisposable или нечто, созданное с использованием звонков на DLL. ГК не'т знают, как бороться с такими объектами. Если класс имеет, например, только типы значений, тогда я Дон'т считаю этот класс как класс с неуправляемыми ресурсами. В моем коде я придерживаюсь следующей практики:
<!
public class SomeClass : IDisposable
{
/// <summary>
/// As usually I don't care was object disposed or not
/// </summary>
public void SomeMethod()
{
if (_disposed)
throw new ObjectDisposedException("SomeClass instance been disposed");
}
public void Dispose()
{
Dispose(true);
}
private bool _disposed;
protected virtual void Dispose(bool disposing)
{
if (_disposed)
return;
if (disposing)//we are in the first call
{
}
_disposed = true;
}
}
[1]: https://msdn.microsoft.com/en-us/library/system.objectdisposedexception(в=против 110).аспн
Наиболее оправданным вариантом использования для утилизации управляемых ресурсов, является подготовка для GC, чтобы освободить ресурсы, которые в противном случае никогда не будут собраны.
Яркий пример-циклические ссылки.
В то время как он'ов рекомендуется использовать шаблоны, чтобы избежать циклических ссылок, если вы в конечном итоге с (например) 'ребенок' объект, который имеет ссылку на его 'родительская', на этом можно остановиться ГК взимании родительской, если вы просто бросить ссылку и опираться на ГК - Плюс, если вы реализовали метод завершения, это'll никогда не будет называться.
Единственный способ обойти это, чтобы вручную разорвать циклические ссылки, устанавливая родительских ссылок в NULL на детей.
Реализации IDisposable на родителей и детей это лучший способ, чтобы сделать это. Когда Dispose для родителей, вызов Dispose для всех детей, и в детской метода Dispose, установить родительский ссылок в null.
Ваш приведенный пример кода не является хорошим примером для интерфейс IDisposable
использования. Очистка словарь normally должен'т пойти на распоряжаться
метод. Элементы словаря будут очищены и утилизированы, когда он выходит из области видимости. Интерфейс IDisposable
реализация обязана освободить часть оперативной памяти/обработчики, которые не выпустят/бесплатно даже после того, как они выходят за рамки.
Следующий пример показывает хороший пример для шаблона IDisposable, который с каким-то кодом и комментарии.
public class DisposeExample
{
// A base class that implements IDisposable.
// By implementing IDisposable, you are announcing that
// instances of this type allocate scarce resources.
public class MyResource: IDisposable
{
// Pointer to an external unmanaged resource.
private IntPtr handle;
// Other managed resource this class uses.
private Component component = new Component();
// Track whether Dispose has been called.
private bool disposed = false;
// The class constructor.
public MyResource(IntPtr handle)
{
this.handle = handle;
}
// Implement IDisposable.
// Do not make this method virtual.
// A derived class should not be able to override this method.
public void Dispose()
{
Dispose(true);
// This object will be cleaned up by the Dispose method.
// Therefore, you should call GC.SupressFinalize to
// take this object off the finalization queue
// and prevent finalization code for this object
// from executing a second time.
GC.SuppressFinalize(this);
}
// Dispose(bool disposing) executes in two distinct scenarios.
// If disposing equals true, the method has been called directly
// or indirectly by a user's code. Managed and unmanaged resources
// can be disposed.
// If disposing equals false, the method has been called by the
// runtime from inside the finalizer and you should not reference
// other objects. Only unmanaged resources can be disposed.
protected virtual void Dispose(bool disposing)
{
// Check to see if Dispose has already been called.
if(!this.disposed)
{
// If disposing equals true, dispose all managed
// and unmanaged resources.
if(disposing)
{
// Dispose managed resources.
component.Dispose();
}
// Call the appropriate methods to clean up
// unmanaged resources here.
// If disposing is false,
// only the following code is executed.
CloseHandle(handle);
handle = IntPtr.Zero;
// Note disposing has been done.
disposed = true;
}
}
// Use interop to call the method necessary
// to clean up the unmanaged resource.
[System.Runtime.InteropServices.DllImport("Kernel32")]
private extern static Boolean CloseHandle(IntPtr handle);
// Use C# destructor syntax for finalization code.
// This destructor will run only if the Dispose method
// does not get called.
// It gives your base class the opportunity to finalize.
// Do not provide destructors in types derived from this class.
~MyResource()
{
// Do not re-create Dispose clean-up code here.
// Calling Dispose(false) is optimal in terms of
// readability and maintainability.
Dispose(false);
}
}
public static void Main()
{
// Insert code here to create
// and use the MyResource object.
}
}
Я вижу много ответов перешли на разговор об использовании IDisposable, который на управляемые и неуправляемые ресурсы. Я'd предлагает эту статью как одно из лучших объяснений, что я'вэ нашел как IDisposable, который должен быть использован.
https://www.codeproject.com/Articles/29534/IDisposable-What-Your-Mother-Never-Told-You-About
На актуальный вопрос; вы должны использовать IDisposable чтобы очистить управляемых объектов, которые занимают много памяти на короткий ответ будет нет. Причина в том, что как только вы реализовать интерфейс IDisposable, вы должны позволить ему перейти из области. В этот момент все связанные дочерние объекты также рассматриваются и будут вам собраны.
Единственное реальное исключение к этому было бы, если у вас много памяти завязаны на управляемые объекты и вы'вэ блокируются, что поток, ожидающий операции для завершения. Если те объекты, где не будет необходимости, после вызова завершена, то установка этих ссылок в null может позволить сборщику мусора, чтобы собрать их раньше. Но этот сценарий будет представлять плохой код, который необходимо переработать - не в случае использования метода IDisposable.