내보내기(0) 인쇄
모두 확장
이 문서는 기계로 번역한 것입니다. 원본 텍스트를 보려면 포인터를 문서의 문장 위로 올리십시오. 추가 정보
번역
원본

Object.Finalize 메서드

개체가 가비지 수집자에서 회수되기 전에, 해당 개체에서 리소스를 해제하고 다른 정리 작업을 수행할 수 있게 합니다.

네임스페이스:  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 와 같은 관리 되지 않는 리소스를 사용 하는 클래스에 대 한 파일 핸들 또는 데이터베이스 연결과 가비지 수집 중 관리 되는 개체를 사용 하 여 삭제 되 면 해제 되어야 하는.

중요중요

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

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

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

참고참고

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

Visual C++ 구현을 위한 자체 구문이 제공 하면 Finalize 방법. 자세한 내용은의 "소멸자 및 종료자" 절을 참조 하십시오. 방법: 클래스 및 구조체를 인스턴스화할.

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

Finalize 가비지 수집 동안 의해 정리 된 후에 개체 (즉, 개체는 쉽게 액세스할 수 있도록 다시) 부활 하기를 포함 하 여 거의 모든 작업을 걸릴 수 있습니다. 그러나 개체는 한 번만 되살릴 수 있으며 Finalize는 가비지를 수집하는 동안에는 되살린 개체에 대해 호출될 수 없습니다. 한 동작이 있는 구현 Finalize 안 걸리는: 예외는 throw 되지 않습니다.

SafeHandle 대안

안정적인 종료자를 만드는 어렵습니다, 응용 프로그램의 상태에 대 한 가정을 할 수 있기 때문에 같은 시스템 예외 처리 때문에 OutOfMemoryExceptionStackOverflowException 종료자를 종료 합니다. 대신 관리 되지 않는 리소스를 해제 하 여 클래스에 대 한 종료자를 구현에서 파생 된 개체를 사용할 수 있습니다는 System.Runtime.InteropServices.SafeHandle 클래스에 관리 되지 않는 리소스를 하 고 종료 자가 없는 dispose 패턴을 구현 합니다. .NET Framework 클래스를 제공 하면 Microsoft.Win32 에서 파생 된 네임 스페이스 System.Runtime.InteropServices.SafeHandle.

다음 예제는 dispose 패턴 재정의 하는 대신 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


재정의 하는 추가 예제는 Finalize 메서드를 참조 하면 GC.SuppressFinalize 메서드.

.NET Framework

4.5.2, 4.5.1, 4.5, 4, 3.5, 3.0, 2.0, 1.1, 1.0에서 지원

.NET Framework Client Profile

4, 3.5 SP1에서 지원

이식 가능한 클래스 라이브러리

이식 가능한 클래스 라이브러리에서 지원

Windows 스토어 앱용 .NET

Windows 8에서 지원

Windows Phone 앱용 .NET

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(서버 코어 역할은 지원되지 않음), Windows Server 2008 R2(서버 코어 역할은 SP1 이상에서 지원, Itanium은 지원되지 않음)

.NET Framework에서 모든 플랫폼의 전체 버전을 지원하지는 않습니다. 지원되는 버전의 목록을 보려면 .NET Framework 시스템 요구 사항을 참조하십시오.

커뮤니티 추가 항목

추가
표시:
© 2014 Microsoft