CA2213:可處置的欄位應該受到處置

屬性
規則識別碼 CA2213
標題 可處置的欄位應該受到處置
類別 使用方式
修正程式是中斷或非中斷 不中斷
預設在 .NET 8 中啟用 No

原因

實作 System.IDisposable 的型別會宣告同時實 IDisposable 作 之型別的欄位。 宣告 Dispose 型別的 方法不會呼叫 Dispose 欄位的方法。

檔案描述

類型負責處置其所有 Unmanaged 資源。 規則 CA2213 會檢查可處置型別(也就是 IDisposable 實作的型別) T 是否宣告為可處置型 FT 別實例的欄位 F 。 針對在包含型 T 別的方法或初始化運算式內指派本機建立之物件的每個欄位 F ,規則會嘗試尋找 對 FT.Dispose 的呼叫。 規則會搜尋 所 T.Dispose 呼叫的方法,並搜尋較低層級的方法(也就是 由 呼叫的方法所呼叫 T.Dispose 的方法。

注意

除了 特殊案例 之外,規則 CA2213 只會針對在包含類型的方法和初始化運算式內指派本機建立的可處置物件之欄位引發。 如果物件是在 類型 T 之外建立或指派,則不會引發規則。 這可減少包含類型不負責處置物件的案例的雜訊。

特殊情況

即使未在本機建立指派的物件,規則 CA2213 也可以針對下列類型的欄位引發:

將其中一個型別的物件傳遞至建構函式,然後將它指派給欄位,表示 處置擁有權傳送 至新建構的類型。 也就是說,新建構的類型現在負責處置 物件。 如果未處置物件,就會發生 CA2213 違規。

如何修正違規

若要修正此規則的違規,請在實作 的型 IDisposable 別字段上呼叫 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);
    }
}

下列程式碼片段顯示違反規則 CA2213 的類型 TypeB ,方法是將欄位 aFieldOfADisposableType 宣告為可處置類型 ( TypeA ), 而不是在欄位上呼叫 Dispose

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

另請參閱