Отправляет email-рассылки с помощью сервиса Sendsay
  Все выпуски  

DataSet и метод Dispose(). Вызывать или нет?


Информационный Канал Subscribe.Ru

Профессинальное программирование на .NET


Выпуск 7

Здравствуйте, уважаемые подписчики!

Сайт рассылки - DeveloperGuru.NET. Не стеснейтесь задавать вопросы и писать отзывы на сайте или на email.

.NET. Диспозать или не диспозать? Вот в чем вопрос! (Dispose и DataSet)

Надеюсь, что все знают, зачем предназначен интерфейс IDisposable и для чего надо вызывать метод Dispose этого интерфейса. Однако, хочу очень кратко напомнить, на случай, если кто-то забыл (если кто-то слышыт про Dispose впервые, то советую почитать соответствующую литературу).

Итак, если .NET класс не является оболочкой для неуправляемого ресурса (например, connection к базе данных, handle файла и т.п.), то программисту не надо заботиться о его уничтожении. Для этого предназначен сборщик мусора. Если же класс использует неуправляемые ресурсы, то необходим механизм их освобождения. Для этого предназначен интерфейс IDisposable и его метод Dispose. Этот метод следует вызывать для освобождение неуправляемых ресурсов. Кроме того, как правило, переопределяется метод Finalize (для C# это делается созданием метода с синтаксисом деструктора), в котором, также, происходит освобождения неуправляемых ресурсов на случай, если явно вызвать Dispose забыли. Явный вызов Dispose намного предпочтительнее, так как, во-первых, Finalize вызывается сборщиком мусора, который может начать работу через довольно длительное время, во-вторых, объекты, для которых вызывается Finalize, помещаются в специальную очередь завершения и существуют до следующей сборки мусора (т.е. занимают память дополнительное время). В методе Dispose, кроме освобождения неуправляемых ресурсов, вызывается GC.SuppressFinalize(), который сообщает сборщику мусора, что вызывать Finalize для этого объекта не надо.

Весь этот механизм очень подробно описан в книге Джефри Рихтера.

В принципе, если класс имплементирует IDisposable, то надо вызывать Dispose. Это однозначно для таких классов, как SqlConnection и SqlDataReader. Однако, насчет DataSet часто возникают вопросы.

Итак, DataSet имплементирует интерфейс IDisposable. Следовательно, правильно было бы вызывать метод Dispose при завершении работы с датасетом.

Для чего нужен Dispose? Для освобождения неуправляемых ресурсов. Память, занимаемая объектом, освобождается сборщиком мусора независимо от вызова Dispose. А какие неуправляемые ресурсы использует датасет? Никаких. Дело в том, что имплементация IDisposable достается ему в наследство от MarshalByValueComponent.

Что же делает Dispose в случае датасета? Вызывает GC.SuppressFinalize(), который сообщает сборщику мусора, что метод Finalize вызывать не надо. Больше ничего.

Значит, если мы не вызовем Dispose, ничего плохого не произойдет, т.к. никаких неуправляемых ресурсов освобождать не надо? Не совсем так. Дело в том, что тогда сборщик мусора вызовет метод Finalize и переместит объект в очередь завершения, что продлит время жизни объекта до следующей сборки мусора.

Получается, что сторонники вызова Dispose правы. Но давайте рассмотрим DataTable. Он, тоже, наследуется от MarshalByValueComponent. Если следовать нашей логике, необходимо вызывать Dispose и для каждого DataTable в DataSet. Я не знаю никого, кто так делает. А вы? Вызывать Dispose для DataSet и не вызывать для DataTable, как минимум, нелогично, т.к. объектов DataTable больше.

Что же делать? Вызывать или не вызывать? Не вызывать! Дело в том что в конструкторах DataSet и DataTable вызывается GC.SuppressFinalize() и, следовательно, сборщик мусора не будет вызывать Finalize!

Логическая задача

Как всегда, сначала, ответ на задачу из предыдущего выпуска.

Очевидно, вероятность того, что автомобиль находится за любой дверью равна 1/3 для каждой двери. Т.е., когда вы выбираете определенную дверь, то вероятность выигрыша 1/3, а вероятность того, что автомобиль за одной из двух других дверей равна 2/3. То, что ведущий открывает одну из 2-х не выбранных вами дверей ничего не меняет в распределении вероятности, т.е. на 2 невыбранных двери приходится 2/3 вероятности выигрыша. Поскольку за открытой дверью автомобиля нет, вероятность того, что автомобиль находится за невыбранной вами дверью равна 2/3. Т.е., если вы измените решение, то вероятность выигрыша возрастет в 2 раза (2/3 вместо 1/3).

Единственным, кто дал совершенно правильный ответ, был Alexander Makhaev. Поздравляю!

Теперь, новая логическая задача.

Четырем туристам нужно ночью переправиться через реку по подвесному мосту. Мост уже сильно обветшал, в настиле есть дыры, и он может выдержать одновременно не более двух человек (если на мосту окажется более двух человек, мост обрушится). Туристам нужно освещать дорогу фонариком - иначе они могут провалиться в дыру в настиле моста и погибнуть, но у них есть только один фонарик. Эти четыре человека передвигаются с разной скоростью. Адам может перейти мост за одну минуту, Лари - за две минуты, Эджу нужно пять минут, самый медлительный из всех Боно - ему потребуется десять минут, чтобы перейти мост. Ровно через семнадцать минут мост обрушится. Каким образом все четверо могут успеть через него переправиться? (Добавлю, что фонарик нельзя перебросить и т.п. Т.е. он может быть перенесен на другую сторону реки только кем-то из туристов.)

По некоторым сведениям, эта задача применялась на собеседованиях в Microsoft. Требовалось решить ее за 5 минут. Этого времени вполне достаточно. Те, кому я задавал эту задачу, рано или поздно решали ее, но для меня остается загадкой, что некоторые из них делали в течение 20 - 60 минут. Ответ в следущем выпуске рассылки, но самые нетерпеливые могут посмотреть и проверить свой ответ на сайте (Логическая задача про четырех туристов и мост). Там же есть маленькая подсказка. Если задача не решается в течение 10 - 15 минут - воспользуйтесь ею.


На этом все. Желаю приятного программирования.


Технологический партнер рассылки:
PARKING.RU.
Качественный ВИРТУАЛЬНЫЙ ХОСТИНГ на платформе Windows (™): поддержка .NET-приложений, управление сайтом, аренда бизнес-приложений, сертифицированные специалисты.



Вопросы? Пожелания? Пишите: author@developerguru.net

Subscribe.Ru
Поддержка подписчиков
Другие рассылки этой тематики
Другие рассылки этого автора
Подписан адрес:
Код этой рассылки: comp.soft.prog.gurudotnet
Архив рассылки
Отписаться
Вспомнить пароль

В избранное