Ar trebui să vă setați toate obiectele pentru a null
("Nimic" în VB.NET) după ce ați terminat cu ei?
Am înțeles că în .NET este esențial de a dispune de orice instanțe de obiecte care pune în aplicare IDisposable
de interfață pentru a elibera unele resurse deși obiectul poate fi încă ceva după ce este eliminat (prin urmare `isDisposed de proprietate în forme), deci presupun că încă mai pot locui în memorie sau cel puțin în parte?
De asemenea, știu că atunci când un obiect iese din domeniul de aplicare este apoi marcat de colectare gata pentru următoarea trecere de colectorul de gunoi (deși acest lucru poate dura un timp).
Deci, cu asta în minte va setare a null
accelera sistemul eliberarea de memorie, deoarece nu trebuie să afle că nu mai este în domeniul de aplicare și sunt efecte secundare rău?
MSDN articole nu face acest lucru în exemple și în prezent fac asta ca eu nu pot văd ce-i rău. Cu toate acestea am venit peste un amestec de opinii, astfel încât orice comentarii sunt utile.
Karl este absolut corect, nu este nevoie pentru a seta obiecte pentru a nul după utilizare. Dacă un obiect implementează IDisposable, doar asigurați-vă că sunați
IDisposable.Dispose()când're face cu acel obiect (înfășurat într-o "încerca" .. "în sfârșit", sau, o
cu()bloc). Dar, chiar dacă tu nu't uitați să sunați
Dispose(), la finaliser metoda pe obiect ar trebui să fie de asteptare
Dispose () pentru tine.
Am crezut că acest lucru a fost un bun tratament:
și asta
Nu e't orice punct în încercarea de a doua ghici GC și strategii de management, deoarece's tuning auto și opac. Acolo a fost o discuție bună despre mecanismele interioare cu Jeffrey Richter pe Dot Net Rocks aici: Jeffrey Richter pe Windows Model de Memorie și Richters carte CLR prin intermediul C# capitolul 20 are o mare tratament:
Un alt motiv pentru a evita crearea de obiecte pentru a nul atunci când ați terminat cu ele este că poate de fapt să-i țină în viață pentru mai mult timp.
de exemplu
void foo()
{
var someType = new SomeType();
someType.DoSomething();
// someType is now eligible for garbage collection
// ... rest of method not using 'someType' ...
}
va permite obiectului denumit de someType să fie GC'd după apelul la "DoSomething" dar
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;
}
uneori poate menține obiectul în viață până la sfârșitul metoda. De JIT, de obicei, va optimizat departe misiunea să null, astfel încât ambele bucăți de cod, sfârșesc prin a fi la fel.
Nici nu't null obiecte. Puteți verifica afară http://codebetter.com/blogs/karlseguin/archive/2008/04/27/foundations-of-programming-pt-7-back-to-basics-memory.aspx pentru mai multe informații, dar pentru a pune lucrurile la nul a câștigat't face nimic, cu excepția murdar codul.
În general, nu's nu este nevoie să null obiecte după utilizare, dar, în unele cazuri, am găsit-o's o practică bună.
Dacă un obiect implementează IDisposable și este stocat într-un domeniu, cred că's bine să null, doar pentru a evita folosirea obiect eliminate. Bug-uri de următoarele fel pot fi dureroase:
this.myField.Dispose();
// ... at some later time
this.myField.DoSomething();
L's bun la nul pe teren dupa eliminarea, și a obține o NullPtrEx chiar la linie în cazul în care câmpul este folosit din nou. În caz contrar, s-ar putea rula în unele criptic bug pe linie (în funcție de exact ceea ce DoSomething nu).
Sunt șanse ca codul nu este structurate suficient de bine, dacă vă simțiți nevoia de a null
variabile.
Există o serie de moduri de a limita domeniul de aplicare a unei variabile:
După cum sa menționat de către Steve Tranby
using(SomeObject object = new SomeObject())
{
// do stuff with the object
}
// the object will be disposed of
În mod similar, puteți folosi pur și simplu acolade:
{
// Declare the variable and use it
SomeObject object = new SomeObject()
}
// The variable is no longer available
Mi se pare că, folosind acolade, fără nici o "rubrica" să curățați cod și de a ajuta face mai ușor de înțeles.
În general, nu este nevoie pentru a seta la zero. Dar să presupunem că aveți o Resetare funcționalitate în clasa ta.
Atunci s-ar putea face, pentru că nu vreau să sun dispune de două ori, deoarece unele dintre Dispune nu pot fi puse în aplicare în mod corect și arunca Sistem.ObjectDisposed excepție.
private void Reset()
{
if(_dataset != null)
{
_dataset.Dispose();
_dataset = null;
}
//..More such member variables like oracle connection etc. _oraConnection
}
acest fel de "nu este nevoie să setați obiecte pentru a nul după utilizare" nu este în întregime corecte. Există momente în care trebuie să NULL variabila după care dispune acesta.
Da, ar trebui să te sun MEREU `.Dispose () "sau".Close () pe ceva care are o atunci când ați terminat. Fie fișierul mânere, conexiuni la baza de date sau obiecte de unică folosință.
Separat de asta este foarte practic model de LazyLoad.
Spune că am și instanțiată ObjA
de "clasa a". "Clasa a" are o proprietate publică numit PropB
din "clasa B".
Pe plan intern, PropB
folosește privat variabilă de _Bși implicit la null. Când PropB.Obține()
este folosit, se verifică pentru a vedea dacă _PropB
este nul și dacă este, se deschide resursele necesare pentru a instantia un " B " in _PropB
. Apoi se întoarce _PropB
.
La experiența mea, acest lucru este un truc util.
În cazul în care necesitatea de a nul vine este dacă resetați sau schimba în vreun fel faptul că conținutul de _PropBau copilul de valorile anterioare ale "A", va trebui să Eliminați ȘI null
_PropB așa LazyLoad poate reseta pentru a aduce dreptul de valoare în CAZUL în care codul necesită.
Dacă faci numai _PropB.Dispose()
și la scurt timp după aștepta null pentru a verifica LazyLoad pentru a reuși, nu va't fi nulă, și te'll fi uitat la datele vechi. În efect, trebuie să null după Dispose()
doar pentru a fi sigur.
Sigur că am vrea să fie altfel, dar eu'am primit codul, acum prezintă acest comportament după o `Dispose () "pe o" _PropB și în afară de funcția de asteptare care a făcut Dispune (și, astfel, aproape în afara domeniului de aplicare), private prop încă nu't nul, iar datele vechi este încă acolo.
În cele din urmă, eliminate de proprietate va null, dar care's a fost non-deterministe din punctul meu de vedere.
Motivul de bază, ca dbkk face aluzie este că containerul părinte (ObjA " cu " PropB
) este păstrarea exemplu de _PropB în aplicare, în ciuda
Dispose()`.
Stephen Cleary explică foarte bine în acest post: Trebuie sa setez Variabile de la zero pentru a Sprijini Colectarea Gunoiului?
Spune:
Pe Scurt, pentru cei Nerăbdători Da, dacă variabila este un câmp static, sau dacă sunteți scris un enumerable metoda (folosind retur randament) sau o metodă asincron (folosind asincron și așteaptă). În caz contrar, nu.
Acest lucru înseamnă că, în metodele obișnuite (non-enumerable și non-asincron), nu setați variabilele locale, parametrii metoda, sau de exemplu câmpuri la null.
(Chiar daca esti de punere în aplicare IDisposable.Dispune, încă nu ar trebui să setați variabilele de null).
Cel mai important lucru pe care ar trebui să ia în considerare este Câmpuri Statice.
câmpuri Statice sunt întotdeauna rădăcină de obiecte, astfel încât acestea sunt întotdeauna considerat "viu" de colectorul de gunoaie. Dacă un câmp static se referă la un obiect care nu mai este necesar, ar trebui să fie setat la nul, astfel încât colectorul de gunoi va trata ca eligibile pentru colectare.
Setare câmpuri statice la nul este lipsit de sens dacă întregul proces este de a închide. Întreaga heap este pe cale de a fi gunoi colectate de la acel moment, inclusiv toate root obiecte.
Concluzie:
câmpuri Statice; asta e despre asta. Orice altceva este o pierdere de timp**.
Aruncati o privire la acest articol, precum și: http://www.codeproject.com/KB/cs/idisposable.aspx
Pentru cea mai mare parte, stabilind un obiect la nul nu are nici un efect. Singura dată când ar trebui să fie sigur de a face acest lucru este în cazul în care lucrați cu o "obiect mare", care este unul mai mare decât 84K în dimensiune (cum ar fi bitmap).
Există unele cazuri în care este logic să null referințe. De exemplu, atunci când te're scris o colecție--ca o coadă prioritate-și prin contract, nu ar trebui't fi păstrarea acestor obiecte în viață pentru client după client are le-a eliminat din coadă.
Dar acest fel de lucru contează doar în timp a trăit colecții. Dacă coada's nu va supraviețui la sfârșitul funcției acesta a fost creat în, apoi contează mult mai puțin.
Pe ansamblu, ar trebui't deranjez. Lasa compilatorul și GC face locurile lor de muncă, astfel încât să puteți face a ta.
Cred setare ceva de la zero este murdar. Imaginați-vă un scenariu în cazul în care elementul fiind stabilit acum este expus prin intermediul proprietate. Acum este cumva o bucată de cod accidental folosește această proprietate după elementul este eliminat, veți obține o excepție de referință nulă care necesită o anchetă pentru a afla exact ce se întâmplă.
Cred cadru de unică folosință va permite arunca ObjectDisposedException care este mai semnificativ. Nu setarea înapoi la nul va fi mai bine atunci pentru care motiv.
Cred că de proiectare a GC implementatori, puteți't accelera GC cu anulare. Am', sunt'd prefera să nu-ți faci griji cu cât/când GC ruleaza-l trateze ca acest omniprezente Nu protejarea și vizionarea de peste si pentru tine...(arcuri capul în jos, ridică pumnul spre cer)...
Personal, am de multe ori în mod explicit set de variabile pentru a nul când m-am'm făcut cu ei ca o formă de auto-documentare. Eu nu't declara, utilizați, apoi setat la nul mai târziu-eu nul imediat după ce au're nu mai este necesar. Am'm a spune, în mod explicit, "I'm-a terminat oficial cu tine...fi plecat..."
Este anularea necesară într-o GC'd limba? Nr. Este util pentru GC? Poate da, poate nu, nu't știu sigur, de design nu pot't de control, și indiferent de azi's a răspunde cu versiunea asta sau asta, viitorul GC implementari ar putea modifica răspunsul dincolo de controlul meu. În Plus, dacă/atunci când nulling este optimizat afară it's ceva mai mult decât o fantezie comentariu dacă vrei.
M-am gândit dacă mi se face o intenție clară la următoarea prostul care urmează în urmele mele, și dacă "poate" ajuta potential GC uneori, atunci's valoare de ea pentru mine. Cea mai mare parte mă face să mă simt curat și clar, și Mongo îi place să se simtă curat și clar. :)
Mă uit la o astfel de prognoze: limbaje de Programare există pentru a lăsa oamenii să dau și altora o idee de intenție și un compilator un loc de muncă cererea ce să fac ... compilatorul transformă această cerere într-o altă limbă (uneori mai multe) pentru un CPU-CPU(s) ar putea da doi bani pe ce limba ai folosit, fila setări, comentarii, accente stilistice, nume de variabile, etc. ... un CPU's tot despre fluxul de biți care se spune ce registre și opcodes și locații de memorie pentru a învârti. Multe lucruri scrise in codul nu't converti în ceea ce's consumată de către CPU în secvența pe care am specificat-o. C, C++, C#, Lisp, Babel, assembler sau ce este teorie, mai degrabă decât de realitate, scris ca o declarație de muncă. Ceea ce vezi nu este ceea ce veți obține, da, chiar și în limbajul assembler.
Eu nu inteleg mentalitatea de "lucruri inutile" (cum ar fi linii goale) "nu sunt nimic altceva decât zgomot și dezordine cod." Asta mi-a fost mai devreme în cariera mea; am înțeles asta. În acest moment mă aplec spre ceea ce face codul mai clar. L'nu am'm adăugând chiar și 50 de linii de "zgomot" pentru programele mele-it's câteva rânduri aici sau acolo.
Există excepții de la orice regulă. În scenarii cu o memorie volatila, memorie statică, condiții de rasă, singletons, utilizarea "vechi" de date și tot felul de putregai, ca's diferite: aveți NEVOIE pentru a gestiona propria ta memorie, blocarea și anularea ca apropos, pentru că memoria nu este o parte din GC'd Universul ... să sperăm că toată lumea înțelege asta. Restul de timp cu GC'd limbi it's o chestiune de stil, mai degrabă decât o necesitate sau un garantat impuls de performanță.
La sfârșitul zilei, asigurați-vă că ați înțeles ce este eligibil pentru GC și ce's nu; blocare, dispune, de a-și anula în mod corespunzător; wax on, wax off; respira, respira afară; și pentru tot ceea ce am spus: Dacă te simți bine, fă-o. Kilometraj dvs. poate varia...cum ar trebui...
Un obiect presupun .dispose()
metoda pe care forțele de resurse pentru a fi eliminat din memorie.