Ten artykuł został przetłumaczony przez maszynę. Aby wyświetlić jego treść w języku angielskim, zaznacz pole wyboru Angielski. Możesz też wyświetlić angielski tekst w okienku wyskakującym, przesuwając wskaźnik myszy nad konkretny tekst”.
Tłumaczenie
Angielski

Metoda Object.Finalize — ()

.NET Framework (current version)
 

Data opublikowania: październik 2016

Pozwala, aby obiekt spróbował zwolnić zasoby i wykonał inne operacje czyszczenia, zanim zostanie odzyskany przez moduł zbierający elementy bezużyteczne.

Przestrzeń nazw:   System
Zestaw:  mscorlib (w mscorlib.dll)

protected virtual void Finalize()

Finalize Metoda służy do wykonywania operacji oczyszczania niezarządzanych zasobów posiadanych przez bieżący obiekt przed obiekt jest niszczony. Metoda jest chroniona i dlatego jest dostępny tylko za pośrednictwem tej klasy lub klasę pochodną.

W tej sekcji:

Object Klasa zawiera implementacji Finalize metody i moduł garbage collector nie są oznaczane typów pochodnych Object do finalizacji, chyba że zastępują one Finalize metody.

Jeśli typ zastąpienie Finalize Metoda, moduł garbage collector dodaje wpis dla każdego wystąpienia typu wewnętrznej struktury o nazwie Kolejka finalizacji. Kolejka finalizacji zawiera wpisy dla wszystkich obiektów w zarządzanym stosie, którego kod finalizacji musi działać, zanim moduł garbage collector mógł odzyskać pamięć. Następnie wywołuje moduł garbage collector Finalize Metoda automatycznie w następujących warunkach:

  • Po moduł garbage collector wykrył, że obiekt jest niedostępny, chyba że obiekt została zwolniona z finalizacja przez wywołanie GC.SuppressFinalize metody.

  • Podczas zamykania domeny aplikacji chyba że obiekt jest wykluczony z finalizacji. Podczas zamykania sfinalizowaniu nawet obiekty, które są nadal dostępne.

Finalize jest wywoływana automatycznie tylko raz na danego wystąpienia, chyba że obiekt jest ponownie zarejestrowane za pomocą mechanizmu, takich jak GC.ReRegisterForFinalize i GC.SuppressFinalize nie została następnie wywołana metoda.

Finalize operacji ma następujące ograniczenia:

  • Czas, kiedy wykonuje finalizatorów jest niezdefiniowane. Zapewnienie deterministyczna zwolnienia zasobów dla wystąpienia klasy, zaimplementować Close Metoda lub podaj IDisposable.Dispose implementacji.

  • Finalizatorów dwóch obiektów nie ma gwarancji uruchomić w dowolnej kolejności, nawet jeśli jeden obiekt odwołuje się do drugiego. Oznacza to, jeśli obiekt A zawiera odwołanie do obiektu B, mają finalizatory B obiektu może mieć już sfinalizowany podczas uruchamiania finalizatora obiektu, A.

  • Wątek, na którym jest uruchomiony finalizatorów jest nieokreślony.

Finalize Metody mogą nie zostać uruchomione aż do ukończenia lub może nie działać w ogóle w następujących okolicznościach wyjątkowych:

  • Jeśli inny finalizatorów blokuje nieskończoność (przechodzi w pętli nieskończonej, próbuje uzyskać blokadę go może nigdy nie uzyskać i tak dalej). Ponieważ środowisko uruchomieniowe podejmie próbę uruchomienia aż do ukończenia finalizatorów, inne finalizatorów może nie należy wywoływać Jeśli bloki finalizatorów przez czas nieokreślony.

  • Jeśli proces kończy się bez podawania środowisko uruchomieniowe szansy oczyścić. W takim przypadku pierwszy powiadomienie w środowisku uruchomieniowym zakończenia procesu jest powiadomienie komunikat DLL_PROCESS_DETACH.

Środowisko uruchomieniowe kontynuuje finalize obiektów podczas zamykania tylko wtedy, gdy liczba obiektów sfinalizowania kontynuuje zmniejszyć.

Jeśli Finalize lub zastąpieniem Finalize zwraca wyjątek i środowiska wykonawczego nie jest obsługiwana przez aplikację, która zastępuje domyślne zasady, środowisko uruchomieniowe kończy proces i nie aktywne try/finally bloki lub finalizatory są wykonywane. Takie zachowanie gwarantuje integralność procesu, jeśli finalizatora nie można zwolnić ani zniszczyć zasobów.

Należy zastąpić Finalize dla klasy, która używa niezarządzanych zasobów, takich jak dojścia do plików lub połączenia, które można zwolnić, obiektu zarządzanego, który używa tych jest pomijany podczas wyrzucania elementów bezużytecznych bazy danych.

System_CAPS_importantWażne

