Sonlandırıcılar (C# Programlama Kılavuzu)
Sonlandırıcılar (geçmişe yıkıcı olarak adlandırılır), bir sınıf örneği çöp toplayıcı tarafından toplanırken gerekli son temizleme işlemlerini gerçekleştirmek için kullanılır. Çoğu durumda, yönetilmeyen tanıtıcıları sarmak için veya türetilmiş sınıfları kullanarak System.Runtime.InteropServices.SafeHandle sonlandırıcı yazmaktan kaçınabilirsiniz.
Açıklamalar
- Sonlandırıcılar yapılarda tanımlanamaz. Bunlar yalnızca sınıflarla kullanılır.
- Bir sınıfın yalnızca bir sonlandırıcısı olabilir.
- Sonlandırıcılar devralınamaz veya aşırı yüklenemez.
- Sonlandırıcılar çağrılamaz. Bunlar otomatik olarak çağrılır.
- Sonlandırıcı değiştiricileri almaz veya parametreleri yoktur.
Örneğin, aşağıdaki sınıf için bir sonlandırıcı bildirimidir Car
.
class Car
{
~Car() // finalizer
{
// cleanup statements...
}
}
Sonlandırıcı, aşağıdaki örnekte gösterildiği gibi bir ifade gövdesi tanımı olarak da uygulanabilir.
public class Destroyer
{
public override string ToString() => GetType().Name;
~Destroyer() => Console.WriteLine($"The {ToString()} finalizer is executing.");
}
Sonlandırıcı örtük olarak nesnenin temel sınıfını çağırır Finalize . Bu nedenle, sonlandırıcı çağrısı örtük olarak aşağıdaki koda çevrilir:
protected override void Finalize()
{
try
{
// Cleanup statements...
}
finally
{
base.Finalize();
}
}
Bu tasarım, yöntemin Finalize
en çok türetilenden en az türetilene kadar devralma zincirindeki tüm örnekler için özyinelemeli olarak çağrıldığı anlamına gelir.
Not
Boş sonlandırıcılar kullanılmamalıdır. Bir sınıf sonlandırıcı içerdiğinde, kuyrukta Finalize
bir girdi oluşturulur. Bu kuyruk çöp toplayıcısı tarafından işlenir. GC kuyruğu işlediğinde her sonlandırıcıyı çağırır. Boş sonlandırıcılar, yalnızca temel sınıf sonlandırıcısını çağıran sonlandırıcılar veya yalnızca koşullu olarak yayılan yöntemleri çağıran sonlandırıcılar gibi gereksiz sonlandırıcılar, gereksiz performans kaybına neden olur.
Programcının sonlandırıcının ne zaman çağrıldığı üzerinde hiçbir denetimi yoktur; ne zaman çağrıleceğine çöp toplayıcı karar verir. Atık toplayıcı, uygulama tarafından artık kullanılmayan nesneleri denetler. Bir nesneyi sonlandırma için uygun kabul ederse, sonlandırıcıyı (varsa) çağırır ve nesneyi depolamak için kullanılan belleği geri kazanır. çağırarak Collectçöp toplamayı zorlamak mümkündür, ancak çoğu zaman performans sorunları oluşturabileceğinden bu çağrıdan kaçınılmalıdır.
Not
Sonlandırıcıların uygulama sonlandırmanın bir parçası olarak çalıştırılıp çalıştırılmayacağı her .NET uygulamasına özgüdür. Bir uygulama sonlandırıldığında, .NET Framework bu tür bir temizleme gizlenmediği sürece (örneğin, kitaplık yöntemine GC.SuppressFinalize
yapılan bir çağrıyla) henüz çöp toplanmamış nesneler için sonlandırıcıları çağırmak için her zaman makul çabayı gösterir. .NET 5 (.NET Core dahil) ve sonraki sürümler, uygulama sonlandırmanın bir parçası olarak sonlandırıcıları çağırmaz. Daha fazla bilgi için bkz. GitHub sorunu dotnet/csharpstandard #291.
Uygulamadan çıkıldığında güvenilir bir şekilde temizleme gerçekleştirmeniz gerekiyorsa, olay için System.AppDomain.ProcessExit bir işleyici kaydedin. Bu işleyici, uygulamadan çıkmadan önce temizleme gerektiren tüm nesneler için (veya) IAsyncDisposable.DisposeAsync()çağrılmasını sağlar IDisposable.Dispose() . Finalize'ı doğrudan çağıramadığınız ve çöp toplayıcının çıkış öncesinde tüm sonlandırıcıları çağırdığından emin olaamadığınız için veya DisposeAsync
kaynaklarının Dispose
serbest olduğundan emin olmanız gerekir.
Kaynakları serbest bırakmak için sonlandırıcıları kullanma
Genel olarak, C# geliştiricinin bir bölümünde atık toplama ile çalışma zamanını hedeflemeyen diller kadar bellek yönetimi gerektirmez. Bunun nedeni, .NET çöp toplayıcısının nesneleriniz için bellek ayırmayı ve serbest bırakma işlemini örtük olarak yönetmesidir. Ancak, uygulamanız windows, dosyalar ve ağ bağlantıları gibi yönetilmeyen kaynakları kapsüllediğinde, bu kaynakları boşaltmak için sonlandırıcıları kullanmanız gerekir. Nesne sonlandırma için uygun olduğunda, çöp toplayıcı nesnesinin Finalize
yöntemini çalıştırır.
Kaynakların açık sürümü
Uygulamanız pahalı bir dış kaynak kullanıyorsa, çöp toplayıcı nesneyi boşaltmadan önce kaynağı açıkça serbest bırakmak için bir yol sağlamanızı da öneririz. Kaynağı serbest bırakmak için, arabiriminden IDisposable nesne için gerekli temizlemeyi gerçekleştiren bir Dispose
yöntem uygulayın. Bu, uygulamanın performansını önemli ölçüde artırabilir. Kaynaklar üzerinde bu açık denetimle bile, yönteme yapılan çağrı başarısız olursa sonlandırıcı kaynakları temizlemek için Dispose
bir koruma haline gelir.
Kaynakları temizleme hakkında daha fazla bilgi için aşağıdaki makalelere bakın:
- Yönetilmeyen Kaynakları Temizleme
- Dispose Yöntemi Uygulama
- DisposeAsync Yöntemi Uygulama
using
Deyim
Örnek
Aşağıdaki örnek, devralma zinciri oluşturan üç sınıf oluşturur. sınıfı First
temel sınıfıdır, Second
öğesinden First
türetilir ve Third
öğesinden Second
türetilir. Üçünü de sonlandırıcıları var. içinde Main
, en çok türetilmiş sınıfın bir örneği oluşturulur. Bu koddan elde edilen çıkış, uygulamanın hedeflediği .NET uygulamasına bağlıdır:
- .NET Framework: Çıktı, uygulama sonlandırıldığında üç sınıf için sonlandırıcıların en çok türetilenden en az türetilene kadar otomatik olarak çağrıldığını gösterir.
- .NET 5 (.NET Core dahil) veya sonraki bir sürüm: Bu .NET uygulaması, uygulama sonlandırıldığında sonlandırıcıları çağırmadığından çıkış yok.
class First
{
~First()
{
System.Diagnostics.Trace.WriteLine("First's finalizer is called.");
}
}
class Second : First
{
~Second()
{
System.Diagnostics.Trace.WriteLine("Second's finalizer is called.");
}
}
class Third : Second
{
~Third()
{
System.Diagnostics.Trace.WriteLine("Third's finalizer is called.");
}
}
/*
Test with code like the following:
Third t = new Third();
t = null;
When objects are finalized, the output would be:
Third's finalizer is called.
Second's finalizer is called.
First's finalizer is called.
*/
C# dili belirtimi
Daha fazla bilgi için C# Dil Belirtimi'nin Sonlandırıcılar bölümüne bakın.