Condividi tramite


Chiamare correttamente GC.SuppressFinalize

Aggiornamento: novembre 2007

TypeName

CallGCSuppressFinalizeCorrectly

CheckId

CA1816

Category

Microsoft. Utilizzo

Breaking Change

Non sostanziale

Causa

Un metodo che rappresenta un'implementazione di Dispose non chiama GC.SuppressFinalize.

-oppure-

Un metodo che non rappresenta un'implementazione di Dispose chiama GC.SuppressFinalize.

-oppure-

Un metodo chiama GC.SuppressFinalize e passa un elemento diverso da this (Me in Visual Basic).

Descrizione della regola

Il metodo 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 Dispose, le risorse dell'oggetto vengono liberate. In questo modo, la finalizzazione non è più necessaria. 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.

Correzione di 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.

Modificare tutte le chiamate a GC.SuppressFinalize per passare 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 erroneamente GC.SuppressFinalize passandolo true (True in Visual Basic).

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

I tipi eliminabili devono dichiarare un finalizzatore

Vedere anche

Riferimenti

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