Sdílet prostřednictvím


Implementujte metodu Dispose

Metoda Dispose je primárně implementována pro uvolnění nespravovaných prostředků. Při práci s členy instance, které jsou implementace IDisposable, je běžné kaskádové volání Dispose. Existují další důvody pro implementaci Dispose, například uvolnění paměti, která byla přidělena, odebrání položky přidané do kolekce nebo signál uvolnění zámku, který byl získán.

Systém .NET garbage collector nepřiděluje ani neuvolňuje nespravovanou paměť. Vzor pro likvidaci objektu, označovaný jako dispose vzor, zajišťuje řízení doby života objektu. Vzor Dispose se používá pro objekty, které implementují rozhraní IDisposable. Tento vzor je běžný při interakci s popisovači souborů a rour, popisovači registru, popisovači čekání nebo ukazateli na bloky nespravované paměti, protože ten správce paměti nemůže uvolnit nespravované objekty.

Aby bylo možné zajistit, aby prostředky byly vždy správně vyčištěny, měla by být metoda Dispose idempotentní, aby byla volána vícekrát bez vyvolání výjimky. Další vyvolání Dispose by navíc nemělo dělat nic.

Příklad kódu zadaný pro metodu GC.KeepAlive ukazuje, jak proces uvolňování paměti může způsobit, že se finalizátor může spustit, i když nespravovaný odkaz na objekt nebo jeho členy je stále používán. Je vhodné využít GC.KeepAlive, aby byl objekt nezpůsobilý pro garbage collection od začátku aktuální rutiny do bodu, kde je tato metoda volána.

Spropitné

Pokud jde o injektování závislostí, při registraci služeb v IServiceCollectionse doba života služby implicitně spravuje vaším jménem. IServiceProvider a odpovídající IHost orchestrují čištění prostředků. Konkrétně jsou implementace IDisposable a IAsyncDisposable správně odstraněny na konci své stanovené životnosti.

Další informace naleznete v tématu Injektování závislostí v .NET.

Kaskádová volání dispose

Pokud vaše třída vlastní instanci jiného typu, který implementuje IDisposable, obsahující třída by měla také implementovat IDisposable. Obvykle třída, která vytvoří instanci IDisposable implementace a uloží ji jako člena instance (nebo vlastnost), je také zodpovědná za vyčištění. To pomáhá zajistit, aby odkazované uvolnitelné typy měly možnost předvídatelně provést vyčištění pomocí metody Dispose. V následujícím příkladu je třída sealed (nebo NotInheritable v jazyce Visual Basic).

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

Spropitné

  • Pokud má vaše třída IDisposable pole nebo vlastnost, ale ji nevlastní, třída nemusí implementovat IDisposable. Obvykle se třídou, která vytváří a ukládá podřízený objekt IDisposable, stává i jeho vlastníkem, ale v některých případech lze vlastnictví převést na jiný typ IDisposable.
  • Existují případy, kdy můžete chtít provést null-kontrolu ve finalizátoru (která zahrnuje metodu Dispose(false), kterou spustí finalizátor). Jedním z hlavních důvodů je, že si nejste jistí, jestli se instance plně inicializovala (například výjimka může být vyvolána v konstruktoru).

Dispose() a Dispose(bool)

Rozhraní IDisposable vyžaduje implementaci jedné metody bez parametrů Dispose. Všechny nezapečetěné třídy by také měly mít přetíženou metodu Dispose(bool).

Podpisy metod jsou:

  • public nevirtuální (NotOverridable v jazyce Visual Basic) (IDisposable.Dispose implementace).
  • protected virtual (Overridable v jazyce Visual Basic) Dispose(bool).

Metoda Dispose()

