.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:
SuppressFinalize
yalnı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 .
IDisposable
Sonlandı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). SuppressFinalize
GC'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.
SuppressFinalize
Nesnelerinizin sonlandırıcı kuyrukta bekleyen uzun bir süre yaşayabilir olarak optimizasyon, önemsiz değildir. Aramaya cazip gelmeSuppressFinalize
Aklı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, IDisposable
kodun IDisposable
nesnelerini 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
IDisposable
değ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 .
sealed
olarak @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
.
SupressFinalize
sisteme 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.
SupressFinalize
sadece 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 Dispose
yöntemi uygulayan nesneler yönteminde çağrılmalıdır, IDisposable
bu şekilde birileri Dispose
yö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.