In het artikel, Nieuwe instanties van objecten coderen, schreef ik over de verschillende manieren waarop Nieuw instanties van objecten kunnen worden gemaakt. Het tegenovergestelde probleem, het weggooien van een object, is iets waar u zich in VB.NET niet vaak zorgen over hoeft te maken. .NET bevat een technologie genaamd Vuilnisman (GC) die meestal alles stil en efficiënt achter de schermen verzorgt. Maar af en toe, meestal bij het gebruik van bestandsstromen, sql-objecten of grafische (GDI +) objecten (dat wil zeggen, onbeheerde bronnen), moet u mogelijk de controle over het verwijderen van objecten in uw eigen code overnemen.
Eerst wat achtergrondinformatie
Net als een constructor (de Nieuw trefwoord) maakt een nieuwe voorwerp, een destructor is een methode die wordt aangeroepen wanneer een object wordt vernietigd. Maar er is een addertje onder het gras. De mensen die .NET hebben gemaakt, realiseerden zich dat het een formule was voor bugs als twee verschillende stukjes code een object daadwerkelijk konden vernietigen. Dus de .NET GC heeft eigenlijk de controle en het is meestal de enige code die de instantie van het object kan vernietigen. De GC vernietigt een object wanneer het daartoe besluit en niet eerder. Normaal gesproken, nadat een object de ruimte heeft verlaten, is dat zo
vrijgelaten door de Common Language Runtime (CLR). De GC vernietigt objecten wanneer de CLR meer vrij geheugen nodig heeft. Dus het komt erop neer dat je niet kunt voorspellen wanneer GC het object daadwerkelijk zal vernietigen.(Welllll... Dat is waar bijna de hele tijd. Je kan bellen GC.Collect en forceer een vuilnisophaalcyclus, maar autoriteiten zeggen universeel dat het een slecht idee en totaal overbodig.)
Als uw code bijvoorbeeld een Klant object, lijkt het erop dat deze code het opnieuw zal vernietigen.
Klant = niets
Maar dat is niet zo. (Een object instellen op Niets wordt gewoonlijk genoemd, dereferentie het object.) Eigenlijk betekent dit alleen dat de variabele niet meer aan een object is gekoppeld. Enige tijd later zal de GC merken dat het object beschikbaar is voor vernietiging.
Trouwens, voor beheerde objecten is dit allemaal niet echt nodig. Hoewel een object als een knop een verwijderingsmethode biedt, is het niet nodig om het te gebruiken en weinig mensen doen dat. Windows Forms-componenten worden bijvoorbeeld toegevoegd aan een containerobject met de naam componenten. Wanneer u een formulier sluit, wordt de verwijderingsmethode automatisch aangeroepen. Meestal hoeft u zich hier alleen zorgen over te maken bij het gebruik van onbeheerde objecten, en zelfs dan alleen om uw programma te optimaliseren.
De aanbevolen manier om bronnen vrij te maken die mogelijk in het bezit zijn van een object, is door de aan te roepen Gooi weg methode voor het object (indien beschikbaar) en verwijs vervolgens naar het object.
Klant. Wegwerpen () Klant = niets
Omdat GC een verweesd object vernietigt, is het niet echt nodig, of u nu de objectvariabele op niets instelt of niet.
Een andere aanbevolen manier om ervoor te zorgen dat objecten worden vernietigd wanneer ze niet meer nodig zijn, is door de code die een object gebruikt in een Gebruik makend van blok. Een gebruiksblok garandeert de verwijdering van een of meer van dergelijke bronnen wanneer uw code ermee klaar is.
In de GDI + serie, de Gebruik makend van blok wordt vrij vaak gebruikt om die vervelende grafische objecten te beheren. Bijvoorbeeld ...
MyBrush gebruiken als LinearGradientBrush _. = Nieuwe LinearGradientBrush (_. Me. ClientRectangle, _. Kleur. Blauwe kleur. Rood, _. LinearGradientMode. Horizontaal) <... meer code ...> Einde gebruik
myBrush wordt automagisch verwijderd wanneer het einde van het blok wordt uitgevoerd.
De GC-benadering voor het beheren van geheugen is een grote verandering ten opzichte van de manier waarop VB6 het deed. COM-objecten (gebruikt door VB6) werden vernietigd toen een interne teller met referenties nul bereikte. Maar het was te gemakkelijk om een fout te maken, dus de interne teller stond uit. (Omdat het geheugen vastliep en niet beschikbaar was voor andere objecten toen dit gebeurde, werd dit een "geheugenlek" genoemd.) In plaats daarvan controleert GC eigenlijk of iets naar een object verwijst en vernietigt het wanneer er geen meer is referenties. De GC-aanpak heeft een goede geschiedenis in talen zoals Java en is een van de grote verbeteringen in .NET.
Op de volgende pagina bekijken we de IDisposable-interface... de interface die u moet gebruiken wanneer u onbeheerde objecten in uw eigen code moet verwijderen.
Als u uw eigen object codeert dat onbeheerde bronnen gebruikt, moet u de gebruiken ID wegwerp interface voor het object. Microsoft maakt dit gemakkelijk door een codefragment op te nemen dat het juiste patroon voor u creëert.
Klik hier om de afbeelding weer te geven
Klik op de knop Terug in uw browser om terug te keren
De toegevoegde code ziet er als volgt uit (VB.NET 2008):
Klasse ResourceClass. Implementeert IDisposable. 'Om overtollige oproepen te detecteren. Privé verwijderd als Boolean = False. 'IDwegwerpbaar. Protected Overridable Sub Dispose (_. ByVal disposing As Boolean) If Not Me. Dan weggegooid. Als u het dan weggooit. 'Vrij andere staat (beheerde objecten). Stop als. 'Bevrijd je eigen staat (onbeheerde objecten). 'Stel grote velden in op null. Stop als. Me.disposed = Waar. Einde Sub. #Region "IDisposable Support" 'Deze code is door Visual Basic toegevoegd aan. 'het wegwerppatroon correct implementeren. Public Sub Dispose () Implementeert IDisposable. Gooi weg. 'Wijzig deze code niet. 'Voer de opschooncode in. 'Gooi (ByVal disposing As Boolean) hierboven weg. Gooi (True) GC.SuppressFinalize (Me) End Sub weg. Beveiligde overschrijvingen Sub Finalize () 'Wijzig deze code niet. 'Voer de opschooncode in. 'Gooi (ByVal disposing As Boolean) hierboven weg. Gooi (False) MyBase weg. Finalize () End Sub. #Einde regio. Einde klasse
Gooi weg is bijna een "afgedwongen" ontwikkelaarspatroon in .NET. Er is eigenlijk maar één juiste manier om het te doen en dit is het. Je zou kunnen denken dat deze code iets magisch doet. Dat is niet zo.
Merk allereerst op dat de interne vlag verwijderd sluit gewoon het hele ding kort, zodat u kunt bellen Wegwerpen (weggooien) zo vaak als je wilt.
De code ...
GC.SuppressFinalize (ik)
... maakt uw code efficiënter door de GC te vertellen dat het object al is weggegooid (een 'dure' operatie in termen van uitvoeringscycli). Finalize is Protected omdat GC het automatisch aanroept wanneer een object wordt vernietigd. Je mag Finalize nooit bellen. De Booleaanse afvoeren vertelt de code of uw code de verwijdering van het object heeft geïnitieerd (True) of dat de GC dit heeft gedaan (als onderdeel van de Afronden sub. Merk op dat dit de enige code is die de Boolean gebruikt afvoeren is:
Als u het dan weggooit. 'Vrij andere staat (beheerde objecten). Stop als
Wanneer u een object weggooit, moeten al zijn bronnen worden verwijderd. Wanneer de CLR vuilnisman beschikt over een object, alleen de onbeheerde bronnen moeten worden verwijderd omdat de garbage collector automatisch voor de beheerde bronnen zorgt.
Het idee achter dit codefragment is dat u code toevoegt om voor beheerde en onbeheerde objecten op de aangegeven locaties te zorgen.
Wanneer u een klasse afleidt van a basisklasse die IDisposable implementeert, hoeft u geen van de basismethoden te negeren, tenzij u andere bronnen gebruikt die ook moeten worden verwijderd. Als dat gebeurt, moet de afgeleide klasse de wegwerpmethode (disposing) van de basisklasse overschrijven om over de bronnen van de afgeleide klasse te beschikken. Maar vergeet niet om de Dispose (disposing) -methode van de basisklasse aan te roepen.
Beschermde overschrijvingen Subverwijdering (ByVal-verwijdering als Booleaans) Als niet ik. Dan verwijderd. Als u het dan weggooit. 'Voeg uw code toe om beheerde bronnen vrij te maken. Stop als. 'Voeg uw code toe om onbeheerde bronnen vrij te maken. Stop als. MyBase. Wegwerpen (weggooien) Einde Sub
Het onderwerp kan enigszins overweldigend zijn. Het doel van de uitleg hier is om te "demystificeren" wat er werkelijk gebeurt, omdat de meeste informatie die je kunt vinden het je niet vertelt!