используя () и распоряжаться несколькими обернутыми потоками - PullRequest
3 голосов
/ 03 августа 2009

Прав ли я, что вам нужно только использовать () для внешнего потока, если вы делаете, например,

MemoryStream mstr = new MemoryStream();

using(StreamWriter w = new StreamWriter(mstr)) {
    ....
}

Поскольку утилита StreamWriter также должна удалять / закрывать базовый поток, в этом нет необходимости?:

using(MemoryStream mstr = new MemoryStream())
using(StreamWriter w = new StreamWriter(mstr)) {
    ....
}

(Обратите внимание, что это всего лишь примеры того, как утилизировать упакованные потоки, а не искать альтернативы, такие как просто использование StringWriter и т.

Ответы [ 5 ]

9 голосов
/ 03 августа 2009

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

using (MemoryStream mstr = new MemoryStream())
using (StreamWriter w = new StreamWriter(mstr) {
    ....
}

// cannot attempt to access mstr here

Если вы не включите его таким образом, то все равно возможно получить доступ к mstr вне области действия, где он действителен

MemoryStream mstr = new MemoryStream();
using (StreamWriter w = new StreamWriter(mstr) {
    ....
}

mstr.Write(...); // KABOOM! ObjectDisposedException occurs here!

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

7 голосов
/ 03 августа 2009

Мое эмпирическое правило: если он реализует IDisposable, избавьтесь от него.

Хотя в настоящее время (и, вероятно, навсегда) вызов StreamWriter.Dispose () закрывает базовый поток, другие производные от потока классы, которые вы можете использовать в будущем, могут и не использоваться. Кроме того, похоже, что на самом деле он также не вызывает Dispose (), поэтому не-MemoryStreams могут не удаляться должным образом (хотя я не могу представить ни одного, который бы пострадал от этого прямо сейчас).

Итак, хотя вы можете безопасно утилизировать только StreamWriter, я считаю, что гораздо лучше всегда использовать блоки для одноразовых по возможности.

4 голосов
/ 03 августа 2009

При взгляде на метод StreamWriter.Dispose в Reflector, похоже, что лежащие в основе потоки закрываются, но не удаляются. Я бы поместил каждый поток в блок "using", чтобы все их возможности были удалены.

3 голосов
/ 03 августа 2009

Чтобы ответить на ваш актуальный вопрос. Метод утилизации TextWriter's

public void Dispose()
{
    this.Dispose(true);
    GC.SuppressFinalize(this);
}

Вызывает защищенную утилизацию и передает ей значение true. От TextWriter.Dispose (Boolean)

Когда параметр удаления равен true , этот метод освобождает все ресурсы проводится какими-либо управляемыми объектами, которые это Ссылки TextWriter. Этот метод вызывает метод Dispose каждого указанный объект.

Однако лучше всего обернуть все, что реализует IDisposable в блоке using, поскольку мы не можем гарантировать, что защищенный метод Dipose всегда будет вызываться с параметром true .

0 голосов
/ 03 августа 2009

Лучше всегда использовать блок using.

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

...