Ключевое слово C# USING - когда и когда его не использовать?
Я хотел бы знать, когда я должен и не должен оборачивать вещи в блок USING.
Из того, что я понимаю, компилятор переводит это в try / finally, где finally вызывает Dispose() для объекта.
Я всегда использую ИСПОЛЬЗОВАНИЕ вокруг соединений с базой данных и доступа к файлам, но это скорее привычка, чем 100% понимание. Я знаю, что вы должны подробно (или с использованием) использовать объекты Dispose(), которые контролируют ресурсы, чтобы гарантировать, что они высвобождаются мгновенно, а не всякий раз, когда CLR чувствует, что это так, но именно здесь мое понимание нарушается.
Не утилизируются ли IDisposable, когда они выходят за рамки?
Нужно ли использовать ИСПОЛЬЗОВАНИЕ только тогда, когда мой объект использует Dispose, чтобы привести себя в порядок?
Спасибо
Изменить: я знаю, что есть несколько других постов по ключевому слову USING, но меня больше интересуют ответы, касающиеся CLR и точно, что происходит внутри
Эндрю
3 ответа
Нет, IDisposable
предметы не выбрасываются, когда они выходят за рамки. Именно по этой причине нам нужно IDisposable
- для детерминированной очистки.
В конце концов они будут собирать мусор, и если будет финализатор, он будет (возможно) вызываться - но это может занять много времени в будущем (не подходит для пулов соединений и т. Д.). Сборка мусора зависит от нагрузки на память - если ничто не требует дополнительной памяти, нет необходимости запускать цикл GC.
Интересно (возможно), есть некоторые случаи, когда "использование" является болью - когда класс-нарушитель создает исключение для Dispose()
иногда. WCF является нарушителем этого. Я обсуждал эту тему (с простым обходным путем) здесь.
В основном - если класс реализует IDisposable
и у вас есть экземпляр (т. е. вы создали его или что-то еще), ваша задача - обеспечить его удаление. Это может означать "использование" или передавать его другому фрагменту кода, который принимает на себя ответственность.
Я на самом деле видел отладочный код типа:
#if DEBUG
~Foo() {
// complain loudly that smoebody forgot to dispose...
}
#endif
(где Dispose
звонки GC.SuppressFinalize
)
"Не удаляются ли IDisposables, когда они выходят за рамки?"
Нет. Если объект IDisposable является финализуемым, что не одно и то же, тогда он будет завершен, когда будет собран мусор.
Который может быть скоро или почти никогда.
Книга Джеффа Рихтера по C#/CLR очень хороша во всем этом, и книга Руководства по разработке инфраструктуры также полезна.
Нужно ли использовать ИСПОЛЬЗОВАНИЕ только тогда, когда мой объект использует Dispose, чтобы привести себя в порядок?
Вы можете использовать "использование" только тогда, когда объект реализует IDisposable. Компилятор будет возражать, если вы попытаетесь сделать иначе.
Чтобы добавить к другим ответам, вы должны использовать using
(или явное удаление) всякий раз, когда объект содержит какие-либо ресурсы, кроме управляемой памяти. Примерами могут быть такие вещи, как файлы, сокеты, соединения с базой данных или даже дескрипторы рисования GDI.
Сборщик мусора в конечном итоге завершит работу с этими объектами, но только в неустановленное время в будущем. Вы не можете рассчитывать на то, что это произойдет своевременно, и вы, возможно, исчерпали этот ресурс за это время.