Vzhledem k tomu, že metoda Dispose, která je bez parametrů a non-virtual (NotOverridable v jazyce Visual Basic), je volána, když už není potřeba (příjemcem typu), je jejím účelem uvolnit nespravované prostředky, provést obecné vyčištění a indikovat, že finalizátor, pokud existuje, nemusí být spuštěn. Uvolnění skutečné paměti přidružené ke spravovanému objektu je vždy úlohou garbage collectoru. Z tohoto důvodu má standardní implementaci:

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

Metoda Dispose provede veškeré vyčištění objektů, takže garbage collector už nemusí volat přepsání objektů pomocí Object.Finalize. Proto volání metody SuppressFinalize zabraňuje garbage collectoru ve spuštění finalizátoru. Pokud typ nemá žádný finalizátor, volání GC.SuppressFinalize nemá žádný vliv. Skutečné vyčištění provádí přetěžování dané metody Dispose(bool).

Přetížení metody Dispose(bool)

V přetížení označuje parametr disposing typu Boolean, zda volání metody pochází z metody Dispose (její hodnota je true) nebo z ukončovací metody (její hodnota je false).

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

    if (disposing)
    {
        // Dispose managed state (managed objects).
        // ...
    }

    // Free unmanaged resources.
    // ...

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

     If disposing Then

         ' Free managed resources.
         ' ...

     End If

     ' Free unmanaged resources.
     ' ...

     disposed = True
End Sub

Důležitý

Parametr disposing by měl být při zavolání z finalizátoru false a při zavolání z metody trueIDisposable.Dispose. Jinými slovy, je to true, pokud je volán deterministicky, a false, pokud je volán nedeterministicky.

Tělo metody se skládá ze tří bloků kódu:

  • Blok pro podmíněné vrácení, pokud je objekt již zlikvidován.

  • Podmíněný blok, který uvolní spravované prostředky. Tento blok se spustí, pokud je hodnota disposingtrue. Mezi spravované prostředky, které uvolní, patří:

    • Spravované objekty, které implementují IDisposable. Podmíněný blok lze použít k volání implementace Dispose (kaskádová dispose). Pokud jste k zabalení nespravovaného prostředku použili odvozenou třídu System.Runtime.InteropServices.SafeHandle, měli byste zde zavolat metodu SafeHandle.Dispose().
    • Spravované objekty, které spotřebovávají velké množství paměti nebo využívají málo prostředků. Přiřaďte velké spravované objektové odkazy na null, aby byly s větší pravděpodobností nedostupnější. Tím se uvolní rychleji, než kdyby byly uvolněny nedeterministicky.
  • Blok, který uvolní nespravované prostředky. Tento blok se spustí bez ohledu na hodnotu parametru disposing.

Pokud volání metody pochází z finalizátoru, měl by se spustit pouze kód, který uvolní nespravované prostředky. Implementátor je odpovědný za to, aby falešná cesta neinteragovala se spravovanými objekty, které mohly být ukončeny. To je důležité, protože pořadí, ve kterém garbage collector zpracovává spravované objekty během finalizace, je nedeterministické.

Implementace vzoru Dispose

Všechny nezapečetěné třídy (nebo třídy jazyka Visual Basic, které nejsou upraveny jako NotInheritable), by se měly považovat za potenciální základní třídu, protože by mohly být zděděné. Pokud implementujete vzor Dispose pro libovolnou potenciální základní třídu, musíte do své třídy přidat následující metody:

  • Implementace Dispose, která volá metodu Dispose(bool).
  • Metoda Dispose(bool), která provádí skutečné vyčištění.
  • Pokud se vaše třída zabývá nespravovanými prostředky, buď přepište metodu Object.Finalize, nebo zabalte nespravovaný prostředek pod třídu SafeHandle.

Důležitý

