CA2202: オブジェクトを複数回破棄しません

Item [値]
規則 ID CA2202
カテゴリ Microsoft.Usage
互換性に影響する変更点 なし

原因

メソッドの実装に、同じオブジェクトに対して System.IDisposable.Dispose または Dispose と同等のメソッド (一部の型に対する Close() メソッドなど) を複数回呼び出す可能性があるコード パスが含まれています。

Note

このルールは非推奨とされました。 詳細については、「非推奨の規則」を参照してください。

規則の説明

正しく実装された Dispose メソッドは、例外をスローせずに複数回呼び出すことができます。 ただし、これは保証されているわけではないため、System.ObjectDisposedException を生成しないようにするには、オブジェクトに対して Dispose を複数回呼び出さないようにする必要があります。

違反の修正方法

この規則の違反を修正するには、コード パスに関係なく、オブジェクトに対して Dispose が 1 回だけ呼び出されるように実装を変更します。

どのようなときに警告を抑制するか

この規則による警告は抑制しないでください。 オブジェクトに対する Dispose が複数回安全に呼び出し可能であることがわかっている場合でも、その実装が将来変更される可能性があります。

例 1

入れ子になった using ステートメント (Visual Basic では Using) は、CA2202 警告の違反の原因となる可能性があります。 入れ子になった内側の using ステートメントの IDisposable リソースに、外側の using ステートメントのリソースが含まれている場合、入れ子になったリソースの Dispose メソッドは含まれているリソースを解放します。 この状況が発生すると、外側の using ステートメントの Dispose メソッドは、そのリソースの 2 回目の破棄を試みます。

次の例では、外側の using ステートメントで作成された Stream オブジェクトは、stream オブジェクトを含む StreamWriter オブジェクトの Dispose メソッドで、内側の using ステートメントの最後に解放されます。 外側の using ステートメントの最後に、stream オブジェクトがもう一度解放されます。 この 2 回目の解放は、CA2202 の違反になります。

using (Stream stream = new FileStream("file.txt", FileMode.OpenOrCreate))
{
    using (StreamWriter writer = new StreamWriter(stream))
    {
        // Use the writer object...
    }
}

例 2

この問題を解決するには、外側の using ステートメントの代わりに、try/finally ブロックを使用します。 finally ブロックで、stream リソースが null でないことを確認します。

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();
}

ヒント

上記の ?. 構文は、null 条件演算子です。

関連項目