Sette objekter til Null / Ingenting etter bruk i .NET

stemmer
174

Bør du sette alle objektene til null( Nothingi VB.NET) når du er ferdig med dem?

Jeg forstår at i NET er det viktig å kvitte seg med alle forekomster av objekter som implementerer IDisposablegrensesnittet for å frigjøre noen ressurser selv om objektet kan fortsatt være noe etter at den er plassert (derav isDisposedeiendom i former), så jeg antar det kan fortsatt ligge i minne eller i det minste delvis?

Jeg vet også at når et objekt går ut av omfang er det da merket for samlingen klar for neste passering av søppelinnsamler (selv om dette kan ta tid).

Så med dette i tankene vil sette den til nullsystemet raskere frigjøre minne som det ikke trenger å regne ut at det ikke lenger er i omfang og de er noen dårlige bivirkninger?

MSDN artikler aldri gjøre dette i eksemplene og i dag gjør jeg dette som jeg ikke kan se skade. Men jeg har kommet over en blanding av meninger så kommentarer er nyttige.

Publisert på 05/08/2008 klokken 20:14
kilden bruker
På andre språk...                            


13 svar

stemmer
67

Karl er helt riktig, det er ikke nødvendig å sette objekter til null etter bruk. Hvis et objekt implementerer IDisposable, bare sørg for at du ringer IDisposable.Dispose()når du er ferdig med det objektet (innpakket i en try.. finally, eller en using()blokk). Men selv om du ikke husker å ringe Dispose(), bør finaliser metoden på objektet være ringer Dispose()for deg.

Jeg trodde dette var en god behandling:

Grave i IDisposable

og dette

forstå IDisposable

Det er ikke noen vits i å prøve å andre gjette GC og sine strategier fordi det er selv tuning og ugjennomsiktig. Det var en god diskusjon om det indre arbeidet med Jeffrey Richter på Dot Net Rocks her: Jeffrey Richter på Windows Memory Model og Richters bok CLR via # C kapittel 20 har en god behandling:

Svarte 05/08/2008 kl. 20:56
kilden bruker

stemmer
33

En annen grunn til å unngå å sette gjenstander til null når du er ferdig med dem er at det faktisk kan holde dem i live lenger.

f.eks

void foo()
{
    var someType = new SomeType();
    someType.DoSomething();
    // someType is now eligible for garbage collection         

    // ... rest of method not using 'someType' ...
}

vil tillate objektet henvist av sometype som skal GC'd etter kallet til "DoSomething", men

void foo()
{
    var someType = new SomeType();
    someType.DoSomething();
    // someType is NOT eligible for garbage collection yet
    // because that variable is used at the end of the method         

    // ... rest of method not using 'someType' ...
    someType = null;
}

noen ganger kan det holde objektet i live frem til slutten av metoden. Den JIT vil vanligvis optimalisert bort oppgaven til null , slik at begge kodebiter ende opp med å være den samme.

Svarte 15/08/2008 kl. 14:43
kilden bruker

stemmer
15

Nei ikke null stedene. Du kan sjekke ut http://codebetter.com/blogs/karlseguin/archive/2008/04/27/foundations-of-programming-pt-7-back-to-basics-memory.aspx for mer informasjon, men å sette ting til null vil ikke gjøre noe, bortsett fra skitne koden din.

Svarte 05/08/2008 kl. 20:23
kilden bruker

stemmer
7

Generelt, er det ingen grunn til null gjenstander etter bruk, men i noen tilfeller synes jeg det er en god praksis.

Hvis et objekt implementerer IDisposable og lagres i et felt, jeg tror det er bra å nulle det, bare for å unngå å bruke den solgte gjenstand. Feilene av følgende typen kan være smertefullt:

this.myField.Dispose();
// ... at some later time
this.myField.DoSomething();

Det er godt å nulle banen etter å avhende det, og få en NullPtrEx rett på linjen der feltet brukes igjen. Ellers kan du kjøre inn i noen kryptiske feil ned linjen (avhengig av nøyaktig hva DoSomething gjør).

Svarte 09/08/2008 kl. 11:16
kilden bruker

stemmer
7

Også:

using(SomeObject object = new SomeObject()) 
{
  // do stuff with the object
}
// the object will be disposed of
Svarte 05/08/2008 kl. 20:37
kilden bruker

