Najbolje prakse u korištenju programa Dispose and Finalize u .Netu

Microsoft .Net Framework nudi sakupljač smeća koji se pokreće u pozadini i oslobađa memoriju koju zauzimaju upravljani objekti kada na njih više nije navedena referenca. Iako je sakupljač smeća spretan u čišćenju memorije koju zauzimaju upravljani objekti, nije zajamčeno da će se memorija koju zauzimaju neupravljani objekti očistiti kada se izvrši sljedeći GC ciklus. Ako u svojoj aplikaciji imate neupravljane resurse, trebali biste osigurati da takve resurse izričito oslobodite kada završite s upotrebom. U ovom ću članku istaknuti najbolje prakse koje biste trebali slijediti za čišćenje resursa korištenih u vašoj aplikaciji.

GC koristi generacije za održavanje i upravljanje relativnim životnim vijekom objekata koji su stvoreni u memoriji. Objekti koji se kreiraju novi se smještaju u generaciju 0. Osnovna pretpostavka je da novostvoreni objekt može imati kraće vrijeme trajanja, dok objekt koji je star može imati duži životni vijek. Kada se objekti koji borave u generaciji 0 ne povrate nakon GC ciklusa, oni se premještaju u generaciju 1. Slično tome, ako objekti koji borave u generaciji 1 prežive čišćenje GC-a, premještaju se u generaciju 2. Imajte na umu da se GC izvodi češće u niže generacije koje u višim. Dakle, objekti koji borave u generaciji 0 čistili bi se češće u usporedbi s objektima koji borave u generaciji 1. Dakle,bolja je programska praksa osigurati upotrebu više lokalnih objekata od višeg opsega kako bi se izbjeglo premještanje objekata u više generacije.

Imajte na umu da kada u svojoj klasi imate destruktor, izvršavanje ga tretira kao Finalize () metodu. Budući da je finalizacija skupa, destruktore biste trebali koristiti samo ako je potrebno - kada u klasi imate neke resurse koje biste trebali očistiti. Kada u svojoj klasi imate finalizator, objekti tih klasa premještaju se u red za finalizaciju. Ako su predmeti dostupni, premještaju se u red "Dostupni". GC vraća memoriju koju zauzimaju objekti koji nisu dostupni. Povremeno GC provjerava jesu li dostupni objekti koji se nalaze u redu "Dostupno". Ako nisu dostupni, memorija koju zauzimaju ti objekti se vraća. Dakle, očito je da bi objektima koji se nalaze u "Dostupnom" redu trebalo više vremena da ih sakupljač smeća očisti.Loša je praksa imati prazne destruktore u svojoj C # klasi jer bi se objekti za takve klase premještali u red za finalizaciju, a zatim u red "Dostupni", ako je potrebno.

Konačno se implicitno poziva kada se povrati memorija koju zauzima objekt. Međutim, GC zajamčeno neće pozvati finalizator - on može ili ne mora uopće biti pozvan. U osnovi, finalizator radi u nedeterminističkom načinu rada - vrijeme izvođenja ne garantira da će finalizator uopće biti pozvan. Međutim, možete prisiliti da se pozove finalizator, iako to uopće nije dobra praksa jer postoje povezane kazne za izvedbu. Finalizatore uvijek treba zaštititi i uvijek ih koristiti za čišćenje samo upravljanih resursa. Nikada ne biste trebali dodijeliti memoriju unutar finalizatora, pisati kod za implementaciju sigurnosti niti ili pozivati ​​virtualne metode iz finalizatora.

Metoda Dispose s druge strane pruža pristup "determinističkom čišćenju" prema čišćenju resursa u .Net-u. Međutim, metodu Dispose za razliku od finalizatora treba pozvati izričito. Ako u klasi imate definiranu metodu Dispose, trebali biste osigurati da je ona pozvana. Dakle, metodu Dispose klijentski kod treba eksplicitno pozvati. Ali što ako zaboravite nazvati Dispose metodu koju izlaže klasa koja koristi neupravljane resurse? Klijenti instance klase koja implementira sučelje IDisposable trebali bi eksplicitno pozvati Dispose metodu. U tom slučaju trebate nazvati Dispose iz završnog programa. Ova automatska deterministička strategija finalizacije osigurava čišćenje neupravljanih resursa korištenih u vašem kodu.

Trebali biste implementirati IDisposable na svaku vrstu koja ima finalizator. Preporučuje se praksa da se i Dispose i Finalize implementiraju kada u vašoj klasi imate neupravljane resurse.

Sljedeći isječak koda ilustrira kako možete implementirati obrazac Dispose Finalize u C #.

zaštićeno virtualno prazno zbrinjavanje (uklanjanje bool-a)

        {

            ako (odlaganje)

            {

                // pisanje koda za čišćenje upravljanih objekata

            }

            // pisanje koda za čišćenje neupravljanih objekata i resursa

        }

Ova parametrizirana metoda odlaganja može se automatski pozvati iz destruktora kao što je prikazano u isječku koda u nastavku.

  ~ Resursi ()

        {

            ako (! odloženo)

            {

                disposed = true;

                Raspolagati (lažno);

            }

        }