IDisposable, действительно ли это важно - PullRequest
11 голосов
/ 17 марта 2010

Исходя из C / C ++ давным-давно, у меня все еще есть привычка следить за тем, чтобы все ресурсы были очищены правильно. Я всегда гарантирую, что Dispose вызывается для классов IDisposable, и внедряю шаблоны Dispose в мои классы, содержащие одноразовые объекты.

Однако в моем окружении я более или менее единственный, кто делает это. Другие просто не понимают, что я делаю, и думают, что мой код сложнее понять.

Они просто создают соединения с базой данных, открывают потоки и т. Д., Не вызывая Close или Dispose. Иногда они устанавливают для локальной переменной или переменной-члена значение «Ничего» в конце метода (угадайте их фон).

Моя проблема в том, что их код работает так же хорошо, как и мой. Код, который со временем создает тысячи объектов подключения к базе данных, просто работает.

Итак, игнорируя любые аргументы о корректности кода, следуя рекомендациям и т. Д., действительно ли значение IDiposable ?

Кто-нибудь на самом деле исчерпал ресурсы из-за того, что не выбрасывал объекты?

Edit: Спасибо за все ответы. Интересно видеть, что у некоторых людей были проблемы, когда они не выбрасывали. Хотя это кажется редким явлением, и я предполагаю, что GC / JIT хорошо справляется с поддержанием использования ресурсов в нормальных условиях.

Из-за этого ни мои коллеги, ни я не изменю своего поведения, но приятно быть правым.

Ответы [ 9 ]

26 голосов
/ 17 марта 2010

Да, я максимально увеличил количество Oracle-курсоров при циклическом отображении объекта подключения, например, потому что я забыл закрыть программу чтения команд - это было только 100 циклов на одно соединение, и мне нужно было поддерживать что, возможно, сотни соединений делают это одновременно.

Ваши коллеги-разработчики должны научиться использовать синтаксис using() { ... } , если они не могут быть обеспокоены тем, чтобы самостоятельно закрывать какие-либо неуправляемые ресурсы. В любом случае, это хорошая практика, и вам следует использовать ее, поскольку вы сами можете забыть поместить свои Dispose() вызовы в предложение finally {}, чтобы действительно очистить их в случае возникновения необработанного исключения.

Если вы не можете завоевать их сердца - измените свое мнение - создайте тесты, которые нарушают их код, максимально используя ресурсы, которые они не очищают, - а затем покажите, что «исправить» просто и легко, и позволяет их код должен быть гораздо более масштабируемым. Или просто покажите это своему боссу и скажите им, что это позволит ему / ей продавать продукт в виде новой версии с более высокой степенью масштабируемости :) Ваши коллеги-разработчики будут проинструктированы делать это все время в будущем, надеюсь, и вы также будете в почете.

5 голосов
/ 17 марта 2010

Да, это важно. Когда объект реализует IDisposable, он явно указывает, что он содержит ресурсы, которые должны быть освобождены, когда объект больше не нужен.

Большинство все равно будет очищать свои ресурсы, когда объект будет завершен, но финализация не является детерминированной и не может использоваться для управления ресурсами.

Простая упаковка объявлений переменных в блоке using(...) облегчает правильную утилизацию.

4 голосов
/ 17 марта 2010

Некоторые из этих ресурсов, например дескрипторы, являются ограниченным ресурсом для всей системы, поэтому, если ваше приложение не выпускает эти другие приложения или даже ОС может пострадать. Взгляните на последнюю статью Марка Руссиновича в статье о расширении границ серии Windows для примера.

3 голосов
/ 17 марта 2010

Да, я также столкнулся с проблемой с объектами подключения к базе данных Oracle, которые не удаляются.

Проблема Майка Атласа, описанная выше, плохая, но, по крайней мере, было ясно, что происходит не так.Проблема, с которой мы столкнулись, заключалась в том, что время от времени под большой нагрузкой сайт начинал выдавать ошибки, когда мы пытались открыть соединение, но к тому времени, когда мы смотрели на систему, все это очищалось (потому что сборщик garabe очистилобъекты и освободил пул соединений).Воспроизведение было очень трудным, пока я не просмотрел код и не заметил, что соединение не закрывалось в случае ошибки, изменение значения на using устранило всю проблему.

Короткий ответ: если объект предпринимает усилия для реализации IDisposable, это происходит по какой-то причине, поэтому ВСЕГДА избавьтесь от него, когда закончите, в идеале с помощью оператора using.Не становитесь умными или хитрыми с утилизацией иногда, но не в других случаях, когда вы не думаете, что вам нужно бла-бла-бла.Просто делайте то, что работает каждый раз.

Короче и более удовлетворительный ответ: вы правы, а ваши коллеги - дебилы, которые не знают, что делают.

1 голос
/ 17 марта 2010

Отсутствие (или закрытие) соединений с базой данных в конечном итоге укусит вас, да. Я видел, как это случилось.

0 голосов
/ 20 марта 2010

Да, да, да , имеет значение.

Недавно я профилировал приложение, которое никогда не профилировалось. Это просто приложение Winforms, ничего страшного, правда?

Неправильно.

Не реализовав IDisposible и не отменяя ссылки на обработчики событий, приложение теряло память как сито.

.NET Framework не освобождает вас от необходимости убирать за собой, он просто снижает вероятность того, что вы что-то сломаете, если этого не сделаете.

Потратьте час, профилируйте свою заявку с помощью ANTS Profiler . Это бесплатная пробная версия. Если вы не видите утечек памяти, продолжайте свой путь. Если вы это сделаете, то это потому, что вы полагались на .NET Framework в качестве опоры.

0 голосов
/ 17 марта 2010

Помимо очевидных (уже упомянутых) случаев истощения ресурсов, еще одно преимущество IDisposable заключается в том, что, поскольку он гарантирует, что Dispose () вызывается при выходе из блока using, вы можете использовать его для любых вещей, даже вещи, которые не просто «выполняют операции с ресурсом ОС».

Таким образом, это похоже на замену блоков Ruby для бедняков или на один небольшой пример использования макросов Lisp.

0 голосов
/ 17 марта 2010

Отсутствие размещенных в базе данных объектов IDisposable - это надежный и эффективный способ создания исключений OutOfMemoryException в средах.

DataSet реализует IDisposable, и я прочитал, что нет необходимости вызывать Dispose, потому что объекты, которые должны быть расположены для набора данных, создаются только во время разработки (дизайнером Visual Studio). Я никогда не видел OOM из неразмещенных наборов данных (просто OOM из огромных DataSets)

0 голосов
/ 17 марта 2010

У меня был случай, о котором я, к сожалению, не помню деталей, но это были какие-то многослойные потоки. Поток файла нижнего уровня иногда закрывался до сброса средства форматирования текста верхнего уровня, что приводило к потере последнего вывода, записанного в средство форматирования текста.

...