Domanda

L' .NET garbage collector, infine, liberare memoria, ma cosa succede se si desidera che la memoria indietro subito?Il codice che avete bisogno di utilizzare in classe MyClass per chiamare

MyClass.Dispose()

e liberare tutto lo spazio utilizzato da variabili e oggetti in MyClass?

È stato utile?

Soluzione

IDisposable non ha nulla a che fare con la liberazione di memoria.IDisposable è un modello per liberare non gestito delle risorse, e la memoria è sicuramente una risorsa gestita.

Il link che puntano al GC.Raccogliere() sono la risposta corretta, anche se l'uso di questa funzione è generalmente scoraggiato da Microsoft .NET documentazione.

Edit: Dopo aver guadagnato una notevole quantità di karma per questa risposta, mi sento una certa responsabilità di elaborare su di esso, per timore che un nuovo arrivato .NETTO di gestione delle risorse avere l'impressione sbagliata.

All'interno di un .NET processo, ci sono due tipi di risorsa-gestiti e non gestiti."Gestiti" significa che il runtime è il controllo della risorsa, mentre "non gestito" significa che è responsabilità del programmatore.E c'è davvero un solo tipo di risorsa gestita che teniamo in .NET oggi -- memoria.Il programmatore dice il runtime per allocare la memoria e dopo che il runtime di capire quando la memoria liberata.Il meccanismo che .NET utilizza per questo scopo si chiama garbage collection e si possono trovare un sacco di informazioni su GC su internet semplicemente utilizzando Google.

Per altri tipi di risorse .NET non sa nulla di pulizia li, quindi ha a che fare affidamento sulla programmatore di fare la cosa giusta.A tal fine, la piattaforma offre al programmatore di tre strumenti:

  1. L'interfaccia IDisposable e "utilizzo di" dichiarazione in C#e VB
  2. Finalizzatori
  3. IDisposable modello implementato da molti BCL classi

Il primo di essi permette al programmatore di efficienza acquisire una risorsa, utilizzare e quindi rilasciare entro lo stesso metodo.

using (DisposableObject tmp = DisposableObject.AcquireResource()) {
    // Do something with tmp
}
// At this point, tmp.Dispose() will automatically have been called
// BUT, tmp may still a perfectly valid object that still takes up memory

Se "AcquireResource" è un metodo factory che (per esempio) apre un file e "Smaltire" chiude automaticamente il file, allora questo codice non può perdita di un file di risorse.Ma la memoria per "tmp" oggetto in sé, potrebbe essere ancora assegnati.Questo perché l'interfaccia IDisposable, non ha assolutamente alcuna connessione con il garbage collector.Se si fatto per assicurarsi che la memoria è stata liberata, l'unica opzione sarebbe quella di chiamare GC.Collect() per forza di una procedura di garbage collection.

Tuttavia, non può essere sottolineato abbastanza che questo è probabilmente una buona idea.È generalmente molto meglio lasciare che il garbage collector di fare ciò che è stato progettato per fare, che è quello di gestire la memoria.

Cosa succede se la risorsa è stata utilizzata per un periodo di tempo più lungo, in modo che la sua vita attraversa diversi metodi?Chiaramente, il "utilizzando" l'istruzione non è più applicabile, in modo che il programmatore dovrebbe chiamare manualmente "Smaltire" quando lui o lei è fatto con la risorsa.E cosa succede se il programmatore si dimentica?Se non c'è un ripiego, quindi il processo o il computer può essere eseguito alla fine di qualsiasi risorsa non viene liberato correttamente.

Che è dove i finalizzatori venire.Un finalizzatore è un metodo di classe che ha un rapporto speciale con il garbage collector.Il GC promesse che-prima di liberare la memoria per un oggetto di quel tipo, prima di dare il finalizzatore di una possibilità di fare qualche tipo di pulizia.

Quindi, nel caso di un file, teoricamente non c'è bisogno di chiudere manualmente il file a tutti.Possiamo solo aspettare fino a quando il garbage collector viene a e poi lascia il finalizzatore fare il lavoro.Purtroppo, questo non funziona bene, in pratica, perché il garbage collector viene eseguito in modalità non in modo deterministico.Il file può rimanere aperto notevolmente più lunghi rispetto a programmatore prevede.E se un numero sufficiente di file vengono tenute aperte, il sistema potrebbe non riuscire quando si tenta di aprire un file aggiuntivo.

Per la maggior parte delle risorse, ci vogliono entrambe le cose.Vogliamo una convenzione per poter dire "abbiamo finito con questa risorsa" e vogliamo fare in modo che ci sia almeno qualche possibilità per la pulizia avviene automaticamente se ci dimentichiamo di farlo manualmente.Questo è dove il "IDisposable" modello entra in gioco.Questa è una convenzione che permette IDispose e un finalizzatore per giocare bene insieme.Si può vedere come il modello funziona, cercando il la documentazione ufficiale per IDisposable.

Linea di fondo: Se ciò che si vuole veramente fare è assicurarsi che la memoria viene liberata, quindi IDisposable e finalizzatori non vi aiuterà.Ma l'interfaccia IDisposable, è parte di un modello estremamente importante che tutti .NET i programmatori dovrebbero capire.

Altri suggerimenti

Si può solo smaltire le istanze che implementano l'interfaccia IDisposable.

Per forza di un bidone della spazzatura raccogliere il (non gestito) memoria:

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

Questo di solito è una pessima abitudine, ma c'è per esempio un bug nel x64 versione .NET framework che rende il GC comportarsi strano in alcuni scenari, e allora si potrebbe desiderare di fare questo.Non so se il bug è stato risolto ancora.Qualcuno lo sa?

Per smaltire una classe, fare questo:

instance.Dispose();

o come questa:

using(MyClass instance = new MyClass())
{
    // Your cool code.
}

che si tradurranno in fase di compilazione di:

MyClass instance = null;    

try
{
    instance = new MyClass();        
    // Your cool code.
}
finally
{
    if(instance != null)
        instance.Dispose();
}

È possibile implementare l'interfaccia IDisposable, come questo:

public class MyClass : IDisposable
{
    private bool disposed;

    /// <summary>
    /// Construction
    /// </summary>
    public MyClass()
    {
    }

    /// <summary>
    /// Destructor
    /// </summary>
    ~MyClass()
    {
        this.Dispose(false);
    }

    /// <summary>
    /// The dispose method that implements IDisposable.
    /// </summary>
    public void Dispose()
    {
        this.Dispose(true);
        GC.SuppressFinalize(this);
    }

    /// <summary>
    /// The virtual dispose method that allows
    /// classes inherithed from this one to dispose their resources.
    /// </summary>
    /// <param name="disposing"></param>
    protected virtual void Dispose(bool disposing)
    {
        if (!disposed)
        {
            if (disposing)
            {
                // Dispose managed resources here.
            }

            // Dispose unmanaged resources here.
        }

        disposed = true;
    }
}

Le risposte a questa domanda hanno avuto più di un po ' confuso.

Il titolo chiede di smaltimento, ma poi dice che vuole indietro la memoria immediatamente.

.Net è gestito, il che significa che quando si scrive .Netto di applicazioni non è necessario preoccuparsi di memoria direttamente, il costo è di non avere il controllo diretto di memoria.

.Net decide quando è il momento migliore per pulire e liberare la memoria, non è come l' .Net coder.

Il Dispose è un modo di dire .Net che hai fatto qualcosa, ma non si libera la memoria fino a quando è il momento migliore per farlo.

Fondamentalmente .Net effettivamente raccogliere la memoria indietro quando è il metodo più semplice per farlo è molto bravo a decidere quando.A meno che non si sta scrivendo qualcosa di molto intensivo di memoria normalmente non è necessario annullare (questo è parte del motivo per cui i giochi non sono spesso scritti in .Net di sicurezza, hanno bisogno di un controllo completo)

In .Net, è possibile utilizzare GC.Collect() a forza di farlo immediatamente, ma che è quasi sempre cattiva pratica.Se .Net non ha ripulito ma che significa che non è un buon momento per farlo.

