Jak likvidovat třídu .NET?

hlasů
39

.NET garbage collector bude nakonec uvolnit paměť, ale co když chcete, aby paměti zpět okamžitě? Jaký kód budete potřebovat pro použití ve třídě MyClassvolání

MyClass.Dispose()

a uvolnit veškerý použitý prostor o proměnných a objektů MyClass?

Položena 15/08/2008 v 16:26
zdroj uživatelem
V jiných jazycích...                            


20 odpovědí

hlasů
99

IDisposable nemá nic společného s uvolněním paměti. IDisposable je vzor pro uvolnění neřízené zdroje - a paměť je zcela určitě podařilo zdroj.

Odkazy ukazující na GC.Collect () jsou správná odpověď, ačkoli použití této funkce je obecně odrazena v dokumentaci Microsoft .NET.

Edit: Poté, co získal značné množství karmy Za tuto odpověď, cítím určitou zodpovědnost vypracovat na to, lest nováček řízení .NET zdrojů dostat špatný dojem.

Uvnitř procesu NET, existují dva druhy zdrojů - řízené i neřízené. „Managed“ znamená, že runtime je pod kontrolou zdroje, zatímco „neudržovaných“ znamená, že je programátor odpovědnost. A tam je opravdu jen jeden druh spravovaného prostředku, že se staráme o .NET dnes - paměť. Programátor říká runtime přidělit paměť a poté je až do běhu, aby zjistili, kdy může uvolněna paměť. Mechanismus, který .NET používá pro tento účel se nazývá garbage collection a najdete spoustu informací o GC na internetu jednoduše pomocí Googlu.

Pokud jde o ostatní druhy zdrojů, .NET neví nic o jejich čištění tak, že se musí spoléhat na programátora dělat správnou věc vím. Za tímto účelem je platforma poskytuje programátorovi tři nástroje:

  1. IDisposable rozhraní a „použití“ prohlášení ve VB a C #
  2. finalizers
  3. IDisposable vzor jak byly provedeny mnoha BCL tříd

První z nich umožňuje programátor efektivně získat zdroj, použijte ji a pak ji uvolněte vše v rámci stejného postupu.

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

Je-li „AcquireResource“ je způsob výroby, který (například) otevře soubor a „zlikvidovat“ automaticky zavře soubor, pak tento kód nemůže unikat zdroj souboru. Ale vzpomínka na „tmp“ objekt sám může také být ještě přiděleno. To proto, že IDisposable rozhraní nemá absolutně nic společného s garbage collector. Pokud si to chcete, aby zajistily, že paměť byla uvolněna, jedinou možností by bylo zavolat GC.Collect()vynutit úklid.

Nicméně, to nemůže být dostatečně zdůrazněno, že je to asi není dobrý nápad. To je obecně mnohem lepší nechat garbage collector dělat to, co bylo navrženo k tomu, který je ke správě paměti.

Co se stane v případě, že prostředek je používán po delší dobu, takže její životnost kříží několik metod? Je zřejmé, že „použití“ prohlášení již neplatí, takže programátor by musel ručně volání „zlikvidovat“, když on nebo ona se provádí pomocí zdroje. A co se stane v případě, že programátor zapomene? Pokud není žádný záložní, pak se proces nebo počítač může nakonec dojdou podle toho zdroj není správně uvolněna.

To je, kde finalizers přijít dovnitř. Finalizer je metoda na třídy, která má zvláštní vztah s garbage collector. GC slibuje, že - před uvolnění paměti pro libovolný objekt tohoto typu - bude to první dát finalizer šanci udělat nějaké čištění.

Takže v případě souboru, jsme teoreticky nemusí zavřít soubor ručně vůbec. Můžeme jen čekat, až se garbage collector se dostává do něj a pak nechat Finalizer dělat práci. Bohužel to nefunguje dobře v praxi, protože garbage collector běží nedeterministicky. Soubor může zůstat otevřený podstatně déle, než programátor očekává. A je-li dostatek soubory zůstat otevřené, systém může selhat při pokusu o otevření dalšího souboru.

