Domanda

Uso un modello di implementazione IDisposable predefinito (modello) per il mio codice.

frammento di codice:

public void Dispose()
{
    Dispose(true);

    GC.SuppressFinalize(this);
}

protected virtual void Dispose(bool isDisposing)
{
    if (!this.disposed)
    {
        if (isDisposing)
        {
            //cleanup managed resources
        }

        //cleanup unmanaged resources

        this.disposed = true;
    }
}

La mia domanda: perché è la chiamata " GC.SuppressFinalize (this) " nel metodo pubblico Dispose? Vorrei inserire " GC.SuppressFinalize (questo) " in " if (isDisposing) " sezione del metodo protetto, dopo aver eliminato le risorse gestite.

In questo modo:

protected virtual void Dispose(bool isDisposing)
{
    if (!this.disposed)
    {
       if (isDisposing)
       {
           //cleanup managed resources

           GC.SuppressFinalize(this);
       }

       //cleanup unmanaged resources

       this.disposed = true;
    }
}
È stato utile?

Soluzione

Suppongo sia un chiaro caso di modello di Template Design.

La tua classe astratta è progettata per occuparsi di tutte le attività importanti / necessarie richieste (qui, GC.SuppressFinalize (questa)) e consentire a una classe derivata di sovrascrivere solo una parte del codice.

Ci sono 2 casi qui:
Snippet 1, SuppressFinalize, in Dispose
Snippet 2, SuppressFinalize, in Dispose (true)

Qui, Snippet 1, si assicura che GC.SuppressFinalize sia sempre eseguito. Mentre snippet 2, lascia l'esecuzione di GC.SuppressFinalize in balia della classe derivata .

Quindi, mettendo GC.SuppressFinalize, nel metodo Dispose, tu come progettista della tua classe ti assicurerai sempre che indipendentemente dal codice scritto dalle classi derivate, GC.SuppressFinalize verrà eseguito.

Questo è solo il vantaggio di scrivere SuppressFinalize in Dispose piuttosto che Dispose (true).

Altri suggerimenti

Il metodo Dispose (bool isDisposing) non fa parte del IDisposable interfaccia.

Normalmente chiameresti Dispose (true) dalla tua Dispose e chiama Dispose (false) dal finalizzatore, come fallback nel caso in cui l'oggetto non sia già stato disposti.

Chiamata SuppressFinalize dice al GC che non è necessario chiamare il finalizzatore del tuo oggetto, presumibilmente perché tutta la pulizia è stata eseguita quando è stato chiamato Dispose .

Se non hai un finalizzatore nella tua classe, non devi assolutamente chiamare SuppressFinalize , poiché non c'è alcun finalizzatore da sopprimere!

Joe Duffy ha alcune ottime linee guida su smaltimento, finalizzazione, raccolta dei rifiuti ecc. .

Penso che entrambi i layout avrebbero potuto essere scelti, ma probabilmente volevano enfatizzare "mettere tutto il codice di deallocazione in questo metodo" nel metodo Dispose protetto, quindi hanno messo l'altro artefatto dello smaltimento (soppressione della finalizzazione) altrove.

Supponiamo inoltre che una classe derivata avesse un altro motivo per chiamare il metodo Dispose protetto, ma voleva comunque che si verificasse la finalizzazione (per qualunque motivo immaginato, non lo so).

Causa. Lo scopo è quando il codice gestito (il tuo codice) elimina l'oggetto eliminando così la finalizzazione. Le persone di solito creano un altro percorso verso Dispose (eliminazione bool) tramite un finalizzatore e la chiamata non avrebbe alcun senso per il finalizzatore.

L'idea è che il tuo codice di pulizia dovrebbe essere chiamato solo una volta. Tuttavia ci sono due punti di ingresso: il metodo Dispose e i finalizzatori di oggetti. Quando viene chiamato Dispose , si annulla la finalizzazione in modo che il codice di cleanup venga chiamato solo una volta. Il codice qui potrebbe illustrarlo meglio.

Quote:

// NOTE: Leave out the finalizer altogether if this class doesn't 
// own unmanaged resources itself, but leave the other methods
// exactly as they are. 
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top