С# ИСПОЛЬЗОВАНИЕ ключевого слова - когда и когда не использовать его?

Я хотел бы знать, когда я должен и не должен обматывать вещи в блоке USING.

Из того, что я понимаю, компилятор переводит его в try/finally, где, наконец, вызывает Dispose() на объекте.

Я всегда использую ИСПОЛЬЗОВАНИЕ вокруг соединений с базой данных и доступа к файлам, но это больше по привычке, а не на 100% -ном понимании. Я знаю, что вы должны эксплицировать (или использовать) объекты Dispose(), которые управляют ресурсами, чтобы гарантировать, что они будут выпущены мгновенно, а не всякий раз, когда CLR чувствует себя так, но это то, где мое понимание ломается.

Являются ли IDisposables не удалены, когда они выходят из области видимости?

Нужно ли мне использовать ИСПОЛЬЗОВАНИЕ, когда мой объект использует Dispose для упорядочивания?

Спасибо

Изменить: я знаю, что есть несколько других сообщений по ключевому слову USING, но меня больше интересуют ответы, связанные с CLR и точно, что происходит внутри.

Эндрю

Ответ 1

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

В конечном итоге они получат сбор мусора, и если есть финализатор, он будет (возможно) называться - но это может быть долгое время (не подходит для пулов соединений и т.д.). Сбор мусора зависит от давления памяти - если ничего не требуется для дополнительной памяти, нет необходимости запускать цикл GC.

Интересно (возможно) есть случаи, когда "использование" - это боль - когда класс-нарушитель иногда вызывает исключение на Dispose(). WCF является нарушителем этого. Я обсуждал эту тему (с простым обходным решением) здесь.

В принципе - если класс реализует IDisposable, и у вас есть экземпляр (т.е. вы его создали или что-то еще), ваша работа должна гарантировать, что он будет удален. Это может означать "использование", или это может означать передачу его другому фрагменту кода, который берет на себя ответственность.

Я действительно видел код отладки типа:

#if DEBUG
    ~Foo() {
        // complain loudly that smoebody forgot to dispose...
    }
#endif

(где Dispose вызывает GC.SuppressFinalize)

Ответ 2

"Являются ли IDisposables не удалены, когда они выходят за рамки?"

Нет. Если объект IDisposable является финализированным, что не то же самое, тогда он будет завершен, когда будет собран мусор.

Что может быть скоро или может быть почти никогда.

Книга Джеффа Рихтера С#/CLR очень хороша во всем этом, а книга рекомендаций по дизайну Framework также полезна.

Нужно ли мне использовать ИСПОЛЬЗОВАНИЕ, когда мой объект использует Dispose для аккуратности себя?

Вы можете использовать только "использование", когда объект реализует IDisposable. Компилятор будет возражать, если вы попытаетесь сделать иначе.

Ответ 3

Чтобы добавить к другим ответам, вы должны использовать using (или явный Dispose) всякий раз, когда объект содержит любые ресурсы, кроме управляемой памяти. Примерами могут быть такие файлы, как файлы, сокеты, соединения с базой данных или даже ручки рисования GDI.

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