Dispose metodu uygulama

yönteminin Dispose uygulanması öncelikli olarak, unmanaged resources serbest bırakmaktır. Uygulama olan örnek üyeleriyle çalışırken IDisposable çağrıları basamaklama yaygındır Dispose . Örneğin, ayrılmış belleği Disposeserbest bırakmak, bir koleksiyona eklenmiş bir öğeyi kaldırmak veya alınan kilidin serbest bırakılmış olduğunu işaret etmek gibi, uygulamak için ek nedenler vardır.

.NET çöp toplayıcısı, yönetmemiş belleği ayırmaz veya serbest bırakmaz. Dispose deseni olarak adlandırılan bir nesneyi atma deseni, bir nesnenin yaşam süresine göre sırayı dayatır. Dispose deseni arabirimi IDisposable uygulayan nesneler için kullanılır ve dosya ve kanal tanıtıcıları, kayıt defteri tanıtıcıları, bekleme tanıtıcıları veya yönetici olmayan bellek bloklarının işaretçileri ile etkileşimde kullanılır. Bunun nedeni, atık toplayıcının kurtaramayan nesneleri geri alamadığıdır.

Kaynakların her zaman uygun şekilde temizlenmesine yardımcı olmak için, Dispose bir yöntemin bir özel durum olmadan birden çok kez çağrılması için bir kez etkili olması gerekir. Ayrıca, sonraki çağrılar hiçbir Dispose şey yapmamalı.

yöntemi için sağlanan kod GC.KeepAlive örneği, bir sonlandırıcının çalışmasına nasıl neden olabilir, ancak nesne veya üyeleri için yöneti olmayan bir başvuru hala kullanılırken, yöntemi için sağlanan kod örneği gösterir. Nesnenin, geçerli yordamın GC.KeepAlive başından bu yöntemin çağrıldı olduğu noktaya kadar çöp toplama için uygun olmayan bir yöntem kullanmak mantıklı olabilir.

İpucu

Bağımlılık eklemeyle ilgili olarak, hizmetleri bir 'ye IServiceCollectionkaydettirerek IServiceCollection için örtülü olarak yönetilir. ve IServiceProvider karşılık gelen IHost kaynak temizlemeyi düzenleme. Özellikle, ve uygulamaları IDisposableIAsyncDisposable belirtilen yaşam sürelerinin sonunda düzgün bir şekilde atıldı.

Daha fazla bilgi için bkz . .NET'te bağımlılık ekleme.

Kasa tanıtıcıları

Bir nesnenin sonlandırıcısı için kod yazmak, doğru yapılmaması durumunda sorunlara neden olabilecek karmaşık bir görevdir. Bu nedenle, bir sonlandırıcı uygulamak System.Runtime.InteropServices.SafeHandle yerine nesneleri oluşturmanizi öneririz.

, System.Runtime.InteropServices.SafeHandle yönetilemeyen bir kaynağı tanımlayan bir sarmalamalı System.IntPtr soyut bir yönetilen tür. Bu Windows Unix'te bir dosya tanımlayıcısı olan tanıtıcıyı tanımlayabilir. Bu kaynağın bir kez ve yalnızca bir kez serbest bırakılması, SafeHandleSafeHandleSafeHandle atılması veya tüm başvuruların bırakılması ve örneğin son hale getirildiklerinin sağlanması için gereken tüm mantığı sağlar.

soyut System.Runtime.InteropServices.SafeHandle bir temel sınıftır. Türetilmiş sınıflar, farklı tanıtıcı türleri için belirli örnekler sağlar. Bu türetilen sınıflar için hangi değerlerin geçersiz System.IntPtr olarak kabul edilir ve tanıtıcının nasıl serbest bırakılacağı doğrulanır. Örneğin, dosyasından, SafeFileHandleSafeHandleIntPtrs açık dosya tanıtıcılarını/SafeHandle.ReleaseHandle()tanımlayıcılarını tanıtan sarmak için türetilen ve kapatmak için yöntemini geçersiz kılar (closeUnix CloseHandle üzerinde işlev veya Windows). .NET SafeHandleSafeHandle kitaplıklarında, yönetimiz bir kaynak oluşturmanın çoğu API'ler bunu bir içinde sarmalar ve ham işaretçiyi geri teslim etmek yerine gerektiğinde size geri döner. Bir unmanaged IntPtr bileşeniyle etkileşime geçmeniz ve bir unmanaged kaynağı için bir elde edersiniz, sarmak için kendi SafeHandle tür oluşturabilirsiniz. Sonuç olarak, sonlandırıcılarıSafeHandle uygulamak için türlerin az olması gerekir; çoğu atılabilir desen uygulaması yalnızca diğer yönetilen kaynakları sarmalar ve bunların bazıları olabilir SafeHandle.

Ad alanı içinde aşağıdaki türetilmiş sınıflar Microsoft.Win32.SafeHandles güvenli tanıtıcılar sağlar:

Dispose() ve Dispose(bool)

ArabirimiIDisposable, tek bir parametresiz yöntemin uygulanmasını gerektirir. Dispose Ayrıca, korumalı olmayan tüm sınıflarda ek bir aşırı yükleme yöntemi Dispose(bool) olması gerekir.

Yöntem imzaları:

  • publicsanal olmayan (NotOverridable Visual Basic) (IDisposable.Dispose uygulama).
  • protected virtual(Overridable Visual Basic) Dispose(bool).

Dispose() yöntemi

public, sanal olmayan (NotOverridable Visual BasicDispose), parametresiz yöntem artık gerekli olmadığı zaman çağrılır (türünde bir tüketici tarafından), amacı yönetilmeyen kaynakları serbest, genel temizleme gerçekleştirmek ve varsa sonlandırıcının çalıştırmak zorunda olmadığını belirtmektir. Yönetilen bir nesneyle ilişkili gerçek belleği serbest bırakarak her zaman çöp toplayıcının etki alanı olur. Bu nedenle, standart bir uygulaması vardır:

public void Dispose()
{
    // Dispose of unmanaged resources.
    Dispose(true);
    // Suppress finalization.
    GC.SuppressFinalize(this);
}
Public Sub Dispose() _
    Implements IDisposable.Dispose
    ' Dispose of unmanaged resources.
    Dispose(True)
    ' Suppress finalization.
    GC.SuppressFinalize(Me)
End Sub

yöntemi Dispose tüm nesne temizleme işlemini gerçekleştirir, bu nedenle atık toplayıcının artık nesnelerin geçersiz kılmasını çağırma ihtiyacı Object.Finalize yoktur. Bu nedenle yöntemine yapılan çağrı SuppressFinalize , atık toplayıcının sonlandırıcıyı çalıştırmasını önler. Türün sonlandırıcısı yoksa çağrısının GC.SuppressFinalize hiçbir etkisi yoktur. Gerçek temizleme işleminin yöntem aşırı yüklemesi tarafından gerçekleştirilecek Dispose(bool) olduğunu unutmayın.

Dispose(bool) yöntemi aşırı yüklemesi

Aşırı yüklemede parametresi, disposing yöntem BooleanDispose çağrısının bir yöntemden mi (değeri ) yoksa sonlandırıcıdan mı ( truedeğeri) kaynak olduğunu belirten bir değeridir false.

protected virtual void Dispose(bool disposing)
{
    if (_disposed)
    {
        return;
    }

    if (disposing)
    {
        // TODO: dispose managed state (managed objects).
    }

    // TODO: free unmanaged resources (unmanaged objects) and override a finalizer below.
    // TODO: set large fields to null.

    _disposed = true;
}
Protected Overridable Sub Dispose(disposing As Boolean)
     If disposed Then Exit Sub	

     ' A block that frees unmanaged resources.
     
     If disposing Then
         ' Deterministic call…
         ' A conditional block that frees managed resources.    	
     End If
     
     disposed = True
End Sub

Önemli

parametresi disposing , sonlandırıcıdan false çağrıldıklarından ve yönteminden true çağrıldıklarından olmalıdır IDisposable.Dispose . Başka bir deyişle, belirlenimci true olarak çağrılır ve false belirlenimci olmayan bir şekilde çağrılır.

yönteminin gövdesi üç kod bloğu içerir:

  • Nesne zaten atıldı ise koşullu dönüş için bir blok.

  • Yönetilmeyen kaynakları serbest bırakan bir blok. Bu blok, parametresinin değerinden bağımsız olarak yürütülür disposing .

  • Yönetilen kaynakları serbest bırakan koşullu bir blok. Değeri ise bu blok yürütülür disposingtrue. Serbest bıraktığı yönetilen kaynaklar şunları içerebilir:

    • uygulayan yönetilen nesneler IDisposable. Koşullu blok, uygulamalarına çağrı yapmak için kullanılabilir Dispose (basamaklı dispose). Unmanaged kaynağınızı sarmak System.Runtime.InteropServices.SafeHandle için türetilmiş bir sınıfı kullandıysanız, burada uygulamasını çağırmanız SafeHandle.Dispose() gerekir.

    • Büyük miktarda bellek tüketen veya az kaynak tüketen yönetilen nesneler. Büyük yönetilen nesne başvurularını' atayarak null ulaşılma ihtimalini daha yüksek hale seçin. Bu, bunları belirleyici olmayan şekilde geri ödemeye göre daha hızlı serbest bıraktır.

Yöntem çağrısı sonlandırıcıdan geliyorsa, yalnızca yürütülemeyen kaynakları serbest bırakan kod yürütülülür. Uygulamacı, yanlış yolun atmış olabilir yönetilen nesnelerle etkileşim kurmay olmasını sağlamakla sorumludur. Sonlaştırma sırasında çöp toplayıcının yönetilen nesneleri atma sırası belirleyici değildir, çünkü bu önemlidir.

Basamaklı dispose çağrıları

Sınıfınız bir alana veya özele sahipse ve türü uygulayıyorsa IDisposable, içeren sınıfın da uygulaması gerekir IDisposable. Bir uygulama örneği olan ve bir IDisposable örnek üyesi olarak depolayarak bir sınıf da onun temizleme sorumludur. Bu, başvurulan atılabilir türlere yöntemi aracılığıyla belirleyici bir şekilde temizleme yapma fırsatı verildiğini sağlamaya yardımcı Dispose olmaktır. Bu örnekte, sınıfıdır (veya sealed Visual BasicNotInheritable).

using System;

public sealed class Foo : IDisposable
{
    private readonly IDisposable _bar;

    public Foo()
    {
        _bar = new Bar();
    }

    public void Dispose() => _bar.Dispose();
}
Public NotInheritable Class Foo
    Implements IDisposable

    Private ReadOnly _bar As IDisposable

    Public Sub New()
        _bar = New Bar()
    End Sub

    Public Sub Dispose() Implements IDisposable.Dispose
        _bar.Dispose()
    End Sub
End Class

İpucu

Bir sonlandırıcıda nulldenetim Dispose(false) gerçekleştirmek istemeniz (sonlandırıcı tarafından çağrılan yöntemi içerir), birincil nedenlerinden biri örneğin tam olarak başlatılmış olup olmadığından emin olmadığınız durumlardır (örneğin, oluşturucuda bir özel durum oluşabilir).

Dispose desenini uygulama

Tüm korumalı olmayan sınıflar (veya Visual Basic NotInheritabledeğiştirilmeyen sınıflar) devralınabilir, çünkü olası bir temel sınıf olarak değerlendirilmelidir. Olası bir temel sınıf için dispose desenini uygulayan aşağıdakiler sağlansa gerekir:

  • yöntemini Dispose çağıran bir Dispose(bool) uygulama.
  • Gerçek Dispose(bool) temizlemeyi gerçekleştiren bir yöntem.
  • Bundan türetilen bir SafeHandle sınıf, yönetimiz kaynağınızı sarmalar (önerilir) veya yöntemine geçersiz kılma Object.Finalize . sınıfı SafeHandle bir sonlandırıcı sağlar, bu nedenle kendiniz yazmanız gerek değildir.

Önemli

Bir temel sınıfın yalnızca yönetilen nesnelere başvurarak dispose desenini uygulaması mümkündür. Bu durumlarda sonlandırıcı gerekli değildir. Sonlandırıcı yalnızca doğrudan unmanaged kaynaklara başvurursanız gereklidir.

Güvenli tanıtıcı kullanan bir temel sınıf için dispose desenini uygulamak için genel bir desen örneği burada vesildir.

using Microsoft.Win32.SafeHandles;
using System;
using System.Runtime.InteropServices;

class BaseClassWithSafeHandle : IDisposable
{
    // To detect redundant calls
    private bool _disposedValue;

    // Instantiate a SafeHandle instance.
    private SafeHandle _safeHandle = new SafeFileHandle(IntPtr.Zero, true);

    // Public implementation of Dispose pattern callable by consumers.
    public void Dispose() => Dispose(true);

    // Protected implementation of Dispose pattern.
    protected virtual void Dispose(bool disposing)
    {
        if (!_disposedValue)
        {
            if (disposing)
            {
                _safeHandle.Dispose();
            }

            _disposedValue = true;
        }
    }
}
Imports Microsoft.Win32.SafeHandles
Imports System.Runtime.InteropServices

Class BaseClassWithSafeHandle : Implements IDisposable
    ' Flag: Has Dispose already been called?
    Dim disposed As Boolean = False
    ' Instantiate a SafeHandle instance.
    Dim handle As SafeHandle = New SafeFileHandle(IntPtr.Zero, True)

    ' Public implementation of Dispose pattern callable by consumers.
    Public Sub Dispose() _
               Implements IDisposable.Dispose
        Dispose(True)
        GC.SuppressFinalize(Me)
    End Sub

    ' Protected implementation of Dispose pattern.
    Protected Overridable Sub Dispose(disposing As Boolean)
        If disposed Then Return

        If disposing Then
            handle.Dispose()
        End If

        disposed = True
    End Sub
End Class

Not

Önceki örnekte deseni göstermek için SafeFileHandle bir nesnesi kullanılmıştır; bunun yerine nesnesinden türetilen SafeHandle herhangi bir nesne kullanılabilir. Örneğin nesnesinin düzgün bir şekilde örneğini oluşturmaz SafeFileHandle .

burada, geçersiz kılmaya neden olan temel bir sınıf için dispose deseninin uygulanmasına genel bir desen ve bir ve sonra ve sonra ve son ve son olarak ve daha fazla örnek ve daha fazla bilgi ve daha fazla bilgi ve zaman ve daha fazla bilgi ve daha fazla bilgi ve zaman ve daha fazla bilgi ve daha fazla bilgi Object.Finalize

using System;

class BaseClassWithFinalizer : IDisposable
{
    // To detect redundant calls
    private bool _disposedValue;

    ~BaseClassWithFinalizer() => Dispose(false);

    // Public implementation of Dispose pattern callable by consumers.
    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    // Protected implementation of Dispose pattern.
    protected virtual void Dispose(bool disposing)
    {
        if (!_disposedValue)
        {
            if (disposing)
            {
                // TODO: dispose managed state (managed objects)
            }

            // TODO: free unmanaged resources (unmanaged objects) and override finalizer
            // TODO: set large fields to null
            _disposedValue = true;
        }
    }
}
Class BaseClassWithFinalizer : Implements IDisposable
    ' Flag: Has Dispose already been called?
    Dim disposed As Boolean = False

    ' Public implementation of Dispose pattern callable by consumers.
    Public Sub Dispose() _
               Implements IDisposable.Dispose
        Dispose(True)
        GC.SuppressFinalize(Me)
    End Sub

    ' Protected implementation of Dispose pattern.
    Protected Overridable Sub Dispose(disposing As Boolean)
        If disposed Then Return

        If disposing Then
            ' Dispose managed objects that implement IDisposable.
            ' Assign null to managed objects that consume large amounts of memory or consume scarce resources.
        End If

        ' Free any unmanaged objects here.
        '
        disposed = True
    End Sub

    Protected Overrides Sub Finalize()
        Dispose(False)
    End Sub
End Class

İpucu

C# içinde, geçersiz karak değil bir sonlandırıcı sağlayarak bir sonlandırıcı uygulayın . Bu Visual Basic ile bir sonlandırıcı oluşturunProtected Overrides Sub Finalize().

Türetilen bir sınıf için dispose desenini uygulama

Temel sınıf uygulaması IDisposable.Dispose türetilmiş sınıfları tarafından devralındığından, arabirimini uygulayan IDisposable bir sınıftan türetilmiş bir sınıf uygulanmamalıdır IDisposable . Bunun yerine, türetilmiş bir sınıfı temizlemek için aşağıdakileri sağlarsınız:

  • Temel sınıf yöntemini geçersiz kılan ve türetilmiş sınıfın gerçek temizleme işlemini gerçekleştiren bir protected override void Dispose(bool) Yöntem. bu yöntem ayrıca, base.Dispose(bool) bir bağımsız değişken olarak disposing durumu ( bool disposing parametre) geçirerek ( MyBase.Dispose(bool) Visual Basic olarak) metodunu çağırmalıdır.
  • Öğesinden SafeHandle türetilen bir sınıf, Yönetilmeyen kaynağınızı sarmalanmış (önerilir) veya yöntemine bir geçersiz kılma Object.Finalize . SafeHandleSınıfı, sizi kod içine almak zorunda kalmanızı sağlayan bir Sonlandırıcı sağlar. Bir Sonlandırıcı sağlarsanız, bağımsız değişkenle aşırı yüklemeyi false çağırmalıdır Dispose(bool) .

Aşağıda, bir güvenli tanıtıcı kullanan türetilmiş bir sınıf için Dispose deseninin uygulanması için genel bir düzenin örneği verilmiştir:

using Microsoft.Win32.SafeHandles;
using System;
using System.Runtime.InteropServices;

class DerivedClassWithSafeHandle : BaseClassWithSafeHandle
{
    // To detect redundant calls
    private bool _disposedValue;

    // Instantiate a SafeHandle instance.
    private SafeHandle _safeHandle = new SafeFileHandle(IntPtr.Zero, true);

    // Protected implementation of Dispose pattern.
    protected override void Dispose(bool disposing)
    {
        if (!_disposedValue)
        {
            if (disposing)
            {
                _safeHandle.Dispose();
            }

            _disposedValue = true;
        }

        // Call base class implementation.
        base.Dispose(disposing);
    }
}
Imports Microsoft.Win32.SafeHandles
Imports System.Runtime.InteropServices

Class DerivedClassWithSafeHandle : Inherits BaseClassWithSafeHandle
    ' Flag: Has Dispose already been called?
    Dim disposed As Boolean = False
    ' Instantiate a SafeHandle instance.
    Dim handle As SafeHandle = New SafeFileHandle(IntPtr.Zero, True)

    ' Protected implementation of Dispose pattern.
    Protected Overrides Sub Dispose(disposing As Boolean)
        If disposed Then Return

        If disposing Then
            handle.Dispose()
            ' Free any other managed objects here.
            '
        End If

        ' Free any unmanaged objects here.
        '
        disposed = True

        ' Call base class implementation.
        MyBase.Dispose(disposing)
    End Sub
End Class

Not

Önceki örnek, bir nesneyi göstermek için bir SafeFileHandle nesnesi kullanır; bunun yerine ondan türetilmiş SafeHandle herhangi bir nesne kullanılabilir. Örneğin nesnesinin düzgün şekilde örneklemez SafeFileHandle olduğunu unutmayın.

Geçersiz kılan Object.Finalize türetilmiş bir sınıf için Dispose deseninin uygulanması için genel bir model aşağıda verilmiştir:

class DerivedClassWithFinalizer : BaseClassWithFinalizer
{
    // To detect redundant calls
    private bool _disposedValue;

    ~DerivedClassWithFinalizer() => this.Dispose(false);

    // Protected implementation of Dispose pattern.
    protected override void Dispose(bool disposing)
    {
        if (!_disposedValue)
        {
            if (disposing)
            {
                // TODO: dispose managed state (managed objects).
            }

            // TODO: free unmanaged resources (unmanaged objects) and override a finalizer below.
            // TODO: set large fields to null.
            _disposedValue = true;
        }

        // Call the base class implementation.
        base.Dispose(disposing);
    }
}
Class DerivedClassWithFinalizer : Inherits BaseClassWithFinalizer
    ' Flag: Has Dispose already been called?
    Dim disposed As Boolean = False

    ' Protected implementation of Dispose pattern.
    Protected Overrides Sub Dispose(disposing As Boolean)
        If disposed Then Return

        If disposing Then
            ' Dispose managed objects that implement IDisposable.
            ' Assign null to managed objects that consume large amounts of memory or consume scarce resources.
        End If

        ' Free any unmanaged objects here.
        '
        disposed = True

        ' Call the base class implementation.
        MyBase.Dispose(disposing)
    End Sub

    Protected Overrides Sub Finalize()
        Dispose(False)
    End Sub
End Class

Ayrıca bkz.