Distruggi manualmente gli oggetti C #

Sono abbastanza nuovo nell’apprendimento di C # (da Java e C ++ in background) e ho una domanda sullo smaltimento dei rifiuti manuale: è persino ansible distruggere manualmente un object in C #? Conosco l’interfaccia IDisposable , ma suppongo di avere a che fare con una class che non ho scritto e non la implementa? Non avrebbe un metodo .Dispose() , quindi l’ using { } è fuori e .Finalize è sempre protected o private quindi non è nemmeno un’opzione.

(Sto solo cercando di imparare cosa è ansible in C # in questo caso, suppongo che se tutto il resto fallisce potrei ereditare l’ipotetica class ImNotDisposable modo che implementi IDisposable.)

Non distruggi manualmente gli oggetti .Net. Questo è ciò che significa essere un ambiente gestito.

Infatti, se l’object è effettivamente raggiungibile, il che significa che hai un riferimento che puoi usare per dire al GC quale object vuoi distruggere, la raccolta di quell’object sarà imansible. Il GC non raccoglierà mai alcun object ancora raggiungibile.

Quello che puoi fare è chiamare GC.Collect() per forzare una raccolta generale. Tuttavia, questa non è quasi mai una buona idea.

Invece, probabilmente è meglio fingere semplicemente che qualsiasi object che non utilizza risorse non gestite e che non è raggiungibile da nessun altro object nel programma venga immediatamente distrutto. So che questo non succede, ma a questo punto l’object è solo un blocco di memoria come qualsiasi altro; non puoi recuperarlo e alla fine verrà raccolto, quindi potrebbe anche essere morto per te.

Un’ultima nota su IDisposable . Dovresti usarlo solo per tipi che racchiudono risorse non gestite : cose come socket, connessioni al database, oggetti gdi, ecc. E l’abbonamento occasionale di eventi / delegati.

Se l’object non è raggiungibile, puoi chiamare GC.Collect() e l’object verrà distrutto. Il concetto di IDisposable non ha nulla a che fare con il CLR ed è principalmente per il codice utente da implementare per eseguire una logica di smaltimento aggiuntiva . Chiamare Dispose () su un object non libererà l’object stesso dalla memoria, sebbene possa benissimo disporre di tutte le risorse a cui questo object fa riferimento.

Dovrei aggiungere che mentre quello che ho detto è un modo per raggiungere questo objective, nel 99,999% delle applicazioni non dovresti mai chiamare GC.Collect() perché spesso peggiorerà le prestazioni della tua applicazione invece di migliorarla.

Sebbene sia ansible triggersre la garbage collection (è necessario triggersre GC per tutte le generazioni perché non si può essere sicuri della generazione in cui si trova l’object finalizzabile) non è ansible forzare necessariamente la finalizzazione di un particolare object. Puoi solo dipendere da supposizioni su come funziona il garbage collector.

Inoltre, poiché la finalizzazione avviene sul proprio thread, è necessario chiamare WaitForPendingFinalizers dopo aver triggersto la garbage collection.

 GC.Collect(GC.MaxGeneration); GC.WaitForPendingFinalizers(); 

Come è stato notato da altri, questo può effettivamente danneggiare le prestazioni dell’applicazione perché invocando inutilmente il GC può promuovere oggetti altrimenti di breve durata in generazioni più elevate, che sono più costosi da raccogliere e raccolti meno frequentemente.

In generale, una class che implementa un finalizzatore (distruttore) e non implementa IDisposable è disapprovata. E tutto ciò che implementa IDisposable dovrebbe chiamare la logica del finalizzatore e sopprimersi dalla finalizzazione alla garbage collection.

Jeff Richter ha recentemente pubblicato un piccolo trucco per ricevere una notifica quando si verifica la garbage collection .

Un altro grande articolo su Nozioni di base su Garbage Collector e suggerimenti per le prestazioni di Rico Mariani (MSFT)

No, non puoi distruggere un object specifico.

È ansible invocare il garbage collector, che cercherà gli oggetti da distruggere, ma non è quasi mai una buona idea.

È ansible forzare l’esecuzione del garbage collector dopo che la variabile che si desidera distruggere non rientra nello scope, ma normalmente non si vuole farlo, poiché il garbage collector è più efficiente se lasciato a fare il proprio lavoro.

La forzatura della garbage collection può essere fatta con GC.Collect , ma non farlo. Nei miei 10 anni come sviluppatore .NET, non ne ho mai avuto bisogno.

Non è ansible distruggere un object in modo deterministico. Il CLR determina quando viene recuperato l’object contrassegnato. Ciò significa che mentre è ansible contrassegnare un object per il recupero e garantire che le risorse gestite e non gestite siano riordinate per lo smaltimento (implementando il modello IDisposable), il tempo effettivo di rilascio della memoria dipende dal CLR. Questo è diverso dal C ++ in cui potresti effettivamente cancellare qualcosa e poi sarebbe stato rilasciato.

Buona programmazione,

Scott

Non puoi distruggere manualmente un object “come C ++ delete”, tutto ciò che puoi fare è chiudere tutte le risorse esclusive che l’object ha acquisito e annullare tutti i riferimenti a questo object, in modo che il GC possa raccoglierlo, inoltre non chiamare GC .Collect () da solo, il processo GC è costoso, in quanto deve sospendere tutti gli altri thread per raccogliere in modo sicuro gli oggetti dalla memoria, quindi affidati al GC e si avvierà quando necessario.

Supponi di avere una matrice di classi e hai creato due oggetti matrice a matrice e batrice. In C # puoi distruggere manualmente (finalizzare) un object in questo modo:

aMatrix = NULL;

GC.Collect ();

Il garbage collector noterà che aMatrix è NULL e lo distruggerà (finalizzandolo). Che questa sia o meno una buona idea è una storia diversa.