Jeśli SafeHandle obiekt jest dostępny który otacza niezarządzanego zasobu, zalecaną alternatywą jest implementacji wzorca usuwania z bezpiecznego dojścia, a nie zastępuje Finalize. Aby uzyskać więcej informacji, zobacz Alternatywna SafeHandle sekcji.

Object.Finalize Metoda nie działa domyślnie, ale należy zastąpić Finalize tylko wtedy, gdy konieczne i tylko wydanie niezarządzanych zasobów. Odzyskiwanie pamięci zwykle trwać znacznie dłużej, jeśli operacja finalizacji działa, ponieważ wymaga co najmniej dwóch wyrzucania. Ponadto można zastąpić Finalize tylko typy metoda odwołania. Środowisko uruchomieniowe języka wspólnego tylko Kończenie znajdujących się w typach odwołań. Ignoruje finalizatorów dla typów wartości.

Każdy implementację Finalize typu pochodnego musi wywołać implementację jego typ podstawowy Finalize. Dotyczy to tylko aplikacji, które można wywoływać kod Finalize.

System_CAPS_noteUwaga

Kompilator języka C# nie pozwala na zastąpienie Finalize metody. Zamiast tego należy podać finalizatorów zaimplementowanie destruktor dla swojej klasy. Destruktor C# automatycznie wywołuje destruktor klasy bazowej.

Visual C++ również ma własną składnię implementowania Finalize metody. Aby uzyskać więcej informacji, zobacz sekcję "Destruktory i finalizatory" z Porady: Definiowanie oraz stosowanie klas i struktur (C++ CLI).

Wyrzucanie elementów bezużytecznych jest deterministyczna, nie wiadomo dokładnie, gdy moduł garbage collector wykonuje finalizacji. Aby zwolnić zasoby natychmiast, również można zaimplementować wzorca usuwania i IDisposable interfejsu. IDisposable.Dispose Implementacja może być wywoływana przez konsumenta klasy zwolnienie niezarządzanych zasobów i służy Finalize Metoda zwolnienie niezarządzanych zasobów w przypadku gdy Dispose nie zostanie wywołana metoda.

Finalize może zająć prawie wszystkich akcji, w tym resurrecting obiektu (tj. udostępnienie obiektu ponownie), po jego został oczyszczony podczas wyrzucania elementów bezużytecznych. Jednak obiekt można tylko być aktywowanych raz; Finalize nie można wywołać dla aktywowanych obiektów podczas wyrzucania elementów bezużytecznych. Istnieje jedna akcja który implementacja Finalize nigdy nie powinny mieć: nigdy nie powinien on zgłosić wyjątek.

Tworzenie niezawodnych finalizatorów często trudno jest, ponieważ nie można wprowadzić założenia dotyczące stanu aplikacji i nieobsługiwanych wyjątków systemu, takich jak OutOfMemoryException i StackOverflowException Zakończenie finalizatorów. A nie Implementowanie finalizatorów dla klasy, aby zwolnić zasoby niezarządzane, można użyć obiektu, który jest tworzony na podstawie System.Runtime.InteropServices.SafeHandle klasy do opakowywania niezarządzanych zasobów, a następnie implementacji wzorca usuwania bez finalizatorów. .NET Framework zawiera następujące klasy w Microsoft.Win32 przestrzeni nazw, które są uzyskiwane z System.Runtime.InteropServices.SafeHandle:

W poniższym przykładzie użyto wzorca usuwania z bezpieczne dojścia, zamiast zastępowanie Finalize metody. Definiuje FileAssociation klasę, która otacza rejestru informacji o aplikacji, która obsługuje pliki z rozszerzeniem określonego pliku. Zwracane jako dojścia do rejestru dwóch out Parametry przez system Windows RegOpenKeyEx wywołania funkcji są przekazywane do SafeRegistryHandle Konstruktor. Chroniony przez typ Dispose następnie wywołuje metodę SafeRegistryHandle.Dispose Metoda zwolnienia tych dwóch uchwytów.

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();
      }
   }
}

Poniższy przykład sprawdza, czy Finalize Metoda jest wywoływana, gdy obiekt zastępuje Finalize jest niszczony. Należy zauważyć, że w aplikacji produkcyjnych, Finalize Metoda może zostać zastąpiona wydanie niezarządzane zasoby utrzymywane przez obiekt. Należy również zauważyć, że w przykładzie C# zawiera destruktor zamiast zastępowanie Finalize metody.

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 M:System.Object.Finalize method, see the M:System.GC.SuppressFinalize(System.Object) method.

Platforma uniwersalna systemu Windows
Dostępne od 8
.NET Framework
Dostępne od 1.1
Biblioteka klas przenośnych
Obsługiwane w: przenośne platformy .NET
Silverlight
Dostępne od 2.0
Windows Phone Silverlight
Dostępne od 7.0
Windows Phone
Dostępne od 8.1
Powrót do początku
Pokaż: