CA1816:正確呼叫 GC.SuppressFinalize

型別名稱

CallGCSuppressFinalizeCorrectly

CheckId

CA1816

分類

Microsoft。使用方式

中斷變更

不中斷

原因

規則描述

在物件可讓記憶體回收之前,IDisposable.Dispose 方法讓使用者可以隨時釋放資源。如果呼叫 IDisposable.Dispose 方法,則會釋放物件的資源。這使得不需要最終處理。IDisposable.Dispose 應該呼叫 GC.SuppressFinalize,以便讓記憶體回收行程不會呼叫物件的完成項。

 

若要避免使用完成項的衍生類別需要重新實作 [System.IDisposable] 以及呼叫它,未使用完成項的非密封型別仍應該呼叫 GC.SuppressFinalize

如何修正違規

若要修正此規則的違規情形:

如果方法是 Dispose 的實作,請將呼叫加入至 GC.SuppressFinalize

如果方法不是 Dispose 的實作,請移除對 GC.SuppressFinalize 的呼叫,或將其移至型別的 Dispose 實作。

變更 GC.SuppressFinalize 的所有呼叫以傳遞 this (Visual Basic 中的 Me)。

隱藏警告的時機

只有在考慮使用 GC.SuppressFinalize 控制其他物件的存留期時,才隱藏這項規則的警告。如果 Dispose 的實作並未呼叫 GC.SuppressFinalize,請勿隱藏這項規則的警告。在這種情況下,無法隱藏最終化將會降低效能且不提供任何好處。

範例

下列範例會示範不正確呼叫 GC.SuppressFinalize 的方法。

Imports System
Imports System.Data.SqlClient

Namespace Samples

    Public Class DatabaseConnector
        Implements IDisposable

        Private _Connection As New SqlConnection

        Public Sub Dispose() Implements IDisposable.Dispose
            Dispose(True)
            GC.SuppressFinalize(True)   ' Violates rules
        End Sub 

        Protected Overridable Sub Dispose(ByVal disposing As Boolean)
            If disposing Then 
                If _Connection IsNot Nothing Then
                    _Connection.Dispose()
                    _Connection = Nothing 
                End If 
            End If 
        End Sub 

    End Class 

End Namespace
using System;
using System.Data.SqlClient;
namespace Samples
{
    public class DatabaseConnector : IDisposable
    {
        private SqlConnection _Connection = new SqlConnection();

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(true);  // Violates rule
        }

        protected virtual void Dispose(bool disposing)
        {
            if (disposing)
            {
                if (_Connection != null)
                {
                    _Connection.Dispose();
                    _Connection = null;
                }
            }
        }
    }
}

下列範例示範以正確方式呼叫 GC.SuppressFinalize 的方法。

Imports System
Imports System.Data.SqlClient

Namespace Samples

    Public Class DatabaseConnector
        Implements IDisposable

        Private _Connection As New SqlConnection

        Public Sub Dispose() Implements IDisposable.Dispose
            Dispose(True)
            GC.SuppressFinalize(Me)
        End Sub 

        Protected Overridable Sub Dispose(ByVal disposing As Boolean)
            If disposing Then 
                If _Connection IsNot Nothing Then
                    _Connection.Dispose()
                    _Connection = Nothing 
                End If 
            End If 
        End Sub 

    End Class 

End Namespace
using System;
using System.Data.SqlClient;

namespace Samples
{
    public class DatabaseConnector : IDisposable
    {
        private SqlConnection _Connection = new SqlConnection();

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

        protected virtual void Dispose(bool disposing)
        {
            if (disposing)
            {
                if (_Connection != null)
                {
                    _Connection.Dispose();
                    _Connection = null;
                }
            }
        }
    }
}

相關規則

CA2215:Dispose 方法應該呼叫基底類別處置

CA2216:可處置類型應該宣告完成項

請參閱

其他資源

Implementing Finalize and Dispose