Какие объекты класса C# получают неуправляемые ресурсы? Есть ли список?

Я работал над сериализацией и десериализацией объекта класса с использованием XML, когда натолкнулся на этот пост в блоге, который показывает, как это сделать на Windows Phone 7 с использованием изолированной области хранения. Windows Phone 7 - это платформа, для которой я разрабатываю:

В этом примере единственным объектом, для которого он явно вызывает Dispose(), является объект TextReader. Я посмотрел объект TextReader на MSDN и обнаружил, что в документации сказано следующее:

Освобождает неуправляемые ресурсы, используемые TextReader, и дополнительно освобождает управляемые ресурсы.

Поэтому я предполагаю, что причина, по которой он это делает, заключается в немедленном высвобождении неуправляемых ресурсов, полученных объектом TextReader. Мне бы не пришло в голову сделать это, если бы не его пост в блоге. Очевидно, что я не хочу начинать вызывать Dispose() для каждого видимого объекта, так что является хорошим эмпирическим правилом, по крайней мере, для расследования, когда конкретный объект должен вызывать Dispose() для него или нет? Есть ли какие-то рекомендации для этого или списка где-нибудь, по крайней мере, популярных объектов.NET, которые требуют такой специальной обработки?

4 ответа

Решение

Очевидно, я не хочу начинать вызывать Dispose() для каждого объекта в

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

В общем, любой объект, который реализует IDisposable следует утилизировать, как только вы закончите с ним, как правило, используя using заявление.

Большинство объектов, которые не имеют неуправляемых ресурсов, не реализуют IDisposable (и не имеют Dispose() методы), так что вам не о чем беспокоиться.

Единственными исключениями являются базовые классы, которые реализуют IDisposable в случае, если некоторые производные реализации имеют что-то, чтобы избавиться (например, IEnumerator, Component, или же TextReader).
Однако не всегда очевидно, какие конкретные реализации необходимо утилизировать (и они могут измениться в любое время), поэтому вы всегда должны их утилизировать.

Очевидно, что я не хочу начинать вызывать Dispose() для каждого видимого объекта, так что является хорошим эмпирическим правилом, по крайней мере, для расследования, когда конкретный объект должен вызывать Dispose() для него или нет?

Это не является проблемой. Компилятор не позволит вам вызвать Dispose() для объекта, который его не реализует.

И вы должны вызывать Dispose() для каждого объекта, который его реализует (что он будет делать через IDisposable интерфейс). Это руководство, которому вы должны следовать. На самом деле, это то, что это означает, когда объект реализует IDisposable: что у него есть неуправляемые ресурсы, которые должны быть освобождены.

Это станет гораздо менее трудоемким делом, если вы просто закроете создание и использование объектов в using утверждение, например:

using (DisposableObject obj = new DisposableObject(...))
{
    obj.DoWork();
} // obj.Dispose() is automatically called here, even if an exception is thrown

На самом деле вы должны избавиться от объектов, которые реализуют IDisposable.

Стандартный способ сделать это в отличие от прямого вызова Dispose():

using(AnyIDisposable obj = ...)
{
    // work with obj here
}
//The Dispose() method is already called here

Пожалуйста, поправьте меня, если я ошибаюсь. Что касается чтения / понимания, все предложения.NET Framework являются управляемыми (на взгляд программиста, хотя при нижележащем использовании они могут использовать неуправляемый код), поэтому теоретически вам не нужно вызывать Dispose() или использовать, потому что gc будет Береги себя. Но иногда очень рекомендуется их использовать, см. IDisposable Interface и Какие управляемые классы в.NET Framework выделяют (или используют) неуправляемую память? и http://blogs.msdn.com/b/kimhamil/archive/2008/11/05/when-to-call-dispose.aspx

РЕДАКТИРОВАТЬ: (вы правы noob) Для пояснения я добавлю ответ Nayan из интерфейса IDisposable

Рекомендуется вызывать утилизировать или использовать, когда:

1.В вашем классе много объектов и есть много перекрестных ссылок. Несмотря на то, что все это управляется, GC может быть не в состоянии восстановить память из-за живых ссылок. У вас есть шанс (кроме написания финализатора) распутать ссылки и разбить ссылки так, как вы их прикрепили. Следовательно, вы помогаете ГК восстановить память.

2. У вас есть несколько открытых потоков, которые живы до тех пор, пока объект класса не умрет. Несмотря на то, что такими реализациями файлов / сети и т. Д. Управляют, они углубляются в дескрипторы в режиме Win32. Следовательно, вы получаете возможность написать метод Dispose, где вы можете закрыть потоки. То же самое верно для объектов GDI и некоторых других.

3. Вы пишете класс, который использует неуправляемые ресурсы, и вы хотите отправить сборку третьим лицам. Вам лучше использовать одноразовый шаблон, чтобы убедиться, что вы можете освободить ручки, чтобы избежать утечки.

4.Ваш класс реализует множество обработчиков событий и подключает их к событиям. Объекты классов, которые представляют события, такие как Form и т. Д., Не будут освобождены GC, так как реализации, локальные для вашего класса (возможно), все еще подключены к этим событиям. Вы можете отцепить эти обработчики событий в Dispose; снова помогает GC.

Другие вопросы по тегам