(0) exportieren Drucken
Alle erweitern
Dieser Artikel wurde maschinell übersetzt. Bewegen Sie den Mauszeiger über die Sätze im Artikel, um den Originaltext anzuzeigen. Weitere Informationen
Übersetzung
Original

Object.Finalize-Methode

Gibt einem Objekt Gelegenheit, Ressourcen freizugeben und andere Bereinigungen durchzuführen, bevor es von der Garbage Collection freigegeben wird.

Namespace:  System
Assembly:  mscorlib (in mscorlib.dll)

'Declaration
Protected Overridable Sub Finalize

Die Finalize-Methode wird verwendet, um Bereinigungsvorgänge auf die nicht verwalteten Ressourcen auszuführen, die durch das aktuelle Objekt verwendet werden, bevor das Objekt zerstört wird. Die Methode ist geschützt und kann daher nur über diese oder eine abgeleite Klasse aufgerufen werden.

In diesem Abschnitt

Wie Vervollständigung funktioniert

Die Object-Klasse stellt keine Implementierung für die Finalize-Methode bereit und der Garbage Collector markiert zum Abschluss nicht die Typen, die von Object abgeleitet sind, es sei denn sie überschreiben die Finalize-Methode.

Wenn ein Typ die Finalize-Methode überschreibt, fügt der Garbage Collector einen Eintrag für jede Instanz des Typs einer internen Struktur hinzu, die die Finalisierungswarteschlange. Die Finalisierungswarteschlange enthält Einträge für alle Objekte im verwalteten Heap, dessen Finalisierungscode ausgeführt werden muss, bevor der Garbage Collector deren Speicher freigeben kann. Der Garbage Collector ruft dann die Finalize-Methode automatisch unter den folgenden Bedingungen eintreten:

  • Nachdem ein Objekt nicht zugegriffen wird, es sei denn, das Objekt vom Abschluss durch einen Aufruf der GC.SuppressFinalize-Methode ungebunden wurde.

  • Während des Herunterfahrens einer Anwendungsdomäne, es sei denn, das Objekt vom Abschluss außer ist. Während des Herunterfahrens werden sogar Objekte, die sich noch zugänglich sind, abgeschlossen.

Finalize wird automatisch nur einmal auf einer bestimmten Instanz aufgerufen, es sei denn, das Objekt erneut registriert ist, indem Sie einen Mechanismus wie GC.ReRegisterForFinalize verwendet und die GC.SuppressFinalize-Methode anschließend nicht aufgerufen wurde.

Die Durchführung von Finalize unterliegt folgenden Einschränkungen:

  • Der genaue Zeitpunkt, zu dem der Finalizer während der Garbage Collection ausgeführt wird, ist undefiniert. Um deterministische Freigabe von Ressourcen für Instanzen Ihrer Klasse sicherstellen, implementieren Sie eine Close-Methode oder eine IDisposable.Dispose Implementierung.

  • Es ist nicht gewährleistet, dass die Finalizer zweier Objekte in einer bestimmten Reihenfolge ausgeführt werden, selbst dann nicht, wenn eines der Objekte auf das andere verweist. Das bedeutet, dass, wenn Objekt A einen Verweis hat, z von B gesammelt und beide Finalizer besitzen, geschlossen wurden möglicherweise Objekt B bereits als der Finalizer von Anfang des Objekts A ab.

  • Der Thread, für den der Finalizer ausgeführt wird, ist nicht angegeben.

Die Finalize-Methode ausgeführt würde möglicherweise nicht vollständig oder kann nicht an alle unter den folgenden außergewöhnliche Situationen ausgeführt:

  • Wenn eine andere Finalizerblöcke unbegrenzt (wechselt in eine Endlosschleife, in Versuche, eine Sperre zu erhalten, die es nicht erhalten kann, z.). Da die Laufzeit versucht, Finalizer vollständig ausführen zu können, werden andere Finalizer nicht aufgerufen werden, wenn ein Finalizer unbegrenzt blockiert.

  • Wenn der Prozess beendet wird, ohne der Laufzeit eine Möglichkeit zu geben zu bereinigen. In diesem Falle ist die erste Benachrichtigung der Laufzeit über die Beendigung des Prozesses eine DLL_PROCESS_DETACH-Benachrichtigung.

Die Laufzeit wird fortgesetzt, um Objekte beim Herunterfahren abzuschließen nur, wenn die Anzahl der finalisierbaren Objekte fortgesetzt wird, um zu verringern.

Wenn Finalize oder eine Überschreibung von Finalize eine Ausnahme auslöst und die Laufzeit nicht von einer Anwendung gehostet wird, die die Standardrichtlinien überschreibt, beendet die Laufzeit den Prozess und kein aktives try/finally, blockiert oder Finalizer ausgeführt werden. So wird Prozessintegrität sichergestellt, wenn der Finalizer Ressourcen nicht freigeben oder zerstören kann.

Hinweise für Implementierer

Sie sollten Finalize für eine Klasse überschreiben, die nicht verwaltete Ressourcen wie Dateihandles oder Datenbankverbindungen verwendet, die freigegeben werden müssen, wenn das verwaltete Objekt, das diese verwendet, während der Garbage Collection verworfen wird.

Wichtiger HinweisWichtig

Wenn ein SafeHandle-Objekt verfügbar ist, umschließt dass die nicht verwaltete Ressource, die empfohlene Alternative, das Dispose-Muster mit einer Überschreibung SafeHandle und nicht Finalize zu implementieren ist. Weitere Informationen finden Sie unter Die SafeHandle-Alternative-Abschnitt.

Die Object.Finalize-Methode ist wirkungslos standardmäßig, aber Sie sollten Finalize nur bei Bedarf und überschreiben, nicht verwaltete Ressourcen nur verwenden. Für das Freigeben des Speichers während der Garbage Collection hat, wesentlich länger in Anspruch nehmen, wenn ein Abschlussvorgang ausgeführt wird, da er mindestens zwei Garbage Collections erforderlich. Außerdem sollten Sie die Finalize-Methode nur für Verweistypen überschreiben. Die Common Language Runtime enthält ausschließlich Referenztypen ab. Sie ignoriert Finalizer auf Werttypen.

Jede Implementierung von Finalize in einem abgeleiteten Typ muss die Finalize-Implementierung des Basistyps aufrufen. Dies ist der einzige Fall, in dem Anwendungscode Finalize aufrufen darf.

HinweisHinweis

Der C#-Compiler lässt es nicht möglich, die Finalize-Methode zu überschreiben. Erstellen Sie stattdessen ein Finalizer im Implementieren von Destruktor für die Klasse. Ein C#-Destruktor wird automatisch den Destruktor der Basisklasse auf.

Visual C++ stellt auch eine eigene Syntax für die Implementierung der Finalize-Methode bereit. Weitere Informationen finden Sie den "Destruktor- und Finalizer" Abschnitt von Gewusst wie: Instanziieren Sie Klassen und Strukturen.

Da Garbage Collection nicht deterministisch ist, wissen Sie nicht genau, wenn der Garbage Collector Abschluss ausgeführt wird. Um Ressourcen sofort freizugeben, können Sie auch festlegen um geben Sie Muster frei und die IDisposable-Schnittstelle implementieren. Die IDisposable.Dispose Implementierung kann von Consumern der Klasse aufgerufen werden, um nicht verwaltete Ressourcen freizugeben, und Sie können die Finalize-Methode verwenden, um nicht verwaltete Ressourcen freigibt, im Fall, dass die Dispose-Methode nicht aufgerufen wird.

Finalize können nahezu alle Aktionen, einschließlich das Wiederbeleben eines Objekts ausführen, (das heißt, das Objekt zugegriffen erneut zu) Nachdem diese während der Garbage Collection gelöscht wurde. Ein Objekt kann allerdings nur einmal wieder zugänglich gemacht werden. Finalize kann während der Garbage Collection nicht für wieder zugänglich gemachte Objekte aufgerufen werden. Eine Aktion, die die Implementierung von Finalize nicht ausgeführt werden soll: sollte nie Ausnahmen auslösen.

Die SafeHandle-Alternative

Zuverlässige Finalizer zu erstellen ist häufig schwierig, da Sie Annahmen über den Zustand der Anwendung nicht ausführen können und dass nicht behandelte Systemausnahmen wie OutOfMemoryException und StackOverflowException den Finalizer beenden. Anstatt, einen Finalizer zu implementieren, sodass die Klasse nicht verwaltete Ressourcen freigibt, können Sie ein Objekt verwenden, das von der System.Runtime.InteropServices.SafeHandle-Klasse abgeleitet wird, um die nicht verwalteten Ressourcen zu umschließen, und implementieren dann das Dispose-Muster ohne einen Finalizer. . .NET Framework stellt die folgenden Klassen im Namespace Microsoft.Win32, die von System.Runtime.InteropServices.SafeHandle abgeleitet werden:

Im folgenden Beispiel wird geben Sie Muster frei mit, sichere Handles, anstatt die Finalize-Methode zu überschreiben. Es definiert eine FileAssociation-Klasse, Abrufen der Registrierungsinformationen zum Verwenden umschließt, die Dateien mit einer bestimmten Dateinamenerweiterung bearbeitet. Die zwei Registrierungshandles, die als out von Windows-Funktions-Aufrufe RegOpenKeyEx-Parameter zurückgegeben werden, werden zum SafeRegistryHandle-Konstruktor übergeben. Die geschützte Dispose-Methode des Typs rufen dann die SafeRegistryHandle.Dispose-Methode auf, um diesen zwei Handles freizugeben.


Imports Microsoft.Win32.SafeHandles
Imports System
Imports System.ComponentModel
Imports System.IO
Imports System.Runtime.InteropServices
Imports System.Text

Public Class FileAssociationInfo : Implements IDisposable
   ' Private variables.
   Private ext As String
   Private openCmd As String
   Private args As String
   Private hExtHandle, hAppIdHandle As SafeRegistryHandle

   ' Windows API calls.
   Private Declare Unicode Function RegOpenKeyEx Lib"advapi32.dll" _
                   Alias "RegOpenKeyExW" (hKey As IntPtr, lpSubKey As String, _
                   ulOptions As Integer, samDesired As Integer, _
                   ByRef phkResult As IntPtr) As Integer
   Private Declare Unicode Function RegQueryValueEx Lib "advapi32.dll" _
                   Alias "RegQueryValueExW" (hKey As IntPtr, _
                   lpValueName As String, lpReserved As Integer, _
                   ByRef lpType As UInteger, lpData As String, _
                   ByRef lpcbData As UInteger) As Integer   
   Private Declare Function RegSetValueEx Lib "advapi32.dll" _
                  (hKey As IntPtr, _
                  <MarshalAs(UnmanagedType.LPStr)> lpValueName As String, _
                  reserved As Integer, dwType As UInteger, _
                  <MarshalAs(UnmanagedType.LPStr)> lpData As String, _
                  cpData As Integer) As Integer 
   Private Declare Function RegCloseKey Lib "advapi32.dll" _
                  (hKey As IntPtr) As Integer

   ' Windows API constants.
   Private Const HKEY_CLASSES_ROOT As Integer = &h80000000
   Private Const ERROR_SUCCESS As Integer = 0

   Private Const KEY_QUERY_VALUE As Integer = 1
   Private Const KEY_SET_VALUE As Integer = &h2

   Private REG_SZ As UInteger = 1

   Private Const MAX_PATH As Integer  = 260

   Public Sub New(fileExtension As String)
      Dim retVal As Integer = 0
      Dim lpType As UInteger = 0

      If Not fileExtension.StartsWith(".") Then 
         fileExtension = "." + fileExtension
      End If   
      ext = fileExtension

      Dim hExtension As IntPtr = IntPtr.Zero
      ' Get the file extension value.
      retVal = RegOpenKeyEx(New IntPtr(HKEY_CLASSES_ROOT), fileExtension, 0, 
                            KEY_QUERY_VALUE, hExtension)
      if retVal <> ERROR_SUCCESS Then 
         Throw New Win32Exception(retVal)
      End If  
      ' Instantiate the first SafeRegistryHandle.
      hExtHandle = New SafeRegistryHandle(hExtension, True)

      Dim appId As New String(" "c, MAX_PATH)
      Dim appIdLength As UInteger = CUInt(appId.Length)
      retVal = RegQueryValueEx(hExtHandle.DangerousGetHandle(), String.Empty, _
                               0, lpType, appId, appIdLength)
      if retVal <> ERROR_SUCCESS Then
         Throw New Win32Exception(retVal)
      End If   
      ' We no longer need the hExtension handle.
      hExtHandle.Dispose()

      ' Determine the number of characters without the terminating null.
      appId = appId.Substring(0, CInt(appIdLength) \ 2 - 1) + "\shell\open\Command"

      ' Open the application identifier key.
      Dim exeName As New string(" "c, MAX_PATH)
      Dim exeNameLength As UInteger = CUInt(exeName.Length)
      Dim hAppId As IntPtr
      retVal = RegOpenKeyEx(New IntPtr(HKEY_CLASSES_ROOT), appId, 0, 
                            KEY_QUERY_VALUE Or KEY_SET_VALUE, hAppId)
      If retVal <> ERROR_SUCCESS Then 
         Throw New Win32Exception(retVal)
      End If   

      ' Instantiate the second SafeRegistryHandle.
      hAppIdHandle = New SafeRegistryHandle(hAppId, True)

      ' Get the executable name for this file type.
      Dim exePath As New string(" "c, MAX_PATH)
      Dim exePathLength As UInteger = CUInt(exePath.Length)
      retVal = RegQueryValueEx(hAppIdHandle.DangerousGetHandle(), _
                               String.Empty, 0, lpType, exePath, exePathLength)
      If retVal <> ERROR_SUCCESS Then
         Throw New Win32Exception(retVal)
      End If     
      ' Determine the number of characters without the terminating null.
      exePath = exePath.Substring(0, CInt(exePathLength) \ 2 - 1)

      exePath = Environment.ExpandEnvironmentVariables(exePath)
      Dim position As Integer = exePath.IndexOf("%"c)
      If position >= 0 Then
         args = exePath.Substring(position)
         ' Remove command line parameters ('%0', etc.).
         exePath = exePath.Substring(0, position).Trim()
      End If   
      openCmd = exePath
   End Sub

   Public ReadOnly Property Extension As String
      Get
         Return ext
      End Get
   End Property

   Public Property Open As String
      Get
         Return openCmd
      End Get    
      Set 
        If hAppIdHandle.IsInvalid Or hAppIdHandle.IsClosed Then
           Throw New InvalidOperationException("Cannot write to registry key.")
        End If    
        If Not File.Exists(value) Then
           Dim message As String = String.Format("'{0}' does not exist", value)
           Throw New FileNotFoundException(message) 
        End If
        Dim cmd As String = value + " %1"
        Dim retVal As Integer = RegSetValueEx(hAppIdHandle.DangerousGetHandle(), String.Empty, 0, 
                                              REG_SZ, value, value.Length + 1)
        If retVal <> ERROR_SUCCESS Then 
           Throw New Win32Exception(retVal)
        End If                             
      End Set
   End Property   

   Public Sub Dispose() _
      Implements IDisposable.Dispose 
      Dispose(true)
      GC.SuppressFinalize(Me)
   End Sub   

   Protected Sub Dispose(disposing As Boolean)
      ' Ordinarily, we release unmanaged resources here 
      ' but all are wrapped by safe handles.

      ' Release disposable objects.
      If disposing Then
         If hExtHandle IsNot Nothing Then hExtHandle.Dispose()
         If hAppIdHandle IsNot Nothing Then hAppIdHandle.Dispose()
      End If
   End Sub
End Class


Das folgende Beispiel überprüft, ob die Finalize-Methode aufgerufen wird, wenn ein Objekt, das Finalize überschreibt, zerstört wird. Beachten Sie, dass in einer Produktionsanwendung die Finalize-Methode überschrieben werden würde, um nicht verwaltete vom Objekt belegte Ressourcen freizugeben. Beachten Sie außerdem, dass im C#-Beispiel ein Destruktor bereitgestellt wird, statt die Finalize-Methode zu überschreiben.


Imports System.Diagnostics

Public Class ExampleClass
   Dim sw As StopWatch

   Public Sub New()
      sw = Stopwatch.StartNew()
      Console.WriteLine("Instantiated object")
   End Sub 

   Public Sub ShowDuration()
      Console.WriteLine("This instance of {0} has been in existence for {1}",
                        Me, sw.Elapsed)
   End Sub

   Protected Overrides Sub Finalize()
      Console.WriteLine("Finalizing object")
      sw.Stop()
      Console.WriteLine("This instance of {0} has been in existence for {1}",
                        Me, sw.Elapsed)
   End Sub
End Class

Module Demo
   Public Sub Main()
      Dim ex As New ExampleClass()
      ex.ShowDuration()
   End Sub
End Module
' The example displays output like the following:
'    Instantiated object
'    This instance of ExampleClass has been in existence for 00:00:00.0011060
'    Finalizing object
'    This instance of ExampleClass has been in existence for 00:00:00.0036294


Ein zusätzliches Beispiel, das die Finalize-Methode überschrieben wird, finden Sie die GC.SuppressFinalize-Methode.

.NET Framework

Unterstützt in: 4.5.2, 4.5.1, 4.5, 4, 3.5, 3.0, 2.0, 1.1, 1.0

.NET Framework Client Profile

Unterstützt in: 4, 3.5 SP1

Portable Klassenbibliothek

Unterstützt in: Portable Klassenbibliothek

.NET für Windows Store-Apps

Unterstützt in: Windows 8

.NET für Windows Phone-Apps

Unterstützt in: Windows Phone 8, Silverlight 8.1

Windows Phone 8.1, Windows Phone 8, Windows 8.1, Windows Server 2012 R2, Windows 8, Windows Server 2012, Windows 7, Windows Vista SP2, Windows Server 2008 (Server Core-Rolle wird nicht unterstützt), Windows Server 2008 R2 (Server Core-Rolle wird mit SP1 oder höher unterstützt; Itanium wird nicht unterstützt)

.NET Framework unterstützt nicht alle Versionen sämtlicher Plattformen. Eine Liste der unterstützten Versionen finden Sie unter Systemanforderungen für .NET Framework.

Community-Beiträge

HINZUFÜGEN
Anzeigen:
© 2014 Microsoft