web-dev-qa-db-ja.com

MemoryStream.Close()またはMemoryStream.Dispose()

どちらに電話しますか?

両方を呼び出す必要がありますか?

すでに呼び出している場合、もう一方は例外をスローしますか?

55
ashwnacharya

Close()およびDispose()は、MemoryStreamで呼び出された場合、2つのことのみを行います。

  • オブジェクトを将来誤って使用すると例外がスローされるように、オブジェクトを破棄済みとしてマークします。
  • たぶん1 管理オブジェクトへの参照を解放します。これにより、GCの実装に応じてGCのジョブが少し簡単になります。 (今日のGCアルゴリズムでは、実際の違いはないため、これは学術的な議論のポイントであり、現実世界に大きな影響はありません。)

MemoryStreamには破棄する管理対象外のリソースがないため、技術的に破棄する必要はありません。 MemoryStreamを破棄しないことの効果は、_byte[]_への参照を削除することとほぼ同じです。GCは両方を同じ方法でクリーンアップします。

どちらに電話しますか?両方を呼び出す必要がありますか?

ストリームのDispose()メソッド Close()メソッドに直接委任2、両方ともまったく同じことを行います。

すでに呼び出している場合、もう一方は例外をスローしますか?

IDisposable.Dispose()のドキュメント は、任意のオブジェクトでDispose()を複数回呼び出すことが安全であることを具体的に示しています3。 (特定のクラスに当てはまらない場合、そのクラスは契約に違反する方法でIDisposableインターフェースを実装します。これはバグになります。)

つまり、MemoryStreamを破棄するかどうかは大きな違いにはなりません。 Close/Disposeメソッドを持っている唯一の本当の理由は、Streamから継承するためです。これは、doには、管理されていないリソース(ファイルまたはソケット記述子など)があります。


1 Monoの実装 は_byte[]_参照を解放しません。 Microsoftが実装しているかどうかはわかりません。

2  "このメソッドはCloseを呼び出し、次にStream.Dispose(Boolean)を呼び出します。"

3  "オブジェクトのDisposeメソッドが複数回呼び出された場合、オブジェクトは最初の呼び出し以降のすべての呼び出しを無視する必要があります。"

103
cdhowie

これにはusingブロックを使用できます。スコープ外になると、自動的にDisposeを呼び出します。

例:

using (MemoryStream ms = new MemoryStream())
{
    // Do something with ms..
}
// ms is disposed here

これが役に立てば幸いです。

7
Kevin

usingインターフェイスを実装しているオブジェクトが破棄されるように、IDisposableブロックを使用します

7
TalentTuner

次のコードは、ご覧のようにリフレクターからのStream.Disposeです。破棄する場合、閉じる必要はありません(使用時に暗黙的です)

public void Dispose()
{
    this.Close();
}
4
vc 74

どちらに電話しますか?

それらのいずれか。

両方を呼び出す必要がありますか?

いいえ、どちらでも十分です。

すでに呼び出している場合、もう一方は例外をスローしますか?

いいえ、使い捨てのパターンは、Disposeの後続の呼び出しが悪影響を引き起こさないことを宣言しています。

4
QrystaL

Close()を呼び出すと、Dispose()が内部的に呼び出されてリソースが解放されます。

詳細については、次のリンクを参照してください。 msdn

3
Hps

上記のどれでもない。 CloseまたはDisposeを呼び出す必要はありません。

MemoryStreamはアンマネージリソースを保持しないため、回収するリソースはメモリのみです。コードがMemoryStreamを参照しなくなった場合、ガベージコレクション中に残りのMemoryStreamオブジェクトでメモリが回収されます。

MemoryStreamへの長命の参照がある場合、その参照をnullに設定して、MemoryStreamのガベージコレクションを許可できます。 CloseおよびDisposeは、SteamバッファーもMemoryStreamオブジェクトも適切に解放しません。

StreamMemoryStreamもファイナライザーを持たないため、CloseまたはDisposeを呼び出して_GC.SuppressFinalize_を呼び出して最適化する必要はありません。ガベージコレクション。抑制するファイナライザーはありません。

MemoryStream のドキュメントでは、次のように記述しています。

このタイプはIDisposableインターフェースを実装しますが、実際に破棄するリソースはありません。つまり、Dispose()を直接呼び出したり、using(C#の場合)やUsing(Visual Basicの場合)などの言語構造を使用して破棄する必要はありません。

2
Edward Brey

Dispose()のみを呼び出すと、トリックが実行されます=)

1
Singleton

.NET 3.5(他のバージョンはチェックしていません)では、MemoryStreamを破棄するときにメソッドは次の順序で呼び出されます。

  1. Stream.Dispose()
    • closeを呼び出すだけです
  2. Stream.Close()
    • dispose(true)を呼び出してから、GC.SuppressFinalize(this)を呼び出します
  3. MemoryStream.Dispose(true)
    • _isOpen、_writable、および_expandableフラグをfalseに設定します
  4. Stream.Dispose(true)
    • アクティブな場合、非同期イベントを閉じます
1
Tor Langlo

最初の解決策として、可能な限りusingステートメントを使用することをお勧めします。これはここで説明されています: http://msdn.Microsoft.com/en-us/library/yh598w02.aspx

IDisposableオブジェクトのライフタイムが単一のメソッドに制限されている場合、usingステートメントで宣言してインスタンス化する必要があります。 usingステートメントは、オブジェクトのDisposeメソッドを正しい方法で呼び出し、(前に示したように使用する場合)、Disposeがすぐにスコープから外れるようにしますusingブロック内では、オブジェクトは読み取り専用であり、変更または再割り当てできません。

他のほとんどの.NETフレームワーククラスで提案されているように、ここで質問に答えると、Close()とDispose()の間に違いはなく、どちらのメソッドを呼び出すかは重要ではありません。両方ではなく1つを呼び出す必要があります。ただし、には例外があります

例外があります。たとえば、System.Windows.Forms.FormとSystem.Data.SqlClient.SqlConnectionは、Close()とDispose()で異なる動作をします。

詳細については、こちらで確認できます。 https://blogs.msdn.Microsoft.com/kimhamil/2008/03/15/the-often-non-difference-between-close-and-dispose/

0
sin2akshay