.NET'te hangi koşullar altında kullanmalıyım GC.SuppressFinalize()?
Bu yöntemi kullanmamın bana sağladığı avantajlar nelerdir?
.NET'te hangi koşullar altında kullanmalıyım GC.SuppressFinalize()?
Bu yöntemi kullanmamın bana sağladığı avantajlar nelerdir?
Yanıtlar:
SuppressFinalizeyalnızca sonlandırıcısı olan bir sınıf tarafından çağrılmalıdır. Çöp Toplayıcısına (GC) şunu bildiriyor:this nesnenin tamamen temizlendiğini .
IDisposableSonlandırıcınız olduğunda önerilen kalıp:
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);
}
}
Normalde, CLR, oluşturulduklarında sonlandırıcı içeren nesneler üzerindeki sekmeleri tutar (bunları oluşturmak daha pahalı hale getirir). SuppressFinalizeGC'ye nesnenin düzgün bir şekilde temizlendiğini ve sonlandırıcı kuyruğuna gitmesi gerekmediğini bildirir. Bir C ++ yıkıcıya benziyor, ancak bir şey gibi davranmıyor.
SuppressFinalizeNesnelerinizin sonlandırıcı kuyrukta bekleyen uzun bir süre yaşayabilir olarak optimizasyon, önemsiz değildir. Aramaya cazip gelmeSuppressFinalizeAklınıza gelen diğer nesneleri . Bu, gerçekleşmeyi bekleyen ciddi bir kusur.
Tasarım yönergeleri, nesneniz uygulanırsa bir sonlandırıcının gerekli olmadığını bildirir IDisposable, ancak bir sonlandırıcınız varsa,IDisposable , sınıfınızın deterministik olarak temizlenmesine izin vermek için .
Çoğu zaman kaçabilmeniz gerekir IDisposable kaynakları temizlemek . Bir sonlandırıcıya yalnızca nesneniz yönetilmeyen kaynaklara bağlı olduğunda ve bu kaynakların temizlendiğinden emin olmanız gerektiğinde sonlandırmaya ihtiyacınız vardır.
Not: Bazen kodlayıcılar, IDisposablekodun IDisposablenesnelerini düzgün bir şekilde bertaraf ettiğini test etmek için kendi sınıflarının yapılarındaki hata ayıklama işlemlerine bir sonlandırıcı ekler .
public void Dispose() // Implement IDisposable
{
Dispose(true);
#if DEBUG
GC.SuppressFinalize(this);
#endif
}
#if DEBUG
~MyClass() // the finalizer
{
Dispose(false);
}
#endif
IDisposabledeğilse sealed, GC.SuppressFinalize(this) kullanıcı tanımlı bir sonlandırıcı içermese bile çağrıyı içermelidir . Bu, kullanıcı tanımlı bir sonlandırıcı ekleyen ancak yalnızca korunan Dispose(bool)yöntemi geçersiz kılan türetilmiş türler için uygun semantik sağlamak için gereklidir .
sealedolarak @SamHarwell tarafından bahsedilen türetilmiş sınıfları için, önemlidir. CodeAnalysis, sınıf mühürlenmediğinde ca1816 + ca1063 ile sonuçlanır, ancak kapalı sınıflar olmadan iyidir SuppressFinalize.
SupressFinalizesisteme sonlandırıcıda yapılacak her türlü işin zaten yapıldığını söyler, bu yüzden sonlandırıcının çağrılmasına gerek yoktur. .NET belgelerinden:
IDisposable arabirimini uygulayan nesneler, çöp toplayıcının, bunu gerektirmeyen bir nesne üzerinde Object.Finalize öğesini çağırmasını önlemek için bu yöntemi IDisposable.Dispose yönteminden çağırabilir.
Genel olarak, herhangi bir Dispose()yöntemin çoğuGC.SupressFinalize() , çünkü sonlandırıcıda temizlenecek her şeyi temizlemelidir.
SupressFinalizesadece sistemin nesneyi sonlandırıcı iş parçacığına kuyruğa almamasına izin veren bir optimizasyon sağlayan bir şeydir. Düzgün yazılmış Dispose()/ sonlandırıcı çağrılı olsun veya olmasın düzgün çalışmalıdır GC.SupressFinalize().
Bu yöntem, bu Disposeyöntemi uygulayan nesneler yönteminde çağrılmalıdır, IDisposablebu şekilde birileri Disposeyöntemi çağırdığında GC sonlandırıcıyı başka bir kez çağırmaz .
Bkz. GC.SuppressFinalize (Object) Yöntemi - Microsoft Belgeleri
Dispose(true);
GC.SuppressFinalize(this);
Nesnede sonlandırıcı varsa, .net sonlandırma kuyruğuna bir başvuru koydu.
Çağrı yaptığımızdan Dispose(ture), bu nesneyi temizlediğinden, bu işi yapmak için sonlandırma sırasına ihtiyacımız yok.
Bu yüzden GC.SuppressFinalize(this)sonlandırma kuyruğundaki kaldır referansını çağırın .
Bir sınıf veya bundan türetilen herhangi bir şey, bir sonlandırıcıya sahip bir nesneye son canlı referansı tutabilirse, o sonlandırıcıdan olumsuz etkilenebilecek herhangi bir işlemden sonra nesneye ya GC.SuppressFinalize(this)da GC.KeepAlive(this)çağrılmalı, böylece sonlandırıcının kazandığından emin olunmalıdır. bu işlem tamamlanıncaya kadar çalıştırılmaz.
Sonlandırıcı olmayan herhangi bir sınıfın maliyeti GC.KeepAlive()ve GC.SuppressFinalize(this)esas olarak aynıdır ve sonlandırıcıları olan sınıflar genellikle çağırmalıdır GC.SuppressFinalize(this), bu nedenle son işlevi olarak sonuncu işlev olarak kullanmak Dispose()her zaman gerekli olmayabilir, ancak olmayacaktır. yanlış olmak.