C # Form.Close vs Form.Dispose

88

Jestem nowy w C # i próbowałem spojrzeć na wcześniejsze posty, ale nie znalazłem dobrej odpowiedzi.

Czy w aplikacji formularza systemu Windows w języku C # z pojedynczym formularzem jest używany Form.Close()lepszy lub Form.Dispose()?

MSDN mówi, że wszystkie zasoby w obiekcie są zamknięte, a formularz jest usuwany po wywołaniu Close. Mimo to natknąłem się na kilka przykładów w Internecie, które podążają za rozporządzeniem, a nie zamknięciem.

Czy jeden ma przewagę nad drugim? W jakich scenariuszach powinniśmy preferować jeden nad drugim?

topgun_ivard
źródło
Nieco inne pytanie, ta sama odpowiedź, IMO: tj. Close i Dispose są zwykle równoważne, z wyjątkiem tego, że możesz wywołać Close więcej niż raz.
ChrisW
2
@Chrisw: Możesz także zadzwonić do Dispose więcej niż raz.
Henk Holterman
@ChrisW, Dispose również powinno działać więcej niż raz. bluebytesoftware.com/blog/…
Steven Evers
Rzecz, która sprawiła, że ​​zamknąłem === raczej usuń niż zamknij == form.Visible = false; Spodziewałem się, że zamknięcie będzie łagodniejszą metodą niż pozbycie się.
Pete Kirkham
4
@Pete Kirkham: Jeśli chcesz form.Visible = false;, możesz zadzwonić form.Hide(). W rzeczywistości form.Hide()po prostu ustawia this.Visible = false;.
Dirk Vollmar

Odpowiedzi:

171

Informacje na tym forum w witrynie MSDN.

Form.Close()wysyła odpowiednie komunikaty systemu Windows, aby zamknąć okno win32. W trakcie tego procesu, jeśli formularz nie był wyświetlany modalnie, na formularzu wywoływana jest funkcja Dispose. Usunięcie formularza zwalnia niezarządzane zasoby, które są przechowywane w formularzu.

Jeśli zrobisz form1.Show()lub Application.Run(new Form1()), Dispose zostanie wywołane, gdy Close()zostanie wywołane.

Jeśli jednak zrobisz, form1.ShowDialog() aby wyświetlić formularz modalnie, formularz nie zostanie usunięty i będziesz musiał zadzwonić do form1.Dispose()siebie. Uważam, że jest to jedyny przypadek, w którym powinieneś się martwić o samodzielne pozbycie się formularza.

Kyra
źródło
Czy pierwsza wersja zawierała cytat? +1, aby zrekompensować.
Henk Holterman
@Dan pierwsza wersja była do niczego ... (przepraszam @Kyra)
jjnguy
13
To trochę różni się od stanów MSDN pod adresem msdn.microsoft.com/en-us/library/… : „ Jedynym warunkiem, w którym formularz nie jest usuwany po zamknięciu, jest sytuacja, gdy jest on częścią interfejsu wielu dokumentów (MDI) aplikacji, a formularz nie jest widoczny. W takim przypadku konieczne będzie ręczne wywołanie metody Dispose, aby oznaczyć wszystkie kontrolki formularza do czyszczenia pamięci. " Jednak powinno być łatwo sprawdzić, czy formularze modalne są usuwane, czy nie, za pomocą prostej próbki.
Dirk Vollmar
14

Zasadniczo zawsze zalecałbym jawne wywoływanie metody Dispose dla dowolnej klasy, która ją oferuje, albo przez bezpośrednie wywołanie metody, albo poprzez umieszczenie w bloku „using”.

Najczęściej klasy implementujące IDisposible robią to, ponieważ opakowują niezarządzany zasób, który należy zwolnić. Chociaż te klasy powinny mieć finalizatory, które działają jako zabezpieczenie, wywołanie Dispose pomoże zwolnić tę pamięć wcześniej i przy niższym narzucie.

W przypadku obiektu Form, jak zauważył odsyłacz do Kyry, udokumentowano, że metoda Close wywołuje Dispose w twoim imieniu, więc nie musisz tego robić jawnie. Jednak zawsze wydawało mi się, że poleganie na szczegółach implementacji. Wolę zawsze wywoływać zarówno Close, jak i Dispose dla klas, które je implementują, w celu ochrony przed zmianami / błędami implementacji i ze względu na przejrzystość. Prawidłowo zaimplementowana metoda Dispose powinna być bezpieczna do wielokrotnego wywoływania.

Jesse Squire
źródło
6

Niewywołanie Closeprawdopodobnie omija wysyłanie kilku wiadomości Win32, które wydaje się być dość ważne, chociaż nie mogłem dokładnie powiedzieć, dlaczego ...

Closema tę zaletę, że podnosi zdarzenia (które można anulować) tak, aby osoba postronna (do formularza) mogła obserwować FormClosingi FormClosedodpowiednio reagować.

Nie jestem pewien, czy FormClosingi / lub FormClosedzostaną podniesione, jeśli po prostu pozbędziesz się formularza, ale zostawię to Tobie do eksperymentowania.

Czerwony pies
źródło
2
Jeśli usuniesz formularz, zdarzenia zamknięcia i zamknięcia nie są wywoływane.
matrix
4
wywołanie metody Dispose spowodowałoby migotanie okna, gdy jest używane w oknie Modal-Form przez okno mdi-child
dotNETbeginner
1

Używanie usingto całkiem dobry sposób:

using (MyForm foo = new MyForm())
{
    if (foo.ShowDialog() == DialogResult.OK)
    {
        // your code
    }
}
Mustafa Burak Kalkan
źródło
0

Close () - zarządzany zasób można tymczasowo zamknąć i ponownie otworzyć.

Dispose () - trwale usuwa zarządzany lub nie zarządzany zasób

Yuresh Karunanayake
źródło
3
Dzieje się tak tylko wtedy, gdy formularz został wyświetlony przy użyciu ShowDialog(). W przeciwnym razie Close()usunie również formularz.
Peter Duniho
-1

Jeśli użyjesz form.close () w swoim formularzu i ustawisz zdarzenie FormClosing swojego formularza i albo użyjesz form.close () w tym zdarzeniu, wpadniesz w nieograniczoną pętlę i wystąpił argument argument poza zakresem, a rozwiązaniem jest zmiana formularza .close () z form.dispose () w przypadku zamknięcia formularza. Mam nadzieję, że ta mała wskazówka ci pomoże !!!

Hadi Erfanian
źródło
-1

To, co właśnie eksperymentowałem z narzędziami diagnostycznymi VS, to nazwałem this.Close (), a następnie wyzwolono zdarzenie formclosing. Następnie, kiedy wywołuję this.Dispose () na końcu zdarzenia Formclosing, w którym pozbywam się wielu innych obiektów, czyści wszystko znacznie płynniej.

smoothumut
źródło