Condividi tramite


CA1816: Chiamare GC.SuppressFinalize correttamente

TypeName

CallGCSuppressFinalizeCorrectly

CheckId

CA1816

Category

Microsoft. Utilizzo

Breaking Change

Non sostanziale

Causa

Descrizione della regola

Il metodo IDisposable.Dispose consente agli utenti di rilasciare risorse in qualsiasi momento prima che l'oggetto diventi disponibile per un'operazione di Garbage Collection. Se viene chiamato il metodo IDisposable.Dispose, le risorse dell'oggetto vengono liberate. In questo modo non è necessario effettuare la finalizzazione. IDisposable.Dispose dovrebbe chiamare GC.SuppressFinalize affinché il finalizzatore dell'oggetto non venga chiamato dal Garbage Collector.

 

Per evitare che tipi derivati con finalizzatori debbano implementare nuovamente [System.IDisposable] e chiamarlo, è ancora necessario che i tipi non sealed senza finalizzatori chiamino GC.SuppressFinalize.

Come correggere le violazioni

Per correggere una violazione di questa regola:

Se il metodo è un'implementazione di Dispose, aggiungere una chiamata a GC.SuppressFinalize.

Se il metodo non è un'implementazione di Dispose, rimuovere la chiamata a GC.SuppressFinalize oppure spostarla nell'implementazione di Dispose del tipo.

Modifica tutte le chiamate in GC.SuppressFinalize per passare l'elemento this (Me in Visual Basic).

Esclusione di avvisi

Escludere un avviso da questa regola solo se si utilizza deliberatamente GC.SuppressFinalize per controllare la durata di altri oggetti. Non escludere un avviso da questa regola se un'implementazione di Dispose non chiama GC.SuppressFinalize. In questa situazione, la mancata esclusione della finalizzazione comporta un calo delle prestazioni e non offre alcun vantaggio.

Esempio

Nell'esempio riportato di seguito viene illustrato un metodo che chiama GC.SuppressFinalize in modo non corretto.

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

Nell'esempio riportato di seguito viene illustrato un metodo che chiama correttamente 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;
                }
            }
        }
    }
}

Regole correlate

CA2215: I metodi Dispose devono chiamare il metodo Dispose della classe base

CA2216: I tipi Disposable devono dichiarare un finalizzatore

Vedere anche

Riferimenti

Implementazione dei metodi Finalize e Dispose per la pulizia delle risorse non gestite