W artykule „Kodowanie nowych instancji obiektów” pisałem o różnych sposobach tego Nowy wystąpienia obiektów mogą być tworzone. Odwrotnym problemem, jakim jest usuwanie obiektu, jest coś, o co nie będziesz musiał się zbyt często martwić w VB.NET. .NET zawiera technologię o nazwie Śmieciarz (GC), który zwykle zajmuje się wszystkim za kulisami cicho i skutecznie. Ale czasami, zwykle podczas korzystania ze strumieni plików, obiektów SQL lub obiektów graficznych (GDI +) (czyli niezarządzane zasoby), może być konieczne przejęcie kontroli nad rozmieszczaniem obiektów we własnym kodzie.
Po pierwsze, jakieś tło
Tak jak konstructor (the Nowy słowo kluczowe) tworzy nowy obiekt, a destructor to metoda wywoływana po zniszczeniu obiektu. Ale jest haczyk. Ludzie, którzy stworzyli .NET, zdali sobie sprawę, że jest to formuła na błędy, jeśli dwa różne fragmenty kodu mogą faktycznie zniszczyć obiekt. Tak więc .NET GC jest w rzeczywistości pod kontrolą i zwykle jest to jedyny kod, który może zniszczyć instancję obiektu. GC niszczy obiekt, kiedy podejmuje decyzję, a nie wcześniej. Zwykle jest to po tym, jak obiekt opuści zakres
wydany przez środowisko uruchomieniowe języka wspólnego (CLR). GC niszczy obiektów, gdy CLR potrzebuje więcej wolnej pamięci. W związku z tym nie można przewidzieć, kiedy GC faktycznie zniszczy obiekt.(Welllll... To prawda prawie cały czas. Możesz zadzwonić GC.Collect i wymusić a cykl usuwania śmieci, ale władze powszechnie twierdzą, że to zły pomysł i zupełnie niepotrzebne).
Na przykład, jeśli Twój kod utworzył Klient obiekt, może się wydawać, że ten kod ponownie go zniszczy.
Klient = nic
Ale tak nie jest. (Ustawienie obiektu na Nothing jest zwykle nazywane, dereferencje obiekt). W rzeczywistości oznacza to po prostu, że zmienna nie jest już powiązana z obiektem. Jakiś czas później GC zauważy, że obiekt jest dostępny do zniszczenia.
Nawiasem mówiąc, w przypadku obiektów zarządzanych nie jest to tak naprawdę konieczne. Chociaż obiekt taki jak przycisk będzie oferował metodę Dispose, nie jest konieczne jego używanie i niewiele osób tak robi. Na przykład komponenty Windows Forms są dodawane do obiektu kontenera o nazwie składniki. Po zamknięciu formularza jego metoda Dispose jest wywoływana automatycznie. Zwykle musisz martwić się o to wszystko podczas korzystania z niezarządzanych obiektów, a nawet wtedy, aby zoptymalizować program.
Zalecanym sposobem na zwolnienie zasobów, które mogą znajdować się w obiekcie, jest wywołanie Dysponować metoda dla obiektu (jeśli jest dostępna), a następnie wyrejestruj obiekt.
Klient. Dysponować() Klient = nic
Ponieważ GC zniszczy osierocony obiekt, niezależnie od tego, czy ustawisz zmienną obiektu na Nic, tak naprawdę nie jest to konieczne.
Innym zalecanym sposobem upewnienia się, że obiekty są niszczone, gdy nie są już potrzebne, jest umieszczenie kodu używającego obiektu w pliku Za pomocą blok. Blok przy użyciu gwarantuje usunięcie jednego lub więcej takich zasobów, gdy kod zostanie z nimi zakończony.
W serii GDI +, Za pomocą blok jest używany dość często do zarządzania tymi nieznośnymi obiektami graficznymi. Na przykład ...
Używanie myBrush jako LinearGradientBrush _. = Nowy LinearGradientBrush (_. Mnie. ClientRectangle, _. Kolor. Niebieski kolor. Czerwony, _. LinearGradientMode. Poziomy) <... wi kodu ...> Zakończ używanie
myBrush jest usuwany automatycznie po zakończeniu bloku.
Podejście GC do zarządzania pamięcią to duża zmiana w stosunku do sposobu, w jaki VB6 to zrobił. Obiekty COM (używane przez VB6) zostały zniszczone, gdy wewnętrzny licznik odniesień osiągnął zero. Ale zbyt łatwo było popełnić błąd, więc wewnętrzny licznik był wyłączony. (Ponieważ pamięć była związana i niedostępna dla innych obiektów, kiedy to się stało, nazywało się to „wyciekiem pamięci”.) Zamiast tego GC sprawdza, czy coś odnosi się do obiektu i niszczy go, gdy już go nie ma Bibliografia. Podejście GC ma dobrą historię w językach takich jak Java i jest jednym z dużych ulepszeń w .NET.
Na następnej stronie przyjrzymy się interfejsowi IDisposable... interfejs używany, gdy trzeba usunąć niezarządzane obiekty we własnym kodzie.
Jeśli kodujesz własny obiekt korzystający z niezarządzanych zasobów, powinieneś użyć IDisposable interfejs dla obiektu. Microsoft ułatwia to, dołączając fragment kodu, który tworzy odpowiedni wzorzec dla Ciebie.
Kliknij tutaj, aby wyświetlić ilustrację
Kliknij przycisk Wstecz w przeglądarce, aby powrócić
Dodany kod wygląda następująco (VB.NET 2008):
Klasa ResourceClass. Implementuje IDisposable. „Aby wykryć zbędne połączenia. Prywatny unieszkodliwiany jako wartość logiczna = fałsz. „IDisposable. Protected Overridable Sub Dispose (_. ByVal pozbywa się jako logiczny) Jeśli nie mnie. Jeśli pozbywasz się wtedy. „Uwolnij inny stan (obiekty zarządzane). End If. „Uwolnij swój własny stan (niezarządzane obiekty). „Ustaw duże pola na zero. End If. Me.disposed = True. Napis końcowy. #Region „IDisposable Support” ”Ten kod został dodany przez Visual Basic do. „prawidłowo wdrożyć wzór jednorazowy. Public Sub Dispose () Implementuje IDisposable. Dysponować. „Nie zmieniaj tego kodu. „Wprowadź kod czyszczenia. „Usuń (ByVal disposing As Boolean) powyżej. Usuń (True) GC.SuppressFinalize (Me) End Sub. Protected Overrides Sub Finalize () 'Nie zmieniaj tego kodu. „Wprowadź kod czyszczenia. „Usuń (ByVal disposing As Boolean) powyżej. Usuń (Fałsz) MyBase. Finalize () End Sub. # Region końcowy. Klasa końcowa
Dysponować jest prawie „wymuszonym” wzorcem projektowania programistów w .NET. Jest tylko jeden właściwy sposób, aby to zrobić i to jest to. Możesz pomyśleć, że ten kod robi coś magicznego. Tak nie jest.
Najpierw zauważ, że wewnętrzna flaga unieszkodliwiony po prostu zewrzyj całość, abyś mógł zadzwonić Utylizacja (utylizacja) tak często, jak chcesz.
Kod ...
GC.SuppressFinalize (Me)
... sprawia, że Twój kod jest bardziej wydajny, informując GC, że obiekt został już usunięty („droga” operacja pod względem cykli wykonania). Finalizacja jest chroniona, ponieważ GC wywołuje ją automatycznie po zniszczeniu obiektu. Nigdy nie powinieneś dzwonić do Finalizacji. Boolean utylizacja informuje kod, czy Twój kod zainicjował zbycie obiektu (True), czy też GC to zrobiła (w ramach Sfinalizować pod. Zauważ, że jedynym kodem, który wykorzystuje wartość logiczną utylizacja jest:
Jeśli pozbywasz się wtedy. „Uwolnij inny stan (obiekty zarządzane). End If
Gdy pozbywasz się obiektu, wszystkie jego zasoby muszą zostać usunięte. Kiedy CLR Śmieciarz usuwa obiekt tylko niezarządzane zasoby muszą zostać usunięte, ponieważ śmieciarz automatycznie dba o zasoby zarządzane.
Idea tego fragmentu kodu polega na dodaniu kodu do zarządzania obiektami zarządzanymi i niezarządzanymi we wskazanych lokalizacjach.
Kiedy wyprowadzasz klasę z klasa podstawowa która implementuje IDisposable, nie musisz przesłonić żadnej z podstawowych metod, chyba że użyjesz innych zasobów, które również muszą zostać usunięte. Jeśli tak się stanie, klasa pochodna powinna zastąpić metodę Dispose (disposing) klasy bazowej, aby pozbyć się zasobów klasy pochodnej. Pamiętaj jednak, aby wywołać metodę Dispose (disposing) klasy podstawowej.
Protected Overrides Sub Dispose (ByVal disposing As Boolean) If Not Me.disposed Następnie. Jeśli pozbywasz się wtedy. „Dodaj swój kod do bezpłatnych zasobów zarządzanych. End If. „Dodaj swój kod, aby zwolnić niezarządzane zasoby. End If. MyBase. Utylizacja (utylizacja) Napis końcowy
Temat może być nieco przytłaczający. Wyjaśnienie to ma na celu „wyjaśnienie” tego, co się faktycznie dzieje, ponieważ większość informacji, które można znaleźć, nie mówi wam!