U většiny zdrojů, chceme, aby obě tyto věci. Chceme konvence, aby bylo možné říci „my hotovi s tímto zdrojem teď“ a my chceme, aby se ujistil, že je tu aspoň určitá šance k vyčištění se stane automaticky, pokud bychom zapomenout na to ručně. Že je místo, kde „IDisposable“ vzorek vstoupí do hry. Jedná se o konvence, která umožňuje IDispose a finalizer hrát pěkně pohromadě. Můžete vidět, jak vzorec funguje tak, že při pohledu na oficiální dokumentaci pro IDisposable .

Sečteno a podtrženo: Pokud to, co opravdu chcete udělat, je jen ujistit, že paměť je uvolněna, pak IDisposable a finalizers vám nepomůže. Ale IDisposable rozhraní je součástí velmi důležité vzoru, který všechny programátory .NET měli rozumět.

Odpovězeno 15/08/2008 v 16:40
zdroj uživatelem

hlasů
20

Můžete disponovat pouze případy, které implementují rozhraní IDisposable.

Vynutit odpadky sbírat okamžitě uvolnit (Neřízený) paměť:

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

To je obvykle špatná praxe, ale je zde například chyba v 64bitové verzi .NET framework, který umožňuje GC chovat divně v některých případech, a pak budete chtít, aby to udělat. Já nevím, jestli chyba dosud nebyly vyřešeny. Ví někdo?

Disponovat třídu tak učiníte:

instance.Dispose();

nebo takto:

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

které se projeví při kompilaci-time:

MyClass instance = null;    

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

Můžete implementovat rozhraní IDisposable takto:

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;
    }
}
Odpovězeno 15/08/2008 v 16:48
zdroj uživatelem

hlasů
17

Odpovědi na tuto otázku dostali víc než jen trochu zmatený.

Titulní ptá k dispozici, ale pak říká, že chtějí paměť zpět okamžitě.

.net je řízena , což znamená, že když píšete .Net aplikací, nemusíte se obávat paměti přímo, cena je to, že nemají přímou kontrolu nad pamětí a to buď.

.net rozhodne, kdy je nejlepší vyčistit a volné paměti, tě jako Net kodér.

DisposeJe způsob, jak říct, .Net, že jste udělali něco, ale nebude to vlastně uvolnit paměť, dokud je to nejlepší čas, aby tak učinily.

V podstatě .Net bude skutečně sbírat paměť zpět, když je to nejjednodušší pro to dělat tak - je to velmi dobrý v rozhodování o tom, kdy. Pokud nepíšete něco velmi náročné na paměť obvykle nemusíte zvrátit to (to je jedním z důvodů, hry nejsou často psané v .Net - dosud potřebují úplnou kontrolu)

V Net můžete použít GC.Collect()jej okamžitě nutit, ale to je téměř vždy špatná praxe. Pokud Net nebyl vyčištěn ji přesto to znamená, že není nijak zvlášť vhodná doba na to, aby tak učinily.

GC.Collect()zvedne objekty, které Net identifikuje jako provedeno. Pokud jste dosud likvidovány objekt, který potřebuje to .NET může rozhodnout, aby tento objekt. To znamená, že GC.Collect()je účinná pouze tehdy, pokud správně implementovat jedno instance.

GC.Collect()Je není náhradou za správné používání IDisposable.

Takže zlikvidovat a paměť přímo nesouvisí, ale nemusí být. Správně likvidaci bude vaše .Net aplikací účinnější, a proto využívají méně paměti ačkoli.


99% času v .Net následujícího důvodu je nejlepší praxe:

Pravidlo 1: Jestliže se nezabývají ničím neřízeným nebo že implementuje IDisposable pak se nemusíte starat o odložte.

Pravidlo 2: Pokud máte lokální proměnné, který implementuje IDisposable ujistit, že jste se ho zbavit v současném rozsahu:

//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();
}

Pravidlo 3: Pokud třída má vlastnost nebo členské proměnné, která implementuje IDisposable pak tato třída by měla zavést IDisposable taky. V metodu vyřazení této třídě se také můžete zbavit svých IDisposable vlastností:

//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
    }
}

To není opravdu kompletní, což je důvod, proč je příklad uzavřen. Dědění tříd může být nutné dodržovat následující pravidla ...

Pravidlo 4: Pokud třída využívá neřízený zdroj následně realizovat IDispose a přidejte finaliser.

.net nemůže nic dělat s neřízeným zdrojem, takže teď se bavíme o paměti. Pokud nechcete vyčistit můžete získat únik paměti.

Dispose metoda musí vypořádat s oběma řízených a neřízených zdrojů.

Finaliser je bezpečnostní pojistka - zajistí, že pokud někdo vytváří a instance vaší třídy a nedaří se ho zbavit se ‚nebezpečné‘ neřízené zdroje mohou ještě být vyčištěn od 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);
}

Nakonec toto přetížení odložte která trvá boolean vlajku:

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;
}

Všimněte si, že když je to všechno na svém místě jiný spravovaný kód vytváří instanci své třídy může jen brát to jako každá jiná IDisposable (pravidla 2 a 3).

Odpovězeno 31/08/2008 v 10:56
zdroj uživatelem

hlasů
14

Bylo by vhodné zmínit, že likvidovat nemusí vždy odkazovat na paměti? I disponovat prostředky taková reference na soubory častěji než paměť. GC.Collect () přímo souvisí s garbage collector CLR a může nebo nemusí volné paměti (Správce úloh). To bude pravděpodobně ovlivní aplikace v záporných směrech (např výkon).

Na konci dne, proč chcete, aby paměti zpět okamžitě? Je-li tlak paměti odjinud OS dostanete paměť ve většině případů.

Odpovězeno 15/08/2008 v 16:41
zdroj uživatelem

hlasů
5

Podívejte se na tento článek

Provádění vzoru vyřazení, IDisposable a / nebo finalizer nemá absolutně nic společného s tím, když se dostane paměti uvolněno; místo toho, to má co do činění s říká GC , jak se kultivovat, že paměť. Voláte-li dispose (), které nejsou v žádném případě interakci s GC.

GC se spustí pouze tehdy, když se zjistí, že je třeba k (takzvaným tlak paměti) a potom (a jen tehdy) to bude DEALLOCATE paměti pro nevyužité předměty a kompaktní paměťovém prostoru.

Jste mohli zavolat GC.Collect (), ale opravdu neměli, pokud tam je velmi dobrý důvod k (což je téměř vždy „Nikdy“). Když se vynutit kolekce cyklus out-of-band takhle vlastně způsobí GC dělat více práce a nakonec může skončit bolí svůj výkon aplikací. Po dobu trvání sběrného GC cyklus aplikace je ve skutečnosti ve zmrazeném stavu ... čím více GC cyklů, které běží, tím více času aplikace stráví zmrazeny.

Tam jsou také některé nativní Win32 API volání můžete provést osvobodit svou pracovní sadu, ale i ty, které je třeba se vyhnout, pokud je zde velmi dobrý důvod to udělat.

Celý předpoklad za gargbage shromážděny běhu je, že nemusíte se bát (tolik), o tom, kdy runtime přiděluje / zruší přidělení skutečné paměti; stačí se starat o tom, zda je váš objekt ví, jak uklidit po sobě, když žádal.

Odpovězeno 17/08/2008 v 15:22
zdroj uživatelem

hlasů
3

Kompletní vysvětlení Joe Duffy na „ disponovat dopracování a Resource Management “:

