2013-05-15 13 views
13

Dokumentacja na PowerShell here ma następujący ciekawy komentarz w nim:Dlaczego ta zmienna musi mieć wartość null po usunięciu obiektu?

PowerShell powershell = PowerShell.Create(); 

using (powershell) 
{ 
    //... 
} 

// Even after disposing of the PowerShell object, we still 
// need to set the powershell variable to null so that the 
// garbage collector can clean it up. 
powershell = null; 

Dlaczego powershell muszą być ustawione na null po wyrzucać?

+2

To pytanie C#, a nie pytanie PowerShell. –

+1

@AnsgarWiechers - Masz rację; po zbadaniu linku to dziwny wzór. Czy ktoś może powiedzieć, dlaczego nie skorzystał z 'using (PowerShell powershell = PowerShell.Create()) {'? Styl preferencji? –

+8

Dla zapisu, który jest ogólnie kiepską praktyką i po prostu nie jest w ogóle potrzebny w tym kontekście. Jest mało prawdopodobne, aby to miało jakikolwiek wpływ, a gdyby tak było, byłoby to maleńkie. Zmienna powinna zostać właśnie utworzona w 'użyciu', ale nawet bez tego nie ma uzasadnienia dla jej anulowania. Pozostała część metody wypełni * bardzo * szybko, a obiekt powershell nie zużyje znacznej ilości zasobów po usunięciu. – Servy

Odpowiedz

16

To nie jest bezpośrednio problem PowerShell. Gdy kończy się blok using, określony obiekt (obiekty) mają wywoływane metody. Zwykle wykonują one pewne operacje czyszczenia, często w celu uniknięcia wycieku pamięci i tak dalej. Jednak Dispose() nie usuwa obiektu. Jeśli odniesienie do niego nadal istnieje poza blokiem using (jak w tym przykładzie), to sam obiekt nadal znajduje się w zasięgu. Nie można go pozbyć się ze śmiecia, ponieważ wciąż istnieje odniesienie do niego, więc wciąż zajmuje pamięć.

To, co robią w twoim przykładzie, to odwołanie. Kiedy powershell jest ustawiona na null, obiekt PowerShell, na który wskazywał, zostaje osierocony, ponieważ nie istnieją żadne inne zmienne odnoszące się do niego. Po odczytaniu tego przez garbage collector może zwolnić pamięć. Tak się stanie na końcu metody (ponieważ powershell wykracza poza zakres), ale w ten sposób odzyskasz zasoby systemowe nieco wcześniej.

(Edit: jak Brian Rasmussen zwraca uwagę, że środowisko wykonawcze NET jest niezwykle mądry o zbieranie śmieci Po osiągnięciu ostatniej odniesienie do powershell w kodzie, środowisko wykonawcze powinien wykryć, że nie jest to potrzebne. więcej i zwolnij go do zbierania śmieci, więc linia powershell = null; nic nie robi.)

Nawiasem mówiąc, ten wzór wydaje mi się bardzo dziwny. Zazwyczaj podejście jest mniej więcej tak:

using (PowerShell powershell = PowerShell.Create()) 
{ 
    //... 
} 

ten sposób powershell wykracza poza zakres na końcu bloku using, tuż po jej wyrzucać. Łatwiej jest określić, gdzie zmienna jest istotna, i zapisać kod, ponieważ nie potrzebujesz już linii powershell = null. Powiedziałbym nawet, że jest to lepsza praktyka kodowania, ponieważ powershell nigdy nie istnieje w stanie już ułożonym. Jeśli ktoś zmieni oryginalny kod i spróbuje użyć powershell poza blokiem using, cokolwiek się stanie, będzie prawdopodobnie złe.

+6

Środowisko wykonawcze .NET nie wymaga odwołań zerowych i wykrywa obiekty, które kwalifikują się do gromadzenia, gdy tylko nie są już przywoływane (tj. Zdarza się to zazwyczaj przed zakończeniem metody). –

+0

@Justin Morgan Re wzór wyglądający dziwnie, dobrze by był zgodny z resztą jakości próbki kodu, to chyba ;-) – noonand

+0

@BrianRasmussen Doskonały punkt! Co oznacza, że ​​jest to jeszcze mniej przydatne. –

7

Nie trzeba jej ustawiać na wartość null, a tak naprawdę nie powinno być. Odśmiecacz .NET jest w stanie wykryć, że obiekt nie jest używany po określonej instrukcji, nawet jeśli twój kod nie przypisuje wartości pustej do odpowiedniej zmiennej. (Szczegółowe informacje znajdują się w sekcji http://blogs.msdn.com/b/cbrumme/archive/2003/04/19/51365.aspx). Co do tego, dlaczego "oficjalny" przykład zawiera ten dodatkowy kod z wprowadzającymi w błąd komentarzami, nawet dokumenty mogą mieć błędy ...

1

Porada jest niepoprawna, o ile nieosiągalny, kwalifikuje się do śmieci kolekcja. (Patrz What is the correct way to free memory in C# dla niektórych kod wykazując tym) jedyne powody null rzeczy są

  • Aby łatwiej rozwiązywać pamięci przecieki
  • Aby usunąć odniesienia (npWłaściwości publiczne), że GC może mieć problemy determinującym są nieosiągalne

których Zarówno byś naprawdę tylko wewnątrz obiektów Dispose metoda

Powiązane problemy