Ustawianie obiektów na null / Nothing po użyciu w .NET

głosy
173

Należy ustawić wszystkie obiekty do null( Nothingw VB.NET) po zakończeniu z nimi?

Rozumiem, że w .NET istotne jest, aby wyrzucać żadnych wystąpień obiektów, które implementują IDisposableinterfejs do uwolnienia pewnych zasobów chociaż obiekt może być jeszcze coś po dokonaniu jej zbycia (stąd isDisposedwłasności w formach), więc zakładam, że to może jeszcze znajdować się w pamięci lub przynajmniej częściowo?

Wiem też, że gdy obiekt znajdzie się poza zakresem jest następnie zaznaczono kolekcji gotowy do następnego przejścia kolektora śmieci (choć może to zająć trochę czasu).

Więc z tą myślą będzie to ustawienie, aby nullprzyspieszyć system zwalniania pamięci, ponieważ nie muszą pracować, że to już nie jest w zasięgu i są jakieś złe skutki uboczne?

Artykuły MSDN nie robić tego w przykładach i obecnie to zrobić jak nie widzę szkody. Jednak mam natknąć mieszaniny opinii więc wszelkie komentarze są użyteczne.

Utwórz 05/08/2008 o 21:14
źródło użytkownik
W innych językach...                            


13 odpowiedzi

głosy
66

Karl jest absolutnie poprawne, nie ma potrzeby ustawiania obiektów do wartości null po użyciu. Jeśli obiekt implementuje IDisposable, po prostu upewnij się, że nazywają IDisposable.Dispose()kiedy skończysz z tym przedmiotem (zawinięte w try.. finally, albo do using()bloku). Ale nawet jeśli nie pamięta, aby zadzwonić Dispose(), metoda finaliser na obiekcie należy dzwoniąc Dispose()do ciebie.

Myślałem, że to było dobre leczenie:

Kopanie w IDisposable

i to

Zrozumienie IDisposable

Nie ma żadnego sensu zgadywać GC i jego strategie zarządzania, bo to samo strojenie i nieprzejrzysty. Nie był to dobry dyskusji na temat wewnętrznych mechanizmów z Jeffrey Richter na Dot Net Rocks tutaj: Jeffrey Richter na szybach model pamięci i Richters książki CLR za pośrednictwem C # rozdziale 20 ma wielką leczenia:

Odpowiedział 05/08/2008 o 21:56
źródło użytkownik

głosy
33

Innym powodem, aby uniknąć ustawiania obiektów na null, gdy skończysz z nich jest to, że może rzeczywiście utrzymać je przy życiu dłużej.

na przykład

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

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

pozwoli przedmiot skierowany przez someType być GC'd po wywołaniu „doSomething”, ale

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

może czasami zachować obiekt żywy aż do końca metody. JIT będzie zwykle optymalizowana dala zadanie null , więc oba bity kodu końcu jest taka sama.

Odpowiedział 15/08/2008 o 15:43
źródło użytkownik

głosy
15

No nie pustych obiektów. Możesz sprawdzić http://codebetter.com/blogs/karlseguin/archive/2008/04/27/foundations-of-programming-pt-7-back-to-basics-memory.aspx uzyskać więcej informacji, ale ustawienie rzeczy null nic nie da, chyba brudnej kodzie.

Odpowiedział 05/08/2008 o 21:23
źródło użytkownik

głosy
7

Na ogół nie ma potrzeby null obiektów po użyciu, ale w niektórych przypadkach uważam, że jest to dobra praktyka.

Jeśli obiekt implementuje IDisposable i jest przechowywany w polu, myślę, że to dobre, aby go NULL, tak aby uniknąć korzystania z umieszczoną obiekt. Błędy z poniższego rodzaju mogą być bolesne:

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

To jest dobre na null pole po utylizacji go i uzyskać prawo NullPtrEx na linii, gdzie pole jest ponownie wykorzystywane. W przeciwnym razie, można uruchomić w jakimś tajemniczym bug wzdłuż linii (w zależności od tego, co dokładnie robi DoSomething).

Odpowiedział 09/08/2008 o 12:16
źródło użytkownik

głosy
7

Również:

using(SomeObject object = new SomeObject()) 
{
  // do stuff with the object
}
// the object will be disposed of
Odpowiedział 05/08/2008 o 21:37
źródło użytkownik

głosy
6

Są szanse, że Twój kod nie jest skonstruowany na tyle ciasno, jeśli czujesz potrzebę nullzmiennych.

Istnieje wiele sposobów, aby ograniczyć zakres zmiennej:

Jak wspomniano przez Steve Tranby

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

Podobnie, można po prostu użyć nawiasów klamrowych:

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

Uważam, że przy użyciu nawiasów klamrowych, bez żadnych „pozycji”, aby naprawdę oczyścić kod i pomóc uczynić go bardziej zrozumiałym.

Odpowiedział 09/08/2008 o 13:13
źródło użytkownik

głosy
5

Na ogół nie ma potrzeby, aby ustawić na null. Ale załóżmy, że masz resecie funkcjonalność w swojej klasie.

Następnie można zrobić, ponieważ nie chcesz, aby zadzwonić dysponowania dwa razy, ponieważ niektóre z Zużyty nie mogą być realizowane prawidłowo i rzucać System.ObjectDisposed wyjątek.

private void Reset()
{
    if(_dataset != null)
    {
       _dataset.Dispose();
       _dataset = null;
    }
    //..More such member variables like oracle connection etc. _oraConnection
 }
Odpowiedział 17/04/2012 o 09:55
źródło użytkownik

głosy
4

Jedyny czas, należy ustawić zmienną do NULL, gdy zmienna nie wykracza poza zakres i nie trzeba już dane z nim związane. W przeciwnym razie nie ma potrzeby.

Odpowiedział 05/08/2008 o 21:32
źródło użytkownik

głosy
3

tego rodzaju „nie ma potrzeby ustawiania obiektów na null po użyciu” nie jest do końca prawdziwe. Są chwile, które trzeba NULL zmiennej po utylizacji go.

Tak, zawsze należy zadzwonić .Dispose()lub .Close()na cokolwiek, co ma go, gdy skończysz. Czy to uchwyty plików, połączenia z bazą danych lub jednorazowych przedmiotów.

Oddzielny od to bardzo praktyczny wzór LazyLoad.

Muszę powiedzieć i wystąpienia ObjAz class A. Class Ama własność publiczną o nazwie PropBod class B.

Wewnętrznie PropBużywa prywatną zmienną _Bi domyślne null. Kiedy PropB.Get()jest używany, to sprawdza czy _PropBjest zerowy, a jeżeli tak, to otwiera zasoby potrzebne do instancji BINTO _PropB. Następnie powraca _PropB.

Do mojego doświadczenia wynika, że ​​jest to bardzo przydatna sztuczka.

Gdzie potrzeba null przychodzi to jeśli zresetować lub zmienić w jakiś sposób, że zawartość _PropBbyły dziecko z poprzednich wartości A, trzeba będzie utylizować oraz pustego się _PropBtak LazyLoad można zresetować aby pobrać odpowiednią wartość, jeśli kod wymaga.

Jeśli tylko zrobić _PropB.Dispose()i wkrótce spodziewać null czek na LazyLoad aby odnieść sukces, nie będzie zerowy, a będziesz patrząc na nieaktualne dane. W efekcie, należy wartość null go po Dispose()prostu mieć pewność.

I pamiętaj, żeby to było inaczej, ale mam kod teraz wykazujące to zachowanie po Dispose()na zasadzie _PropBi na zewnątrz funkcji wywołującej że zrobił Dispose (a więc prawie poza zakresem), prywatna prop nadal nie jest NULL, a dane nieświeży jest nadal.

Ostatecznie nieruchomość usytuowaną będzie wartość null na zewnątrz, ale to już nie deterministyczne z mojego punktu widzenia.

Rdzeń powodu, jak dbkk nawiązuje że pojemnik nadrzędny ( ObjAz PropB) jest utrzymanie wystąpienie _PropBzakresie, mimo Dispose().

Odpowiedział 11/04/2012 o 02:12
źródło użytkownik

głosy
1

Spójrz na ten artykuł, a także: http://www.codeproject.com/KB/cs/idisposable.aspx

W przeważającej części, ustawienie obiektu null nie ma żadnego wpływu. Jedyny czas, należy upewnić się, aby zrobić to, jeśli pracujesz z „dużego obiektu”, który jest jednym większe niż 84K wielkości (takich jak mapy bitowe).

Odpowiedział 17/08/2008 o 05:46
źródło użytkownik

głosy
1

Istnieją pewne przypadki, gdzie to ma sens null referencje. Na przykład, kiedy piszesz kolekcji - jak kolejki priorytetowej - i przez swój kontrakt, nie powinno być utrzymanie tych obiektów przy życiu przez klienta po klient usunął je z kolejki.

Ale takie rzeczy liczy się tylko długo żyli kolekcji. Jeśli kolejka nie będzie przetrwać koniec funkcji Powstał w, to liczy się dużo mniej.

Na całość, to naprawdę nie powinno niepokoić. Niech kompilator i GC wykonywać swoją pracę, dzięki czemu można robić swoje.

Odpowiedział 05/08/2008 o 21:46
źródło użytkownik

głosy
0

Wierzę przez projektowaniu implementors GC, nie można przyspieszyć GC z zniweczenia. Jestem pewien, że wolą się nie martwić się o jak / kiedy GC prowadzi - traktować go tak wszechobecne Istota ochrony i czuwa nad i dla ciebie ... (łuki głową w dół, podnosi pięść do nieba) .. ,

Osobiście często jawnie ustawić zmienne null gdy skończę z nimi jako forma dokumentacji własnej. I nie deklaruje, używać, a następnie ustawić na null później - ja NULL natychmiast po ich już nie są potrzebne. Mówię wyraźnie: „Ja jestem z wami zrobić oficjalnie ... zniknie ...”

Konieczne jest uniemożliwienie w języku GC'd? Nie jest to pomocne dla GC? Może tak, może nie, nie wiem na pewno, przez projektowanie Naprawdę nie mogę go kontrolować, a niezależnie od dzisiejszej odpowiedzi z tej wersji lub że przyszłe implementacje GC może zmienić odpowiedź poza moją kontrolą. Plus, jeśli / kiedy Zerowanie jest zoptymalizowany na to trochę więcej niż fantazyjny komentarzu jeśli będzie.

Ja figura jeśli to sprawia, że moim zamiarem wyraźniejszy do kolejnej słabej głupca, który następuje w moje ślady, a jeśli to „może” potencjalnie pomóc GC czasem, wtedy warto do mnie. Głównie to sprawia, że czuję się czyste i jasne, a Mongo lubi czuć czyste i jasne. :)

Patrzę na to tak: istnieją języków programowania, aby pozwolić ludziom dać innym ludziom pomysł intencyjny oraz kompilator prośbą zadanie, co robić - kompilator zamienia ten wniosek w innym języku (czasami kilka) dla CPU - CPU (s) może dać prześmieszny co język używany, ustawienia zakładki, komentarze stylistyczne akcenty, nazw zmiennych, itd - CPU wszystko o strumieniu bitowym, który mówi to, co rejestruje i rozkazy i miejsc pamięci, aby kręcić. Wiele rzeczy napisane w kodzie nie przekształcić co spożywane przez CPU w sekwencji mamy określony. Nasz C, C ++, C #, Lisp, Babel, asemblera lub cokolwiek jest teoria, a nie rzeczywistość, napisany w sprawozdaniu z pracy. Co widać nie jest to, co masz, tak, nawet w języku asemblera.

Rozumiem mentalności „zbędnych rzeczy” (jak pustych wierszy) „są niczym innym, jak hałas i zaśmiecać kodu.” To było mnie wcześniej w mojej karierze; I całkowicie rozumiem. W tym momencie ja skłaniam się ku tym, co sprawia, że ​​kod jaśniejsze. To nie jest tak Dodaję nawet 50 wierszy „szumu” do moich programów - to kilka linijek tu czy tam.

Istnieją wyjątki od każdej reguły. W scenariuszach z ulotnej pamięci, pamięci statycznej warunkach wyścigowych, pojedynczych, korzystanie z „nieświeży” danych i wszelkich tego rodzaju zgnilizny, że jest inaczej: trzeba zarządzać swoją własną pamięć, blokowania i znoszący tak apropos, ponieważ pamięć nie jest częścią GC'd Universe - miejmy nadzieję, że każdy to rozumie. Resztę czasu z języków GC'd to kwestia stylu, zamiast konieczności lub gwarantowany wzrost wydajności.

Pod koniec dnia, upewnij się, że rozumiesz, co kwalifikuje się do GC, a co nie; Blokada, a zużyty i powodują utratę odpowiednio; na wosk, wosk off; wdech i wydech; i do wszystkiego innego mówię: Jeśli czuje się dobrze, zrób to. Może się wahać ... tak jak powinno ...

Odpowiedział 10/05/2016 o 13:07
źródło użytkownik

głosy
-1

Niektóre przedmiot załóżmy .dispose()metodę, która zmusza do zasobu mają być usunięte z pamięci.

Odpowiedział 05/08/2008 o 21:21
źródło użytkownik

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