Dříve v .NET Framework je celý život, finalizers byly důsledně označuje jako destruktorů od C # programátory. Jak jsme se stali chytřejší v průběhu času, snažíme se smířit s tím, že metoda Dispose je opravdu více ekvivalentní C ++ destructor (deterministický) , zatímco finalizer je něco zcela oddělené (nedeterministické) . Skutečnost, že C # vypůjčené C ++ syntaxi destructor (tj ~ T ()) jistě měl alespoň trochu dělat s vývojem tohoto chybný.

Odpovězeno 26/08/2008 v 10:36
zdroj uživatelem

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

pak si můžete udělat něco takového

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

nebo

using (MyClass instance = new MyClass())
{

}
// instance will be disposed right here as it goes out of scope
Odpovězeno 15/08/2008 v 16:32
zdroj uživatelem

hlasů
2

Napsal jsem souhrn destruktory a odložte a sběr odpadků na http://codingcraftsman.wordpress.com/2012/04/25/to-dispose-or-not-to-dispose/

Chcete-li odpovědět na původní otázku:

  1. Nesnažte se řídit svou paměť
  2. Likvidaci není o správě paměti, je to o nespravovaném řízení zdrojů
  3. Finalizers jsou přirozenou součástí likvidujte vzoru a ve skutečnosti zpomalit uvolňování paměti spravovaných objektů (protože mají jít do fronty finalizaci pokud již zlikvidovat, d)
  4. GC.Collect je zlé, jak to dělá objeví několik krátkých-žil objekty, které mají být zapotřebí delší dobu, takže je zpomaluje byly shromažďovány.

Nicméně GC.Collect by mohlo být užitečné, pokud jste měli výkonnostní kritickou část kódu a chtěli snížit pravděpodobnost, že odvoz odpadu zpomalovat to. Zavoláte dřív.

Na vrcholu se, že tam je argument ve prospěch tohoto vzoru:

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

proti

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

Ale hlavní odpověď je, že odvoz odpadu prostě funguje, pokud vás flákat s ním!

Odpovězeno 02/05/2012 v 23:13
zdroj uživatelem

hlasů
2

