Co oznacza tylda przed nazwą funkcji w C #?

164

Patrzę na jakiś kod i ma to stwierdzenie:

~ConnectionManager()
{
    Dispose(false);
}

Klasa implementuje IDisposableinterfejs, ale nie wiem, czy jest to część tego, do czego służy tylda (~).

Keith Sirmons
źródło

Odpowiedzi:

213

~ jest destruktorem

  1. Destruktory są wywoływane automatycznie i nie można ich wywołać jawnie.
  2. Destruktorów nie można przeciążać. W ten sposób klasa może mieć najwyżej jeden destruktor.
  3. Destruktory nie są dziedziczone. Tak więc klasa nie ma innych destruktorów poza tą, która może być w niej zadeklarowana.
  4. Destruktorów nie można używać ze strukturami. Są używane tylko z klasami. Instancja kwalifikuje się do zniszczenia, gdy żaden kod nie może jej już używać.
  5. Uruchomienie destruktora instancji może nastąpić w dowolnym momencie po tym, jak instancja kwalifikuje się do zniszczenia.
  6. Gdy instancja zostanie zniszczona, destruktory w jej łańcuchu dziedziczenia są wywoływane w kolejności od najbardziej do najmniej pochodnych.

Sfinalizować

W języku C # metoda Finalize wykonuje operacje, które mógłby wykonać standardowy destruktor C ++. W C # nie nadajesz jej nazwy Finalize - używasz składni destruktora C ++ polegającej na umieszczeniu symbolu tyldy (~) przed nazwą klasy.

Dysponować

Zaleca się usuwanie obiektów w metodzie Close()lub Dispose(), którą może wywołać jawnie użytkownik klasy. Finalize (destructor) są wywoływane przez GC.

IDisposable interfejs mówi światu, że klasa posiada na zasobach, które muszą być usunięte i zapewnia użytkownikom możliwość ich uwolnienia. Jeśli musisz zaimplementować finalizator w swojej klasie, metoda Dispose powinna używać GC.SuppressFinalize()metody, aby upewnić się, że finalizacja wystąpienia jest pomijana.

Czego używać?

Jawne wywołanie destruktora jest nielegalne. Twój destruktor zostanie wywołany przez śmieciarza. Jeśli masz do czynienia z cennymi niezarządzanymi zasobami (takimi jak uchwyty plików), które chcesz zamknąć i pozbyć się tak szybko, jak to możliwe, powinieneś zaimplementować interfejs IDisposable.

Patrick Desjardins
źródło
3
Nie wiem, jak to było w przeszłości. Ale teraz destruktory są dziedziczone. Sprawdź ten link, aby uzyskać więcej informacji (sprawdź przykład na końcu): msdn.microsoft.com/en-us/library/66x5fx1b.aspx
RononDex
1
@RononDex w punkcie 3 tej samej strony, do której odsyłasz, stwierdza: „Finalizatory nie mogą być dziedziczone” , co jest sprzeczne z Twoim komentarzem. Trzeba przyznać, że jest to trochę zagmatwane, ponieważ chociaż nie można ich dziedziczyć, Finalizemetoda jest wywoływana rekurencyjnie dla wszystkich instancji w łańcuchu dziedziczenia, od najbardziej do najmniej wyprowadzonych” . Pamiętaj jednak, że to nie to samo zachowanie, które można uzyskać z dziedzicznych destruktorów.
Mark Amery,
@MarkAmery ah widzę, więc w zasadzie są wywoływani w odwrotnej kolejności w porównaniu z czymś, co jest dziedziczone?
RononDex
45

To jest finalizator . Szczerze mówiąc, bardzo rzadko trzeba będzie pisać finalizator. Naprawdę musisz napisać tylko, jeśli:

  • Masz bezpośredni dostęp do niezarządzanego zasobu (np. Przez IntPtr) i nie możesz z niego korzystać, SafeHandleco ułatwia
  • Implementujesz IDisposablew klasie, która nie jest zapieczętowana. (Wolę zapieczętować klasy, chyba że są przeznaczone do dziedziczenia). W takich przypadkach finalizator jest częścią kanonicznego wzorca Dispose.
Jon Skeet
źródło
9

Służy do wskazania destruktora dla klasy.

torialny
źródło
12
Oba są poprawne, w zależności od specyfikacji języka C #, którą czytasz. Najnowsza wersja MS (ujednolicony C # 3.0) określa je jako destruktory (np. Sekcja 10.13), ale specyfikacja ECMA określa je jako finalizatory.
Jon Skeet
@ 1800INFORMATION: Element składniowy jest właściwie nazywany destruktorem. Jeśli klasa ma destruktor, kompilator C # automatycznie wygeneruje finalizator, który zawiera ogólnie bezużyteczny try/finallyblok, który zapewnia Finalizewywołanie metody nadrzędnej . Większość rzeczy, które są prawdziwe w przypadku destruktorów, dotyczy finalizatorów i odwrotnie, ale słowa te mają nieco inne znaczenie.
supercat
4

Tak samo jak C ++, jest to destruktor; jednak w C # nie jest to wywoływane jawnie, jest wywoływane, gdy obiekt zostanie zebrany.

Santiago Palladino
źródło
1

~ zwykle reprezentuje dekonstruktora. który jest uruchamiany tuż przed śmiercią obiektu.

Oto opis dekonstruktorów C #, które znalazłem

stephenbayer
źródło
4
poprawnym terminem powinien być destruktor / finalizator, a nie dekonstruktor. Dekonstruktor oznacza składnię do dekonstruowania konstruktora.
Eriawan Kusumawardhono