共用方式為


物件存留期:物件建立和終結的方式(Visual Basic)

類別的實例,物件,是使用 New 關鍵詞建立的。 初始化工作通常必須先在新的 物件上執行,才能使用它們。 常見的初始化工作包括開啟檔案、連線到資料庫,以及讀取登錄機碼的值。 Visual Basic 會使用稱為 建構 函式的程式來控制新物件的初始化(允許控制初始化的特殊方法)。

對象離開範圍之後,Common Language Runtime 會釋放它(CLR)。 Visual Basic 會使用稱為 解構函式的程式控制系統資源的發行。 建構函式和解構函式一起支援建立健全且可預測的類別庫。

使用建構函式和解構函式

建構函式和解構函式負責管理物件的創建和銷毀。 Sub New Visual Basic 中的 和 Sub Finalize 程式會初始化和終結 物件;它們會取代 Class_Initialize Visual Basic 6.0 和舊版中使用的 和 Class_Terminate 方法。

子新增

Sub New 構函式只能在建立類別時執行一次。 除了相同類別或衍生類別之另一個建構函式的第一行程式代碼之外,無法明確呼叫它。 此外,方法中的 Sub New 程式代碼一律會在 類別的任何其他程式碼之前執行。 如果您未明確定義Sub New類別的程式,Visual Basic 會在運行時間隱含建立Sub New建構函式。

若要建立類別的建構函式,請在類別定義中的任何位置建立名為 Sub New 的程式。 若要建立參數化建構函式,請指定自變數的名稱和數據類型, Sub New 就像您指定任何其他程式的自變數一樣,如下列程式代碼所示:

Sub New(ByVal s As String)

建構函式經常多載,如下列程式碼所示:

Sub New(ByVal s As String, i As Integer)

當您定義衍生自另一個類別的類別時,建構函式的第一行必須是基類建構函式的呼叫,除非基類具有不採用任何參數的可存取建構函式。 例如,對包含上述建構函式之基類的呼叫會是 MyBase.New(s)。 否則, MyBase.New 是選擇性的,而且Visual Basic運行時間會隱含地呼叫它。

撰寫程式代碼以呼叫父物件的建構函式之後,您可以將任何其他初始化程式代碼新增至 Sub New 程式。 Sub New 當呼叫為參數化建構函式時,可以接受自變數。 這些參數會從呼叫建構函式的程式傳遞,例如 Dim AnObject As New ThisClass(X)

子程式完成

在釋放物件之前,CLR 會自動針對定義Finalize程式的物件呼叫 Sub Finalize 方法。 Finalize方法可以包含必須在物件終結之前執行的程式代碼,例如關閉檔案的程式代碼和儲存狀態資訊。 執行 Sub Finalize會稍微降低效能,因此只有在需要明確釋放物件時,才應該定義 Sub Finalize 方法。

備註

CLR 中的垃圾收集器不會(且無法)處理操作系統直接在 CLR 環境外執行的非受控物件。 這是因為必須以不同的方式處理不同的未受管理物件。 該資訊並未直接與非受管物件關聯;必須在該物件的文件中找尋該資訊。 使用非受控物件的類別必須在其類別的Finalize方法中處置這些物件。

Finalize 解構函式是一個受保護的方法,只能由其所屬類別或衍生類別呼叫。 系統會在物件終結時自動呼叫Finalize,因此您不應該從衍生類別的Finalize實作外部明確呼叫 Finalize

Class_Terminate不同的是,一旦對象被設為 nothing,它就會立即執行,而當物件超出作用域時,Visual Basic 通常會有一段延遲才會呼叫 Finalize 解構函式。 Visual Basic .NET 允許第二種解構函式 , IDisposable.Dispose隨時可以明確呼叫以立即釋放資源。

備註

Finalize解構函式不應該擲回例外狀況,因為它們無法由應用程式處理,而且可能會導致應用程式終止。

New 和 Finalize 方法如何在類別階層中運作

每當建立類別的實例時,Common Language Runtime (CLR) 會嘗試執行名為 New的程式,如果它存在於該物件中。 New 是一種稱為 constructor 的程序,用來在物件執行任何其他程式碼之前初始化新物件。 建構函式可用來開啟檔案、連接到資料庫、初始化變數,以及完成任何其他必須在物件使用前進行的工作。

建立衍生類別的實例時, Sub New 基類的建構函式會先執行,後面接著衍生類別中的建構函式。 這是因為 Sub New 建構函式中的第一行程式碼使用語法 MyBase.New() 呼叫類別階層中其父類別的建構函式。 接著會針對類別階層中的每個類別呼叫Sub New建構子,直到到達基類的建構子為止。 此時,基類建構函式中的程式代碼會執行,後面接著所有衍生類別中每個建構函式中的程式代碼,最後執行大多數衍生類別中的程序代碼。

