C # 'da bir sınıftaki bir yıkıcı ile Finalize yöntemi arasındaki fark nedir?


98

Bir sınıftaki bir yıkıcı ile Finalize yöntemi arasında varsa, fark nedir?

Geçenlerde Visual Studio 2008'in Finalize yöntemiyle eşanlamlı bir yıkıcı olarak gördüğünü keşfettim, bu da Visual Studio'nun bir sınıfta her iki yöntemi de aynı anda tanımlamanıza izin vermeyeceği anlamına geliyor.

Örneğin, aşağıdaki kod parçası:

class TestFinalize
{
    ~TestFinalize()
    {
        Finalize();
    }

    public bool Finalize()
    {
        return true;
    }
}

Yıkıcıda Finalize çağrısında şu hatayı verir:

Çağrı, aşağıdaki yöntemler veya özellikler arasında belirsizdir: 'TestFinalize. ~ TestFinalize ()' ve 'TestFinalize.Finalize ()'

Ve Finalize çağrısı yorumlanırsa, aşağıdaki hatayı verir:

'ManagementConcepts.Service.TestFinalize' yazın, aynı parametre türlerine sahip 'Finalize' adlı bir üyeyi zaten tanımlıyor

Yanıtlar:


68

C #'daki bir yıkıcı System.Object.Finalizeyöntemi geçersiz kılar . Bunu yapmak için yıkıcı sözdizimini kullanmanız gerekir. Manuel olarak geçersiz kılma Finalizesize bir hata mesajı verecektir.

Temel olarak, Finalizeyöntem bildiriminizle yapmaya çalıştığınız şey , temel sınıfın yöntemini gizlemektir . Derleyicinin, newdeğiştirici kullanılarak susturulabilecek bir uyarı vermesine neden olur (eğer çalışacaksa). Burada dikkat edilmesi gereken önemli şey olduğunu sen olamaz hem overridebir beyan newBir yıkıcı ve hem sahip böylece aynı anda aynı adla üye Finalizebir hata ile sonuçlanır yöntemi (ama olabilir , tavsiye edilmez ancak bir beyan public new void Finalize()yöntemi ise bir yıkıcı ilan etmiyorsunuz).


71

Wikipedia, sonlandırıcı makalesinde bir sonlandırıcı ile yıkıcı arasındaki fark hakkında bazı iyi tartışmalara sahiptir .

C # gerçekten "gerçek" bir yıkıcıya sahip değil. Sözdizimi bir C ++ yıkıcısına benzer, ancak gerçekten bir sonlandırıcıdır. Örneğinizin ilk bölümünde bunu doğru yazdınız:

~ClassName() { }

Yukarıdakiler, bir Finalizeişlev için sözdizimsel şekerdir . Tabandaki sonlandırıcıların çalışmasının garantili olmasını sağlar, ancak aksi takdirde Finalizeişlevi geçersiz kılmakla aynıdır . Bu, yıkıcı sözdizimini yazdığınızda, gerçekten sonlandırıcıyı yazdığınız anlamına gelir.

Microsoft'a göre , sonlandırıcı, çöp toplayıcının topladığında ( Finalize) çağırdığı işleve atıfta bulunurken, yıkıcı sonuç olarak çalışan kod parçanızdır (oluşan sözdizimsel şeker Finalize). Aynı şey olmaya o kadar yakınlar ki, Microsoft hiçbir zaman ayrım yapmamalıydı.

Microsoft'un C ++ 'ın "yıkıcı" terimini kullanması yanıltıcıdır, çünkü C ++' da nesne silindiğinde veya yığından çıkar çıkmaz aynı iş parçacığı üzerinde yürütülürken, C # 'da başka bir zamanda ayrı bir iş parçacığı üzerinde yürütülür.


Yıkıcı ve sonlandırıcı arasında böylesi bir ayrımın yapılması gereken önemli bir ayrım olduğunu iddia ediyorum. Ancak, yalnızca kaputun altında neler olup bittiğini umursayanlar söz konusu ayrımla ilgilenirdi.
Kyle Baran

1
Ayrıca, ECMA-334'ün uzun zaman önce resmi olarak "yıkıcı" ve "sonlandırıcı" nın açıkça belirsizliğini ortadan kaldırdığını unutmayın. MS neden hala yanıltıcı şartlarda ısrar ediyor bilmiyorum.
FrankHB