GC.Collect() raccoglie gli oggetti che .Net identifica come fatto con.Se non hai smaltito un oggetto di cui ha bisogno .Net può decidere di tenere l'oggetto.Questo significa che GC.Collect() è efficace solo se è correttamente implementare il monouso istanze.

GC.Collect() è non una sostituzione per il corretto uso IDisposable.

Così Smaltire e la memoria non sono direttamente correlati, ma non hanno bisogno di essere.Corretto smaltimento renderà il vostro .Net app più efficiente, e quindi utilizzare meno memoria però.


Il 99% del tempo .Netto il seguito è migliore pratica:

Regola 1: Se non si occupano di nulla non gestito o che implementa IDisposable quindi non preoccuparti di Smaltire.

Regola 2: Se si dispone di una variabile locale che implementa IDisposable assicurarsi che si sbarazzarsi di esso nell'ambito corrente:

//using is best practice
using( SqlConnection con = new SqlConnection("my con str" ) )
{
    //do stuff
} 

//this is what 'using' actually compiles to:
SqlConnection con = new SqlConnection("my con str" ) ;
try
{
    //do stuff
}
finally
{
    con.Dispose();
}

Regola 3: Se una classe ha una proprietà o di un membro di una variabile che implementa IDisposable quindi che la classe deve implementare IDisposable troppo.In che classe il metodo Dispose è anche possibile smaltire i IDisposable proprietà:

//rather basic example
public sealed MyClass :
   IDisposable
{   
    //this connection is disposable
    public SqlConnection MyConnection { get; set; }

    //make sure this gets rid of it too
    public Dispose() 
    {
        //if we still have a connection dispose it
        if( MyConnection != null )
            MyConnection.Dispose();

        //note that the connection might have already been disposed
        //always write disposals so that they can be called again
    }
}

Questo non è davvero completo, che è il motivo per cui l'esempio è sigillato.Ereditando le classi possono avere bisogno di osservare la regola successiva...

Regola 4: Se una classe utilizza un non gestito risorsa implementare IDispose e aggiungi un finaliser.

.Net non può fare nulla con il non gestito la risorsa, così ora stiamo parlando di memoria.Se non pulito è possibile ottenere una perdita di memoria.

Il metodo Dispose bisogno di trattare con entrambi gestito e non gestito risorse.

Il finaliser è un fermo di sicurezza, assicura che se qualcun altro crea e istanza della classe e non riesce a smaltire il 'pericoloso' non gestito le risorse possono ancora essere ripulito da .Net.

~MyClass()
{
    //calls a protected method 
    //the false tells this method
    //not to bother with managed
    //resources
    this.Dispose(false);
}

public void Dispose()
{
    //calls the same method
    //passed true to tell it to
    //clean up managed and unmanaged 
    this.Dispose(true);

    //as dispose has been correctly
    //called we don't need the 

    //'backup' finaliser
    GC.SuppressFinalize(this);
}

Infine questo sovraccarico di Disporre che prende un flag booleano:

protected virtual void Dispose(bool disposing)
{
    //check this hasn't been called already
    //remember that Dispose can be called again
    if (!disposed)
    {
        //this is passed true in the regular Dispose
        if (disposing)
        {
            // Dispose managed resources here.
        }

        //both regular Dispose and the finaliser
        //will hit this code
        // Dispose unmanaged resources here.
    }

    disposed = true;
}

Si noti che una volta che questo è tutto a posto altro codice gestito la creazione di un'istanza della classe può solo trattare come qualsiasi altro IDisposable (Regole 2 e 3).

Sarebbe opportuno anche ricordare che smaltire non fare sempre riferimento alla memoria?Ho disporre di risorse tali riferimenti a file più spesso di memoria.GC.Raccogliere() si riferisce direttamente la CLR garbage collector e può o non può liberare la memoria (nel Task Manager).È probabile che l'impatto della vostra applicazione in maniera negativa (ad esempio, prestazioni).

Alla fine della giornata, perché si desidera che la memoria indietro subito?Se non c'è memoria da altrove, l'OS si arriva memoria nella maggior parte dei casi.

Date un'occhiata a questo articolo

