これを全体的に行う最善の方法は、FileStream を自分自身だけで閉じることだと思います。上位のレイヤーに存在するものを暗黙的に認識していないため、それらの上位レイヤーに影響を与えるようなことを行うと、事実上エラーになります。
そうは言っても、高レベルの構成要素は、提供された下層のレイヤーについても公理的に何も仮定すべきではありません。そうする場合は、明示的にそうする必要があります。
1) 既存のストリームから作成された場合、上位レベルの構成は、基になるストリームとは独立して閉じられる(事実上、独自の使用のために割り当てられたすべてのリソースを破棄する) か、基になるストリームを含めて閉じられる必要があります。これらは、Close() と CloseSelf() などの 2 つの異なる関数呼び出しである必要があります (既存のコードとの下位互換性を維持するように実装する場合)。
2) 既存のストリームから作成されなかった場合 (つまり、コンストラクターが基になるストリームを作成する必要があった場合)、上位レベルの構成を閉じると、基になるストリームも強制的に閉じられる必要があります。上位レベルの構造の暗黙の部分。この場合、CloseSelf() は単純に Close() を呼び出します。
これらのクラスをそのまま実装するのは無駄に思えます。(例として) シリアル入力とシリアル出力に同じファイルを使用することを計画している場合、子孫クラスのより高いレベルの機能にアクセスしたい場合、システムによって事実上、それを 2 つの別個のエンティティとして扱うように強制されます。別の方法は、下位レベルの構成に固執し、上位レベルの機能を自分で実装することです。つまり、既存の子孫クラスの独自の特別なバージョンを効果的に再実装します。
上記のように実行された場合、典型的な機能は現在と同じくらい簡単に実装できますが、より洗練されたアプリケーションでは、ファイルに単一のロックを配置し、必要に応じて必要に応じて再利用する機能を保持します。ロックと関連するすべてのリソースを放棄し、それらを即座に再割り当てしなければならないのではなく、正当な理由なくシステムにオーバーヘッドとメモリの断片化を追加します。
ただし、現在の状況下では、正しいことは明らかです。FileStream は、その一部となるオブジェクトについて何も知らないと想定できないため、最も外側の囲み構造を閉じる必要があります。これは、ブルーノらが指摘したように、どちらの方法でも機能するかどうかに関係なく適用され、その理由は互換性です。仮定は、最も醜いバグのひいおじいちゃんです。