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

Звонить только Dispose() сделает свое дело =)

В.NET 3.5 (не проверял другие версии), при вызове MemoryStream методы вызываются в следующем порядке:

  1. Stream.Dispose ()
    • просто звонит Close
  2. Stream.Close ()
    • вызывает Dispose(true), затем GC.SuppressFinalize (this)
  3. MemoryStream.Dispose (правда)
    • устанавливает для флагов _isOpen, _writable и _expandable значение false
  4. 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/

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