CA1816: Chiamare GC.SuppressFinalize correttamente

Proprietà valore
ID regola CA1816
Title Chiamare GC.SuppressFinalize correttamente
Categoria Utilizzo
Correzione che causa un'interruzione o un'interruzione Nessuna interruzione
Abilitato per impostazione predefinita in .NET 8 Come suggerimento

Causa

Le violazioni di questa regola possono essere causate da:

Descrizione regola

Il IDisposable.Dispose metodo consente agli utenti di rilasciare le risorse in qualsiasi momento prima che l'oggetto diventi disponibile per l'operazione di Garbage Collection. Se viene chiamato il IDisposable.Dispose metodo , libera le risorse dell'oggetto . In questo modo, la finalizzazione non è necessaria. IDisposable.Dispose deve chiamare GC.SuppressFinalize in modo che il Garbage Collector non chiami il finalizzatore dell'oggetto.

Per evitare che i tipi derivati con finalizzatori debbano ripetere IDisposable e chiamarlo, i tipi non bloccati senza finalizzatori devono comunque chiamare GC.SuppressFinalize.

Come correggere le violazioni

Per correggere una violazione di questa regola:

Quando eliminare gli avvisi

Eliminare un avviso da questa regola solo se si usa GC.SuppressFinalize deliberatamente per controllare la durata di altri oggetti. Non eliminare un avviso da questa regola se un'implementazione di Dispose non chiama GC.SuppressFinalize. In questa situazione, la mancata eliminazione della finalizzazione degrada le prestazioni e non offre alcun vantaggio.

Eliminare un avviso

Se si vuole eliminare una singola violazione, aggiungere direttive del preprocessore al file di origine per disabilitare e quindi riabilitare la regola.

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

Per disabilitare la regola per un file, una cartella o un progetto, impostarne la gravità none su nel file di configurazione.

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

Per altre informazioni, vedere Come eliminare gli avvisi di analisi del codice.

Esempio che viola CA1816

Questo codice mostra un metodo che chiama , ma non passa questo (C#) o Me (Visual Basic).This code shows a method that calls GC.SuppressFinalize, but't pass this (C#) or Me (Visual Basic). Di conseguenza, questo codice viola la regola CA1816.

Public Class DatabaseConnector
    Implements IDisposable

    Private _Connection As New SqlConnection

    Public Sub Dispose() Implements IDisposable.Dispose
        Dispose(True)
        ' Violates rules
        GC.SuppressFinalize(True)
    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
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;
            }
        }
    }
}

Esempio che soddisfa CA1816

In questo esempio viene illustrato un metodo che chiama correttamente passando questo (C#) o Me (Visual Basic).This example shows a method that correctly calls GC.SuppressFinalize by passing this (C#) or Me (Visual Basic).

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

Vedi anche