Обновление (1 декабря 2009 г.):
Я хотел бы изменить этот ответ и признать, что первоначальный ответ был ошибочным.
Первоначальный анализ действительно применим к объектам, которые требуют доработки - и точка, которую практики не следует принимать на поверхности без точного, глубокого понимания, все еще остается в силе.
Однако оказывается, что DataSets, DataViews, DataTables подавляют финализацию в своих конструкторах - вот почему вызов Dispose () для них явно ничего не делает.
Предположительно, это происходит потому, что у них нет неуправляемых ресурсов; поэтому, несмотря на то, что MarshalByValueComponent делает допуски для неуправляемых ресурсов, этим конкретным реализациям нет необходимости и, следовательно, они могут отказаться от завершения.
(То, что авторы .NET позаботятся о том, чтобы подавить финализацию для тех типов, которые обычно занимают больше всего памяти, говорит о важности этой практики в целом для финализуемых типов.)
Несмотря на то, что эти детали все еще недостаточно документированы с момента создания .NET Framework (почти 8 лет назад), довольно удивительно (что вы по сути оставлены на своих собственных устройствах, чтобы просеивать хотя и противоречивые, неоднозначные материалы для размещения время от времени это расстраивает, но обеспечивает более полное понимание структуры, на которую мы опираемся каждый день).
После долгих чтений вот мое понимание:
Если объект требует завершения, он может занимать память дольше, чем нужно - вот почему: a) Любой тип, который определяет деструктор (или наследует от типа, который определяет деструктор) считается финализуемым; б) При выделении (до запуска конструктора) указатель помещается в очередь финализации; c) Для финализуемого объекта обычно требуется 2 коллекции для восстановления (вместо стандартного 1); d) Подавление финализации не приводит к удалению объекта из очереди финализации (как сообщает! FinalizeQueue в SOS)
Эта команда вводит в заблуждение; Знание того, какие объекты находятся в очереди финализации (само по себе), не помогает; Было бы полезно знать, какие объекты находятся в очереди завершения и все еще требуют завершения (есть ли команда для этого?)
Подавление финализации немного выключает заголовок объекта, указывая среде выполнения, что ему не нужно вызывать свой финализатор (не нужно перемещать очередь FReachable); Он остается в очереди Финализации (и по-прежнему сообщается! FinalizeQueue в SOS)
Все классы DataTable, DataSet, DataView имеют корни в MarshalByValueComponent, финализируемом объекте, который может (потенциально) обрабатывать неуправляемые ресурсы
- Поскольку DataTable, DataSet и DataView не представляют неуправляемые ресурсы, они подавляют завершение в своих конструкторах
- Хотя это необычный шаблон, он освобождает вызывающего абонента от необходимости беспокоиться о вызове Dispose после использования
- Это, а также тот факт, что DataTable потенциально могут совместно использоваться различными DataSets, вероятно, поэтому DataSets не заботятся о том, чтобы избавиться от дочерних DataTables
- Это также означает, что эти объекты появятся под! FinalizeQueue в SOS
- Тем не менее, эти объекты должны быть восстановлены после одной коллекции, как и их не финализируемые аналоги
4 (новые ссылки):
Оригинальный ответ:
Есть много вводящих в заблуждение и, как правило, очень плохих ответов на этот вопрос - любой, кто приземлился здесь, должен игнорировать шум и внимательно читать ссылки ниже.
Без сомнения, Dispose должен вызываться для любых объектов Finalizable.
DataTables являются Завершается.
Calling Dispose значительно ускоряет восстановление памяти.
MarshalByValueComponent вызывает GC.SuppressFinalize (this) в его Dispose () - пропустить это означает, что нужно ждать десятки, если не сотни коллекций Gen0, прежде чем память будет освобождена:
С этим базовым пониманием завершения мы
уже можно вывести некоторые очень важные
вещи:
Во-первых, объекты, которые требуют доработки
жить дольше, чем объекты, которые не делают.
На самом деле они могут жить намного дольше.
Например, предположим, что объект
находится в gen2 должен быть завершен.
Завершение будет запланировано, но
объект все еще находится в gen2, поэтому он будет
не будет повторно собран до следующего
коллекция gen2 происходит. Это может быть
очень долго, и, на самом деле,
если дела пойдут хорошо, это будет
долгое время, потому что коллекции gen2
являются дорогостоящими, и поэтому мы хотим, чтобы они
случается очень редко. Старшая
объекты, нуждающиеся в доработке, могут
придется ждать десятки, если нет
сотни коллекций gen0 перед
их пространство освоено.
Во-вторых, объекты, которые требуют доработки
наносить побочный ущерб. Поскольку
внутренние указатели объекта должны оставаться
действителен, не только объекты
нуждаюсь в доработке
в памяти, но все объект
относится, прямо и косвенно,
также останется в памяти. Если огромный
дерево объектов было закреплено
один объект, который требуется
доработка, потом все дерево
задержался бы, потенциально надолго
время, как мы только что обсудили. это
Поэтому важно использовать финализаторы
экономно и размещать их на объектах
которые имеют как можно меньше внутреннего объекта
указатели по возможности. В дереве
Пример, который я только что привел, вы можете легко
избежать проблемы, перемещая
ресурсы, нуждающиеся в доработке до
отдельный объект и хранение
ссылка на этот объект в корне
дерева. С этим скромным изменением
только один объект (надеюсь, хороший
маленький объект) будет задерживаться и
стоимость завершения сведена к минимуму.
Наконец, объекты, требующие доработки
создать работу для финализатора потока.
Если ваш процесс завершения
сложный, единственный
Финализатор потока будет тратить
много времени на выполнение этих шагов,
что может вызвать отставание в работе и
поэтому заставлять больше объектов задерживаться
жду доработки. Следовательно,
жизненно важно, чтобы
финализаторы делают так мало работы, как
возможный. Помните также, что хотя
все указатели объектов остаются в силе
во время завершения, это может быть
случай, когда эти указатели приводят к
объекты, которые уже были
доработан и поэтому может быть меньше
чем полезно. Как правило, безопаснее
избегать следования указателям на объекты в
код завершения, хотя
указатели действительны. Безопасный, короткий
Путь к коду завершения - лучший.
Возьмите его от кого-то, кто видел сотни МБ не ссылочных DataTables в Gen2: это чрезвычайно важно и совершенно пропущено ответами в этой теме.
Ссылка:
1 -
http://msdn.microsoft.com/en-us/library/ms973837.aspx
2 -
http://vineetgupta.spaces.live.com/blog/cns!8DE4BDC896BEE1AD!1104.entry
http://www.dotnetfunda.com/articles/article524-net-best-practice-no-2-improve-garbage-collector-performance-using-finalizedispose-pattern.aspx
3 -
http://codeidol.com/csharp/net-framework/Inside-the-CLR/Automatic-Memory-Management/