Este artículo se tradujo automáticamente. Para ver el artículo en inglés, active la casilla Inglés. Además, puede mostrar el texto en inglés en una ventana emergente si mueve el puntero del mouse sobre el texto.
Traducción
Inglés

Interfaz IDisposable

 

Proporciona un mecanismo para liberar recursos no administrados.

Para examinar el código fuente de .NET Framework para este tipo, consulte el Reference Source.

Espacio de nombres:   System
Ensamblado:  mscorlib (en mscorlib.dll)

[ComVisibleAttribute(true)]
public interface IDisposable

NombreDescripción
System_CAPS_pubmethodDispose()

Realiza tareas definidas por la aplicación asociadas a la liberación o al restablecimiento de recursos no administrados.

System_CAPS_noteNota

Para ver el código fuente de .NET Framework para este tipo, consulte el Reference Source. Puede examinar el código fuente en línea, descargar la referencia para visualizarlo sin conexión y paso a paso el código fuente (incluidas revisiones y actualizaciones) durante la depuración; see instructions.

Es el uso principal de esta interfaz liberar recursos no administrados. El recolector de elementos no utilizados libera automáticamente la memoria asignada a un objeto administrado cuando ya no se utiliza ese objeto. Sin embargo, no es posible predecir cuándo se realizará la recolección de elementos. Además, el recolector de elementos no utilizados no tiene ningún conocimiento de los recursos no administrados como identificadores de ventanas o abrir archivos y secuencias.

Use la Dispose método de esta interfaz para liberar explícitamente los recursos no administrados que junto con el recolector de elementos no utilizados. El consumidor de un objeto puede llamar a este método cuando el objeto ya no es necesario.

System_CAPS_warningAdvertencia

Es una novedad para agregar el IDisposable interfaz a una clase existente. Porque ya existentes a los consumidores de su tipo no pueden llamar a Dispose, no puede estar seguro de que se publican los recursos no administrados mantenidos por su tipo.

Dado que la IDisposable.Dispose implementación es invocada por el consumidor de un tipo cuando ya no son necesarios los recursos que pertenecen a una instancia, o bien debe encapsular el objeto administrado en un SafeHandle (la alternativa recomendada), o se debe invalidar Object.Finalize para liberar recursos no administrados en caso de que el consumidor olvide llamar a Dispose.

System_CAPS_importantImportante

En .NET Framework, el compilador de C++ admite la eliminación determinista de recursos y no se permite la implementación directa de la Dispose método.

Para obtener una explicación detallada acerca de cómo esta interfaz y la Object.Finalize método se usan, vea la Garbage Collection y Implementar un método Dispose temas.

Implemente IDisposable solo si está usando recursos no administrados directamente. Si la aplicación simplemente utiliza un objeto que implementa IDisposable, no proporcionan un IDisposable implementación. En su lugar, debe llamar a del objeto IDisposable.Dispose implementación cuando haya terminado de usarlo. Dependiendo del lenguaje de programación, puede hacerlo de dos maneras:

  • Mediante el lenguaje construir como el using instrucción en C# y Visual Basic.

  • Al ajustar la llamada a la IDisposable.Dispose implementación en un try/catch bloque.

System_CAPS_noteNota

Documentación de los tipos que implementan IDisposable tenga en cuenta este hecho e incluir un recordatorio para llamar a su Dispose implementación.

Si su lenguaje admite una construcción como la con instrucción en C# y la mediante instrucción en Visual Basic, puede usar en lugar de llamar explícitamente a IDisposable.Dispose usted mismo. En el ejemplo siguiente se usa este enfoque en la definición de un WordCount clase que conserva la información acerca de un archivo y el número de palabras en ella.

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; } }
}   

El using instrucción es realmente una comodidad sintáctica. En tiempo de compilación, el compilador de lenguaje implementa el lenguaje intermedio (IL) para una try/catch bloque.

Para obtener más información sobre la using instrucción, consulte la Using (Instrucción, Visual Basic) o using (Instrucción, Referencia de C#) temas.

Si su lenguaje de programación no admite una construcción como la using instrucción en C# o Visual Basic, o si no desea usarlo, puede llamar a la IDisposable.Dispose implementación desde el finally bloquear de un try/catch instrucción. En el ejemplo siguiente se reemplaza el using bloquear en el ejemplo anterior con un try/catch/finally bloque.

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; } }
}   

Para obtener más información sobre la try/finally de patrón, vea Instrucción Try...Catch...Finally (Visual Basic), try-finally (Referencia de C#), o try-finally (Instrucción) (C).

Debe implementar IDisposable solo si el tipo utiliza recursos no administrados directamente. Pueden llamar los consumidores de su tipo de su IDisposable.Dispose implementación para liberar recursos cuando ya no es necesaria la instancia. Para controlar los casos en que producirá un error al llamar a Dispose, debería usar una clase derivada de SafeHandle encapsular los recursos no administrados, o se debe invalidar el Object.Finalize método para un tipo de referencia. En cualquier caso, use el Dispose método para realizar cualquier limpieza es necesaria después de usar los recursos no administrados, como la liberación o el restablecimiento de los recursos no administrados.

System_CAPS_importantImportante

Si va a definir una clase base que utiliza los recursos no administrados y que tiene, o es probable que tenga, subclases que deben estar en su lugar, debe implementar la IDisposable.Dispose método y proporcionar una segunda sobrecarga de Dispose, como se describe en la sección siguiente.

Debe implementar una clase base con subclases que deben ser descartables IDisposable como se indica a continuación. Debe usar este patrón siempre que implemente IDisposable en cualquier tipo que no es sealed (NotInheritable en Visual Basic).

  • Debe proporcionar un método Dispose() público y no virtual, y un método Dispose(Boolean disposing) virtual protegido.

  • El Dispose() debe llamar al método Dispose(true) y se debe suprimir la finalización de rendimiento.

  • El tipo base no debe incluir ningún finalizador.

El siguiente fragmento de código refleja el patrón de dispose para las clases base. Se supone que el tipo no reemplaza el Object.Finalize método.

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.
         //
      }

      // Free any unmanaged objects here.
      //
      disposed = true;
   }
}

Si invalida el Object.Finalize método, la clase debe implementar el patrón siguiente.

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);
   }
}

Las subclases deben implementar el patrón desechable de la siguiente forma:

  • Deben invalidar Dispose(Boolean) y llamar a la implementación Dispose(Boolean) de la clase base.

  • Pueden proporcionar un finalizador si es necesario. El finalizador debe llamar a Dispose(false).

Tenga en cuenta que las clases derivadas no propios implementen el IDisposable interfaz y no incluyen una sin parámetros Dispose método. Solo invalidan la clase base Dispose(Boolean) método.

El siguiente fragmento de código refleja el patrón de dispose para las clases derivadas. Se supone que el tipo no reemplaza el Object.Finalize método.

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);
   }
}

En el ejemplo siguiente se muestra cómo crear una clase de recurso que implementa el IDisposable interfaz.

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.
    }
}

Plataforma universal de Windows
Disponible desde 8
.NET Framework
Disponible desde 1.1
Biblioteca de clases portable
Se admite en: plataformas portátiles de .NET
Silverlight
Disponible desde 2.0
Windows Phone Silverlight
Disponible desde 7.0
Windows Phone
Disponible desde 8.1
Volver al principio
Mostrar: