Esporta (0) Stampa
Espandi tutto
Il presente articolo è stato tradotto automaticamente. Passare il puntatore sulle frasi nell'articolo per visualizzare il testo originale. Ulteriori informazioni.
Traduzione
Originale

Metodo Object.Finalize

Consente a un oggetto di provare a liberare risorse ed eseguire altre operazioni di pulizia prima che l'oggetto stesso venga reclamato dalla procedura di Garbage Collection.

Spazio dei nomi:  System
Assembly:  mscorlib (in mscorlib.dll)

'Dichiarazione
Protected Overridable Sub Finalize

Il metodo di Finalize viene utilizzato per eseguire operazioni di pulitura sulle risorse non gestite utilizzate dall'oggetto corrente prima che venga eliminato. Il metodo è protetto, pertanto è accessibile soltanto attraverso questa classe o una classe derivata.

Contenuto della sezione:

Il funzionamento di finalizzazione

La classe di Object non fornisce un'implementazione per il metodo di Finalize e il Garbage Collector non contrassegna i tipi derivati da Object per la finalizzazione a meno che esegue l'override del metodo di Finalize.

Se un tipo eseguire l'override del metodo di Finalize, il Garbage Collector viene aggiunta una voce per ogni istanza del tipo a una struttura interna denominata coda di finalizzazione. La coda di finalizzazione contiene voci per tutti gli oggetti nell'heap gestito di esecuzione del codice di finalizzazione deve eseguire prima che il Garbage Collector sia in grado di recuperare la memoria. Il Garbage Collector chiama quindi il metodo di Finalize automaticamente nelle seguenti circostanze:

  • Dopo che un oggetto diventa accessibile, a meno che l'oggetto sia stato esentato dalla finalizzazione da una chiamata al metodo di GC.SuppressFinalize.

  • Durante l'arresto di un dominio applicazione, a meno che l'oggetto sia esente dalla finalizzazione. Durante la chiusura, anche gli oggetti che sono ancora accessibili vengono finalizzati.

Finalize automaticamente viene chiamato una volta su un'istanza specificata, a meno che l'oggetto non sia registrato utilizzando un meccanismo come GC.ReRegisterForFinalize e il metodo di GC.SuppressFinalize avanti non è stata chiamata.

Le operazioni di Finalize hanno i seguenti limiti:

  • Non è definito il momento esatto in cui viene eseguito il finalizzatore durante la procedura di Garbage Collection. Per garantire la versione deterministica delle risorse per le istanze della classe, implementare un metodo di Close o fornire un'implementazione di IDisposable.Dispose.

  • Non è certo che i finalizzatori di due oggetti vengano eseguiti in un ordine specifico, anche se un oggetto fa riferimento all'altro. Ovvero se l'oggetto A include un riferimento a un oggetto B e dispongono di finalizzatori, l'oggetto B già finalizzazione quando il finalizzatore di oggetto All'avvio.

  • Il thread su cui viene eseguito il finalizzatore non è specificato.

Il metodo di Finalize potrebbe non funzionare dopo il completamento o potrebbe non funzionare affatto in condizioni eccezionali seguenti:

  • Se gli altri blocchi del tempo (immette ciclo infinito, tenta di ottenere un blocco che non può ottenere mai, e così via). Poiché il runtime tenta di eseguire i finalizzatori dopo il completamento, altri finalizzatori non possono essere chiamati se un finalizzatore blocca infinito.

  • Se il processo terminerà senza fornire al runtime una probabilità pulire. In questo caso, la prima notifica di completamento del processo effettuata dal runtime è una notifica DLL_PROCESS_DETACH.

Il runtime continua a finalizzare gli oggetti durante l'arresto solo quando il numero di oggetti finalizzabili continua a diminuire.

Se Finalize o un override di Finalize genera un'eccezione e il runtime non ospitate da un'applicazione che esegue l'override dei criteri predefiniti, il runtime termina il processo e non try/blocchi o finalizzatore attivi difinally vengono eseguiti. Questo comportamento garantisce l'integrità del processo qualora il finalizzatore non possa liberare o distruggere risorse.

Note per gli implementatori

È necessario eseguire l'override di Finalize per una classe che utilizza risorse non gestite come handle di file o connessioni di database che devono essere rilasciati quando l'oggetto gestito che li utilizzano viene rimosso durante un'operazione di Garbage Collection.

Nota importanteImportante

Se un oggetto di SafeHandle è disponibile che va a capo alla risorsa non gestita, si consiglia di implementare il modello dispose con handles e non override sicure Finalize. Per ulteriori informazioni, vedere la sezione di L'alternativa SafeHandle.

Il metodo di Object.Finalize non esegue alcuna operazione per impostazione predefinita, ma è necessario eseguire l'override di Finalize solo se necessario e rilasciare le sole risorse non gestite. Recuperare memoria durante un'operazione di Garbage Collection consente di richiedere molto più tempo se un'operazione di finalizzazione viene eseguita, poiché richiede almeno due Garbage Collection. Inoltre, è necessario eseguire l'override del metodo di Finalize solo per i tipi di riferimento. Common Language Runtime completa solo tipi di riferimento. Ignora i finalizzatori i tipi di valore.

Ogni implementazione di Finalize in un tipo derivato deve chiamare la propria implementazione di Finalize del tipo di base. Questo è l'unico caso in cui il codice dell'applicazione può chiamare il metodo Finalize.

NotaNota

Il compilatore c# non consente di eseguire l'override del metodo di Finalize. Al contrario, si fornisce un finalizzatore implementando distruttore per la classe. Un distruttore c# chiama automaticamente il distruttore della classe base.

Visual C++ fornisce una sintassi specifica per l'implementazione del metodo di Finalize. Per ulteriori informazioni, vedere la sezione "finalizzatori e distruttori" di Procedura: Creazione di istanze delle classi e gli struct.

Poiché il Garbage Collection è non deterministico, non sapere precisamente quando il Garbage Collector esegue la finalizzazione. Per rilasciare subito le risorse, è anche possibile scegliere per implementare eliminare il modello e l'interfaccia IDisposable. L'implementazione di IDisposable.Dispose può essere chiamata dai consumer della classe per liberare le risorse non gestite che è possibile utilizzare il metodo di Finalize per liberare le risorse gestite nel caso in cui il metodo di Dispose non venga chiamato.

Finalize può accettare quasi tutte le azioni, inclusa resuscitare un oggetto ovvero rendere l'oggetto accessibile ancora) dopo che è stato pulito durante un'operazione di Garbage Collection. L'oggetto può, tuttavia, essere ripristinato soltanto una volta; Finalize non può essere chiamato su oggetti ripristinati durante la procedura di Garbage Collection. Esistono un provvedimento che l'implementazione di Finalize non deve essere mai: non deve mai generare un'eccezione.

Alternativa SafeHandle

Creare i finalizzatori affidabili è spesso difficile, poiché non è possibile apportare supposizione sullo stato dell'applicazione e poiché le eccezioni non gestite di sistema come OutOfMemoryException e StackOverflowException terminano il finalizzatore. Anziché implementare un finalizzatore della classe rilasciare le risorse non gestite, è possibile utilizzare un oggetto derivato dalla classe di System.Runtime.InteropServices.SafeHandle per eseguire il wrapping delle risorse non gestite e quindi applicare il modello di eliminazione senza un finalizzatore. .NET Framework fornisce le classi nello spazio dei nomi di Microsoft.Win32 derivate da System.Runtime.InteropServices.SafeHandle:

Nell'esempio seguente viene utilizzato eliminare il modello con safe handles anziché eseguire l'override del metodo di Finalize. Definisce una classe di FileAssociation che esegue il wrapping delle informazioni del Registro di sistema sull'applicazione che gestisce i file con un'estensione di file. Le due handle del Registro di sistema restituite come parametri di out da chiamate RegOpenKeyEx di funzioni Windows vengono passate al costruttore di SafeRegistryHandle. Il metodo protetto di Dispose del tipo chiama quindi il metodo di SafeRegistryHandle.Dispose per liberare queste due punti.


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


Nell'esempio seguente si verifica che venga chiamato il metodo Finalize quando viene eliminato un oggetto che esegue l'override di Finalize. Si noti che, in un'applicazione di produzione, l'override del metodo Finalize verrebbe eseguito per rilasciare risorse non gestite mantenute dall'oggetto. Si noti inoltre che nell'esempio C# viene fornito un distruttore e non viene eseguito l'override del metodo Finalize.


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


Per un altro esempio che esegue l'override del metodo di Finalize, vedere il metodo di GC.SuppressFinalize.

.NET Framework

Supportato in: 4.5.2, 4.5.1, 4.5, 4, 3.5, 3.0, 2.0, 1.1, 1.0

.NET Framework Client Profile

Supportato in: 4, 3.5 SP1

Libreria di classi portabile

Supportato in: Libreria di classi portabile

.NET per applicazioni Windows Store

Supportato in: Windows 8

.NET per applicazioni Windows Phone

Supportato 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 (ruoli di base del server non supportati), Windows Server 2008 R2 (ruoli di base del server supportati con SP1 o versione successiva, Itanium non supportato)

.NET Framework non supporta tutte le versioni di ciascuna piattaforma. Per un elenco delle versioni supportate, vedere Requisiti di sistema di .NET Framework.

Aggiunte alla community

AGGIUNGI
Mostra:
© 2014 Microsoft