MemoryStream.Close() или MemoryStream.Dispose()
Какой мне позвонить?
Нужно ли называть оба?
Другой бросит исключение, если я уже позвонил одному из них?
10 ответов
Close()
а также Dispose()
когда вызывается на MemoryStream
, служат только для двух вещей:
- Пометьте объект как удаленный, чтобы в будущем при случайном использовании объекта возникло исключение.
- Возможно 1 выпуск ссылок на управляемые объекты, которые могут сделать работу GC немного легче в зависимости от реализации GC. (В современных алгоритмах GC это не имеет большого значения, так что это является предметом для академической дискуссии и не оказывает существенного влияния на реальный мир.)
MemoryStream
не имеет никаких неуправляемых ресурсов для утилизации, поэтому вам не придется технически их утилизировать. Эффект не избавиться от MemoryStream
примерно то же самое, что сбросить ссылку на byte[]
- GC очистит оба одинаково.
Какой мне позвонить? Нужно ли называть оба?
Dispose()
метод делегирования потоков непосредственно Close()
метод 2, так что оба делают одно и то же.
Другой бросит исключение, если я уже позвонил одному из них?
Документация для IDisposable.Dispose()
конкретно утверждает, что это безопасно позвонить Dispose()
несколько раз на любом объекте 3. (Если это не так для определенного класса, тогда этот класс реализует IDisposable
интерфейс таким образом, что нарушает его контракт, и это будет ошибка.)
Все это говорит: это действительно не имеет большого значения, если вы располагаете MemoryStream
или нет. Единственная реальная причина, по которой это Close
/ Dispose
методы, потому что он наследует от Stream
, который требует, чтобы эти методы были частью его контракта для поддержки потоков, которые имеют неуправляемые ресурсы (такие как дескрипторы файлов или сокетов).
1 реализация Моно не выпускает byte[]
ссылка. Я не знаю, если реализация Microsoft делает.
2 "Этот метод вызывает метод Close, который затем вызывает Stream.Dispose (Boolean)."
3 "Если метод Dispose объекта вызывается более одного раза, объект должен игнорировать все вызовы после первого".
Ни один из вышеперечисленных. Вам не нужно звонить либо Close
или же Dispose
,
MemoryStream
не содержит никаких неуправляемых ресурсов, поэтому единственный ресурс, который нужно восстановить - это память. Память будет восстановлена во время сбора мусора с остальной частью MemoryStream
объект, когда ваш код больше не ссылается на MemoryStream
,
Если у вас есть долгоживущая ссылка на MemoryStream
, вы можете установить эту ссылку на ноль, чтобы позволить MemoryStream
быть мусором Close
а также Dispose
не освободить ни паровой буфер, ни MemoryStream
объект собственно.
Так как ни Stream
ни MemoryStream
есть финализатор, звонить не нужно Close
или же Dispose
вызывать GC.SuppressFinalize
вызываться для оптимизации сбора мусора. Нет финализатора для подавления.
Документы для MemoryStream говорят об этом так:
Этот тип реализует
IDisposable
интерфейс, но на самом деле не имеет никаких ресурсов для утилизации. Это означает, что избавиться от него напрямуюDispose()
или с помощью языковой конструкции, такой какusing
(в C#) илиUsing
(в Visual Basic) не требуется.
Вы можете использовать using
блок для этого. Он будет автоматически звонить Dispose
когда он выходит за пределы своей сферы.
Пример:
using (MemoryStream ms = new MemoryStream())
{
// Do something with ms..
}
// ms is disposed here
Надеюсь, это помогло.
Использование using
блок, так что ваш объект расположен, если его реализует IDisposable
интерфейс
Следующий код - Stream.Dispose из отражателя, как вы можете видеть, вам не нужно закрываться, если вы утилизируете (что подразумевается при использовании using)
public void Dispose()
{
this.Close();
}
Какой мне позвонить?
Любой из них.
Нужно ли называть оба?
Нет, одного достаточно.
Другой бросит исключение, если я уже позвонил одному из них?
Нет, одноразовый шаблон объявляет, что последующие вызовы Dispose не вызывают негативных последствий.
Вызов Close() внутренне вызовет Dispose() для освобождения ресурсов.
Смотрите эту ссылку для получения дополнительной информации: MSDN
В.NET 3.5 (не проверял другие версии), при вызове MemoryStream методы вызываются в следующем порядке:
- Stream.Dispose ()
- просто звонит Close
- Stream.Close ()
- вызывает Dispose(true), затем GC.SuppressFinalize (this)
- MemoryStream.Dispose (правда)
- устанавливает для флагов _isOpen, _writable и _expandable значение false
- Stream.Dispose (правда)
- закрывает асинхронное событие, если активно
В качестве первого решения рекомендуется использовать операторы везде, где это возможно. Это описано здесь: http://msdn.microsoft.com/en-us/library/yh598w02.aspx
Когда время жизни объекта IDisposable ограничено одним методом, вы должны объявить и создать его экземпляр в операторе using. Оператор using вызывает метод Dispose для объекта правильным образом и (когда вы используете его, как показано ранее), он также заставляет сам объект выходить из области действия, как только вызывается Dispose. Внутри блока using объект доступен только для чтения и не может быть изменен или переназначен.
Теперь перейдем к вопросу, как другие предлагали в большинстве классов среды.NET, между Close() и Dispose() нет разницы, и не имеет значения, какой из двух методов вы вызываете. Вы должны назвать один, но не оба. Однако есть и исключения.
Есть исключения; например, System.Windows.Forms.Form и System.Data.SqlClient.SqlConnection имеют различное поведение для Close() и Dispose().
Для получения полной информации вы можете проверить здесь: https://blogs.msdn.microsoft.com/kimhamil/2008/03/15/the-often-non-difference-between-close-and-dispose/