DataSet и DataTable оба реализуют IDisposable, поэтому, согласно общепринятым рекомендациям, я должен вызывать их методы Dispose ().
Однако из того, что я прочитал, DataSet и DataTable на самом деле не имеют никаких неуправляемых ресурсов, поэтому Dispose () на самом деле ничего не делает.
Кроме того, я не могу просто использовать, using(DataSet myDataSet...)
потому что DataSet имеет коллекцию DataTables.
Поэтому, чтобы быть в безопасности, мне нужно было бы перебрать myDataSet.Tables, избавиться от каждого из DataTables, а затем избавиться от DataSet.
Итак, стоит ли вызывать Dispose () для всех моих DataSets и DataTables?
Приложение:
Для тех из вас, кто считает, что DataSet должен быть утилизирован: в общем, шаблон для утилизации должен использоваться using
или try..finally
, потому что вы хотите гарантировать, что будет вызван Dispose ().
Тем не менее, это становится ужасно быстро для коллекции. Например, что вы делаете, если один из вызовов Dispose () выдал исключение? Вы проглатываете это (что «плохо»), чтобы вы могли продолжить распоряжаться следующим элементом?
Или вы предлагаете мне просто вызвать myDataSet.Dispose () и забыть об удалении DataTables в myDataSet.Tables?
Ответы:
Вот несколько обсуждений, объясняющих, почему Dispose не является необходимым для DataSet.
Распорядиться или не распорядиться? :
Следует ли вызывать Dispose для объектов DataTable и DataSet? включает в себя некоторые объяснения от MVP:
Понимание метода Dispose и наборов данных? имеет комментарий от авторитета Скотта Аллена:
Таким образом, существует общее мнение, что в настоящее время нет веских причин для вызова Dispose для DataSet.
источник
using
вызывается ли он явно или неявно с помощью блока, решать вам.Обновление (1 декабря 2009 г.):
Я хотел бы изменить этот ответ и признать, что первоначальный ответ был ошибочным.
Первоначальный анализ действительно применяется к объектам, которые требуют доработки, и точка зрения, что практики не должны приниматься на поверхности без точного, глубокого понимания, остается в силе.
Однако оказывается, что DataSets, DataViews, DataTables подавляют финализацию в своих конструкторах - вот почему вызов Dispose () для них явно ничего не делает.
Предположительно, это происходит потому, что у них нет неуправляемых ресурсов; поэтому, несмотря на тот факт, что MarshalByValueComponent учитывает неуправляемые ресурсы, эти конкретные реализации не нуждаются и поэтому могут отказаться от завершения.
(То, что авторы .NET позаботятся о том, чтобы подавить финализацию для тех типов, которые обычно занимают больше всего памяти, говорит о важности этой практики в целом для финализуемых типов.)
Несмотря на то, что эти детали все еще недостаточно документированы с момента создания .NET Framework (почти 8 лет назад), довольно удивительно (что вы по сути оставлены на своих собственных устройствах, чтобы просеивать хотя и противоречивые, неоднозначные материалы, чтобы собрать воедино кусочки). иногда разочаровывает, но обеспечивает более полное понимание структуры, на которую мы полагаемся каждый день).
После большого чтения, вот мое понимание:
Если объект требует финализации, он может занимать память дольше, чем нужно - вот почему: a) любой тип, который определяет деструктор (или наследует от типа, который определяет деструктор), считается финализуемым; б) При выделении (до запуска конструктора) указатель помещается в очередь финализации; c) Для финализуемого объекта обычно требуется 2 коллекции (вместо стандартной 1); d) Подавление финализации не удаляет объект из очереди финализации (как сообщает! FinalizeQueue в SOS) Эта команда вводит в заблуждение; Знание того, какие объекты находятся в очереди завершения (само по себе), не помогает; Было бы полезно знать, какие объекты находятся в очереди завершения и все еще требуют завершения (есть ли команда для этого?)
Подавление завершения выключает немного в заголовке объекта, указывая среде выполнения, что ему не нужно вызывать свой Finalizer (не нужно перемещать очередь FReachable); Он остается в очереди Финализации (и продолжает сообщаться! FinalizeQueue в SOS)
Классы DataTable, DataSet, DataView имеют корни в MarshalByValueComponent, финализируемом объекте, который может (потенциально) обрабатывать неуправляемые ресурсы.
4 (новые ссылки):
Оригинальный ответ:
Есть много вводящих в заблуждение и вообще очень плохих ответов на этот вопрос - любой, кто приземлился здесь, должен игнорировать шум и внимательно прочитать ссылки ниже.
Без сомнения, Dispose должен вызываться для любых объектов Finalizable.
DataTables являются Завершаемыми.
Вызов Dispose значительно ускоряет восстановление памяти.
MarshalByValueComponent вызывает GC.SuppressFinalize (this) в своем Dispose () - пропустить это означает, что нужно ждать десятки, если не сотни коллекций 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-производительность с помощью-finalizedispose-pattern.aspx
3 - http://codeidol.com/csharp/net-framework/Inside-the-CLR/Automatic-Memory-Management/
источник
TableAdapter
с?Вы должны предположить, что он делает что-то полезное, и вызывать Dispose, даже если он ничего не делает в текущем. Воплощения NET Framework, нет никаких гарантий, что так будет и в будущих версиях, что приведет к неэффективному использованию ресурсов.
источник
DataTable
это не запечатано - не так уж важно, когда вы делаетеnew DataTable
, но довольно важно, когда принимаетеDataTable
в качестве аргумента или в результате вызова метода.Даже если у объекта нет неуправляемых ресурсов, утилизация может помочь GC, разбивая графы объектов. В общем, если объект реализует IDisposable, тогда должен быть вызван Dispose ().
Делает ли Dispose () что-то или нет, зависит от данного класса. В случае DataSet реализация Dispose () наследуется от MarshalByValueComponent. Он удаляет себя из контейнера и вызывает событие Disposed. Исходный код ниже (разобран с помощью .NET Reflector):
источник
Вы сами создаете таблицы данных? Потому что перебирать дочерние элементы любого объекта (как в DataSet.Tables) обычно не нужно, так как задача родителя - распоряжаться всеми дочерними элементами.
Как правило, правило таково: если вы создали его, и он реализует IDisposable, утилизируйте его. Если вы НЕ создали его, то НЕ утилизируйте его, это работа родительского объекта. Но у каждого объекта могут быть свои особые правила, проверьте документацию.
Для .net 3.5, он явно говорит «Утилизируйте его, когда он больше не используется», так что я бы так и сделал.
источник
Я вызываю dispose в любое время, когда объект реализует IDisposeable. Это там по причине.
DataSets может быть огромным занятием памяти. Чем раньше они могут быть помечены для очистки, тем лучше.
Обновить
Прошло 5 лет с тех пор, как я ответил на этот вопрос. Я все еще согласен с моим ответом. Если есть метод dispose, его следует вызывать, когда вы закончите с объектом. Интерфейс IDispose был реализован по причине.
источник
Если ваше намерение или контекст этого вопроса на самом деле является сборкой мусора, то вы можете установить для наборов данных и таблиц данных значение null в явном виде или использовать ключевое слово using и позволить им выйти из области видимости. Утилизация не так много, как сказал ранее Tetraneutron. GC будет собирать объекты набора данных, на которые больше нет ссылок, а также те, которые находятся вне области видимости.
Я действительно хочу, чтобы НАСТОЯЩИЕ люди заставляли голосовать, чтобы написать комментарий, прежде чем опровергнуть ответ.
источник
Наборы данных реализуют IDisposable основательно MarshalByValueComponent, который реализует IDisposable. Поскольку наборы данных управляются, нет никакой реальной выгоды от вызова утилизации.
источник
Попробуйте использовать функцию Clear (). Это прекрасно работает для меня для утилизации.
источник
источник