Finalizátor (přepsání Object.Finalize) se vyžaduje pouze v případě, že přímo odkazujete na nespravované prostředky. Jedná se o vysoce pokročilý scénář, kterému se obvykle můžete vyhnout:

  • Pokud vaše třída odkazuje pouze na spravované objekty, je stále možné, aby třída implementuje vzor Dispose. Není nutné implementovat finalizér.
  • Pokud potřebujete řešit nespravované prostředky, důrazně doporučujeme zabalit nespravovaný IntPtr popisovač do SafeHandle. SafeHandle poskytuje finalizátor, takže si ho nemusíte psát sami. Další informace najdete v odstavci Bezpečné popisovače.

Základní třída se spravovanými prostředky

Tady je obecný příklad implementace modelu Dispose pro základní třídu, která vlastní pouze spravované prostředky.

using System;
using System.IO;

public class DisposableBase : IDisposable
{
    // Detect redundant Dispose() calls.
    private bool _isDisposed;

    // Instantiate a disposable object owned by this class.
    private Stream? _managedResource = new MemoryStream();

    // 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 (!_isDisposed)
        {
            _isDisposed = true;

            if (disposing)
            {
                // Dispose managed state.
                _managedResource?.Dispose();
                _managedResource = null;
            }
        }
    }
}
Imports System.IO

Public Class DisposableBase
    Implements IDisposable

    ' Detect redundant Dispose() calls.
    Private _isDisposed As Boolean

    ' Instantiate a disposable object owned by this class.
    Private _managedResource As Stream = New MemoryStream()

    ' 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 Not _isDisposed Then
            _isDisposed = True

            If disposing Then
                ' Dispose managed state.
                _managedResource?.Dispose()
                _managedResource = Nothing
            End If
        End If
    End Sub
End Class

Poznámka

Předchozí příklad používá fiktivní objektMemoryStream k ilustraci vzoru. Místo toho lze použít jakýkoli IDisposable.

Základní třída s nespravovanými prostředky

Tady je příklad implementace vzoru Dispose pro základní třídu, která přepíše Object.Finalize, aby se vyčistily nespravované prostředky, které vlastní. Příklad také ukazuje způsob, jak implementovat Dispose(bool) bezpečným způsobem. Synchronizace může být důležitá při práci s nespravovanými prostředky v aplikaci s více vlákny. Jak už bylo zmíněno dříve, jedná se o pokročilý scénář.

using System;
using System.IO;
using System.Runtime.InteropServices;
using System.Threading;

public class DisposableBaseWithFinalizer : IDisposable
{
    // Detect redundant Dispose() calls in a thread-safe manner.
    // _isDisposed == 0 means Dispose(bool) has not been called yet.
    // _isDisposed == 1 means Dispose(bool) has been already called.
    private int _isDisposed;

    // Instantiate a disposable object owned by this class.
    private Stream? _managedResource = new MemoryStream();

    // A pointer to 10 bytes allocated on the unmanaged heap.
    private IntPtr _unmanagedResource = Marshal.AllocHGlobal(10);

    ~DisposableBaseWithFinalizer() => 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)
    {
        // In case _isDisposed is 0, atomically set it to 1.
        // Enter the branch only if the original value is 0.
        if (Interlocked.CompareExchange(ref _isDisposed, 1, 0) == 0)
        {
            if (disposing)
            {
                _managedResource?.Dispose();
                _managedResource = null;
            }

            Marshal.FreeHGlobal(_unmanagedResource);
        }
    }
}
Imports System
Imports System.IO
Imports System.Runtime.InteropServices
Imports System.Threading

Public Class DisposableBaseWithFinalizer
    Implements IDisposable

    ' Detect redundant Dispose() calls in a thread-safe manner.
    ' _isDisposed == 0 means Dispose(bool) has not been called yet.
    ' _isDisposed == 1 means Dispose(bool) has been already called.
    Private _isDisposed As Integer

    ' Instantiate a disposable object owned by this class.
    Private _managedResource As Stream = New MemoryStream()

    ' A pointer to 10 bytes allocated on the unmanaged heap.
    Private _unmanagedResource As IntPtr = Marshal.AllocHGlobal(10)

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

    ' 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)
        ' In case _isDisposed is 0, atomically set it to 1.
        ' Enter the branch only if the original value is 0.
        If Interlocked.CompareExchange(_isDisposed, 1, 0) = 0 Then
            If disposing Then
                _managedResource?.Dispose()
                _managedResource = Nothing
            End If

            Marshal.FreeHGlobal(_unmanagedResource)
        End If
    End Sub