Attuazione del modello Dispose, IDisposable, e/o di un finalizzatore non ha assolutamente nulla a che fare con quando la memoria viene recuperato;invece, ha tutto a che fare con il dire che il GC come per liberare memoria.Quando si chiama Dispose() non sono in alcun modo interagire con il GC.

Il GC viene eseguito solo quando si determina la necessità, chiamato memoria di pressione) e poi (e solo poi) sarà deallocare la memoria per gli oggetti non utilizzati e compatto lo spazio di memoria.

Si potrebbe chiamata GC.Raccogliere (), ma davvero non dovrebbe, a meno che non c'è un molto una buona ragione (che è quasi sempre "Mai").Quando si forza un out-of-band ciclo di raccolta come questa, è effettivamente causare il GC per lavorare di più e, infine, può finire male, le prestazioni delle applicazioni.Per tutta la durata del GC ciclo di raccolta l'applicazione è in realtà in uno stato congelato...più GC cicli di esecuzione, il tempo più la vostra applicazione spende congelati.

Ci sono anche alcuni nativa Win32 API chiamate è possibile effettuare gratuitamente il tuo set di lavoro, ma anche quelli che dovrebbero essere evitato a meno che non ci sia un molto buon motivo per farlo.

Tutta la premessa alla base di un gargbage raccolti runtime è che non c'è bisogno di preoccuparsi (tanto) quando il runtime alloca/dealloca di memoria effettivo;hai solo bisogno di preoccuparsi di fare in modo che il vostro oggetto sa come pulire dopo di sé, quando richiesto.

public class MyClass : IDisposable
{
    public void Dispose()
    {
       // cleanup here
    }
}

allora si può fare qualcosa di simile a questo

MyClass todispose = new MyClass();
todispose.Dispose(); // instance is disposed right here

o

using (MyClass instance = new MyClass())
{

}
// instance will be disposed right here as it goes out of scope

Spiegazione completa di Joe Duffy su "Smaltire, la Finalizzazione e la Gestione delle Risorse":

In precedenza nel .NET Framework vita, i finalizzatori sono stati costantemente di cui all'come distruttori da C# programmatori.Come possiamo diventare più intelligenti, più di ora, stiamo cercando di venire a patti con il fatto che il Metodo Dispose è davvero più equivalente a un C++ distruttore (deterministico), mentre il finalizzatore è qualcosa di completamente separato (non deterministico).Il fatto che C# in prestito il distruttore di C++ sintassi (cioè~T()) sicuramente avuto almeno un po ' a che fare con lo sviluppo di questo termine improprio.

Ho scritto un riassunto di Distruttori e Smaltire e la raccolta dei rifiuti sul http://codingcraftsman.wordpress.com/2012/04/25/to-dispose-or-not-to-dispose/

Per rispondere alla domanda originale:

  1. Non cercare di gestire la memoria
  2. Smaltire non è circa la gestione della memoria, si tratta di non gestito di gestione delle risorse
  3. Finalizzatori sono una parte innata di Smaltire il modello e la realtà rallentare memoria liberare di oggetti gestiti (come devono andare in coda di Finalizzazione, a meno che già disponiamo d)
  4. GC.Raccogliere è un male in quanto si fa un pò di breve durata, gli oggetti sembrano essere necessari per di più e quindi rallenta essere raccolto.

Tuttavia, GC.Raccolta, può essere utile se si ha un rendimento sezione critica di codice e voleva ridurre il rischio di Garbage Collection rallentare le prestazioni.Si chiama prima.

In cima a quello, c'è un argomento a favore di questo modello:

var myBigObject = new MyBigObject(1);
// something happens
myBigObject = new MyBigObject(2);
// at the above line, there are temporarily two big objects in memory and neither can be collected

vs

myBigObject = null; // so it could now be collected
myBigObject = new MyBigObject(2);

Ma la risposta è che la Garbage Collection, semplicemente, funziona a meno che non si scherza con esso!

Non si può davvero la forza di un GC per pulire un oggetto quando si vuole, anche se ci sono modi per forzare l'esecuzione, nulla dice un po ' tutto l'oggetto che si vuole/si aspettano.È meglio chiamare dispose in un try catch ex infine smaltire fine prova (VB.NET rulz) modo.Ma Smaltire è per la pulizia di risorse di sistema (memoria, maniglie, db connessioni, etc.assegnato l'oggetto in modo deterministico.Smaltire non è (e non può) ripulire la memoria utilizzata dall'oggetto stesso, ma solo il GC può fare.

Questo articolo ha una abbastanza semplice procedura.Tuttavia, avendo per chiamare il GC, invece di lasciare prendere il suo corso naturale è generalmente un segno di cattiva progettazione/gestione della memoria, in particolare se non limitate risorse sono state consumate (connessioni, maniglie, qualsiasi altra cosa che in genere porta all'implementazione di IDisposable).

Che cosa sta causando la necessità di fare questo?

Mi dispiace ma la risposta selezionata qui non è corretto.Come alcuni hanno affermato successivamente Smaltire e l'attuazione di IDisposable ha nulla a che fare con liberando la memoria associata con .NETTO di classe.Esso è principalmente utilizzato tradizionalmente per liberare le risorse gestite come gli handle di file etc.

Mentre l'applicazione può chiamare GC.Raccogliere() per cercare di forzare una collezione dal garbage collector questo sarà solo davvero avere un effetto su quegli elementi che sono alla generazione corretto livello in freachable coda.Quindi è possibile che se hai eliminato tutti i riferimenti all'oggetto potrebbe essere ancora un paio di chiamate per GC.Raccogliere() prima che la memoria non viene liberata.

Non dici la tua domanda PERCHÉ si sente il bisogno di liberare memoria immediatamente.Capisco che a volte ci possono essere circostanze insolite, ma sul serio, in codice gestito è quasi sempre meglio lasciare il runtime di affrontare la gestione della memoria.

Probabilmente il miglior consiglio se pensi che il tuo codice è che utilizza la memoria più veloce di quanto il GC è la liberazione, allora si dovrebbe rivedere il codice per assicurarsi che non vi siano oggetti che non sono più necessari, si fa riferimento a una qualsiasi struttura di dati che si hanno in giro nel di membri statici etc.Anche cercare di evitare le situazioni in cui si devono circolare riferimenti a oggetti, come è possibile che questi non possono essere liberati sia.

@Keith,

Sono d'accordo con tutte le regole tranne il #4.Aggiungendo un finalizzatore deve essere fatto solo in circostanze molto specifiche.Se una classe utilizza risorse non gestite, queste devono essere puliti nel tuo Smaltire(bool) funzione.Questa stessa funzione solo di pulitura delle risorse gestite, quando bool è vero.Aggiungendo un finalizzatore aggiunge una complessità di costo per l'uso di oggetti come ogni volta che si crea una nuova istanza deve essere anche inserito nella coda di finalizzazione, che viene controllato ogni volta che il GC viene eseguito un ciclo di raccolta.Effettivamente, questo significa che il vostro oggetto sopravvive un ciclo/generazione più dovrebbe così il finalizzatore può essere eseguito.Il finalizzatore non deve essere pensato come una "rete di sicurezza".

Il GC solo eseguire un ciclo di raccolta quando si determina che non c'è abbastanza memoria disponibile nel Gen0 heap per eseguire l'assegnazione successiva, a meno che non si "guida" chiamando GC.Raccogliere() per forzare un out-of-band di raccolta.

La linea di fondo è che, non importa cosa, il GC solo sa come liberare risorse da chiamare il metodo Dispose (e, eventualmente, il finalizzatore se uno è implementato).È che il metodo di "fare la cosa giusta" e pulire eventuali risorse non gestite utilizzato e indicare eventuali altre risorse gestite per chiamare il loro metodo Dispose.È molto efficiente in quello che fa e in grado di auto-ottimizzazione, in larga misura, fintanto che non è aiutato da out-of-band cicli di raccolta.Detto questo, a corto di chiamata GC.Raccogliere in modo esplicito si ha alcun controllo su quando e in quale ordine gli oggetti verranno smaltiti e memoria rilasciati.

Se MyClass implementa IDisposable si può fare proprio questo.

MyClass.Dispose();

Best practice in C# è:

using( MyClass x = new MyClass() ) {
    //do stuff
}

Come quello che avvolge la dispose in un try-finally e fa in modo che non è mai mancato.

Se non si vuole (o non può) implementa IDisposable in classe, è possibile forzare la garbage collection come questo (ma è lento) -

GC.Collect();

Interfaccia IDisposable è davvero per le classi che contengono le risorse gestite.Se la tua classe non contiene risorse non gestite, perché non si bisogno per liberare risorse prima che il garbage collector non è vero?In caso contrario, basta assicurarsi l'oggetto viene istanziato il più tardi possibile e che va al di fuori del campo di applicazione il più presto possibile.

Si può avere deterministico oggetto di distruzione in c++

Non si desidera mai chiamata GC.Raccogliere, pasticci con l'autotaratura del garbage collector per rilevare la memoria di pressione e, in alcuni casi, non fanno altro che aumentare l'attuale generazione di ogni oggetto sullo heap.

Per chi distacco IDisposable risposte.Chiamata di un metodo Dispose per non "distruggere" un oggetto come il richiedente descrive.

@Veronica:

IDisposable è per le risorse gestite.

Finalisers sono per le risorse gestite.

Mi dispiace ma non è vero.Normalmente, il finalizzatore fa nulla.Tuttavia, se il smaltire il modello è stato correttamente attuato, il finalizzatore tenta di richiamare Dispose.

Dispose dispone di due lavori:

  • Liberare le risorse gestite, e
  • gratuito nidificati risorse gestite.

E qui la sua dichiarazione entra in gioco, perchè è vero che durante la finalizzazione, un oggetto che non dovrebbe mai cercare di liberare nidificati risorse gestite, in quanto questi sono già stati liberati.Si deve ancora liberare le risorse gestite però.

Ancora, i finalizzatori senza lavoro, oltre che per chiamare Dispose e di dirgli di non toccare gli oggetti gestiti. Dispose, quando chiamate manualmente (o con Using), è gratis tutte le risorse non gestite e passare il Dispose messaggio di oggetti nidificati (e metodi della classe base) ma questo mai liberi (riuscito) di memoria.

Konrad Rudolph - yup, normalmente il finaliser fa nulla.Non si deve implementare a meno che non hai a che fare con le risorse gestite.

Quindi, quando si fa la sua attuazione, si utilizza Microsoft smaltire modello (come già descritto)

  • public Dispose() chiamate protected Dispose(true) - si occupa sia gestito e risorse.Chiamata Dispose() dovrebbe sopprimere la finalizzazione.

  • ~Finalize chiamate protected Dispose(false) - si occupa di risorse non gestite solo.Questo impedisce la memoria non gestita perdite se non si riesce a chiamare il public Dispose()

~Finalize è lento, e non dovrebbe essere usato a meno che non si dispone di risorse non gestite da affrontare.

Risorse gestite, non può perdita di memoria, possono solo uno spreco di risorse per l'applicazione corrente e rallentare la sua procedura di garbage collection.Le risorse non gestite possono perdere e ~Finalize è la migliore pratica per garantire che essi non.

In entrambi i casi using è la prassi migliore.

@Curt Hagenlocher - che è posteriore a quella anteriore.Non ho idea del perché tanti hanno votato quando è sbagliato.

IDisposable è per gestito risorse.

Finalisers sono per non gestito risorse.

Finché si utilizza solo risorse gestite sia @Jon Limjap e io sono del tutto corrette.

Per le classi che utilizzano le risorse non gestite (e tenere a mente che la stragrande maggioranza dei .Net classi non) Patrik risposta è completa e best practice.

Evitare l'uso di GC.Raccogliere - è un modo lento per affrontare con le risorse gestite, e non con quelli non gestiti a meno che non hai compilato correttamente il ~i Finalizzatori.


Ho rimosso il moderatore commento dalla domanda originale, in linea con https://stackoverflow.com/questions/14593/etiquette-for-modifying-posts

In risposta alla domanda originale, con le informazioni fornite da il manifesto originale, si è sicuri al 100% che lui non sa abbastanza circa la programmazione .NETTO anche essere data la risposta:utilizzare GC.Raccogliere().Direi che è il 99,99% di probabilità che lui davvero non ha bisogno di utilizzare GC.Raccogliere() a tutti, come la maggior parte dei manifesti hanno sottolineato.

La risposta corretta si riduce a " Lasciate che i GC fare il suo lavoro.Periodo.Si hanno altre cose di cui preoccuparsi.Ma si potrebbe desiderare di prendere in considerazione se e quando si deve smaltire o pulire oggetti specifici, e se è necessario implementare IDisposable e, possibilmente, di Finalizzare in classe.'

Per quanto riguarda Keith post e la sua Regola #4:

Alcuni manifesti sono confuso regola 3 e regola 4.Keith regola 4 è assolutamente corretto, unequivocately.E ' una regola del quattro senza bisogno di alcuna modifica a tutti.Avrei leggermente riformulare alcune altre sue regole chiare, ma sono sostanzialmente corretti se si analizza correttamente, ed effettivamente leggere l'intero post per vedere come si espande su di loro.

  1. Se la tua classe non fa uso di una risorsa non gestita E inoltre non crea un'istanza di un altro oggetto di una classe che utilizza, direttamente o in ultima analisi, un oggetto gestito (cioè, una classe che implementa IDisposable), quindi non ci sarebbe alcun bisogno per la tua classe per implementare IDisposable stesso, o anche chiamata .disporre su nulla.(In tal caso, è stupido pensare che è effettivamente NECESSARIO per liberare immediatamente la memoria con una forzata GC, comunque.)

  2. Se la classe utilizza una risorsa non gestita, O si crea un'istanza di un altro oggetto che implementa IDisposable, allora la classe deve:

    a) disporre rilasciare immediatamente in un contesto locale in cui sono stati creati, O...

    b) implementa IDisposable nel modello raccomandato all'interno di Keith post, o un paio di migliaia di siti su internet, o letteralmente in circa 300 libri da ora.

    b.1) Inoltre, se (b), ed è una risorsa non gestita che è stato aperto, sia IDisposable E Finalizzare DOVREBBE essere implementato, per Keith Regola #4.
    In questo contesto, Finalizzare assolutamente È una rete di sicurezza, in un certo senso:se qualcuno crea il TUO IDisposable oggetto che utilizza una risorsa non gestita, e non riescono a chiamare dispose, poi Finalizzare è l'ultima possibilità per il TUO oggetto per chiudere la risorsa non gestita correttamente.
    (Finalizzare dovrebbe farlo chiamando Smaltire in modo che il metodo Dispose che salta il rilascio di nulla, MA la risorsa non gestita.In alternativa, se il tuo metodo Dispose dell'oggetto VIENE chiamato correttamente con qualsiasi creata un'istanza dell'oggetto, quindi ENTRAMBI i passaggi sul Smaltire appello a tutti i oggetti IDisposable ha creata, E rilascia le risorse non gestite correttamente, che termina con un invito a sopprimere la Finalizzazione di un oggetto, il che significa che l'impatto dell'utilizzo di Finalizzare è ridotto se l'oggetto viene smaltito correttamente dal chiamante.Tutti questi punti sono inclusi nella Keith post, BTW.)

    b.2) SE la tua classe è solo l'attuazione IDisposable, perché si deve essenzialmente a passare su un Smaltire un IDisposable oggetto si è creata, quindi non implementare un metodo Finalize nella classe in quel caso.Finalizzare è per il trattamento del caso in cui SIA Smaltire è mai stato chiamato da qualunque cosa creata un'istanza dell'oggetto, E una risorsa non gestita è stato utilizzato, che è ancora inedito.

In breve, per quanto riguarda Keith post, non è del tutto corretta, e che il post è la più corretta e completa risposta, a mio parere.Egli può utilizzare alcune brevi-mano dichiarazioni che alcuni trovano di "sbagliato" o di un oggetto, ma il suo post completo espande l'utilizzo di Finalizzare completamente, e lui è assolutamente corretto.Assicurarsi di leggere il suo post completamente prima di saltare su una delle regole o dichiarazioni preliminari nel suo post.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top