stemmer
6

Sjansen er at koden ikke er strukturert tett nok hvis du føler behov for å nullvariabler.

Det finnes en rekke måter å begrense omfanget av en variabel:

Som nevnt av Steve Tranby

using(SomeObject object = new SomeObject()) 
{
  // do stuff with the object
}
// the object will be disposed of

På samme måte kan du bare bruke klammeparenteser:

{
    // Declare the variable and use it
    SomeObject object = new SomeObject()
}
// The variable is no longer available

Jeg synes at det å bruke klammeparenteser uten "overskriften" for å virkelig rense ut koden og bidra til å gjøre det mer forståelig.

Svarte 09/08/2008 kl. 12:13
kilden bruker

stemmer
5

Generelt ikke nødvendig å sette til null. Men si at du har en Reset funksjonalitet i klassen.

Deretter kan du gjøre, fordi du ikke ønsker å ringe disponere to ganger, siden noen av de Kast kan ikke gjennomføres på riktig måte og kaste System.ObjectDisposed unntak.

private void Reset()
{
    if(_dataset != null)
    {
       _dataset.Dispose();
       _dataset = null;
    }
    //..More such member variables like oracle connection etc. _oraConnection
 }
Svarte 17/04/2012 kl. 08:55
kilden bruker

stemmer
5

Den eneste gangen du bør sette en variabel til null er når variabelen ikke går ut av omfanget og du ikke lenger trenger dataene knyttet til den. Ellers er det ikke nødvendig.

Svarte 05/08/2008 kl. 20:32
kilden bruker

stemmer
3

denne typen "det er ikke nødvendig å sette gjenstander til null etter bruk" er ikke helt nøyaktig. Det er tider du trenger til NULL variabelen etter avhende den.

Ja, bør du alltid ringe .Dispose()eller .Close()på noe som har det når du er ferdig. Det være seg fil håndtak, databasetilkoblinger eller engangs stedene.

Atskilt fra det er det veldig praktisk mønster av LazyLoad.

Si jeg har og instansiert ObjAav class A. Class Ahar en offentlig eiendom kalt PropBav class B.

Internt PropBbruker private variable av _Bog mislighold til null. Når PropB.Get()brukes, sjekker den for å se om _PropBer null, og hvis det er, åpner de ressursene som trengs på å bruke en Btil _PropB. Den returnerer deretter _PropB.

Til min erfaring, er dette et veldig nyttig triks.

Der behovet for å null kommer på er hvis du restarte eller endring En annen måte at innholdet _PropBvar barn av de tidligere verdier av A, må du Kast OG nulle ut _PropBså LazyLoad kan tilbake å hente riktig verdi hvis koden krever det.

Hvis du bare gjøre _PropB.Dispose(), og kort tid etter forvente null sjekk LazyLoad for å lykkes, vil det ikke være null, og du vil være å se på foreldede data. I praksis må du nulle den etter Dispose()bare for å være sikker.

Jeg er sikker ønske det var noe annet, men jeg har fått kode akkurat nå viser denne atferden etter en Dispose()på en _PropBog utenfor kalle funksjonen som gjorde Kast (og dermed nesten ute av omfanget), fortsatt ikke er null privat prop, og foreldet data er der fortsatt.

Etter hvert vil den solgte eiendommen null, men som har vært ikke-determinis fra mitt perspektiv.

Kjernen grunn, som dbkk tallbestemmélse er at den overordnede beholderen ( ObjAmed PropB) er å holde forekomsten av _PropBi omfang, til tross for den Dispose().

Svarte 11/04/2012 kl. 01:12
kilden bruker

stemmer
1

Ta en titt på denne artikkelen også: http://www.codeproject.com/KB/cs/idisposable.aspx

For det meste, sette et objekt til null har ingen effekt. Den eneste gangen du bør være sikker på å gjøre det er hvis du arbeider med et "stort objekt", som er en større enn 84k i størrelse (for eksempel punktgrafikk).

Svarte 17/08/2008 kl. 04:46
kilden bruker

stemmer
1

Det er noen tilfeller der det er fornuftig å null referanser. For eksempel, når du skriver en samling - som en prioritert kø - og av kontrakten, bør du ikke være å holde disse objektene i live for klienten etter at kunden har fjernet dem fra køen.