End Class

Poznámka

Spropitné

V jazyce C# implementujete finalizaci tak, že poskytnete finalizační konstruktor , nikoli přepsáním Object.Finalize. V jazyce Visual Basic vytvoříte finalizér s Protected Overrides Sub Finalize().

Implementace vzoru Dispose Pattern pro odvozenou třídu

Třída odvozená z třídy, která implementuje IDisposable rozhraní by neměla implementovat IDisposable, protože základní třída implementace IDisposable.Dispose je zděděna jeho odvozenými třídami. Pokud chcete vyčistit odvozenou třídu, zadejte následující:

  • protected override void Dispose(bool) metoda, která přepíše metodu základní třídy a provádí skutečné vyčištění odvozené třídy. Tato metoda musí také volat metodu base.Dispose(bool) (MyBase.Dispose(bool) v jazyce Visual Basic) a předat jí stav vystavení (bool disposing parametr) jako argument.
  • Buď třída odvozená z SafeHandle, která obalí váš nespravovaný prostředek (doporučeno), nebo přepsání metody Object.Finalize. Třída SafeHandle poskytuje finalizér, který vás zbaví nutnosti jej programovat. Pokud zadáte finalizátor, musí volat přetíženou funkci Dispose(bool) s argumentem false.

Tady je příklad běžného schématu pro implementaci vzoru Dispose pro odvozenou třídu, která používá bezpečnou rukojeť.

using System.IO;

public class DisposableDerived : DisposableBase
{
    // To detect redundant calls
    private bool _isDisposed;

    // Instantiate a disposable object owned by this class.
    private Stream? _managedResource = new MemoryStream();

    // Protected implementation of Dispose pattern.
    protected override void Dispose(bool disposing)
    {
        if (!_isDisposed)
        {
            _isDisposed = true;

            if (disposing)
            {
                _managedResource?.Dispose();
                _managedResource = null;
            }
        }

        // Call base class implementation.
        base.Dispose(disposing);
    }
}
Imports System.IO

Public Class DisposableDerived
    Inherits DisposableBase

    ' To detect redundant calls
    Private _isDisposed As Boolean

    ' Instantiate a disposable object owned by this class.
    Private _managedResource As Stream = New MemoryStream()

    ' Protected implementation of Dispose pattern.
    Protected Overrides Sub Dispose(disposing As Boolean)
        If Not _isDisposed Then
            _isDisposed = True

            If disposing Then
                _managedResource?.Dispose()
                _managedResource = Nothing
            End If
        End If

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

Poznámka

Předchozí příklad používá objekt SafeFileHandle k ilustraci vzoru; místo toho lze použít jakýkoli objekt odvozený z SafeHandle. Všimněte si, že se v příkladu nesprávně vytváří instance objektu SafeFileHandle.

Tady je obecný vzor pro implementaci vzoru Dispose pro odvozenou třídu, která přepisuje Object.Finalize:

using System.Threading;

public class DisposableDerivedWithFinalizer : DisposableBaseWithFinalizer
{
    // Detect redundant Dispose() calls in a thread-safe manner.
    // _isDisposed == 0 means Dispose(bool) has not been called yet.
    // _isDisposed == 1 means Dispose(bool) has been already called.
    private int _isDisposed;

    ~DisposableDerivedWithFinalizer() => Dispose(false);

