175

書き込むメソッドにストリームを送信しています。これらのメソッドでは、バイナリリーダー/ライターを使用しています。リーダー/ライターが参照されていないとき、usingまたは参照されていないときに破棄されると、ストリームも閉じられますか?

BinaryReader / Writerを送信しますが、StreamReaderも使用しています(多分それを回避する必要があります。GetLineとReadLineにのみ使用しています)。ライター/リーダーが閉じられるたびにストリームを閉じる場合、これは非常に厄介です。

4

7 に答える 7

215

はい、、、StreamReaderおよびすべてはStreamWriter、それらを呼び出すときに、それらの基になるストリームを閉じる/破棄します。ただし、リーダー/ライターがガベージコレクションされただけの場合は、ストリームを破棄しませ。常にリーダー/ライターを破棄する必要があります。できればステートメントを使用して破棄する必要があります。(実際、これらのクラスにはファイナライザーがなく、ファイナライザーもありません。)BinaryReaderBinaryWriterDisposeusing

個人的には、ストリームにもusingステートメントを使用することを好みます。using中括弧なしでステートメントを非常にきれいにネストできます。

using (Stream stream = ...)
using (StreamReader reader = new StreamReader(stream, Encoding.Whatever))
{
}

ストリームのusingステートメントは多少冗長ですが(コンストラクターが例外をスローしない限り) 、後日ストリームを削除して直接使用する場合は、すでに適切な処理がStreamReader行われているため、ベストプラクティスと考えています。StreamReaderセマンティクス。

于 2009-06-30T18:23:10.393 に答える
52

これは古いものですが、今日も同じようなことをしたかったのですが、状況が変わったことがわかりました。.net 4.5以降、次のようleaveOpenな議論があります。

public StreamReader( Stream stream, Encoding encoding, bool detectEncodingFromByteOrderMarks, int bufferSize, bool leaveOpen )

唯一の問題は、他のパラメータに何を設定するかが完全に明確ではないことです。ここにいくつかの助けがあります:

StreamReaderコンストラクター(ストリーム)のmsdnページから:

このコンストラクターは、エンコーディングをUTF8Encodingに初期化し、BaseStreamプロパティをstreamパラメーターを使用して初期化し、内部バッファーサイズを1024バイトに初期化します。

ソースコードdetectEncodingFromByteOrderMarks判断すると、true

public StreamReader(Stream stream)
        : this(stream, true) {
}

public StreamReader(Stream stream, bool detectEncodingFromByteOrderMarks)
        : this(stream, Encoding.UTF8, detectEncodingFromByteOrderMarks, DefaultBufferSize) {
}

これらのデフォルトのいくつかが公開されているか、引数がオプションであるため、必要なものを指定できると便利です。

于 2014-01-12T04:55:13.787 に答える
30

はい、そうです。これは、Reflectorを使用した実装を確認することで確認できます。

protected override void Dispose(bool disposing)
{
    try
    {
        if ((this.Closable && disposing) && (this.stream != null))
        {
            this.stream.Close();
        }
    }
    finally
    {
        if (this.Closable && (this.stream != null))
        {    
            this.stream = null;    
            this.encoding = null;
            this.decoder = null;
            this.byteBuffer = null;
            this.charBuffer = null;
            this.charPos = 0;
            this.charLen = 0;
            base.Dispose(disposing);
        }
    }
}
于 2009-06-30T18:22:51.437 に答える
16

6年遅れましたが、おそらくこれは誰かを助けるかもしれません。

StreamReaderは、破棄されるときに接続を閉じます。ただし、StreamReader / StreamWriterで「using(Stream stream = ...){...}」を実行すると、Streamが2回破棄される可能性があります。(1)StreamReaderオブジェクトが破棄される場合(2)およびStreamusingブロックの場合閉じます。これにより、VSのコード分析を実行するときにCA2202警告が発生します。

CA2202ページから直接取得した別の解決策は、try/finallyブロックを使用することです。正しく設定すると、接続が1回だけ閉じられます。

CA2202の下部近くで、Microsoftは以下を使用することをお勧めします。

Stream stream = null;
try
{
    stream = new FileStream("file.txt", FileMode.OpenOrCreate);
    using (StreamWriter writer = new StreamWriter(stream))
    {
        stream = null;
        // Use the writer object...
    }
}
finally
{
    stream?.Dispose();
}

それ以外の...

// Generates a CA2202 warning
using (Stream stream = new FileStream("file.txt", FileMode.Open))
using (XmlReader reader = new XmlReader (stream))
{
    // Use the reader object...
}
于 2015-09-13T21:11:21.870 に答える
2

はい。Dispose()を呼び出してIDisposable( "using"が行う)は、オブジェクトがそのすべてのリソースをクリーンアップするようにする必要があります。これには、ストリームのフラッシュとファイル記述子のクローズが含まれます。

あなたの場合、それを他のメソッドに渡したい場合は、それらのメソッドがusingブロックで読み取り/書き込みを行わないようにする必要があります。

于 2009-06-30T18:22:55.027 に答える
1

必要に応じてこれを修正する簡単な方法は、StreamWriterクラスのDisposeメソッドをオーバーライドすることです。それを行う方法のコードについては、ここにある私の投稿を参照してください:

StreamWriterを破棄すると、基になるストリームが閉じますか?

于 2011-07-21T23:53:57.993 に答える
-2

「using」キーワードまたはdisposeを明示的に呼び出すことによって破棄されたストリーム

于 2009-06-30T18:22:04.230 に答える