Возможно ли это, действительно ли это имеет значение

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

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

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

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

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

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

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

Ни мои коллеги, ни я не изменим поведение из-за этого, но было бы хорошо быть правым.

Ответ 1

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

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

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

Ответ 2

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

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

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

Ответ 3

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

Ответ 4

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

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

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

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

Ответ 5

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

Ответ 6

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

Ответ 7

Не удалять базы данных, выпущенные IDisposable, является надежным и эффективным способом генерации OutOfMemoryExceptions в средах.

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

Ответ 8

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

Таким образом, он как бедный человек заменяет блоки Ruby или один малый вариант использования макросов Lisp.

Ответ 9

Да, да, да. Это важно.

Я недавно профилировал приложение, которое никогда не было профилировано. Это просто приложение Winforms, неважно, правильно?

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

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

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

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