이 문서는 기계 번역을 이용하여 번역되었습니다. 문서를 영문으로 보려면 영문 확인란을 선택하세요. 마우스 포인터를 텍스트 위로 이동시켜 팝업 창에서 영문 텍스트를 표시할 수도 있습니다.
번역
영문

Object.Finalize 메서드 ()

 

게시 날짜: 2016년 11월

가비지 컬렉션이 회수하기 전에 개체가 리소스를 해제하고 다른 정리 작업을 수행할 수 있게 합니다.

네임스페이스:   System
어셈블리:  mscorlib(mscorlib.dll에 있음)

protected virtual void Finalize()

Finalize 메서드를 사용 하는 개체가 소멸 되기 전에 현재 개체에서 보유 하는 관리 되지 않는 리소스에서 정리 작업을 수행 합니다. 메서드가 보호와 이므로 다음이 클래스 또는 파생된 클래스를 통해 액세스할 수 있는 합니다.

섹션 내용

Object 클래스에 대 한 구현을 제공는 Finalize 메서드와 가비지 수집기에서 파생 된 유형을 표시 하지 않는 Object 종료를 재정의 하지 않는 한는 Finalize 메서드.

형식에서 재정의 하는 경우는 Finalize 메서드를 가비지 수집기는 종료 큐 라는 내부 구조에는 유형의 각 항목에 대 한 항목을 추가 합니다. 종료 큐 가비지 수집기가 메모리를 회수할 수 전에 종료 코드를 실행 해야 하는 관리 되는 힙의 모든 개체에 대 한 항목을 포함 합니다. 그런 다음 호출 하는 가비지 수집기는 Finalize 자동으로 다음과 같은 조건 메서드:

  • 가비지 수집기가 개체에를 호출 하 여 종료에서 제외 된 경우가 아니면 개체에 액세스할 수 아닌지 검색 한 후의 GC.SuppressFinalize 메서드.

  • 응용 프로그램 도메인의 종료 하는 동안 없으면 개체를 종료에서 제외 합니다. 여전히 액세스할 수 있는도 개체를 종료 하는 동안 종료 됩니다.

Finalize자동으로 한 번만 호출 지정한 인스턴스에서 개체와 같은 메커니즘을 사용 하 여 다시 등록 하지 않는 한 GC.ReRegisterForFinalizeGC.SuppressFinalize 메서드 이후에 호출 되지 않았습니다.

Finalize작업은 다음과 같은 제한 사항이 있습니다.

  • 종료 자가 실행 되는 경우 정확한 시간 정의 되지 않습니다. 인스턴스 클래스의 구현에 대 한 리소스의 명확한 해제를 위해는 Close 메서드를 제공 하거나는 IDisposable.Dispose 구현 합니다.

  • 두 개체의 종료자 다른 하나의 개체가 참조 하는 경우에 특정 순서로 실행 되도록 보장 되지 않습니다. 즉, 개체 A가 개체 B에 대 한 참조 하는 경우 둘 다 종료자 개체 B 수 이미 종료 되었을 A의 종료 자가 시작 될 때입니다.

  • 종료 자가 실행 되는 스레드 지정 되지 않았습니다.

Finalize 메서드가 완료 될 때까지 실행 되지 않거나 다음과 같은 예외적인 전혀 실행 되지 않습니다.

  • 다른 종료자 무기한으로 차단 하는 경우 (이 되는 무한 루프에는 잠금 수를 가져오려면 및 등 하지을 가져오려고 시도). 런타임에 종료자 실행이 완료 하려고 하기 때문에 다른 종료자 수 경우 호출 종료자 블록 무기한 합니다.

  • 프로세스는 런타임을 정리할 수 있는 기회를 제공 하지 않고도 종료 합니다. 이 경우 런타임 종료 프로세스의 첫 번째 알림을 DLL_PROCESS_DETACH 알림입니다.

런타임에서 줄어드는 경우 개체의 수를 계속 하는 동안에 개체를 종료 하는 동안 종료를 계속 합니다.

경우 Finalize 또는 재정의 Finalize 에서 예외를 throw 하 고 런타임이 기본 정책 보다 우선 하는 응용 프로그램에서 호스트 되지 않는, 활성화와 프로세스를 종료 하는 런타임 try/finally 블록 또는 종료자 실행 됩니다. 이 동작은 종료자 있음 없거나 리소스를 삭제 하는 경우 프로세스의 무결성을 보장 합니다.

재정의 해야 Finalize 와 같은 관리 되지 않는 리소스를 사용 하는 클래스에 대 한 파일 핸들 또는 가비지 수집 중에 사용 하는 관리 되는 개체는 삭제 될 때 해제 해야 하는 데이터베이스 연결 합니다.

System_CAPS_important중요

경우는 SafeHandle 개체를 사용할 수를 래핑하는 관리 되지 않는 리소스는 safehandle 사용 하 여 dispose 패턴을 구현 하 고 재정의 하지 하는 메서드 대신 Finalize합니다. 자세한 내용은 참조 The SafeHandle 대안 섹션.

