GC.SuppressFinalize può causare problemi di prestazioni?

2

Mi viene chiesto di implementare IDisposable su oggetti che sono risorse gestite al 100%, che non contengono flussi e senza grandi risorse.

Capisco l'importanza di disporre correttamente di grandi risorse e risorse non gestite, ma per quanto riguarda l'altro lato dell'equazione?

Per un oggetto che non beneficia dell'implementazione di IDisposable (piccoli oggetti completamente gestiti), quale impatto negativo può avere GC.SuppressFinalize?

    
posta Andrew Hoffman 26.07.2014 - 18:53
fonte

2 risposte

4

L'unico obiettivo di GC.SuppressFinalize è:

to prevent the finalizer from releasing unmanaged resources that have already been freed by the IDisposable.Dispose implementation.

Origine: MSDN

Una volta eliminato l'oggetto, dovresti chiamare GC.SuppressFinalize(this); , come mostrato in una risposta alla domanda "Quando dovrei usare GC.SuppressFinalize ()? ". Anche l'analisi del codice ' CA1816 è utile.

Ora, implementare IDisposable su oggetti che non hanno risorse non gestite sembra piuttosto strano e discutibile. Poiché l'unica ragione per cui la persona ti ha dato è stata: "è proprio come l'abbiamo sempre fatto, lo fai anche tu", invece di fornire dati di profilazione / benchmarking che dimostrano che l'aggiunta di IDisposable migliorerà qualcosa in un caso specifico, non ci sono motivi reali per farlo.

Potrebbe causare problemi di prestazioni? Difficile da dire: dipenderà dal caso particolare.

Potrebbe causare altri problemi? Ovviamente. Senza contare il fatto che IDisposable è doloroso da implementare, se questa pratica viene utilizzata troppo, il codice diventa illeggibile e impossibile da mantenere:

public int ComputePrice(Rebate rebate)
{
    using (var currentCurrency = this.User.FindCurrency())
    {
        using (var priceWithoutRebate = this.GetPurePrice())
        {
            using (var canApplyRebate = rebate.CanApplyTo(this))
            {
                if (!canApplyRebate)
                {
                    return priceWithoutRebate;
                }

                using (var priceWithRebate = priceWithoutRebate.Apply(rebate))
                {
                    return priceWithRebate;
                }
            }
        }
    }
}
    
risposta data 26.07.2014 - 19:35
fonte
2

Non è necessario utilizzare il modello di Dispose + Finalizer pesante ("doloroso") su una classe IDisposable, se la classe è sigillata e la classe non ha risorse non gestite.

In questa situazione, puoi usare un sottoinsieme del pattern Dispose + Finalizer, che ha solo public Dispose() , non ha finalizzatore e la classe è sealed.

La ragione per sigillare la classe è di evitare i problemi di "Cosa succede se una classe figlia ha risorse non gestite?" e "Cosa succede se una classe figlia in futuro avrà risorse non gestite?"

Joe Duffy, ex Microsoft, ha un lungo articolo (più di 30 pagine) che spiega come implementare correttamente IDisposable e tutte le implementazioni dei sottoinsiemi di permutazioni.

I contributori all'articolo includono Herb Sutter, Brian Grunkemeyer, Jeff Richter e altri luminari C #. L'articolo è molto più approfondito di ciò che viene presentato su MSDN.

Ahimè, il nuovo motore di blog di Joe Duffy non ha fatto un buon lavoro nel preservare l'articolo originale del 2005, quindi sembra un po 'mungito. Ecco il link: link

Vorrei poter allegare il mio documento MS-Word che contiene l'intero articolo di Joe Duffy in un formato molto migliore. : - (

    
risposta data 04.10.2016 - 16:53
fonte

Leggi altre domande sui tag