Finalize Méthode
Réduire la table des matières
Développer la table des matières
Cet article a fait l’objet d’une traduction automatique. Pour afficher l’article en anglais, activez la case d’option Anglais. Vous pouvez également afficher le texte anglais dans une fenêtre contextuelle en faisant glisser le pointeur de la souris sur le texte traduit.
Traduction
Anglais

Object.Finalize, méthode ()

 

Autorise un objet à tenter de libérer des ressources et d'exécuter d'autres opérations de nettoyage avant qu'il ne soit récupéré par l'opération garbage collection.

Espace de noms:   System
Assembly:  mscorlib (dans mscorlib.dll)

protected virtual void Finalize()

Le Finalize méthode est utilisée pour effectuer des opérations de nettoyage sur les ressources non managées détenues par l'objet actuel avant la destruction de l'objet.La méthode est protégée et est donc accessible uniquement par le biais de cette classe ou une classe dérivée.

Dans cette section :

Le Object classe ne fournit pas d'implémentation pour la Finalize (méthode) et que le garbage collector ne marque pas les types dérivés de Object pour la finalisation, sauf si elles remplacent la Finalize (méthode).

Si un type remplace le Finalize (méthode), le garbage collector ajoute une entrée pour chaque instance du type à une structure interne appelée la file d'attente de finalisation.La file d'attente de finalisation contient des entrées pour tous les objets dans le tas managé dont le code de finalisation doit s'exécuter avant que le garbage collector puisse récupérer leur mémoire.Le garbage collector appelle ensuite la Finalize méthode automatiquement dans les conditions suivantes :

  • Une fois que le garbage collector a découvert qu'un objet est inaccessible, sauf si l'objet a été dispensé de finalisation par un appel à la GC.SuppressFinalize (méthode).

  • Pendant l'arrêt d'un domaine d'application, sauf si l'objet est dispensé de finalisation.Pendant l'arrêt, même les objets qui sont encore accessibles sont finalisées.

Finalize est automatiquement appelé qu'une seule fois sur une instance donnée, sauf si l'objet est réinscrit à l'aide d'un mécanisme tel que GC.ReRegisterForFinalize et GC.SuppressFinalize méthode n'a pas été appelé par la suite.

Finalize opérations présentent les limitations suivantes :

  • L'heure exacte lorsque le finaliseur s'exécute n'est pas défini.Pour garantir la libération des ressources pour implémenter des instances de votre classe, un Close méthode ou fournir un IDisposable.Dispose mise en œuvre.

  • Les finaliseurs de deux objets ne sont pas garantis pour s'exécuter dans un ordre spécifique, même si un objet fait référence à l'autre.Autrement dit, si l'objet a une référence à l'objet B et avoir des finaliseurs, objet B peut avoir déjà été finalisation lorsque le finaliseur de l'objet A démarre.

  • Le thread sur lequel s'exécute le finaliseur n'est pas spécifié.

Le Finalize méthode ne peut pas s'exécuter jusqu'à la fin ou peuvent ne pas fonctionner du tout dans les circonstances exceptionnelles suivantes :

  • Si un autre finaliseur se bloque indéfiniment (se déplace dans une boucle infinie, essaie d'obtenir un verrou, il peut obtenir jamais et ainsi de suite).Étant donné que le runtime tente d'exécuter des finaliseurs jusqu'à la fin, autres finaliseurs ne pas être appelés si un finaliseur se bloque indéfiniment.

  • Si le processus se termine sans donner au runtime une chance de le nettoyer.Dans ce cas, le runtime première notification d'arrêt du processus est une notification DLL_PROCESS_DETACH.

Le runtime continue à finaliser les objets pendant l'arrêt aussi longtemps que le nombre d'objets finalisables diminue.

Si Finalize ou une substitution de Finalize lève une exception et que le runtime n'est pas hébergé par une application qui substitue la stratégie par défaut, le runtime termine le processus et aucun actif try/finally finaliseurs ou les blocs sont exécutées.Ce comportement garantit l'intégrité du processus si le finaliseur ne peut pas libérer ou détruire des ressources.

Vous devez substituer Finalize pour une classe qui utilise des ressources non managées telles que les handles de fichiers ou les connexions doivent être libérées lorsque l'objet managé qui les utilise est ignorée lors du nettoyage de base de données.

System_CAPS_importantImportant

Si un SafeHandle objet n'est disponible qui encapsule votre ressource non managée, l'alternative recommandée consiste à implémenter le modèle dispose avec un handle sécurisé et substituez pas Finalize.Pour plus d'informations, consultez alternative de SafeHandle le section.

Le Object.Finalize méthode ne fait rien par défaut, mais vous devez remplacer Finalize uniquement si nécessaire et uniquement pour libérer des ressources non managées.Récupération de mémoire tend à s'allonger considérablement si une opération de finalisation est exécuté, car il requiert au moins deux garbage collections.En outre, vous devez substituer les Finalize types de méthode pour référence uniquement.Le common language runtime finalise uniquement les types référence.Il ignore les finaliseurs sur des types valeur.

Chaque implémentation de Finalize dans un type dérivé doit appeler mise en oeuvre de son type de base de Finalize.C'est le seul cas dans lequel application code est autorisé à appeler Finalize.

System_CAPS_noteRemarque

Le compilateur c# ne vous permet pas de remplacer le Finalize (méthode).À la place, vous fournissez un finaliseur en implémentant un pour votre classe.Un destructeur c# appelle automatiquement le destructeur de sa classe de base.

Visual C++ fournit aussi sa propre syntaxe pour implémenter la Finalize méthode.Pour plus d'informations, consultez la section « Destructeurs et finaliseurs » de How to: Define and Consume Classes and Structs (C++/CLI).

Étant donné que le garbage collection est non déterministe, vous ne connaissez pas précisément lorsque le garbage collector effectue la finalisation.Pour libérer les ressources immédiatement, vous pouvez également choisir d'implémenter le et IDisposable interface.Le IDisposable.Dispose implémentation peut être appelée par les consommateurs de votre classe de libérer les ressources non managées, et vous pouvez utiliser la Finalize méthode pour libérer des ressources non managées dans le cas où la Dispose méthode n'est pas appelée.

Finalize peut effectuer presque n'importe quelle action, y compris ressusciter (un objet qui rendre à nouveau accessible) a été nettoyé pendant le garbage collection.Toutefois, l'objet peut uniquement être réactivé une fois ; Finalize ne peut pas être appelée sur des objets ressuscités pendant le garbage collection.Il existe une action qui votre implémentation de Finalize ne doit jamais prendre : il ne doit jamais lever une exception.

Création des finaliseurs fiables est souvent difficile, car vous ne pouvez pas faire des hypothèses concernant l'état de votre application et non prise en charge des exceptions système telles que OutOfMemoryException et StackOverflowException Arrêter le finaliseur.Au lieu d'implémenter un finaliseur de votre classe pour libérer des ressources non managées, vous pouvez utiliser un objet qui est dérivé de le System.Runtime.InteropServices.SafeHandle de classe pour encapsuler vos ressources non managées et ensuite implémenter le modèle dispose sans un finaliseur.Le .NET Framework fournit les classes suivantes dans le Microsoft.Win32 espace de noms qui sont dérivés de System.Runtime.InteropServices.SafeHandle:

L'exemple suivant utilise le avec des handles sécurisés au lieu de substituer le Finalize (méthode).Il définit un FileAssociation classe qui encapsule les informations du Registre de l'application qui traite les fichiers avec une extension de fichier particulier.Les handles de deux Registre retournés en tant que out paramètres par Windows RegOpenKeyEx des appels de fonction sont transmis à la SafeRegistryHandle constructeur.Le type protégé Dispose méthode appelle ensuite la SafeRegistryHandle.Dispose méthode pour libérer ces deux poignées.

using Microsoft.Win32.SafeHandles;
using System;
using System.ComponentModel;
using System.IO;
using System.Runtime.InteropServices;

public class FileAssociationInfo : IDisposable
{
   // Private variables.
   private String ext;
   private String openCmd;
   private String args;
   private SafeRegistryHandle hExtHandle, hAppIdHandle;

   // Windows API calls.
   [DllImport("advapi32.dll", CharSet= CharSet.Auto, SetLastError=true)]
   private static extern int RegOpenKeyEx(IntPtr hKey, 
                  String lpSubKey, int ulOptions, int samDesired,
                  out IntPtr phkResult);
   [DllImport("advapi32.dll", CharSet= CharSet.Unicode, EntryPoint = "RegQueryValueExW",
              SetLastError=true)]
   private static extern int RegQueryValueEx(IntPtr hKey,
                  string lpValueName, int lpReserved, out uint lpType, 
                  string lpData, ref uint lpcbData);   
   [DllImport("advapi32.dll", SetLastError = true)]
   private static extern int RegSetValueEx(IntPtr hKey, [MarshalAs(UnmanagedType.LPStr)] string lpValueName,
                  int Reserved, uint dwType, [MarshalAs(UnmanagedType.LPStr)] string lpData,
                  int cpData);
   [DllImport("advapi32.dll", SetLastError=true)]
   private static extern int RegCloseKey(UIntPtr hKey);

   // Windows API constants.
   private const int HKEY_CLASSES_ROOT = unchecked((int) 0x80000000);
   private const int ERROR_SUCCESS = 0;

    private const int KEY_QUERY_VALUE = 1;
    private const int KEY_SET_VALUE = 0x2;

   private const uint REG_SZ = 1;

   private const int MAX_PATH = 260;

   public FileAssociationInfo(String fileExtension)
   {
      int retVal = 0;
      uint lpType = 0;

      if (!fileExtension.StartsWith("."))
             fileExtension = "." + fileExtension;
      ext = fileExtension;

      IntPtr hExtension = IntPtr.Zero;
      // Get the file extension value.
      retVal = RegOpenKeyEx(new IntPtr(HKEY_CLASSES_ROOT), fileExtension, 0, KEY_QUERY_VALUE, out hExtension);
      if (retVal != ERROR_SUCCESS) 
         throw new Win32Exception(retVal);
      // Instantiate the first SafeRegistryHandle.
      hExtHandle = new SafeRegistryHandle(hExtension, true);

      string appId = new string(' ', MAX_PATH);
      uint appIdLength = (uint) appId.Length;
      retVal = RegQueryValueEx(hExtHandle.DangerousGetHandle(), String.Empty, 0, out lpType, appId, ref appIdLength);
      if (retVal != ERROR_SUCCESS)
         throw new Win32Exception(retVal);
      // We no longer need the hExtension handle.
      hExtHandle.Dispose();

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

      // Open the application identifier key.
      string exeName = new string(' ', MAX_PATH);
      uint exeNameLength = (uint) exeName.Length;
      IntPtr hAppId;
      retVal = RegOpenKeyEx(new IntPtr(HKEY_CLASSES_ROOT), appId, 0, KEY_QUERY_VALUE | KEY_SET_VALUE,
                            out hAppId);
       if (retVal != ERROR_SUCCESS) 
         throw new Win32Exception(retVal);

      // Instantiate the second SafeRegistryHandle.
      hAppIdHandle = new SafeRegistryHandle(hAppId, true);

      // Get the executable name for this file type.
      string exePath = new string(' ', MAX_PATH);
      uint exePathLength = (uint) exePath.Length;
      retVal = RegQueryValueEx(hAppIdHandle.DangerousGetHandle(), String.Empty, 0, out lpType, exePath, ref exePathLength);
      if (retVal != ERROR_SUCCESS)
         throw new Win32Exception(retVal);

      // Determine the number of characters without the terminating null.
      exePath = exePath.Substring(0, (int) exePathLength / 2 - 1);
      // Remove any environment strings.
      exePath = Environment.ExpandEnvironmentVariables(exePath);

      int position = exePath.IndexOf('%');
      if (position >= 0) {
         args = exePath.Substring(position);
         // Remove command line parameters ('%0', etc.).
         exePath = exePath.Substring(0, position).Trim();
      }
      openCmd = exePath;   
   }

   public String Extension
   { get { return ext; } }

   public String Open
   { get { return openCmd; } 
     set {
        if (hAppIdHandle.IsInvalid | hAppIdHandle.IsClosed)
           throw new InvalidOperationException("Cannot write to registry key."); 
        if (! File.Exists(value)) {
           string message = String.Format("'{0}' does not exist", value);
           throw new FileNotFoundException(message); 
        }
        string cmd = value + " %1";
        int retVal = RegSetValueEx(hAppIdHandle.DangerousGetHandle(), String.Empty, 0, 
                                   REG_SZ, value, value.Length + 1);
        if (retVal != ERROR_SUCCESS)
           throw new Win32Exception(retVal);                          
     } }

   public void Dispose() 
   {
      Dispose(true);
      GC.SuppressFinalize(this);
   }   

   protected void Dispose(bool disposing)
   {
      // Ordinarily, we release unmanaged resources here; 
      // but all are wrapped by safe handles.

      // Release disposable objects.
      if (disposing) {
         if (hExtHandle != null) hExtHandle.Dispose();
         if (hAppIdHandle != null) hAppIdHandle.Dispose();
      }
   }
}

L'exemple suivant vérifie que la Finalize méthode est appelée lorsqu'un objet qui substitue Finalize est détruit.Notez que, dans une application de production, le Finalize méthode est substituée pour libérer des ressources non managées détenues par l'objet.Notez également que l'exemple c# fournit un destructeur au lieu de substituer le Finalize (méthode).

using System;
using System.Diagnostics;

public class ExampleClass
{
   Stopwatch sw;

   public ExampleClass()
   {
      sw = Stopwatch.StartNew();
      Console.WriteLine("Instantiated object");
   } 

   public void ShowDuration()
   {
      Console.WriteLine("This instance of {0} has been in existence for {1}",
                        this, sw.Elapsed);
   }

   ~ExampleClass()
   {
      Console.WriteLine("Finalizing object");
      sw.Stop();
      Console.WriteLine("This instance of {0} has been in existence for {1}",
                        this, sw.Elapsed);
   }
}

public class Demo
{
   public static void Main()
   {
      ExampleClass ex = new ExampleClass();
      ex.ShowDuration();
   }
}
// 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

For an additional example that overrides the Finalize method, see the GC.SuppressFinalize method.

Universal Windows Platform
Disponible depuis 4.5
.NET Framework
Disponible depuis 1.1
Portable Class Library
Pris en charge dans : portable .NET platforms
Silverlight
Disponible depuis 2.0
Windows Phone Silverlight
Disponible depuis 7.0
Windows Phone
Disponible depuis 8.1
Retour au début
Afficher:
© 2016 Microsoft