Men denne typen ting bare teller i lang levde samlinger. Hvis køen ikke kommer til å overleve slutten av funksjonen den ble opprettet i, så det betyr en hel masse mindre.

På en hel, du egentlig ikke bør bry. La kompilatoren og GC gjøre jobben sin, slik at du kan gjøre din.

Svarte 05/08/2008 kl. 20:46
kilden bruker

stemmer
0

Jeg tror ved utformingen av GC implementors, kan du ikke få fart på GC med opphevelsen. Jeg er sikker på at de foretrekker du ikke bekymre deg over hvor / når GC kjører - behandle det som denne allestedsnærværende vesen beskytte og våke over og ut for deg ... (buer hodet ned, hever knyttneven mot himmelen) .. .

Personlig har jeg ofte eksplisitt sette variabler til null når jeg er ferdig med dem som en form for selv dokumentasjon. Jeg vet ikke erklære, bruke, da satt til null senere - jeg null umiddelbart etter at de er ikke lenger nødvendig. Jeg sier, eksplisitt, "Jeg er offisielt ferdig med deg ... være borte ..."

Er oppheve nødvendig i et GC'd språk? Nei Er det nyttig for GC? Kanskje ja, kanskje nei, vet ikke sikkert, ved design jeg virkelig ikke kan kontrollere det, og uavhengig av dagens svar med denne versjonen, eller som kan fremtidige GC implementeringer endre svaret utenfor min kontroll. Pluss hvis / når nulling er optimalisert ut at det er litt mer enn en fancy kommentar hvis du vil.

Jeg tenkte at det gjør min hensikt klarere til neste stakkars idioten som følger i mine fotspor, og hvis det "kanskje" potensielt hjelpe GC noen ganger, så er det verdt det for meg. Stort sett det gjør meg ryddig og tydelig, og Mongo liker å føle seg ryddig og tydelig. :)

Jeg ser på det slik: Programmeringsspråk eksisterer for å la folk gi andre mennesker en idé om hensikt og en kompilator en jobb forespørsel om hva de skal gjøre - kompilatoren konverterer forespørselen til et annet språk (noen ganger flere) for en CPU - CPU (e) kunne gi en uling hvilket språk du brukte, innstillinger kategorien, kommentarer, stilistiske vektlegging, variabelnavn, osv - en CPU handler om bitstrøm som forteller det hva registrerer og opcodes og minneplasser til twiddle. Mange ting som er skrevet i kode ikke konvertere til hva som forbrukes av CPU i sekvensen vi angitt. Vår C, C ++, C #, Lisp, Babel, assembler eller hva som er teori snarere enn virkeligheten, skrevet som en erklæring av arbeid. Det du ser er ikke hva du får, ja, selv i assembler språk.

Jeg forstår tankegangen til "unødvendige ting" (som tomme linjer) "er ikke annet enn støy og rot opp kode." Det var meg tidligere i min karriere; Jeg får helt det. På dette tidspunktet lener jeg mot det som gjør kode klarere. Det er ikke som jeg legger med 50 linjer med "støy" til mine programmer - det er noen få linjer her eller der.

Det finnes unntak til enhver regel. I scenarier med flyktig minne, statisk minne, race conditions, enkeltfødte, bruk av "gammel" data og all den slags rot, er det annerledes: du trenger for å administrere din egen hukommelse, låse og oppheve som apropos fordi minnet er ikke en del av den GC'd Universe - forhåpentligvis alle forstår det. Resten av tiden med GC'd språk det er et spørsmål om stil snarere enn nødvendighet eller en garantert ytelsesforbedring.

På slutten av dagen må du forstå hva som er kvalifisert for GC og hva som ikke; lås, kastes, og opphever hensiktsmessig; voks på, voks av; pust inn pust ut; og for alt annet jeg si: Hvis det føles godt, gjør det. Din kjørelengde kan variere ... som det skal ...

Svarte 10/05/2016 kl. 13:07
kilden bruker

stemmer
-1

Noen objekt antar den .dispose()metode som tvinger ressursen som skal fjernes fra minnet.

Svarte 05/08/2008 kl. 20:21
kilden bruker

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