[C#] 언제 GC.SuppressFinalize ()를 사용해야합니까?

.NET에서 어떤 상황에서 사용해야 GC.SuppressFinalize()합니까?

이 방법을 사용하면 어떤 이점이 있습니까?



답변

SuppressFinalize종료자가있는 클래스에서만 호출해야합니다. 가비지 콜렉터 (GC)에 this오브젝트가 완전히 정리 되었음을 알리고 있습니다.

종료자가 IDisposable있을 때 권장되는 패턴은 다음과 같습니다.

public class MyClass : IDisposable
{
    private bool disposed = false;

    protected virtual void Dispose(bool disposing)
    {
        if (!disposed)
        {
            if (disposing)
            {
                // called via myClass.Dispose(). 
                // OK to use any private object references
            }
            // Release unmanaged resources.
            // Set large fields to null.                
            disposed = true;
        }
    }

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

    ~MyClass() // the finalizer
    {
        Dispose(false);
    }
}

일반적으로 CLR은 객체를 만들 때 종료자가있는 객체의 탭을 유지하므로 생성하는 데 비용이 많이 듭니다. SuppressFinalizeGC에 개체가 올바르게 정리되었으며 종료 자 대기열로 이동할 필요가 없음을 알려줍니다. C ++ 소멸자처럼 보이지만 하나처럼 행동하지는 않습니다.

SuppressFinalize당신의 객체가 종료 자 큐에서 대기하는 시간이 오래 살 수있는 최적화, 사소한하지 않습니다. SuppressFinalize다른 물건을 생각하고 싶은 유혹을 느끼지 마십시오 . 그것은 심각한 결함이 일어나기를 기다리고 있습니다.

디자인 지침은 객체가 구현하는 경우 종료자가 필요하지 않다고 알려주지 IDisposable만 종료자가 있으면 IDisposable클래스를 결정적으로 정리할 수 있도록 구현해야 합니다.

대부분의 경우 IDisposable리소스 정리 를 위해 벗어날 수 있어야 합니다. 개체가 관리되지 않는 리소스를 보유하고 있고 해당 리소스가 정리되도록 보장해야 할 경우에만 종료자가 필요합니다.

참고 : 때때로 코더는 IDisposable코드가 IDisposable객체를 올바르게 배치했는지 테스트하기 위해 자체 클래스의 빌드를 디버깅 하기 위해 종료자를 추가합니다 .

public void Dispose() // Implement IDisposable
{
    Dispose(true);
#if DEBUG
    GC.SuppressFinalize(this);
#endif
}

#if DEBUG
~MyClass() // the finalizer
{
    Dispose(false);
}
#endif


답변

SupressFinalize파이널 라이저에서 수행 된 작업이 이미 완료되었음을 시스템에 알려주므로 파이널 라이저를 호출 할 필요가 없습니다. .NET 문서에서 :

IDisposable 인터페이스를 구현하는 객체는 IDisposable.Dispose 메서드에서이 메서드를 호출하여 가비지 수집기가 Object.Finalize를 필요로하지 않는 개체에서 호출하지 못하게합니다.

일반적으로 finalizer에서 정리할 모든 항목을 정리해야하므로 대부분의 Dispose()메소드는을 호출 할 수 있어야합니다 GC.SupressFinalize().

SupressFinalize시스템이 객체를 종료 자 스레드에 큐잉하지 않도록하는 최적화를 제공하는 것입니다. 제대로 작성된 Dispose()/ 완료자는에 대한 호출 여부에 관계없이 제대로 작동해야합니다 GC.SupressFinalize().


답변

이 메소드는 Dispose을 구현하는 객체 의 메소드에서 호출되어야합니다 IDisposable. 이런 식으로 누군가가 Dispose메소드를 호출하면 GC가 종료자를 다시 호출하지 않습니다 .

참조 : GC.SuppressFinalize (Object) 메서드-Microsoft Docs


답변

Dispose(true);
GC.SuppressFinalize(this);

object에 finalizer가 있으면 .net은 finalization queue에 참조를 넣습니다.

우리는 call을 가지고 있기 때문에 Dispose(ture)객체를 지우 므로이 작업을 수행하기 위해 종료 대기열이 필요하지 않습니다.

따라서 GC.SuppressFinalize(this)종료 큐에서 참조 제거를 호출 하십시오.


답변

클래스 또는 클래스에서 파생 된 클래스가 종료자를 사용하여 오브젝트에 대한 마지막 실시간 참조를 보유 할 수있는 경우, 종료 자에 의해 부정적인 영향을받을 수있는 조작 후 오브젝트에서 호출 GC.SuppressFinalize(this)되거나 종료 GC.KeepAlive(this)되어야합니다. 해당 작업이 완료 될 때까지 실행하지 마십시오.

비용 GC.KeepAlive()과는 GC.SuppressFinalize(this)본질적으로 파이널이없는 그 모든 클래스에서 동일, 일반적으로 호출해야 파이 나라가 할 클래스 GC.SuppressFinalize(this)그래서 마지막 단계로 후자의 기능을 사용하여 Dispose()항상 필요하지 않을 수도 있습니다,하지만 그것은하지 않습니다 틀리다.


답변