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

Capisco limportanza di disporre correttamente di grandi risorse e risorse non gestite, ma per quanto riguarda laltro lato dellequazione?

Per un oggetto che non beneficia dellimplementazione di IDisposable (piccoli oggetti completamente gestiti) , quale impatto negativo può avere GC.SuppressFinalize, se ce ne sono?

Commenti

  • Sembra unottimizzazione prematura. Sei in grado di chiedere alla persona che ti ha chiesto di farlo i risultati che ha ottenuto dalla profilazione e dal benchmarking che mostrano che laggiunta di IDisposable in questo caso migliora limpronta della memoria?
  • @MainMa No, ma questo ' non mi ha impedito di chiedere comunque. Il risultato è stato una risposta di 5 minuti di " è proprio il modo in cui ' labbiamo sempre fatto, lo fai anche tu ".
  • Bene, è possibile implementare IDisposable senza scrivere un distruttore / finalizzatore. Non ' non so se la persona che ti ha chiesto di implementare IDisposable significava che dovresti creare anche un distruttore. Ovviamente, se la classe non ha un distruttore, non ha senso GC.SuppressFinalize. Se la classe ha un distruttore, assicurati di dire GC.SuppressFinalize(this) quando il tuo metodo Dispose è stato eseguito. In caso contrario, listanza non verrà facilmente raccolta in modo indesiderato, verrà accodata su una coda del finalizzatore e verrà raccolta solo in una raccolta di seconda generazione.
  • @JeppeStigNielsen La domanda afferma che gli oggetti sono gestiti interamente risorse, quindi ' non è necessario disporre di un finalizzatore. Se ce nè uno, sappiamo che ' è sbagliato.

Rispondi

Lunico obiettivo di GC.SuppressFinalize è:

impedire al finalizzatore di rilasciare risorse non gestite che sono già state liberate dallimplementazione IDisposable.Dispose.

Fonte: MSDN

Una volta eliminato loggetto, dovresti effettivamente chiamare GC.SuppressFinalize(this);, come mostrato in una risposta alla domanda ” Quando dovrei usare GC.SuppressFinalize ()? “. Anche la regola di analisi del codice “ CA1816 è utile.

Ora, implementando IDisposable su gli oggetti che non hanno risorse non gestite sembrano abbastanza strani e discutibili. Poiché lunico motivo per cui la persona ti ha dato è stato: “è proprio il modo in cui” lo abbiamo sempre fatto, fallo anche tu “, invece di fornire dati di profilazione / benchmarking che mostrano che laggiunta di IDisposable migliorerà qualcosa in un caso specifico, non ci sono ragioni reali per farlo.

Provocherebbe problemi di prestazioni? Difficile a dirsi: dipenderà da un caso particolare.

causa altri problemi? Ovviamente. Senza contare il fatto che IDisposable è doloroso da implementare, se questa pratica viene usata 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; } } } } } 

Commenti

  • Beh, credo che la storia sia che molto tempo fa avevano qualche connessione / problemi di perdita di flusso, probabilmente a causa della perdita di connessione / comando del codice ADO.NET, e questo ha causato enormi perdite di risorse. Sapevano che limplementazione di IDisposable su tutto avrebbe risolto il problema, quindi lhanno fatto, e ha funzionato. ust implementarlo sulla maggior parte degli oggetti.
  • @AndrewHoffman: sembra una spiegazione plausibile. Ma ancora non ' giustifica la pratica corrente.

Risposta

Non è necessario utilizzare il pattern Dispose + Finalizer pesante (“painful”) su una classe IDisposable, if la classe è sigillata e la classe non ha risorse non gestite.

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

La ragione per sigillare la classe è evitare i problemi di “E se una classe figlia avesse risorse non gestite?” e “E se una classe figlia in futuro avesse risorse non gestite?”

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

I collaboratori dellarticolo includono Herb Sutter, Brian Grunkemeyer, Jeff Richter e altri luminari di C #. Larticolo è molto più approfondito di quanto presentato su MSDN.

Ahimè, il nuovo motore di blog di Joe Duffy non ha fatto un buon lavoro nel preservare larticolo originale del 2005, quindi sembra un po alterato. Ecco il link: http://joeduffyblog.com/2005/04/08/dg-update-dispose-finalization-and-resource-management/

Vorrei poter allegare il mio documento MS-Word che contiene lintero articolo di Joe Duffy in una migliore formato. 🙁

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *