2011-07-20 7 views
11

MSDN's example pattern dla wdrożenia do utylizacji() Metoda przedstawia ustawianie odniesienia do nastawionej zarządza zasobami null (_resource = null), lecz nie tak zewnątrz bloku if (disposing):MSDN Dispose() przykład błędne? (Kiedy ustawić zarządzanych odniesienia do NULL)

protected virtual void Dispose(bool disposing) 
{ 
    // If you need thread safety, use a lock around these 
    // operations, as well as in your methods that use the resource. 
    if (!_disposed) 
    { 
     if (disposing) { 
      if (_resource != null) 
       _resource.Dispose(); 
       Console.WriteLine("Object disposed."); 
     } 

     // Indicate that the instance has been disposed. 
     _resource = null; 
     _disposed = true; 
    } 
} 

shouldn 't _resource = null należy umieścić w tym bloku kodu? Jeśli zostanie wykonane połączenie z numerem Dispose(false), wówczas _resource będzie mieć wartość null i nie będzie można go później usunąć! ??

Oczywiście, Dispose(false) jest wywoływany tylko (w praktyce) przez środowisko wykonawcze podczas finalizacji. Ale jeśli _resource nie został wcześniej usunięty, jaka jest potrzeba ustawienia go na wartość null w tym momencie, gdy obiekt (w tym pole członkowskie _resource) zostanie wkrótce zebrany?


[koniec pierwotnego pytania]

Kontynuacja:

Po wielu czytanie wydaje się ustawienie odniesienie do wartości null nie jest konieczne, ale może być dobrym pomysłem dla „ciężkiego” członka obiekty, jeśli masz powody, by sądzić, że klasa zawierająca (ta, która została usunięta) może wkrótce nie zostać wyrzucona do śmieci.

Wiedz o tym, że likwidacja obiektu nie gwarantuje, że obiekt został "zwolniony" po zużyciu kodu. Wyrzucony przedmiot może być trzymany (w zbiorze lub w inny sposób) do różnych celów lub po prostu w wyniku błędu. Mogę sobie wyobrazić, że aplikacja korzystająca z obiektów z kolekcji usuwa je, ale przechowuje w kolekcji dla późniejszego procesu usuwania i stanu końcowego rejestracji (lub czegoś podobnego ... kto wie ...)

Wnioski:

  1. Ustawianie odniesienia do „ciężkich” obiektów członkowskich null wydaje je do zbierania śmieci, nawet jeśli umieszczone obiekt nie zostanie zwolniony.
  2. Przesadą jest usuwanie referencji dla wszystkich obiektów.
  3. Dlatego umieszczenie instrukcji _resource = null (pierwotne pytanie) nie jest ważne z dwóch powodów: (A) Korzystanie z niego w ogóle jest tylko kwestią do przemyślenia po przeczytaniu powyższego; (B) W przykładzie MSDN wykonuje on zarówno dla Dispose(true) i Dispose(false), ale drugi występuje tylko wtedy, gdy obiekt jest sfinalizowany i tak czy inaczej zostanie zebrany śmieci!

Zatem moja preferencja będzie umieścić _resource = null wewnątrz najbardziej wewnętrznej bloku if:

if (disposing) { 
    if (_resource != null) { 
     _resource.Dispose(); 
     _resource = null; 
    } 
} 

Utrzymuje cały kod _resource razem. Dalsze myśli, ktoś?

Więcej czytanie:

+1

Służy ona większego sensu, ale ma trochę szkoda ... Właściwie, to byłoby bardziej zirytowany przez: pisanie na 'Console', a B: pisanie na' Console' nawet jeśli jest już usunięte, a my nie zrobił nie wyrzucaj go (patrz brak nawiasów klamrowych na "jeśli"). –

+0

Haha! 'Console.Writeline()' jest przykładowym kodem. Czy Trace.Writeline() byłaby lepsza? Nie brakuje również klamry - jest na końcu linii 'if' (nie jest zgodna z StyleCop). –

+0

jeszcze raz; pisze "Obiekt unieszkodliwiony". nawet jeśli '_resource' ma wartość zerową i dlatego nie wywołało' .Dispose() '. Mam na myśli najbardziej wewnętrzną * "jeśli". –

Odpowiedz

6

Ustawienie na wartość null powoduje usunięcie odniesienia lub wskaźnika do położenia w stercie. Pozwala to GC przejść i usunąć wszystko, co nie ma żadnych odniesień do niego bez konieczności zgadywania. _resource byłby jakimś wewnętrznym obiektem do użytku, który musi mieć swoje referencje oczyszczone, powiedzmy, że masz wewnętrzny Gniazdo do zamknięcia, że ​​zamknąłbyś/zrzucisz to gniazdo lub inny stały zasób. Po usunięciu ustawia się wartość null i usuwa wszystkie odniesienia (należy usunąć wszystkie odwołania), aby GC mógł wykonać to zadanie poprawnie. Druga połowa mojej odpowiedzi jest przykładem, więc w pewnym sensie powtarza pewne rzeczy, ale mam nadzieję, że wpadniesz na ten pomysł.

ustawienie go na null dwukrotnie nie jest wielka sprawa, ponieważ nie ma żadnego efektu. Unieszkodliwianie powinno być prawdą w czasie czyszczenia wszelkich zasobów i jest to fałsz tylko wtedy, gdy jest (jak powiedziałeś) i tak zostanie zebrane.

+0

Być może to nie robi dużej różnicy gdzie to idzie? Poprzez umieszczenie '_resource = null' zaraz po' _resource.Dispose() 'kod jest łatwiejszy do odczytu/utrzymania, ponieważ te elementy są związane w jednym miejscu (wyobrazić sobie wiele elementów są usuwane z wielu' = null'). –

+0

Również '_resource' jest zarządzanym zasobem (prawdopodobnie nie jest gniazdem). Wzorzec MSDN umieszcza tylko zarządzane obiektu usuwania wewnątrz bloku 'if (disposing)'. Próbuję tylko zrozumieć, czy istnieje powód "_resource = null" nie jest tuż poniżej '_resource.Dispose()'. –

+0

Gniazda mogą być zarządzane w kodzie jako stale otwarte z jakiegoś powodu (tak samo jak złącze WebService lub HttpListener), które muszą być zamknięte lub można mieć przeciek pamięci lub innego rodzaju wycieku zasobów (dla isntance portu, który Cię używany nie jest już dostępny). Większość przedmiotów nie wymaga zarządzania, więc możesz po prostu ustawić je na zero, a GC odbierze je podczas jednej z podróży. –

Powiązane problemy