この質問を読むには複数の方法がありますが、明白な方法、それが書かれた方法から始めましょう。
メソッド内で「使用」を使用すると、スレッドがデータを読み取る前に、このデータが FIFO に入ってから数秒または数分後に GC がメモリ ストリームを削除する可能性がありますか?
いいえ、問題ありません。への呼び出しの一部としてデータを読み取ることができる場合は.ToArray()
、データのコピーが既にあります。後で GC がストリームを収集した場合、アレイは存続します。明確にするために、GC に関して、呼び出した時点でストリームの内部の適切なコピーを読み取ることができれば、.ToArray()
その配列は後で問題ありません。ドキュメントによると、内部データへの参照ではなく、内部データのコピーを取得しています。それでも、内部データ構造への参照がある場合、GC はそれを収集できません。
ただし、別の解釈は次のようになります。このコードには何か問題がありますか?
はい、いいえ。
の現在の実装でBinaryWriter
は、ライター インスタンスが破棄されると、基になるストリームが破棄されます。これは、MemoryStream
処分されることを意味します。
コードをコピーしてコメントを追加させてください。
public byte[] ByteArraySerialize()
{
using (MemoryStream m = new MemoryStream())
{
using (BinaryWriter writer = new BinaryWriter(m))
{
writer.Write((int)this.Opcode);
writer.Write(this.Data);
}
// m is really disposed here
return m.ToArray();
}
}
これは違いがありますか?うーん、ダメ。現在の実装では、メモリ ストリームを破棄しても決して破棄されません。ただし、現在の実装またはその将来について保証されるものは何もありません。これは文書化されていない動作です。このコードを将来のバージョンや .NET の修正プログラムで安定して信頼できるものにしたい場合は、このようには書きません。
そのため、私はこの方法を使用しません。次のようにコードを書き直します。
using (MemoryStream m = new MemoryStream())
using (BinaryWriter writer = new BinaryWriter(m))
{
writer.Write((int)this.Opcode);
writer.Write(this.Data);
writer.Flush();
return m.ToArray();
}
これはライターにすべてのデータをフラッシュするように要求し、そのインスタンスが破棄される前に、メモリ ストリームの内部配列のコピーを作成します。
それか、オーバーロードされたコンストラクターを使用して、ライターにストリームを開いたままにするように依頼します。
using (MemoryStream m = new MemoryStream())
{
using (BinaryWriter writer = new BinaryWriter(m, Encoding.UTF8, true))
{
writer.Write((int)this.Opcode);
writer.Write(this.Data);
}
// m is no longer disposed here
return m.ToArray();
}