顯示類別階層建構函式和繼承的螢幕快照。

當物件不再需要時,CLR 會在釋放記憶體前,呼叫該物件的 Finalize 方法。 方法 Finalize 稱為 , destructor 因為它會執行清除工作,例如儲存狀態資訊、關閉檔案和與資料庫的連線,以及其他在釋放物件之前必須完成的工作。

顯示 Finalize 方法終結器的螢幕快照。

IDisposable 介面

類別實例通常會控制 CLR 未管理的資源,例如 Windows 句柄和資料庫連線。 這些資源必須在類別的方法中Finalize處置,以便在垃圾收集器終結對象時釋放它們。 不過,垃圾收集器只會在 CLR 需要更多可用記憶體時清除物件。 這表示可能需要在物件超出範圍很長一段時間後,資源才會釋出。

除了垃圾回收以外,若您的類別實作IDisposable介面,則可提供一種機制以主動管理系統資源。 IDisposable 有一個方法,Dispose,用戶端在完成使用物件後,應該呼叫此方法。 您可以使用 Dispose 方法來立即釋放資源,並執行關閉檔案和資料庫連線等工作。 Finalize不同於解構函式,Dispose方法不會自動被呼叫。 當您想要立即釋放資源時,類別的客戶端必須明確呼叫 Dispose

實作 IDisposable

實作 介面的 IDisposable 類別應該包含下列程式代碼區段:

  • 用來追蹤物件是否已處置的欄位:

    Protected disposed As Boolean = False
    
  • 重載 Dispose 以釋放類別資源。 這個方法應該由基類的 DisposeFinalize 方法呼叫。

    Protected Overridable Sub Dispose(ByVal disposing As Boolean)
        If Not Me.disposed Then
            If disposing Then
                ' Insert code to free managed resources.
            End If
            ' Insert code to free unmanaged resources.
        End If
        Me.disposed = True
    End Sub
    
  • Dispose 實作,只包含下列程序代碼:

    Public Sub Dispose() Implements IDisposable.Dispose
        Dispose(True)
        GC.SuppressFinalize(Me)
    End Sub
    
  • 只包含下列程式碼的覆寫方法 Finalize:

    Protected Overrides Sub Finalize()
        Dispose(False)
        MyBase.Finalize()
    End Sub
    

衍生自實作 IDisposable 的類別

衍生自實作IDisposable介面的基類的類別,不需要覆寫任何基底方法,除非它使用了需要處理的其他資源。 在此情況下,衍生類別應該覆寫基類的Dispose(disposing)方法,以釋放衍生類別的資源。 此覆寫必須呼叫基類的 Dispose(disposing) 方法。

Protected Overrides Sub Dispose(ByVal disposing As Boolean)
    If Not Me.disposed Then
        If disposing Then
            ' Insert code to free managed resources.
        End If
        ' Insert code to free unmanaged resources.
    End If
    MyBase.Dispose(disposing)
End Sub

衍生類別不應該覆寫基類的 DisposeFinalize 方法。 當從衍生類別的實例呼叫這些方法時,基類的方法實作會調用衍生類別的重寫 Dispose(disposing) 方法。

垃圾收集與 Finalize 解構函式

.NET Framework 會使用 參考追蹤垃圾收集 系統定期釋放未使用的資源。 Visual Basic 6.0 和舊版使用不同的系統,稱為 參考計數 來管理資源。 雖然這兩個系統都會自動執行相同的功能,但有一些重要的差異。

當系統判斷不再需要這類物件時,CLR 會定期終結物件。 當系統資源供不應求時,物件會更快釋放,否則較不頻繁。 物件遺失範圍和 CLR 放開時之間的延遲,這表示與 Visual Basic 6.0 和舊版中的物件不同,您無法確切判斷物件何時會終結。 在這種情況下,據說物件具有 不具決定性的存留期。 在大部分情況下,不具決定性的存留期不會變更您撰寫應用程式的方式,只要您記得 Finalize 當物件失去範圍時,解構函式可能不會立即執行。

垃圾收集系統之間的另一個差異是使用 Nothing。 為了利用 Visual Basic 6.0 和舊版中的參考計數,程式設計人員有時會指派 Nothing 給物件變數,以釋放這些變數保留的參考。 如果變數保留對象的最後一個參考,就會立即釋放對象的資源。 在較新版本的 Visual Basic 中,雖然此程式仍有價值,但執行它永遠不會讓參考的物件立即釋放其資源。 若要立即釋放資源,請使用 物件的 Dispose 方法,如果有的話。 唯一應該將變數設定為Nothing的情況,是當其存留期相對於垃圾收集器偵測遺留物件所花費的時間而言較長時。

另請參閱