BaseStream と Flush
id:parlin:20060103#1136299930より
ま、らっぱ〜被せたらずっとそれを使えって話なんでしょうねえ。
これって結構使いにくいんですよね。たとえば、
public interface Ixxx { void Save(Stream stream) } Ixxx a = ...; Ixxx b = ...; Ixxx c = ...; Stream s = ...; a.Save(s); b.Save(s); c.Save(s);
みたいな場合に、a, b, c の各実装が全く異なる Writer を利用したがったらどうすればいいだろうか?*1
public class A : Ixxx { public void Save(Stream stream) { using (BinaryWriter writer = new BinaryWriter(stream, Encoding.UTF8)) { writer.Write(...); : } } }
a がこのような実装だと、b.Save(s) の中で例外が発生するだろう。BinaryWriter が Dispose() されると、BinaryWriter は出力先である s を Close() するため、b.Save(s) が s に対して書き込みを実施できなくなってしまう。
これに対する対応は「 writer を Dispose() しないで Flush() を呼び出す」である。BinaryWriter は Dispose() または Close() を明示的に呼ばないで放置した場合、出力先ストリームからデタッチされたとみなされるようになっている。標準ライブラリの Writer/Reader 群ではみんなこうなっているんだが、個人的には Dispose() を明示的実装にして Close() を定義しているのと同様に、Detach() とか Release() みたいな名前で出力先を閉じない Close/Dispose を用意してほしかったと思う。
BaseStream
それで BaseStream プロパティなんだけど、内部でバッファリングを行っている Writer/Reader では、
private Stream baseStream; public /*virtual*/ Stream BaseStream { get { this.baseStream.Flush(); return this.baseStream(); } }
みたいな実装になっていて、
StreamWriterとかでベースストリームの更新のタイミングが問題になる
ということは心配しなくてよい*2と思っていたんだけど、StreamWriter.BaseStream はそのような実装になっていないようだ。困るなあ。
ついでに
StreamWriter ではなくて StreamReader だけど、BaseStream とバッファリング関連で言うと DiscardBufferedData() は存在を知っておくべきメソッドですね。