.NET에서 어떤 상황에서 사용해야 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은 객체를 만들 때 종료자가있는 객체의 탭을 유지하므로 생성하는 데 비용이 많이 듭니다. SuppressFinalize
GC에 개체가 올바르게 정리되었으며 종료 자 대기열로 이동할 필요가 없음을 알려줍니다. 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
IDisposable
이 아닌 경우 사용자 정의 종료sealed
자를 GC.SuppressFinalize(this)
포함하지 않더라도 호출을 포함해야합니다 . 이는 사용자 정의 종료자를 추가하지만 보호 된 Dispose(bool)
메서드 만 재정의하는 파생 형식에 대한 적절한 의미 체계를 보장하기 위해 필요합니다 .
sealed
파생 클래스에는 @SamHarwell에서 언급 하지 않은 것이 중요합니다. 클래스가 봉인되지 않은 경우 CodeAnalysis에서 ca1816 + ca1063이 발생하지만 봉인 된 클래스는 SuppressFinalize
.
SupressFinalize
파이널 라이저에서 수행 된 작업이 이미 완료되었음을 시스템에 알려주므로 파이널 라이저를 호출 할 필요가 없습니다. .NET 문서에서 :
IDisposable 인터페이스를 구현하는 객체는 IDisposable.Dispose 메서드에서이 메서드를 호출하여 가비지 수집기가 Object.Finalize를 필요로하지 않는 개체에서 호출하지 못하게합니다.
일반적으로 finalizer에서 정리할 모든 항목을 정리해야하므로 대부분의 Dispose()
메소드는을 호출 할 수 있어야합니다 GC.SupressFinalize()
.
SupressFinalize
시스템이 객체를 종료 자 스레드에 큐잉하지 않도록하는 최적화를 제공하는 것입니다. 제대로 작성된 Dispose()
/ 완료자는에 대한 호출 여부에 관계없이 제대로 작동해야합니다 GC.SupressFinalize()
.
이 메소드는 Dispose
을 구현하는 객체 의 메소드에서 호출되어야합니다 IDisposable
. 이런 식으로 누군가가 Dispose
메소드를 호출하면 GC가 종료자를 다시 호출하지 않습니다 .
클래스 또는 클래스에서 파생 된 클래스가 종료자를 사용하여 오브젝트에 대한 마지막 실시간 참조를 보유 할 수있는 경우, 종료 자에 의해 부정적인 영향을받을 수있는 조작 후 오브젝트에서 호출 GC.SuppressFinalize(this)
되거나 종료 GC.KeepAlive(this)
되어야합니다. 해당 작업이 완료 될 때까지 실행하지 마십시오.
비용 GC.KeepAlive()
과는 GC.SuppressFinalize(this)
본질적으로 파이널이없는 그 모든 클래스에서 동일, 일반적으로 호출해야 파이 나라가 할 클래스 GC.SuppressFinalize(this)
그래서 마지막 단계로 후자의 기능을 사용하여 Dispose()
항상 필요하지 않을 수도 있습니다,하지만 그것은하지 않습니다 틀리다.