Object.Finalize 기본적으로도 메서드는 아무 작업도 수행 하지만 재정의 해야 하는 Finalize 경우에 필요한 유일한 관리 되지 않는 리소스를 해제 합니다. 메모리를 회수는 두 개 이상의 가비지 수집 필요 하기 때문에 종료 작업을 실행 하는 경우 훨씬 더 오래 걸릴 경향이 있습니다. 또한를 재정의 해야 하는 Finalize 메서드 참조에 대 한 형식에 합니다. 공용 언어 런타임에서 참조 형식만 종료합니다. 값 형식에서 종료자를 무시합니다.

모든 구현 Finalize 파생 된 형식에 해당 기본 형식 구현을 호출 해야 Finalize합니다. 이 경우에 코드를 호출할 수 있는 응용 프로그램에서 Finalize합니다.

System_CAPS_note참고

C# 컴파일러를 재정의할 수를 허용 하지 않습니다는 Finalize 메서드. 대신 종료자를 구현 하 여 제공 된 소멸자 클래스에 대 한 합니다. C# 소멸자는 자동으로 기본 클래스의 소멸자를 호출합니다.

Visual c + + 구현 하기 위한 자체 구문이 제공는 Finalize 메서드. 자세한 내용은의 "소멸자 및 종료자" 섹션을 참조 하십시오. 방법: 정의 및 클래스 및 구조체 (c + + CLI)를 사용 합니다.합니다.

가비지 수집 비결 이기 때문에 가비지 수집기가 종료를 수행 하는 경우에 정확 하 게 알지 못하는 합니다. 리소스를 해제 하려면 즉시 수도 있습니다를 구현 하는 삭제 패턴IDisposable 인터페이스입니다. IDisposable.Dispose 구현 클래스의 소비자가 관리 되지 않는 리소스를 해제 하 여 호출할 수 있으며 사용할 수 있습니다는 Finalize 관리 되지 않는 리소스를 해제 하는 방법에는 Dispose 메서드가 호출 되지 않습니다.

Finalize가비지 수집 중 의해 정리 된 후에 개체 (즉, 개체가 액세스할 수 있도록 다시) 부활 하기 등 거의 모든 작업을 수행할 수 있습니다. 그러나 개체 수만 복원할 되지 않습니다. Finalize 가비지 수집 중 부활 개체에서 호출할 수 없습니다. 하나의 액션이 있습니다 하는의 구현 Finalize 받아들이지 해야: 예외를 throw 하지 해야 합니다.

신뢰할 수 있는 종료자를 만드는 것이 쉽지 않습니다, 응용 프로그램의 상태에 대 한 가정을 만들 수 없습니다와 같은 시스템 예외를 처리 하지 않은 있으므로 OutOfMemoryExceptionStackOverflowException 종료자를 종료 합니다. 관리 되지 않는 리소스를 해제 하 여 클래스에 대 한 종료자를 구현 하는 대신에서 파생 된 개체를 사용할 수는 System.Runtime.InteropServices.SafeHandle 에서는 관리 되지 않는 리소스를 래핑하는 클래스 및 다음 종료자 없이 dispose 패턴을 구현 합니다. .NET Framework에서는 다음 클래스는 Microsoft.Win32 네임 스페이스에서 파생 된 System.Runtime.InteropServices.SafeHandle:

다음 예제에서는 삭제 패턴 재정의 하는 대신 safehandle와는 Finalize 메서드. 정의 FileAssociation 특정 파일 확장명을 가진 파일을 처리 하는 응용 프로그램에 대 한 레지스트리 정보를 래핑하는 클래스입니다. 로 반환 하는 두 개의 레지스트리 핸들 out Windows에서 매개 변수 RegOpenKeyEx 함수 호출에 전달 되는 SafeRegistryHandle 생성자입니다. 종류의 보호 Dispose 메서드를 호출는 SafeRegistryHandle.Dispose 메서드를 이러한 두 핸들을 해제 합니다.

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

다음 예제를 확인 하는 Finalize 메서드는 재정의 하는 개체가 Finalize 소멸 됩니다. 유의 프로덕션 응용 프로그램에서의 Finalize 개체에서 보유 하는 관리 되지 않는 리소스를 해제 하기 위해 메서드를 재정의 해야 합니다. 또한 C# 예제에서는 재정의 하는 대신 소멸자를 제공 하는지 유의 Finalize 메서드.

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.

유니버설 Windows 플랫폼
8 이후 사용 가능
.NET Framework
1.1 이후 사용 가능
이식 가능한 클래스 라이브러리
이식 가능한 .NET 플랫폼 에서 지원됨
Silverlight
2.0 이후 사용 가능
Windows Phone Silverlight
7.0 이후 사용 가능
Windows Phone
8.1 이후 사용 가능
맨 위로 이동
표시: