Sonlandırıcılar (C# Programlama Kılavuzu)

Sonlandırıcılar (eski adı yıkıcılar), atık toplayıcı tarafından bir sınıf örneği toplanıyorken gerekli son temizleme işlemlerini gerçekleştirmek için kullanılır. Çoğu durumda, herhangi bir unmanaged tanıtıcıyı sarmak için veya türetilmiş sınıfları kullanarak System.Runtime.InteropServices.SafeHandle bir sonlandırıcı yazmaktan kaçınabilirsiniz.

Açıklamalar

  • Sonlandırıcılar yapılarda tanımlanmalıdır. 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ük devred kullanılamaz.
  • Sonlandırıcılar çağrılaamaz. Bunlar otomatik olarak çağrılır.
  • Sonlandırıcı, değiştiricileri almaz veya parametreleri olmaz.

Örneğin, aşağıdaki sınıf için bir sonlandırıcı Car bildirimidir.

class Car
{
    ~Car()  // finalizer
    {
        // cleanup statements...
    }
}

Sonlandırıcı, aşağıdaki örnekte de olduğu gibi ifade gövdesi tanımı olarak da kullanılabilir.

using System;

public class Destroyer
{
   public override string ToString() => GetType().Name;

   ~Destroyer() => Console.WriteLine($"The {ToString()} finalizer is executing.");
}

Sonlandırıcı, nesnenin temel Finalize sınıfında örtülü olarak çağrır. Bu nedenle, sonlandırıcıya yapılan bir çağrı örtülü olarak aşağıdaki koda çevrilir:

protected override void Finalize()
{
    try
    {
        // Cleanup statements...
    }
    finally
    {
        base.Finalize();
    }
}

Bu tasarım, yöntemin devralma zincirinde en fazla türetilenden en az türetilene kadar tüm örnekler için tekrar tekrar Finalize çağrılır.

Not

Boş sonlandırıcılar kullanılmamalı. Bir sınıf sonlandırıcı içerdiğinde kuyrukta bir giriş Finalize oluşturulur. Bu kuyruk, atık toplayıcı tarafından işlenir. GC kuyruğu işleyene her sonlandırıcıyı çağırıyor. Boş sonlandırıcılar, yalnızca temel sınıf sonlandırıcıyı ç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ı, sonlandırıcının ne zaman çağrıldısı üzerinde denetime sahip olmaz; atık toplayıcısı ne zaman çağırıca karar verir. Atık toplayıcı, uygulama tarafından artık kullanılmaan nesneleri denetler. Bir nesneyi sonlaştırma için uygun olarak kabul ederse, sonlandırıcıyı (varsa) çağırarak nesneyi depolamak için kullanılan belleği geri kazantır. çağrısıyla atık toplamayı zorlamak mümkündür, ancak çoğu zaman bu çağrıdan kaçınılmalıdır çünkü Collect performans sorunları oluşturabilir.

Not

Sonlandırıcıların uygulama sonlandırmanın bir parçası olarak çalıştırıp çalıştırılamalarının her bir .NET uygulamasına özgü olup olmadığı. Bir uygulama sonlandırılırsa, .NET Framework temizleme gizlenmedikçe (örneğin, kitaplık yöntemine bir çağrı tarafından) henüz atık toplamamış nesneler için sonlandırıcıları çağırmaya yardımcı olmak için her makul çabayı GC.SuppressFinalize gösterir. .NET 5 (.NET Core dahil) ve sonraki sürümler, uygulama sonlandırma kapsamında sonlandırıcıları çağırmaz. Daha fazla bilgi için bkz. GitHub/csharpstandard #291 .

Uygulama çıkışta temizleme işlemini güvenilir bir şekilde gerçekleştirmeniz gerekirse, olay için bir System.AppDomain.ProcessExit işleyiciyi kaydetmeniz gerekir. Bu işleyici, uygulama çıkışından önce temizleme gerektiren tüm nesneler IDisposable.Dispose() için çağrılması IAsyncDisposable.DisposeAsync() (veya ) sağlar. Doğrudan Finalize'ı çağıramayabilirsiniz ve çıkıştan önce atık toplayıcının tüm sonlandırıcıları çağırması garanti edilemez, kaynakların serbest bırakılana kadar veya Dispose DisposeAsync kullanmaları gerekir.

Kaynakları serbest bırakmak için sonlandırıcıları kullanma

Genel olarak, C# geliştiricinin parçasında atık toplama ile çalışma zamanlarını hedeflemeyen diller kadar bellek yönetimi gerektirmez. Bunun nedeni, .NET çöp toplayıcının nesneleriniz için bellek ayırmayı ve serbest bırakmayı örtülü olarak yönetmesidir. Ancak, uygulamanız windows, dosyalar ve ağ bağlantıları gibi unmanaged resources kapsüllemektedir, bu kaynakları serbest için sonlandırıcıları kullansanız gerekir. Nesne sonlaştırma için uygun olduğunda, atık toplayıcı Finalize nesnesinin yöntemini çalıştırır.

Kaynakların açık sürümü

Uygulamanız pahalı bir dış kaynak kullanıyorsa, atık toplayıcı nesneyi serbest bırakmadan önce kaynağı açıkça serbest bırakmak için bir yol sağlamanızı da öneririz. Kaynağı serbest bırakmak için, Dispose arabiriminden nesnesi IDisposable için gerekli temizlemeyi gerçekleştiren bir yöntem gerçekleştirin. Bu, uygulamanın performansını önemli ölçüde geliştirebilir. Kaynaklar üzerinde bu açık denetimle bile, yöntem çağrısı başarısız olursa sonlandırıcı kaynakları temizlemek için bir koruma Dispose haline gelir.

Kaynakları temizleme hakkında daha fazla bilgi için aşağıdaki makalelere bakın:

Örnek

Aşağıdaki örnek, devralma zinciri oluşturan üç sınıf oluşturur. sınıfı First temel sınıftır, Second sınıfından türetilen First ve Third sınıfından türetilen Second sınıftır. Üçünün de sonlandırıcıları vardır. içinde, Main en türetilmiş sınıfın bir örneği oluşturulur. Bu kodun çıkışı, uygulamanın hangi .NET uygulamasını hedeflemektedir:

  • .NET Framework: Çıkış, üç sınıf için sonlandırıcıların, uygulama sonlandırılırken en çok türetilmiş sınıftan en az türetilen sınıfa doğru otomatik olarak çağrıldılarını gösterir.
  • .NET 5 (.NET Core dahil) veya sonraki bir sürüm: Bu .NET uygulaması, uygulama sonlandırılan sonlandırıcıları çağırmaz.
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 belirtimlerinin Yıkıcılar bölümüne bakın.

Ayrıca bkz.