W Visual Basic konstruktor to procedura Sub New, która jest wywoływana podczas tworzenia instancji klasy i inicjalizuje obiekt. Destruktor jest realizowany za pomocą metody Finalize lub interfejsu IDisposable (metoda Dispose), co jest szczególnie ważne dla zwalniania zasobów.
W klasycznym Visual Basic konstruktor był automatycznie wywoływany podczas tworzenia obiektów (Class_Initialize), destruktor — podczas usuwania (Class_Terminate). W VB.NET dodano przeciążalne konstruktory, rozdzielenie zwalniania zarządzanych i niezarządzanych zasobów, oraz użycie zbieracza śmieci (GC).
Niewłaściwe użycie konstruktorów lub destruktorów prowadzi do wycieków pamięci, błędnej inicjalizacji obiektów lub blokowania zasobów (np. plików).
Używaj Sub New do inicjalizacji obiektów, koniecznie realizuj Dispose do jawnego zwalniania zasobów. Jeśli używasz destruktora (Finalize), pamiętaj o latencji GC i niemożności przewidzenia momentu wywołania.
Przykład kodu:
Public Class ResourceHolder Implements IDisposable Private resource As SomeResource Public Sub New() resource = New SomeResource() Console.WriteLine("Zasób przydzielony") End Sub Protected Overrides Sub Finalize() Dispose(False) MyBase.Finalize() End Sub Public Sub Dispose() Implements IDisposable.Dispose Dispose(True) GC.SuppressFinalize(Me) End Sub Protected Overridable Sub Dispose(disposing As Boolean) If disposing Then If resource IsNot Nothing Then resource.Release() resource = Nothing End If End If End Sub End Class
Kluczowe cechy:
Czy można ręcznie wywołać konstruktor Sub New dla już istniejącego obiektu?
Nie, konstruktor jest wywoływany tylko podczas tworzenia obiektu. Do ponownej inicjalizacji użyj osobnej metody Reset lub podobnej.
Kiedy jest wywoływany Finalize i czy zawsze jest gwarantowane jego wykonanie?
Finalize jest wywoływane przez zbieracza śmieci podczas niszczenia obiektu, ale jego wywołanie nie jest gwarantowane (np. przy awaryjnym zamknięciu procesu lub odcięciu zasilania).
Po co wywoływać GC.SuppressFinalize wewnątrz Dispose?
Zapobiega to ponownemu wywołaniu Finalize dla już zwolnionego ręcznie obiektu, zwiększając wydajność i zapobiegając wyciekom pamięci.
W projekcie nie zaimplementowano Dispose, i kilka plików pozostało zablokowanych po zakończeniu pracy aplikacji — zasoby nie były zwalniane do momentu interwencji zbieracza śmieci.
Plusy:
Minusy:
Zrealizowano IDisposable i Dispose, użyto Using podczas pracy z zewnętrznymi zasobami. Wszystkie pliki są poprawnie zamykane, a aplikacja działa stabilnie.
Plusy:
Minusy: