IDisposable Interfaz
Definición
Proporciona un mecanismo para liberar recursos no administrados.Provides a mechanism for releasing unmanaged resources.
public interface class IDisposable
public interface IDisposable
[System.Runtime.InteropServices.ComVisible(true)]
public interface IDisposable
type IDisposable = interface
[<System.Runtime.InteropServices.ComVisible(true)>]
type IDisposable = interface
Public Interface IDisposable
- Derivado
- Atributos
Ejemplos
En el ejemplo siguiente se muestra cómo crear una clase de recursos que implementa la IDisposable interfaz.The following example demonstrates how to create a resource class that implements the IDisposable interface.
#using <System.dll>
#using <System.Windows.Forms.dll>
using namespace System;
using namespace System::ComponentModel;
using namespace System::Windows::Forms;
// The following example demonstrates how to create a class that
// implements the IDisposable interface and the IDisposable.Dispose
// method with finalization to clean up unmanaged resources.
//
public ref class MyResource: public IDisposable
{
private:
// Pointer to an external unmanaged resource.
IntPtr handle;
// A managed resource this class uses.
Component^ component;
// Track whether Dispose has been called.
bool disposed;
public:
// The class constructor.
MyResource( IntPtr handle, Component^ component )
{
this->handle = handle;
this->component = component;
disposed = false;
}
// This method is called if the user explicitly disposes of the
// object (by calling the Dispose method in other managed languages,
// or the destructor in C++). The compiler emits as a call to
// GC::SuppressFinalize( this ) for you, so there is no need to
// call it here.
~MyResource()
{
// Dispose of managed resources.
component->~Component();
// Call C++ finalizer to clean up unmanaged resources.
this->!MyResource();
// Mark the class as disposed. This flag allows you to throw an
// exception if a disposed object is accessed.
disposed = true;
}
// Use interop to call the method necessary to clean up the
// unmanaged resource.
//
[System::Runtime::InteropServices::DllImport("Kernel32")]
static Boolean CloseHandle( IntPtr handle );
// The C++ finalizer destructor ensures that unmanaged resources get
// released if the user releases the object without explicitly
// disposing of it.
//
!MyResource()
{
// Call the appropriate methods to clean up unmanaged
// resources here. If disposing is false when Dispose(bool,
// disposing) is called, only the following code is executed.
CloseHandle( handle );
handle = IntPtr::Zero;
}
};
void main()
{
// Insert code here to create and use the MyResource object.
MyResource^ mr = gcnew MyResource((IntPtr) 42, (Component^) gcnew Button());
mr->~MyResource();
}
using System;
using System.ComponentModel;
// The following example demonstrates how to create
// a resource class that implements the IDisposable interface
// and the IDisposable.Dispose method.
public class DisposeExample
{
// A base class that implements IDisposable.
// By implementing IDisposable, you are announcing that
// instances of this type allocate scarce resources.
public class MyResource: IDisposable
{
// Pointer to an external unmanaged resource.
private IntPtr handle;
// Other managed resource this class uses.
private Component component = new Component();
// Track whether Dispose has been called.
private bool disposed = false;
// The class constructor.
public MyResource(IntPtr handle)
{
this.handle = handle;
}
// Implement IDisposable.
// Do not make this method virtual.
// A derived class should not be able to override this method.
public void Dispose()
{
Dispose(true);
// This object will be cleaned up by the Dispose method.
// Therefore, you should call GC.SupressFinalize to
// take this object off the finalization queue
// and prevent finalization code for this object
// from executing a second time.
GC.SuppressFinalize(this);
}
// Dispose(bool disposing) executes in two distinct scenarios.
// If disposing equals true, the method has been called directly
// or indirectly by a user's code. Managed and unmanaged resources
// can be disposed.
// If disposing equals false, the method has been called by the
// runtime from inside the finalizer and you should not reference
// other objects. Only unmanaged resources can be disposed.
protected virtual void Dispose(bool disposing)
{
// Check to see if Dispose has already been called.
if(!this.disposed)
{
// If disposing equals true, dispose all managed
// and unmanaged resources.
if(disposing)
{
// Dispose managed resources.
component.Dispose();
}
// Call the appropriate methods to clean up
// unmanaged resources here.
// If disposing is false,
// only the following code is executed.
CloseHandle(handle);
handle = IntPtr.Zero;
// Note disposing has been done.
disposed = true;
}
}
// Use interop to call the method necessary
// to clean up the unmanaged resource.
[System.Runtime.InteropServices.DllImport("Kernel32")]
private extern static Boolean CloseHandle(IntPtr handle);
// Use C# destructor syntax for finalization code.
// This destructor will run only if the Dispose method
// does not get called.
// It gives your base class the opportunity to finalize.
// Do not provide destructors in types derived from this class.
~MyResource()
{
// Do not re-create Dispose clean-up code here.
// Calling Dispose(false) is optimal in terms of
// readability and maintainability.
Dispose(false);
}
}
public static void Main()
{
// Insert code here to create
// and use the MyResource object.
}
}
Imports System.ComponentModel
' The following example demonstrates how to create
' a resource class that implements the IDisposable interface
' and the IDisposable.Dispose method.
Public Class DisposeExample
' A class that implements IDisposable.
' By implementing IDisposable, you are announcing that
' instances of this type allocate scarce resources.
Public Class MyResource
Implements IDisposable
' Pointer to an external unmanaged resource.
Private handle As IntPtr
' Other managed resource this class uses.
Private component As component
' Track whether Dispose has been called.
Private disposed As Boolean = False
' The class constructor.
Public Sub New(ByVal handle As IntPtr)
Me.handle = handle
End Sub
' Implement IDisposable.
' Do not make this method virtual.
' A derived class should not be able to override this method.
Public Overloads Sub Dispose() Implements IDisposable.Dispose
Dispose(True)
' This object will be cleaned up by the Dispose method.
' Therefore, you should call GC.SupressFinalize to
' take this object off the finalization queue
' and prevent finalization code for this object
' from executing a second time.
GC.SuppressFinalize(Me)
End Sub
' Dispose(bool disposing) executes in two distinct scenarios.
' If disposing equals true, the method has been called directly
' or indirectly by a user's code. Managed and unmanaged resources
' can be disposed.
' If disposing equals false, the method has been called by the
' runtime from inside the finalizer and you should not reference
' other objects. Only unmanaged resources can be disposed.
Protected Overridable Overloads Sub Dispose(ByVal disposing As Boolean)
' Check to see if Dispose has already been called.
If Not Me.disposed Then
' If disposing equals true, dispose all managed
' and unmanaged resources.
If disposing Then
' Dispose managed resources.
component.Dispose()
End If
' Call the appropriate methods to clean up
' unmanaged resources here.
' If disposing is false,
' only the following code is executed.
CloseHandle(handle)
handle = IntPtr.Zero
' Note disposing has been done.
disposed = True
End If
End Sub
' Use interop to call the method necessary
' to clean up the unmanaged resource.
<System.Runtime.InteropServices.DllImport("Kernel32")> _
Private Shared Function CloseHandle(ByVal handle As IntPtr) As [Boolean]
End Function
' This finalizer will run only if the Dispose method
' does not get called.
' It gives your base class the opportunity to finalize.
' Do not provide finalize methods in types derived from this class.
Protected Overrides Sub Finalize()
' Do not re-create Dispose clean-up code here.
' Calling Dispose(false) is optimal in terms of
' readability and maintainability.
Dispose(False)
MyBase.Finalize()
End Sub
End Class
Public Shared Sub Main()
' Insert code here to create
' and use the MyResource object.
End Sub
End Class
Comentarios
El uso principal de esta interfaz es liberar recursos no administrados.The primary use of this interface is to release unmanaged resources. El recolector de elementos no utilizados libera automáticamente la memoria asignada a un objeto administrado cuando ese objeto ya no se utiliza.The garbage collector automatically releases the memory allocated to a managed object when that object is no longer used. Sin embargo, no es posible predecir cuándo se producirá la recolección de elementos no utilizados.However, it is not possible to predict when garbage collection will occur. Además, el recolector de elementos no utilizados no tiene conocimiento de los recursos no administrados, como los identificadores de ventana, ni los archivos y secuencias abiertos.Furthermore, the garbage collector has no knowledge of unmanaged resources such as window handles, or open files and streams.
Utilice el Dispose método de esta interfaz para liberar explícitamente los recursos no administrados junto con el recolector de elementos no utilizados.Use the Dispose method of this interface to explicitly release unmanaged resources in conjunction with the garbage collector. El consumidor de un objeto puede llamar a este método cuando el objeto ya no se necesita.The consumer of an object can call this method when the object is no longer needed.
Advertencia
Se trata de un cambio importante para agregar la IDisposable interfaz a una clase existente.It is a breaking change to add the IDisposable interface to an existing class. Dado que los consumidores preexistentes de su tipo no pueden llamar a Dispose , no puede estar seguro de que se liberarán los recursos no administrados que contiene el tipo.Because pre-existing consumers of your type cannot call Dispose, you cannot be certain that unmanaged resources held by your type will be released.
Dado IDisposable.Dispose que el consumidor de un tipo llama a la implementación cuando los recursos que pertenecen a una instancia de ya no son necesarios, debe ajustar el objeto administrado en un SafeHandle (la alternativa recomendada), o bien debe reemplazar Object.Finalize para liberar los recursos no administrados en caso de que el consumidor olvide llamar a Dispose .Because the IDisposable.Dispose implementation is called by the consumer of a type when the resources owned by an instance are no longer needed, you should either wrap the managed object in a SafeHandle (the recommended alternative), or you should override Object.Finalize to free unmanaged resources in the event that the consumer forgets to call Dispose.
Importante
En el .NET Framework, el compilador de C++ admite la eliminación determinista de recursos y no permite la implementación directa del Dispose método.In the .NET Framework, the C++ compiler supports deterministic disposal of resources and does not allow direct implementation of the Dispose method.
Para obtener una explicación detallada sobre cómo se usan esta interfaz y el Object.Finalize método, vea los temas sobre la recolección de elementos no utilizados e implementación de un método Dispose .For a detailed discussion about how this interface and the Object.Finalize method are used, see the Garbage Collection and Implementing a Dispose Method topics.
Usar un objeto que implementa IDisposableUsing an object that implements IDisposable
Si la aplicación simplemente usa un objeto que implementa la IDisposable interfaz, debe llamar a la implementación del objeto IDisposable.Dispose cuando haya terminado de usarla.If your app simply uses an object that implements the IDisposable interface, you should call the object's IDisposable.Dispose implementation when you are finished using it. En función del lenguaje de programación, puede hacerlo de una de estas dos maneras:Depending on your programming language, you can do this in one of two ways:
Mediante el uso de una construcción de lenguaje como la
using
instrucción en C# y Visual Basic.By using a language construct such as theusing
statement in C# and Visual Basic.Ajustando la llamada a la IDisposable.Dispose implementación en un
try
/finally
bloque.By wrapping the call to the IDisposable.Dispose implementation in atry
/finally
block.
Nota
Documentación para los tipos que implementan IDisposable el hecho y que incluyen un recordatorio para llamar a su Dispose implementación.Documentation for types that implement IDisposable note that fact and include a reminder to call its Dispose implementation.
La instrucción using de C# y Visual BasicThe C# and Visual Basic Using statement
Si su lenguaje admite una construcción como la instrucción using en C# y la instrucción using en Visual Basic, puede utilizarla en lugar de llamar explícitamente a IDisposable.Dispose sí mismo.If your language supports a construct such as the using statement in C# and the Using statement in Visual Basic, you can use it instead of explicitly calling IDisposable.Dispose yourself. En el ejemplo siguiente se usa este enfoque en la definición de una WordCount
clase que conserva la información sobre un archivo y el número de palabras que hay en él.The following example uses this approach in defining a WordCount
class that preserves information about a file and the number of words in it.
using System;
using System.IO;
using System.Text.RegularExpressions;
public class WordCount
{
private String filename = String.Empty;
private int nWords = 0;
private String pattern = @"\b\w+\b";
public WordCount(string filename)
{
if (! File.Exists(filename))
throw new FileNotFoundException("The file does not exist.");
this.filename = filename;
string txt = String.Empty;
using (StreamReader sr = new StreamReader(filename)) {
txt = sr.ReadToEnd();
}
nWords = Regex.Matches(txt, pattern).Count;
}
public string FullName
{ get { return filename; } }
public string Name
{ get { return Path.GetFileName(filename); } }
public int Count
{ get { return nWords; } }
}
Imports System.IO
Imports System.Text.RegularExpressions
Public Class WordCount
Private filename As String
Private nWords As Integer
Private pattern As String = "\b\w+\b"
Public Sub New(filename As String)
If Not File.Exists(filename) Then
Throw New FileNotFoundException("The file does not exist.")
End If
Me.filename = filename
Dim txt As String = String.Empty
Using sr As New StreamReader(filename)
txt = sr.ReadToEnd()
End Using
nWords = Regex.Matches(txt, pattern).Count
End Sub
Public ReadOnly Property FullName As String
Get
Return filename
End Get
End Property
Public ReadOnly Property Name As String
Get
Return Path.GetFileName(filename)
End Get
End Property
Public ReadOnly Property Count As Integer
Get
Return nWords
End Get
End Property
End Class
La using
instrucción es realmente una comodidad sintáctica.The using
statement is actually a syntactic convenience. En tiempo de compilación, el compilador del lenguaje implementa el lenguaje intermedio (IL) de un try
/ finally
bloque.At compile time, the language compiler implements the intermediate language (IL) for a try
/finally
block.
Para obtener más información acerca de la using
instrucción, vea los temas using (instrucción ) o using (instrucción ).For more information about the using
statement, see the Using Statement or using Statement topics.
El bloque try/finallyThe Try/Finally block
Si el lenguaje de programación no admite una construcción como la using
instrucción en C# o Visual Basic, o si prefiere no usarlo, puede llamar a la IDisposable.Dispose implementación desde el finally
bloque de una try
/ finally
instrucción.If your programming language does not support a construct like the using
statement in C# or Visual Basic, or if you prefer not to use it, you can call the IDisposable.Dispose implementation from the finally
block of a try
/finally
statement. En el ejemplo siguiente se reemplaza el using
bloque del ejemplo anterior con un try
/ finally
bloque.The following example replaces the using
block in the previous example with a try
/finally
block.
using System;
using System.IO;
using System.Text.RegularExpressions;
public class WordCount
{
private String filename = String.Empty;
private int nWords = 0;
private String pattern = @"\b\w+\b";
public WordCount(string filename)
{
if (! File.Exists(filename))
throw new FileNotFoundException("The file does not exist.");
this.filename = filename;
string txt = String.Empty;
StreamReader sr = null;
try {
sr = new StreamReader(filename);
txt = sr.ReadToEnd();
}
finally {
if (sr != null) sr.Dispose();
}
nWords = Regex.Matches(txt, pattern).Count;
}
public string FullName
{ get { return filename; } }
public string Name
{ get { return Path.GetFileName(filename); } }
public int Count
{ get { return nWords; } }
}
Imports System.IO
Imports System.Text.RegularExpressions
Public Class WordCount
Private filename As String
Private nWords As Integer
Private pattern As String = "\b\w+\b"
Public Sub New(filename As String)
If Not File.Exists(filename) Then
Throw New FileNotFoundException("The file does not exist.")
End If
Me.filename = filename
Dim txt As String = String.Empty
Dim sr As StreamReader = Nothing
Try
sr = New StreamReader(filename)
txt = sr.ReadToEnd()
Finally
If sr IsNot Nothing Then sr.Dispose()
End Try
nWords = Regex.Matches(txt, pattern).Count
End Sub
Public ReadOnly Property FullName As String
Get
Return filename
End Get
End Property
Public ReadOnly Property Name As String
Get
Return Path.GetFileName(filename)
End Get
End Property
Public ReadOnly Property Count As Integer
Get
Return nWords
End Get
End Property
End Class
Para obtener más información sobre el try
/ finally
patrón, vea try... Detectar... Instrucción Finally, try-finallyo instrucción try-finally.For more information about the try
/finally
pattern, see Try...Catch...Finally Statement, try-finally, or try-finally Statement.
Implementar IDisposableImplementing IDisposable
Debe implementar IDisposable solo si el tipo utiliza directamente los recursos no administrados.You should implement IDisposable only if your type uses unmanaged resources directly. Los consumidores de su tipo pueden llamar IDisposable.Dispose a su implementación de para liberar recursos cuando la instancia de ya no se necesita.The consumers of your type can call your IDisposable.Dispose implementation to free resources when the instance is no longer needed. Para controlar los casos en los que no se puede llamar a Dispose , debe usar una clase derivada de SafeHandle para contener los recursos no administrados, o bien debe reemplazar el Object.Finalize método para un tipo de referencia.To handle cases in which they fail to call Dispose, you should either use a class derived from SafeHandle to wrap the unmanaged resources, or you should override the Object.Finalize method for a reference type. En cualquier caso, se usa el Dispose método para realizar cualquier limpieza necesaria después de usar los recursos no administrados, como liberar, liberar o restablecer los recursos no administrados.In either case, you use the Dispose method to perform whatever cleanup is necessary after using the unmanaged resources, such as freeing, releasing, or resetting the unmanaged resources.
Importante
Si está definiendo una clase base que utiliza recursos no administrados y que tiene, o es probable que tenga, subclases que se deben desechar, debe implementar el IDisposable.Dispose método y proporcionar una segunda sobrecarga de Dispose
, como se describe en la sección siguiente.If you are defining a base class that uses unmanaged resources and that either has, or is likely to have, subclasses that should be disposed, you should implement the IDisposable.Dispose method and provide a second overload of Dispose
, as discussed in the next section.
IDisposable y la jerarquía de herenciaIDisposable and the inheritance hierarchy
Una clase base con subclases que deben ser descartables debe implementar IDisposable de la manera siguiente.A base class with subclasses that should be disposable must implement IDisposable as follows. Debe usar este patrón cada vez que implemente IDisposable en cualquier tipo que no sea sealed
( NotInheritable
en Visual Basic).You should use this pattern whenever you implement IDisposable on any type that isn't sealed
(NotInheritable
in Visual Basic).
Debe proporcionar un método público, no virtual Dispose() y un método virtual protegido
Dispose(Boolean disposing)
.It should provide one public, non-virtual Dispose() method and a protected virtualDispose(Boolean disposing)
method.El Dispose() método debe llamar a
Dispose(true)
y debe suprimir la finalización del rendimiento.The Dispose() method must callDispose(true)
and should suppress finalization for performance.El tipo base no debe incluir ningún finalizador.The base type should not include any finalizers.
El siguiente fragmento de código refleja el patrón de Dispose para clases base.The following code fragment reflects the dispose pattern for base classes. Se supone que el tipo no invalida el Object.Finalize método.It assumes that your type does not override the Object.Finalize method.
using Microsoft.Win32.SafeHandles;
using System;
using System.Runtime.InteropServices;
class BaseClass : IDisposable
{
// Flag: Has Dispose already been called?
bool disposed = false;
// Instantiate a SafeHandle instance.
SafeHandle handle = new SafeFileHandle(IntPtr.Zero, true);
// 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 (disposed)
return;
if (disposing) {
handle.Dispose();
// Free any other managed objects here.
//
}
disposed = true;
}
}
Imports Microsoft.Win32.SafeHandles
Imports System.Runtime.InteropServices
Class BaseClass : 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()
' Free any other managed objects here.
'
End If
disposed = True
End Sub
End Class
Si invalida el Object.Finalize método, la clase debe implementar el siguiente patrón.If you do override the Object.Finalize method, your class should implement the following pattern.
using System;
class BaseClass : IDisposable
{
// Flag: Has Dispose already been called?
bool disposed = 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 (disposed)
return;
if (disposing) {
// Free any other managed objects here.
//
}
// Free any unmanaged objects here.
//
disposed = true;
}
~BaseClass()
{
Dispose(false);
}
}
Class BaseClass : 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
' Free any other managed objects here.
'
End If
' Free any unmanaged objects here.
'
disposed = True
End Sub
Protected Overrides Sub Finalize()
Dispose(False)
End Sub
End Class
Las subclases deben implementar el patrón desechable de la siguiente forma:Subclasses should implement the disposable pattern as follows:
Deben invalidar
Dispose(Boolean)
y llamar a la implementaciónDispose(Boolean)
de la clase base.They must overrideDispose(Boolean)
and call the base classDispose(Boolean)
implementation.Pueden proporcionar un finalizador si es necesario.They can provide a finalizer if needed. El finalizador debe llamar a
Dispose(false)
.The finalizer must callDispose(false)
.
Tenga en cuenta que las clases derivadas no implementan la IDisposable interfaz y no incluyen un Dispose método sin parámetros.Note that derived classes do not themselves implement the IDisposable interface and do not include a parameterless Dispose method. Solo invalidan el método de clase base Dispose(Boolean)
.They only override the base class Dispose(Boolean)
method.
El siguiente fragmento de código refleja el patrón de Dispose para las clases derivadas.The following code fragment reflects the dispose pattern for derived classes. Se supone que el tipo no invalida el Object.Finalize método.It assumes that your type does not override the Object.Finalize method.
using Microsoft.Win32.SafeHandles;
using System;
using System.Runtime.InteropServices;
class DerivedClass : BaseClass
{
// Flag: Has Dispose already been called?
bool disposed = false;
// Instantiate a SafeHandle instance.
SafeHandle handle = new SafeFileHandle(IntPtr.Zero, true);
// Protected implementation of Dispose pattern.
protected override void Dispose(bool disposing)
{
if (disposed)
return;
if (disposing) {
handle.Dispose();
// Free any other managed objects here.
//
}
// Free any unmanaged objects here.
//
disposed = true;
// Call base class implementation.
base.Dispose(disposing);
}
}
Imports Microsoft.Win32.SafeHandles
Imports System.Runtime.InteropServices
Class DerivedClass : Inherits BaseClass
' 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
Métodos
Dispose() |
Realiza tareas definidas por la aplicación asociadas a la liberación o al restablecimiento de recursos no administrados.Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. |