Обертывание MemoryStream при использовании

Мне сказали, что System.IO.MemoryStream не нужно обертывать в блок использования, потому что нет основного ресурса, этот вид идет вразрез с тем, что мне всегда говорили о потоках ( "если есть сомнения, используйте с помощью" ).

Это правда? Почему тогда пример MSDN использует один (кратко изложенный ниже)?

using(MemoryStream memStream = new MemoryStream(100))
{
            // do stuff
}

Ответы

Ответ 1

Идиома С# заключается в том, что если объект реализует IDisposable, то вы используете блок using. Это позволит утилизировать все ресурсы, используемые объектом. Вы не должны знать подробности реализации MemoryStream. То, что вы знаете, это то, что оно реализует IDisposable, чтобы вы правильно распоряжались им. Кроме того, вы считаете, что теперь знаете, что вам не нужно освобождать какие-либо ресурсы, но как вы знаете, что в будущем MemoryStream не изменит свою базовую реализацию, чтобы использовать ресурсы, которые необходимо освободить, используя Dispose? Вы этого не сделаете, так как он реализует IDispoable, у вас есть больше будущего кода, просто используя шаблон сейчас. Во-вторых, что, если вы измените свой код в будущем, чтобы использовать другой тип Stream, который имеет управляемые ресурсы? Упаковывая MemoryStream в блок using, теперь вы уменьшаете проблемы обслуживания в будущем; опять же, это правильный способ использования объектов, а именно Stream, которые реализуют IDisposable. В-третьих, это четкий способ сообщить читателям, что вы сделали это с помощью объекта; это то, что читатели вашего кода ожидают увидеть, увидев, что вы используете объекты, реализующие IDisposable. Наконец, это текущая реализация MemoryStream.Dispose:

protected override void Dispose(bool disposing) {
    try {
        if (disposing) {
            this._isOpen = false;
            this._writable = false;
            this._expandable = false;
        }
     }
     finally {
         base.Dispose(disposing);
     }
}

Таким образом, это означает, что поток закрыт, недоступен для записи и невосстанавливается. Если кто-то еще схватил ссылку на тот же MemoryStream, теперь он становится непригодным для них, что может быть хорошо. Но это действительно наименее важный вопрос; детали реализации не имеют значения.

Используйте блок using, потому что MemoryStream реализует IDispoable. Не используйте блок using, потому что вы думаете, что MemoryStream не имеет ресурсов, которые необходимо освободить.

Ответ 2

Руководящий принцип заключается в том, что если он реализует IDisposable, вы должны избавиться от него. Вы просто работаете с API и не знаете об этой реализации, поэтому у вас нет причин не помещать его в блок использования.

Ответ 3

После быстрого просмотра Reflector оказалось, что Dispose в MemoryStream делает не что иное, как отмечать поток не является открытым, записываемым или расширяемым.

Сказав, что, как общий подход, вы, вероятно, должны придерживаться шаблона размещения; особенно, как Stream, все следуют подходу "декоратор" и должны быть легко заменены друг на друга или обернуть друг друга. Сегодня MemoryStream может быть заменен другим потоком, который заботится завтра.

Ответ 4

Если класс реализует IDisposable, он должен быть удален.

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

Инкапсуляция является одним из краеугольных камней объектно-ориентированного развития. Зачем уходить с пути, чтобы нарушить это, особенно если нет веской причины?

Ответ 5

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

Ответ 6

Как сказал Чарли, рекомендуется использовать Dispose всех объектов классов, которые реализуют IDisposable.

Если вы посмотрите на реализацию MemoryStream.Dispose(bool) (который вызывается Stream.Dispose()), становится очевидным, что вы должны избавиться от него, так как он обновляет несколько флажков управления:

protected override void Dispose(bool disposing)
{
    try
    {
        if (disposing)
        {
            this._isOpen = false;
            this._writable = false;
            this._expandable = false;
        }
    }
    finally
    {
        base.Dispose(disposing);
    }
}