2016-01-05 20 views
0

I recently learned как использовать Microsoft.VisualBasic.FileIO.TextFieldParser для анализа ввода текста. В приведенном примере для меня, TextFieldParser вызываются с помощью ключевого слова usingКак мы можем различать управляемые и неуправляемые ресурсы в C#? Является ли TextFieldParser неуправляемым?

using (var parser = new Microsoft.VisualBasic.FileIO.TextFieldParser(new StringReader(str))) 

Хотя после somefurtherresearches, я заметил, что практика использования using ключевого слова для TextFieldParser не является универсальной.

Насколько я понимаю, .Net Рамка имеет как управляемый, так и неуправляемый ресурс. И когда мы используем неуправляемый ресурс, мы должны worry about утечки памяти, и поэтому мы должны позаботиться об утилизации неуправляемого ресурса, который мы используем. Один из лучших способов сделать это - положить их на using контекст.

Все это заставляет меня задавать два вопроса в моем сознании, один конкретный и один общий. Вот мои вопросы:

  1. Особенности: Действительно ли TextFieldParser управляется или неуправляем?
  2. Общее: Есть ли определенный путь для нас, чтобы узнать, является ли ресурс управляемый или неуправляемый (например, глядя на X вещи в классе, или такие, так, или даже проверить что-то из MSDN - если должно быть проверили - сделают). Мне рассказали некоторые рекомендации по моему короткому опыту программирования, например: (i) большинство классов .Net управляются, (ii) классы System.Drawing имеют некоторые неуправляемые ресурсы, (iii) остерегайтесь всех классов базы данных, сети и COM, потому что они, как правило, неуправляемы и т. д., и список продолжается, и я продолжаю добавлять его до сих пор. Но интересно, есть ли какой-либо определенный способ узнать это?

Я был бы очень признателен, если бы более опытные могли помочь мне в этом вопросе.

ответ

2

Вам не хватает точки. Всякий раз, когда какой-либо класс реализует IDisposable, вы должны позвонить Dispose, когда закончите с ним.

Независимо от того, является ли класс неуправляемыми ресурсами или нет, он является внутренним по отношению к классу, вы не должны заботиться об этом вообще. У каждого класса, который использует неуправляемые ресурсы, также должен быть финализатор, который очищает эти неуправляемые ресурсы, если вы явно не выбрали класс. Dispose просто позволяет вам очищать свои ресурсы (как управляемые, так и неуправляемые, хотя это не обязательно означает освобождение памяти сразу) более детерминированным и немедленным образом. Например, Dispose ing FileStream немедленно выпустит дескриптор файла, а если вы не сделаете Dispose (или Close), файл будет открыт до следующей коллекции и завершения.

EDIT:

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

var control = new MyHelperControl(); 
MyParentForm.Click += control.DoSomething(); 

Теперь, даже если control выходит из области видимости, она будет выжить до тех пор, пока MyParentForm - он по-прежнему ссылается на обработчик событий. Эта же проблема возрастает до абсурдных пропорций, когда родитель имеет такое же время жизни, как и все приложение - это может быть огромная утечка памяти. Примером может быть регистрация обработчиков событий в основной форме приложения или на статическом событии.

Также могут быть другие вещи, которые происходят в Dispose. Например, опять же с формами Windows, при вызове Dispose на Control, много вещей происходит:

  • Все неуправляемые ресурсы высвобождаются. Поскольку элементы управления Winforms являются обертками собственных элементов управления, это, как правило, много ресурсов - сам контроль, любые ручки, кисти, изображения ... все это собственные ресурсы. Они также будут выпущены, если вы забудете Dispose, так как все они имеют финализаторы, но это может занять больше времени, что особенно болезненно, когда вы создаете и уничтожаете многие из этих объектов. Например, есть ограниченная поставка дескрипторов объектов GDI +, и если вы закончите, вы получите OutOfMemoryException, и вы уйдете.
  • Утилизируйте все вспомогательные элементы управления.
  • Удалить все обработчики контекстного меню (помните, контекстное меню - это отдельный компонент, который связан только с другим элементом управления).
  • Удалите любые привязки данных.
  • Удалить сам из родительского контейнера, если таковой имеется.
  • Если элемент управления представляет собой окно со своим собственным контуром сообщения, убейте цикл сообщения.

Самое смешное, что неуправляемые ресурсы материи минимум, на самом деле - они всегда имеют финализации. Управляемые ресурсы сложнее, потому что вам более или менее запрещено обрабатывать управляемые ссылки в финализаторе (потому что они, возможно, уже были выпущены, или они могут быть в середине выпуска, или они могут начать выпускаться в середине вашего финализатора ... это сложно). Так что делать MyParentForm.Click -= this.OnClick; - это нехорошо, что нужно в финализаторе - не говоря уже о том, что вам потребуется сделать каждый такой класс финализированным, что не совсем бесплатно, особенно если вы ожидаете, что финализатор на самом деле запустит (когда вы выполните Dispose, GC предупреждает, что этот экземпляр больше не нуждается в завершении).

+0

Не согласны ли вы более подробно разъяснить, что вы объясните? Означает ли это, что любой класс с 'IDisposable' неуправляем, и любой класс без' IDisposable' управляется? – Ian

+0

@Ian Нет, я имею в виду, что неуместно, имеет ли класс неуправляемый ресурс или нет. Если класс плохо написан, он освободит свои неуправляемые ресурсы в конце концов, даже если вы не вызываете метод Dispose. С другой стороны, метод 'Dispose' может быть полностью * необходим * для управляемых ресурсов, а типичный пример - утечка памяти через обработчики событий. – Luaan

+0

@Ian: Большинство классов, реализующих 'IDisposable', не будут напрямую владеть неуправляемым ресурсом. Однако они часто владеют другим классом, реализующим «IDisposable». Переход к этой цепочке будет длиться большую часть времени в неуправляемом ресурсе. Пример: 'YourClass' имеет поле FileStream. Класс 'FileStream' имеет поле' SafeFileHandle'. «SafeFileHandle» владеет базовым дескриптором неуправляемого файла ОС. Утилизация 'YourClass' должна утилизировать' FileStream', который дипозирует 'SafeFileHandle', который выпустит неуправляемый дескриптор файла. –

1

Использование любого класса impos IDableposable интерфейса должно быть либо завернуто в использование (...) {}, либо удобно размещено там, где это необходимо.