CA2213:破棄可能なフィールドは破棄されなければなりません

プロパティ
ルール ID CA2213
Title 破棄可能なフィールドは破棄されなければなりません
[カテゴリ] 使用方法
修正が中断ありか中断なしか なし
.NET 8 では既定で有効 いいえ

原因

System.IDisposable を実装する型が、IDisposable も実装する型を持つフィールドを宣言しています。 このフィールドの Dispose メソッドは、宣言している型の Dispose メソッドから呼び出されていません。

規則の説明

そのすべてのアンマネージド リソースの破棄は、型が担当します。 規則 CA2213 により、破棄可能な型 (つまり、IDisposable を実装しているもの) T に、破棄可能な型 FT のインスタンスであるフィールド F が宣言されているかどうかが確認されます。 含んでいる型 T のメソッドまたは初期化子内のローカルに作成されたオブジェクトが割り当てられている各フィールド F について、規則により、FT.Dispose の呼び出しの検索が試行されます。 この規則により、T.Dispose とその 1 つ下のレベルで呼び出されるメソッド (つまり、T.Dispose で呼び出されるメソッドによって呼び出されるメソッド) が検索されます。

注意

特殊なケースを除き、含んでいる型のメソッドや初期化子内のローカルに作成された破棄可能なオブジェクトが割り当てられたフィールドに対してのみ規則 CA2213 が呼び出されます。 オブジェクトが T 型の外部で作成または割り当てられた場合、規則は呼び出されません。 これにより、含まれている型がオブジェクトの破棄を担当しない場合のノイズが軽減されます。

特殊なケース

割り当てられたオブジェクトがローカルに作成されていなくても、次の型のフィールドに対しても規則 CA2213 が呼び出される可能性があります。

これらの型のオブジェクトをコンストラクターに渡し、それをフィールドに割り当てると、新しく構築された型への "dispose の所有権の譲渡" が行われます。 つまり、新しく構築された型がオブジェクトの破棄を担当するようになりました。 オブジェクトが破棄されない場合、CA2213 の違反が発生します。

違反の修正方法

この規則違反を修正するには、IDisposable を実装している型のフィールドに対して Dispose を呼び出します。

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

次の場合は、このルールの警告を抑制できます。

  • フラグが設定された型は、そのフィールドが保持するリソースを解放する処理を担当しません (つまり、その型に "dispose の所有権" がありません)
  • Dispose の呼び出しにより、規則チェックより深い呼び出しレベルで発生しています
  • フィールドの dispose の所有権が、含まれる型によって保持されていません。

警告を抑制する

単一の違反を抑制するだけの場合は、ソース ファイルにプリプロセッサ ディレクティブを追加して無効にしてから、規則をもう一度有効にします。

#pragma warning disable CA2213
// The code that's violating the rule is on this line.
#pragma warning restore CA2213

ファイル、フォルダー、またはプロジェクトの規則を無効にするには、構成ファイルでその重要度を none に設定します。

[*.{cs,vb}]
dotnet_diagnostic.CA2213.severity = none

詳細については、「コード分析の警告を抑制する方法」を参照してください。

次のスニペットは、IDisposable を実装する型 TypeA を示しています。

public class TypeA : IDisposable
{
    protected virtual void Dispose(bool disposing)
    {
        if (disposing)
        {
            // Dispose managed resources
        }

        // Free native resources
    }

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    // Disposable types implement a finalizer.
    ~TypeA()
    {
        Dispose(false);
    }
}

次のスニペットは、フィールド aFieldOfADisposableType を破棄可能な型 (TypeA) として宣言し、そのフィールドで Dispose を呼び出さないことで、規則 CA2213 に違反する型 TypeB を示しています。

public class TypeB : IDisposable
{
    // Assume this type has some unmanaged resources.
    TypeA aFieldOfADisposableType = new TypeA();
    private bool disposed = false;

    protected virtual void Dispose(bool disposing)
    {
        if (!disposed)
        {
            // Dispose of resources held by this instance.

            // Violates rule: DisposableFieldsShouldBeDisposed.
            // Should call aFieldOfADisposableType.Dispose();

            disposed = true;
            // Suppress finalization of this disposed instance.
            if (disposing)
            {
                GC.SuppressFinalize(this);
            }
        }
    }

    public void Dispose()
    {
        if (!disposed)
        {
            // Dispose of resources held by this instance.
            Dispose(true);
        }
    }

    // Disposable types implement a finalizer.
    ~TypeB()
    {
        Dispose(false);
    }
}

この違反を修正するには、破棄可能なフィールドに対して Dispose() を呼び出します。

protected virtual void Dispose(bool disposing)
{
   if (!disposed)
   {
      // Dispose of resources held by this instance.
      aFieldOfADisposableType.Dispose();

      disposed = true;

      // Suppress finalization of this disposed instance.
      if (disposing)
      {
          GC.SuppressFinalize(this);
      }
   }
}

関連項目