En azından Mono ile çalışmaktan, C # aslında C ++ 'dan sonra modellenmiştir ve çoğu yerel C # nesnesi C ++ nesneleridir. Mono'yu derleyen derleyicinin çalışma biçimi, bu C ++ nesnelerinin nasıl yok edileceğini ve benzer şekilde, C # nesnesi sonlandırmanın C ++ 'ya nasıl yayıldığını ve bu yıkıcıları çağırdığını belirler. Ayrım, başlık altında mantıklı, ancak yine de C # için gerçekten geçerli değil.
Kenzi

20

Burada bulundu: http://sanjaysainitech.blogspot.com/2007/06/difference-between-destructor-dispose.html

  1. Yıkıcı

    Nesne için temizleme kodunu içeren özel yöntemlerdir. GC tarafından örtük olarak çağrıldıkları için bunları kodunuzda açıkça arayamazsınız. C # 'da, önündeki ~işaret ile sınıf adıyla aynı ada sahiptirler . Sevmek-

    Class MyClass
    {
    
    ~MyClass()
    {
    .....
    }
    }
    

    VB.NET'te yıkıcılar, System.Object sınıfının Finalize yöntemi geçersiz kılınarak gerçekleştirilir.

  2. Elden çıkarmak

    Bunlar, sınıftaki diğer yöntemler gibidir ve açıkça çağrılabilir, ancak nesneyi temizlemek için özel bir amaçları vardır. Dispose yönteminde nesne için temizleme kodu yazıyoruz. Dispose yöntemindeki veritabanı bağlantısı, dosyalar vb. Gibi tüm yönetilmeyen kaynakları serbest bırakmamız önemlidir. Dispose yöntemini uygulayan sınıf, IDisposable arabirimi uygulamalıdır. Dispose yöntemi, attığı nesne için GC.SuppressFinalize yöntemini çağırmalıdır. sınıfı, nesneyi temizlemek için zaten çalıştığı için desturctor'a sahiptir, bu durumda çöp toplayıcının nesnenin Finalize yöntemini çağırmasına gerek yoktur. Referans: http://msdn2.microsoft.com/en-us/library/aa720161(VS.71).aspx

  3. Sonuçlandırmak

    Bir Finalize yöntemi, Dispose yönteminizin çağrılmaması durumunda kaynakları temizlemek için bir koruma görevi görür. Yönetilmeyen kaynakları temizlemek için yalnızca bir Finalize yöntemi uygulamanız gerekir. Çöp toplayıcı yönetilen kaynakları otomatik olarak temizlediğinden, yönetilen nesneler için Finalize yöntemi uygulamamalısınız. Finalize yöntemi GC tarafından dolaylı olarak çağrılır, bu nedenle onu kodunuzdan çağıramazsınız.

    Not: C # 'da Finalize yöntemi geçersiz kılınamaz, bu nedenle dahili uygulaması MSIL'deki Finalize yöntemini geçersiz kılacak bir yıkıcı kullanmanız gerekir ancak VB.NET'te Finalize yöntemi, yıkıcı yöntemini desteklediği için geçersiz kılınabilir.

Güncelleme: Burada yarı ilgili ilginç konu .


1
You should only implement a Finalize method to clean up unmanaged resources: Sonlandır'a koyarsınız. Dispose ile aynı mı?
hqt

@hqt: Bir Disposekişinin sonlandırıcı uygulaması gerekenlerden çok daha fazla uygulanması gereken durumlar. Uygulamak Disposedoğrudan yönetilmeyen bir kaynağın sahibi veya doğrudan doğrudan kendi için son şey kendi sınıf veya türetilmiş sınıfının bir örneği ya doğrudan yönetilmeyen bir kaynağın sahibi veya doğrudan son şey kendi son şey olacağını olasılığı ise vb. Yalnızca Finalizebir kişinin <i> doğrudan </i> sınıfı yönetilmeyen bir kaynağa <i> sahipse ve başka hiçbir şeye sahip değilse </i> - çok daha dar bir senaryo - kaynak temizleme için uygulayın .
supercat

@hqt: Bir sınıf doğrudan yönetilmeyen kaynaklara sahip olacaksa ve diğer nesnelere referanslar da tutuyorsa, yönetilmeyen kaynaklar genellikle kendi sonlandırılabilir sınıflarına bölünmelidir (ideal olarak başka hiçbir şeye güçlü referanslar içermemelidir), yani sınıf Diğer nesnelere atıfta bulunanlar, kaynaklara sahip olmak yerine yalnızca "yönetilmeyen kaynaklara doğrudan sahip olan şeylere" sahip olur ve bu nedenle bir sonlandırıcıya ihtiyaç duymaz.
supercat
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.