Nemůžete opravdu nutit GC na vyčištění objektu, když chcete, i když existují způsoby, jak to nutí utíkat, nic říká, že je vyčistit celý objekt, který chcete / očekávat. To je nejlepší zavolat nakládat do try catch ex konečně nakládat End Try (VB.NET Rulz) cestu. Ale zlikvidujte je určen pro čištění systémových zdrojů (paměť, kliky, db spojení atd přidělené objektu v deterministický způsobem. Likvidaci není (a nemůže) vyčistit paměť používaná samotného objektu, jen GC může udělat.

Odpovězeno 15/08/2008 v 16:42
zdroj uživatelem

hlasů
1

@Keith,

Souhlasím se všemi svými pravidly kromě # 4. Přidání finalizer by mělo být provedeno pouze za velmi specifických okolností. Pokud třída používá nespravované prostředky, ty by měly být čištěny ve vaší funkce Dispose (bool). To samé funkce by měla pouze vyčištění podařilo zdrojů při bool je pravda. Přidání finalizer přidává složitost náklady pro použití vašeho objektu, jako pokaždé, když vytvoříte novou instanci, musí být také umístěn na finalizaci fronty, který je kontrolován při každém GC provozuje sběrný cyklus. Fakticky to znamená, že váš objekt přežije jeden cyklus / generace déle, než by měl, takže Finalizer lze spustit. Finalizer by neměla být chápána jako „záchranná síť“.

GC poběží pouze sběrný cyklus, když zjistí, že není k dispozici dostatek paměti v Gen0 haldy provést další rozdělení, pokud si „pomoci“ to voláním GC.Collect () vynutit sbírku out-of-band ,

Pointa je, že bez ohledu na to, co je GC pouze ví, jak uvolnit prostředky voláním metody dispose (a případně finalizer pokud je implementována). Je na této metody k „dělat správné věci“ a vyčistit jakékoli neřízené prostředky používané a pověřit jiné spravované prostředky volat jejich vyřazení metodu. To je to, co dělá, a může self-optimalizovat do značné míry tak dlouho, dokud to není pomáhal cyklů out-of-band sběrných velmi efektivní. Jak již bylo řečeno, krátké volání GC.Collect explicitně nemáte žádnou kontrolu nad tím, kdy a v jakém pořadí objekty budou zlikvidovány a paměť uvolněna.

Odpovězeno 31/08/2008 v 11:26
zdroj uživatelem

hlasů
1

Litujeme, ale vybraný Odpověď na tuto otázku je nesprávná. Jak několik lidí uvedly, následně zlikvidovat a provádění IDisposable nemá nic společného s uvolňování paměti spojené s třídou .NET. To je hlavně a tradičně se používá na volné neřízených zdrojů, jako popisovačů souboru atd

I když vaše aplikace může zavolat GC.Collect (), aby se pokusili vynutit sbírku garbage collector bude jen opravdu mít vliv na ty položky, které jsou na správné úrovni generace v freachable frontě. Takže je možné, že pokud jste vymazány všechny odkazy na objekt by to mohlo být ještě několik hovorů na GC.Collect () před samotným paměť uvolněna.

Neříkejte ve své otázce PROČ máte pocit, že je třeba okamžitě uvolnit paměť. Chápu, že někdy může být neobvyklé okolnosti, ale vážně, v spravovaný kód je téměř vždy lepší nechat runtime dohodu s správy paměti.

Pravděpodobně nejlepší radou, pokud si myslíte, že váš kód používá paměť rychlejší než GC je to uvolnění, pak byste měli zkontrolovat kód, aby zajistily, že žádné objekty, které již nejsou potřebné, jsou zmíněny v jakýchkoliv datových struktur jste ležících kolem statické členy atd . zkuste to také, aby se zabránilo situacím, kdy budete mít kruhový objekt odkazy, jak je možné, že tyto nemohou být uvolněn jeden.

Odpovězeno 25/08/2008 v 22:29
zdroj uživatelem

hlasů
1

IDisposable rozhraní je opravdu pro třídy, které obsahují nespravované prostředky. Pokud vaše třída neobsahuje neřízené zdroje, proč je třeba , aby se uvolnily prostředky předtím, než ji garbage collector dělá? V opačném případě pouze zajišťuje váš objekt je vytvořena co možná nejpozději a jde mimo rozsah co nejdříve.

Odpovězeno 15/08/2008 v 17:48
zdroj uživatelem

hlasů
1

Tento článek má docela přímočarý návod. Nicméně, zavolat GC místo aby ho vzít svůj přirozený průběh je obvykle příznakem špatného návrhu / správy paměti, zvláště pokud nejsou omezené zdroje jsou spotřebovány (spoje, kliky, cokoliv jiného, co obvykle vede k realizaci IDisposable).

Co je příčinou, abyste je potřeba udělat?

Odpovězeno 15/08/2008 v 16:30
zdroj uživatelem

hlasů
0

V odpovědi na původní otázku, s informacemi dosud dané původním autorem, to je 100% jistý, že nemá dostatek informací o programování v .NET, které mají být dokonce dána odpověď: použijte GC.Collect (). Řekl bych, že to je 99,99% pravděpodobné, že opravdu není nutné používat GC.Collect () vůbec, protože většina plakátů poukázal.

Správná odpověď se scvrkává na ‚Nechť GC dělat svou práci. Doba. Máte jiné věci na starosti. Ale možná budete chtít, aby zvážila, zda a kdy byste měli odstranit nebo vyčistit konkrétní objekty, a zda je nutné provést IDisposable a případně Uzavření ve své třídě.‘

Pokud jde o příspěvek Keithovu a jeho Pravidlo # 4:

Některé obrázky jsou matoucí pravidlo 3 a vládnout 4. Keithovo pravidlo 4 je naprosto správné, unequivocately. Je to jedno pravidlo ze čtyř, které nepotřebuje úpravy vůbec. Já bych trochu přeformulovat některé ze svých dalších pravidel, aby byly jasnější, ale jsou v podstatě správný, pokud je analyzovat správně, a ve skutečnosti přečíst celý příspěvek, aby viděli, jak se rozšiřuje na ně.

  1. Pokud vaše třída nepoužívá neřízený zdroj a také nikdy instanci jiný objekt třídy, která sama používá přímo či nakonec neřízený objekt (tj třída, která implementuje IDisposable), pak by nebylo nutné pro svou třídu buď zavést IDisposable sám, nebo dokonce volat .dispose na cokoliv. (V takovém případě je hloupé si myslet, že skutečně potřebují, aby okamžitě uvolnit paměť s nuceným GC, tak jako tak.)

  2. Pokud vaše třída využívá neřízený zdroj, nebo instanci jiný objekt, který sám o sobě implementuje IDisposable, pak se vaše třída by měla buď:

    a) disponovat / uvolňovat tyto okamžitě v místním kontextu, ve kterém byly vytvořeny, nebo ...

    b) zavést IDisposable ve vzoru doporučenou poštou do Keithovi, nebo několik tisíc míst na internetu, nebo doslova asi 300 knih nyní.

    b.1) Kromě toho, je-li (b), a to je neřízený zdroj, který byl otevřen, a to jak IDisposable a dokončit by vždy měla být provedena, na Keithovi Pravidlo 4 #.
    V této souvislosti je finalizace naprosto IS bezpečnostní síť v jednom smyslu: jestliže někdo instanci VAŠE IDisposable objekt, který používá nespravované zdroj, a oni nedokážou volat likvidovat, pak finalizace je poslední šance pro váš objekt správně uzavřít neřízený zdroj.
    (Uzavřít by se to tím, že volá zlikvidujte v takovým způsobem, že tato metoda Dispose přeskočí uvolnění nic jiného než neřízený zdroj. Případně, pokud metoda Dispose váš objekt je správně nazývá, co instance svůj objekt, pak to OBA přechází na likvidujte volání all IDisposable objekty to instance, a uvolní neřízené zdroje správně, končit s výzvou k potlačení Finalize na objekt, což znamená, že dopad používání Finalize se snižuje, pokud je váš objekt správně zlikvidován volajícím. všechny tyto body jsou zahrnuty v příspěvku Keithovi, BTW).

    b.2) IF vaše třída je pouze provádění IDisposable protože potřebuje v podstatě projít na odložte na IDisposable objekt to instance, pak se neprovádějí metodu Finalize ve své třídě v této věci. Dokončit je pro manipulaci případ, že obě Likvidaci byl nikdy nazvaný jakýmkoli instance svůj objekt a neřízený zdroj byl využit to ještě unreleased.

Stručně řečeno, pokud jde o příspěvek Keithovi, že je zcela v pořádku, a že příspěvek je nejsprávnější a úplnou odpověď, podle mého názoru. Ten se může použít některé krátkodobé ruční prohlášení, že některé najít ‚špatné‘ nebo objekt, ale jeho celý příspěvek rozšiřuje využití Finalizace úplně, a to je naprosto správné. Ujistěte se, že číst jeho příspěvek zcela předtím, než skočí na jednom z pravidel nebo předběžných prohlášení ve svém sloupku.

Odpovězeno 23/03/2012 v 01:50
zdroj uživatelem

hlasů
0

Konrad Rudolph - Jo, normálně finaliser nemá vůbec nic. Měli byste ji nelze realizovat, pokud máte co do činění s neřízených zdrojů.

Pak, když si ji realizovat, použít nakládat vzoru Microsoftu (jak již bylo popsáno)

  • public Dispose()hovory protected Dispose(true)- se zabývá spravovaných i neřízených zdrojů. Volání Dispose()by mělo potlačit finalizaci.

  • ~Finalizehovory protected Dispose(false)- se zabývá pouze neřízených zdrojů. Tím se zabrání neřízené úniky paměti, pokud se vám nepodaří zavolatpublic Dispose()

~Finalize je pomalý, a neměl by být použit, pokud máte neřízené prostředky na řešení.

Řízené zdroje nemohou únik paměti, mohou ztrácet pouze prostředky pro stávající aplikace a zpomalit její odvoz odpadu. Neřízené zdroje mohou unikat, a ~Finalizeje nejlepší praxe, aby zajistily, že tomu tak není.

V každém případě usingje nejlepší praxe.

Odpovězeno 26/08/2008 v 10:30
zdroj uživatelem

hlasů
0

@Keith:

IDisposable je pro spravované zdroje.

Finalizátorů jsou neřízené zdroje.

Je nám líto, ale to je prostě špatně. Za normálních okolností se finalizer nemá vůbec nic. Nicméně, v případě, že disponuje vzor byla provedena správně, finalizer pokusí vyvolat Dispose.

Dispose má dvě úlohy:

  • Volné neřízené zdroje, a
  • zdarma vnořené spravovaných zdrojů.

A tady vaše prohlášení přichází do hry, protože je pravda, že při finalizaci, objekt by měl nikdy se pokusit uvolnit vnořené spravované prostředky, protože mohou již uvolněna. Je třeba ještě volné neřízené zdroje ačkoli.

Přesto finalizers nemají jinou než práci zavolat Disposea říct, že se nedotýkat spravované objekty. DisposeKdyž volal manuálně (nebo prostřednictvím Using), musí osvobodit všechny neřízené zdroje a předat Disposezprávu na vnořených objektů (a metody základní třídy), ale to se nikdy uvolnit jakékoliv (spravovaný) paměti.

Odpovězeno 26/08/2008 v 10:11
zdroj uživatelem

hlasů
0

@Curt Hagenlocher - je to obráceně. Nemám ponětí, proč se tolik hlasoval to, když je to špatně.

IDisposableJe pro spravovaných prostředků.

Finalizátorů jsou neřízené zdroje.

Tak dlouho, jak budete používat pouze spravované prostředky jak @Jon Limjap a já jsou zcela správné.

U tříd, které používají nespravované prostředky (a mějte na paměti, že drtivá většina Net tříd ne) Patrik odpovědí je komplexní a nejlepší praxe.

Vyhnout se používání GC.Collect - je to pomalý způsob, jak se vypořádat s spravovaných prostředků, a nedělá nic s těmi neřízených, pokud jste správně postavený své ~ finalizers.


Odstranil jsem poznámku moderátora z původní otázce v souladu s https://stackoverflow.com/questions/14593/etiquette-for-modifying-posts

Odpovězeno 26/08/2008 v 10:01
zdroj uživatelem

hlasů
0

Můžete mít deterministický destrukci objektu v jazyce C ++

Nikdy chcete volat GC.Collect, že zmatky s vlastní ladění garbage collector detekovat tlak paměti a v některých případech dělat nic jiného, ​​než zvýšit současnou generaci každý objekt na haldě.

Pro ty, kteří vyslání IDisposable odpovědi. Volání Dispose metoda neničí objekt jako Tazatel popisuje.

Odpovězeno 21/08/2008 v 09:05
zdroj uživatelem

hlasů
0

Pokud si nechcete (nebo nemůžete) implementovat IDisposable na třídě, můžete vynutit úklid takového (ale je to pomalé) -

GC.Collect();
Odpovězeno 15/08/2008 v 16:33
zdroj uživatelem

hlasů
-1

Pokud MyClass implementuje IDisposable můžete udělat právě to.

MyClass.Dispose();

Nejlepší praxe v jazyce C # je:

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

As, která obaluje nahoru Zlikvidujte try-finally a zajišťuje, že se to nikdy nevynechal.

Odpovězeno 15/08/2008 v 16:32
zdroj uživatelem

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more