Na przykład:
public class Person
{
public Person()
{
}
~Person()
{
}
}
Kiedy powinienem ręcznie utworzyć destruktor? Kiedy musiałeś stworzyć destruktor?
Na przykład:
public class Person
{
public Person()
{
}
~Person()
{
}
}
Kiedy powinienem ręcznie utworzyć destruktor? Kiedy musiałeś stworzyć destruktor?
Odpowiedzi:
AKTUALIZACJA: To pytanie było przedmiotem mojego bloga w maju 2015 roku . Dzięki za świetne pytanie! Na blogu znajduje się długa lista kłamstw, które ludzie powszechnie wierzą w finalizację.
Kiedy powinienem ręcznie utworzyć destruktor?
Prawie nigdy.
Zazwyczaj jeden tworzy niszczyciel tylko wtedy, gdy klasa trzyma się jakiegoś drogiego niezarządzanego zasobu, który musi zostać wyczyszczony, gdy obiekt zniknie. Lepiej jest użyć wzorca jednorazowego, aby zapewnić oczyszczenie zasobu. Destruktor jest wówczas zasadniczo gwarancją, że jeśli konsument Twojego obiektu zapomni go zutylizować, zasoby nadal zostaną ostatecznie oczyszczone. (Może.)
Jeśli stworzysz destruktor, zachowaj szczególną ostrożność i zrozum, jak działa śmieciarz . Niszczyciele są naprawdę dziwne :
Prawie nic, co jest normalnie prawdziwe, nie jest prawdą w destruktorze. Bądź naprawdę bardzo ostrożny. Pisanie poprawnego destruktora jest bardzo trudne.
Kiedy musiałeś stworzyć destruktor?
Podczas testowania części kompilatora, która obsługuje destruktory. Nigdy nie musiałem tego robić w kodzie produkcyjnym. Rzadko piszę obiekty, które manipulują niezarządzanymi zasobami.
Nazywa się to „finalizatorem” i zwykle powinieneś utworzyć tylko dla klasy, której stan (tj. Pola) zawiera niezarządzane zasoby (tj. Wskaźniki do uchwytów pobranych za pomocą wywołań p / invoke). Jednak w .NET 2.0 i nowszych istnieje lepszy sposób radzenia sobie z usuwaniem niezarządzanych zasobów: SafeHandle . Biorąc to pod uwagę, prawie nigdy nie powinieneś więcej pisać finalizatora.
Nie potrzebujesz go, chyba że klasa utrzymuje niezarządzane zasoby, takie jak uchwyty plików systemu Windows.
Nazywa się to destruktorem / finalizatorem i zwykle jest tworzony podczas implementacji wzorca Disposed.
Jest to rozwiązanie awaryjne, gdy użytkownik twojej klasy zapomina zadzwonić Dispose, aby upewnić się, że (w końcu) twoje zasoby zostaną uwolnione, ale nie masz żadnej gwarancji, kiedy wywoływany jest destruktor.
W tym pytaniu dotyczącym przepełnienia stosu zaakceptowana odpowiedź poprawnie pokazuje, jak zaimplementować wzorzec usuwania. Jest to potrzebne tylko wtedy, gdy klasa zawiera jakiekolwiek niezasłonięte zasoby, których śmieciarz nie zdoła sam się oczyścić.
Dobrą praktyką jest nie wdrażanie finalizatora bez umożliwienia użytkownikowi klasy ręcznego usunięcia obiektu w celu niezwłocznego uwolnienia zasobów.
Gdy masz niezarządzane zasoby i musisz się upewnić, że zostaną one wyczyszczone, gdy obiekt zniknie. Dobrym przykładem mogą być obiekty COM lub programy obsługi plików.
Użyłem destruktora (tylko do celów debugowania), aby sprawdzić, czy obiekt jest usuwany z pamięci w ramach aplikacji WPF. Nie byłem pewien, czy wyrzucanie elementów bezużytecznych naprawdę usuwa obiekt z pamięci, i to był dobry sposób na sprawdzenie.
Destruktory zapewniają niejawny sposób na uwolnienie niezarządzanych zasobów zamkniętych w twojej klasie, są wywoływane, gdy GC się do nich zbliża, i domyślnie wywołują metodę Finalize klasy podstawowej. Jeśli korzystasz z wielu niezarządzanych zasobów, lepiej jest zapewnić jawny sposób uwolnienia tych zasobów za pomocą interfejsu IDisposable. Zobacz przewodnik programowania w języku C #: http://msdn.microsoft.com/en-us/library/66x5fx1b.aspx