    // Protected implementation of Dispose pattern.
    protected override void Dispose(bool disposing)
    {
        // In case _isDisposed is 0, atomically set it to 1.
        // Enter the branch only if the original value is 0.
        if (Interlocked.CompareExchange(ref _isDisposed, 1, 0) == 0)
        {
            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.
        }

        // Call the base class implementation.
        base.Dispose(disposing);
    }
}
Imports System.Threading

Public Class DisposableDerivedWithFinalizer
    Inherits DisposableBaseWithFinalizer

    ' Detect redundant Dispose() calls in a thread-safe manner.
    ' _isDisposed == 0 means Dispose(bool) has not been called yet.
    ' _isDisposed == 1 means Dispose(bool) has been already called.
    Private _isDisposed As Integer

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

    ' Protected implementation of Dispose pattern.
    Protected Overrides Sub Dispose(disposing As Boolean)
        ' In case _isDisposed is 0, atomically set it to 1.
        ' Enter the branch only if the original value is 0.
        If Interlocked.CompareExchange(_isDisposed, 1, 0) = 0 Then
            If disposing Then
                ' TODO: dispose managed state (managed objects).
            End If

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

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

Bezpečné úchyty

Psaní kódu pro finalizátor objektu je složitá úloha, která může způsobit problémy, pokud nejsou provedeny správně. Proto doporučujeme vytvořit System.Runtime.InteropServices.SafeHandle objekty místo implementace finalizátoru.

System.Runtime.InteropServices.SafeHandle je abstraktní spravovaný typ, který obaluje System.IntPtr identifikující nespravovaný prostředek. Ve Windows může jít o identifikaci popisovače a na Unixu o deskriptor souboru. SafeHandle poskytuje veškerou logiku potřebnou k tomu, aby byl tento prostředek uvolněn jednou a pouze jednou, a to buď při odstranění SafeHandle, nebo při vyřazení všech odkazů na SafeHandle a dokončení instance SafeHandle.

System.Runtime.InteropServices.SafeHandle je abstraktní základní třída. Odvozené třídy poskytují konkrétní instance pro různé typy popisovačů. Tyto odvozené třídy ověřují, které hodnoty pro System.IntPtr jsou považovány za neplatné a jak přesně uvolnit popisovač. Například SafeFileHandle je odvozen od SafeHandle k zabalení IntPtrs, které identifikují otevřené držitele souborů a popisovače, a přepíše svou SafeHandle.ReleaseHandle() metodu k jejich zavření (prostřednictvím funkce close na Unixu nebo funkce CloseHandle ve Windows). Většina rozhraní API v knihovnách .NET, které vytvářejí nespravovaný prostředek, zabalí ho do SafeHandle a vrátí SafeHandle podle potřeby, místo předávání surového ukazatele zpět. V situacích, kdy pracujete s nespravovanou komponentou a získáte IntPtr pro nespravovaný prostředek, můžete vytvořit vlastní typ SafeHandle k jeho obalení. V důsledku toho potřebuje jen málo typů, které nejsouSafeHandle, implementovat finalizátory. Většina implementací jednorázových vzorů končí pouze zabalením jiných spravovaných prostředků, z nichž některé můžou být SafeHandle objekty.

Implementace vzorce Dispose pomocí vlastního bezpečného popisovače

Následující kód ukazuje, jak zpracovat nespravované prostředky implementací SafeHandle.

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

// Wraps the IntPtr allocated by Marshal.AllocHGlobal() into a SafeHandle.
class LocalAllocHandle : SafeHandleZeroOrMinusOneIsInvalid
{
    private LocalAllocHandle() : base(ownsHandle: true) { }

    // No need to implement a finalizer - SafeHandle's finalizer will call ReleaseHandle for you.
    protected override bool ReleaseHandle()
    {
        Marshal.FreeHGlobal(handle);
        return true;
    }

