Implementando um método Dispose
O padrão para descartar um objeto, conhecido sistema autônomo um padrão de dispose, impõe ordem no tempo de vida de um objeto.
A type's Disposemethod should release all the resources that it owns.Também deve versão todos os recursos pertencentes a seus tipos base chamando Dispose método. Dispose método deve liberar todos os recursos que ele é proprietário e por sua vez telefonar seu tipo de pai Dispose método, propagando esse padrão a hierarquia de tipos base. Para ajudar a garantir que recursos sempre estão limpos apropriadamente, um Dispose método deve ser que pode ser chamado várias vezes sem gerar uma exceção.
Não existe benefício desempenho na implementação de Dispose método em tipos que usam apenas recursos gerenciado (sistema autônomo arrays) porque eles são automaticamente recuperados pelo coletor de lixo. Use o Dispose método principalmente em objetos gerenciado que usam recursos nativo e em objetos COM que são expostos para o .NET estrutura. Objetos que usam recursos nativo (sistema autônomo, por exemplo, a gerenciadoFileStream implementar classe) a IDisposable interface.
Observação importante: |
---|
Os programadores C++ não devem usar este tópico.Em vez disso, consulte Destruidores e Finalizers em Visual C++.No .NET estrutura versão 2.0, o compilador do C++ oferece suporte para implementação deterministico descarte de recursos e não permite a implementação direta do Dispose método. |
A Dispose método deve telefonar o SuppressFinalize método para o objeto está descartando. Se o objeto estiver na fila de finalização, SuppressFinalize impede que seu Finalize método de chamada. Lembre-se de que a execução de um Finalize método é dispendioso para o desempenho. Se seu Dispose método já trabalhou no sentido de limpar o objeto e não é necessário que o coletor de lixo telefonar do objeto Finalize método.
O exemplo de código fornecido para o GC.KeepAlive método mostra como agressivo lixo coleção pode causar um finalizador para ser executado enquanto ainda está executando um membro do objeto recuperado. É uma mercadoria idéia para chamar o KeepAlive método no participante de uma longa Dispose método.
Exemplo
O exemplo de código a seguir mostra o padrão de design recomendado para implementar um Dispose método de classes que encapsulam recursos não gerenciados.
Classes de recursos normalmente são derivados do complexo nativo classes ou APIs e deve ser personalizado adequadamente.Use esse padrão de código sistema autônomo um ponto de partida para criar uma classe de recurso e fornecem a personalização necessária com base nos recursos que são encapsulamento.
Imports System
Imports System.IO
Class Program
Public Shared Sub Main()
Try
' Initialize a Stream resource to pass
' to the DisposableResource class.
Console.Write("Enter filename and its path: ")
Dim fileSpec As String = Console.ReadLine
Dim fs As FileStream = File.OpenRead(fileSpec)
Dim TestObj As DisposableResource = New DisposableResource(fs)
' Use the resource.
TestObj.DoSomethingWithResource()
' Dispose theresource.
TestObj.Dispose()
Catch e As FileNotFoundException
Console.WriteLine(e.Message)
End Try
End Sub
End Class
' This class shows how to use a disposable resource.
' The resource is first initialized and passed to
' the constructor, but it could also be
' initialized in the constructor.
' The lifetime of the resource does not
' exceed the lifetime of this instance.
' This type does not need a finalizer because it does not
' directly create a native resource like a file handle
' or memory in the unmanaged heap.
Public Class DisposableResource
Implements IDisposable
Private _resource As Stream
Private _disposed As Boolean
' The stream passed to the constructor
' must be readable and not null.
Public Sub New(ByVal stream As Stream)
MyBase.New()
If (stream Is Nothing) Then
Throw New ArgumentNullException("Stream is null.")
End If
If Not stream.CanRead Then
Throw New ArgumentException("Stream must be readable.")
End If
_resource = stream
Dim objTypeName As String = _resource.GetType.ToString
_disposed = False
End Sub
' Demonstrates using the resource.
' It must not be already disposed.
Public Sub DoSomethingWithResource()
If _disposed Then
Throw New ObjectDisposedException("Resource was disposed.")
End If
' Show the number of bytes.
Dim numBytes As Integer = CType(_resource.Length, Integer)
Console.WriteLine("Number of bytes: {0}", numBytes.ToString)
End Sub
Public Overloads Sub Dispose() Implements IDisposable.Dispose
Dispose(True)
' Use SupressFinalize in case a subclass
' of this type implements a finalizer.
GC.SuppressFinalize(Me)
End Sub
Protected Overridable Overloads Sub Dispose(ByVal disposing As Boolean)
If Not _disposed Then
' If you need thread safety, use a lock around these
' operations, as well as in your methods that use the resource.
If disposing Then
If (Not (_resource) Is Nothing) Then
_resource.Dispose()
End If
Console.WriteLine("Object disposed.")
End If
' Indicates that the instance has been disposed.
_resource = Nothing
_disposed = True
End If
End Sub
End Class
using System;
using System.IO;
class Program
{
static void Main()
{
try
{
// Initialize a Stream resource to pass
// to the DisposableResource class.
Console.Write("Enter filename and its path: ");
string fileSpec = Console.ReadLine();
FileStream fs = File.OpenRead(fileSpec);
DisposableResource TestObj = new DisposableResource(fs);
// Use the resource.
TestObj.DoSomethingWithResource();
// Dispose the resource.
TestObj.Dispose();
}
catch (FileNotFoundException e)
{
Console.WriteLine(e.Message);
}
}
}
// This class shows how to use a disposable resource.
// The resource is first initialized and passed to
// the constructor, but it could also be
// initialized in the constructor.
// The lifetime of the resource does not
// exceed the lifetime of this instance.
// This type does not need a finalizer because it does not
// directly create a native resource like a file handle
// or memory in the unmanaged heap.
public class DisposableResource : IDisposable
{
private Stream _resource;
private bool _disposed;
// The stream passed to the constructor
// must be readable and not null.
public DisposableResource(Stream stream)
{
if (stream == null)
throw new ArgumentNullException("Stream in null.");
if (!stream.CanRead)
throw new ArgumentException("Stream must be readable.");
_resource = stream;
_disposed = false;
}
// Demonstrates using the resource.
// It must not be already disposed.
public void DoSomethingWithResource() {
if (_disposed)
throw new ObjectDisposedException("Resource was disposed.");
// Show the number of bytes.
int numBytes = (int) _resource.Length;
Console.WriteLine("Number of bytes: {0}", numBytes.ToString());
}
public void Dispose()
{
Dispose(true);
// Use SupressFinalize in case a subclass
// of this type implements a finalizer.
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
// If you need thread safety, use a lock around these
// operations, as well as in your methods that use the resource.
if (!_disposed)
{
if (disposing) {
if (_resource != null)
_resource.Dispose();
Console.WriteLine("Object disposed.");
}
// Indicate that the instance has been disposed.
_resource = null;
_disposed = true;
}
}
}
Consulte também
Conceitos
Substituindo o método de finalização
Referência
Destruidores e Finalizers em Visual C++
Implementando Finalize e Dispose para Apagar up recursos não gerenciados