    // Allocate bytes with Marshal.AllocHGlobal() and wrap the result into a SafeHandle.
    public static LocalAllocHandle Allocate(int numberOfBytes)
    {
        IntPtr nativeHandle = Marshal.AllocHGlobal(numberOfBytes);
        LocalAllocHandle safeHandle = new LocalAllocHandle();
        safeHandle.SetHandle(nativeHandle);
        return safeHandle;
    }
}

public class DisposableBaseWithSafeHandle : IDisposable
{
    // Detect redundant Dispose() calls.
    private bool _isDisposed;

    // Managed disposable objects owned by this class
    private LocalAllocHandle? _safeHandle = LocalAllocHandle.Allocate(10);
    private Stream? _otherUnmanagedResource = new MemoryStream();

    // 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 (!_isDisposed)
        {
            _isDisposed = true;

            if (disposing)
            {
                // Dispose managed state.
                _otherUnmanagedResource?.Dispose();
                _safeHandle?.Dispose();
                _otherUnmanagedResource = null;
                _safeHandle = null;
            }
        }
    }
}
Imports System
Imports System.IO
Imports System.Runtime.InteropServices
Imports Microsoft.Win32.SafeHandles

' Wraps the IntPtr allocated by Marshal.AllocHGlobal() into a SafeHandle.
Public Class LocalAllocHandle
    Inherits SafeHandleZeroOrMinusOneIsInvalid

    Private Sub New()
        MyBase.New(True)
    End Sub

    ' No need to implement a finalizer - SafeHandle's finalizer will call ReleaseHandle for you.
    Protected Overrides Function ReleaseHandle() As Boolean
        Marshal.FreeHGlobal(handle)
        Return True
    End Function

    ' Allocate bytes with Marshal.AllocHGlobal() and wrap the result into a SafeHandle.
    Public Shared Function Allocate(numberOfBytes As Integer) As LocalAllocHandle
        Dim nativeHandle As IntPtr = Marshal.AllocHGlobal(numberOfBytes)
        Dim safeHandle As New LocalAllocHandle()
        safeHandle.SetHandle(nativeHandle)
        Return safeHandle
    End Function
End Class

Public Class DisposableBaseWithSafeHandle
    Implements IDisposable

    ' Detect redundant Dispose() calls.
    Private _isDisposed As Boolean

    ' Managed disposable objects owned by this class
    Private _safeHandle As LocalAllocHandle = LocalAllocHandle.Allocate(10)
    Private _otherUnmanagedResource As Stream = New MemoryStream()

    ' 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 Not _isDisposed Then
            _isDisposed = True

            If disposing Then
                ' Dispose managed state.
                _otherUnmanagedResource?.Dispose()
                _safeHandle?.Dispose()
                _otherUnmanagedResource = Nothing
                _safeHandle = Nothing
            End If
        End If
    End Sub
End Class

Poznámka

Chování třídy DisposableBaseWithSafeHandle odpovídá chování třídy DisposableBaseWithFinalizer v předchozím příkladu, ale přístup, který je zde ukázaný, je bezpečnější:

  • Není nutné implementovat finalizátor, protože SafeHandle se postará o finalizaci.
  • Není nutné synchronizovat, aby se zajistilo zabezpečení vláken. I když v Dispose implementaci DisposableBaseWithSafeHandleexistuje podmínka závodu, SafeHandle zaručuje, že SafeHandle.ReleaseHandle bude volána pouze jednou.

Integrované bezpečnostní popisovače v .NET

Následující odvozené třídy v oboru názvů Microsoft.Win32.SafeHandles poskytují bezpečné popisovače.

Třída Prostředky, které obsahuje
SafeFileHandle
SafeMemoryMappedFileHandle
SafePipeHandle
Soubory, soubory mapované v paměti a kanály
SafeMemoryMappedViewHandle Zobrazení paměti
SafeNCryptKeyHandle
SafeNCryptProviderHandle
SafeNCryptSecretHandle
Kryptografické konstrukce
SafeRegistryHandle Klíče registru
SafeWaitHandle Obslužné rutiny čekání

Viz také