IDisposable Интерфейс
TOC
Свернуть оглавление
Развернуть оглавление
Данная статья переведена с помощью средств машинного перевода. Чтобы просмотреть ее на английском языке, установите флажок Английский. Вы также можете просматривать английский текст во всплывающем окне, наводя указатель мыши на переведенный текст.
Перевод
Английский

IDisposable - интерфейс

 

Предоставляет механизм для освобождения неуправляемых ресурсов.

Просмотреть исходный код .NET Framework для этого типа можно на портале Reference Source.

Пространство имен:   System
Сборка:  mscorlib (в mscorlib.dll)

[ComVisibleAttribute(true)]
public interface IDisposable

ИмяОписание
System_CAPS_pubmethodDispose()

Выполняет определяемые приложением задачи, связанные с удалением, высвобождением или сбросом неуправляемых ресурсов.

System_CAPS_noteПримечание

Чтобы просмотреть исходный код .NET Framework для этого типа, смотрите Reference Source. Вы можете просмотреть исходный код онлайн, загрузить документацию для оффлайнового просмотра и просмотреть ресурсы (включая патчи и обновления) в процессе отладки; смотрите instructions.

Основное применение этого интерфейса состоит в освобождении неуправляемых ресурсов. Сборщик мусора автоматически освобождает память, связанную с контролируемым объектом, если он больше не используется. Тем не менее, невозможно предсказать когда именно произойдёт сборка мусора.
Кроме того, сборщик мусора не имеет информации о таких неуправляемых ресурсах как дескрипторы окна или открытые файлы и потоки.

Используйте метод Dispose этого интерфейса, чтобы освобождать неуправляемые ресурсы вручную в дополнение к работе сборщика мусора. Получатель объекта может вызвать этот метод, когда объект больше не нужен.

System_CAPS_warningПредупреждение

It is a breaking change to add the IDisposable interface to an existing class.Because pre-existing consumers of your type cannot call Dispose, you cannot be certain that unmanaged resources held by your type will be released.

Поскольку реализация IDisposable.Dispose вызывается объект-получателем типа, когда ресурсы, принадлежащие экземпляром больше не требуются, необходимо либо создать управляемый объект в альтернативной SafeHandle (рекомендуется), или необходимо переопределить Object.Finalize для освобождения неуправляемых ресурсов в случае если объект-получатель забывает вызова Dispose.

System_CAPS_importantВажно

В .NET Framework компилятор С++ поддерживает детерминированное освобождение ресурсов и не позволяет вручную применять метод Dispose.

For a detailed discussion about how this interface and the Object.Finalize method are used, see the Garbage Collection and Implementar un método Dispose topics.

Implement IDisposable only if you are using unmanaged resources directly.If your app simply uses an object that implements IDisposable, don't provide an IDisposable implementation.Instead, you should call the object's IDisposable.Dispose implementation when you are finished using it.Depending on your programming language, you can do this in one of two ways:

  • By using a language construct such as the using statement in C# and Visual Basic.

  • By wrapping the call to the IDisposable.Dispose implementation in a try/catch block.

System_CAPS_noteПримечание

Documentation for types that implement IDisposable note that fact and include a reminder to call its Dispose implementation.

If your language supports a construct such as the statement in C# and the statement in Visual Basic, you can use it instead of explicitly calling IDisposable.Dispose yourself.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; } }
}   

The using statement is actually a syntactic convenience.At compile time, the language compiler implements the intermediate language (IL) for a try/catch block.

For more information about the using statement, see the Using Statement (Visual Basic) or using Statement (C# Reference) topics.

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/catch statement.The following example replaces the using block in the previous example with a try/catch/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; } }
}   

For more information about the try/finally pattern, see Try...Catch...Finally Statement (Visual Basic), try-finally (C# Reference), or try-finally Statement (C).

You should implement IDisposable only if your type uses unmanaged resources directly.The consumers of your type can call your IDisposable.Dispose implementation to free resources when the instance is no longer needed.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.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.

System_CAPS_importantВажно

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.

A base class with subclasses that should be disposable must implement IDisposable as follows.You should use this pattern whenever you implement IDisposable on any type that isn't sealed (NotInheritable in Visual Basic).

  • It should provide one public, non-virtual Dispose() method and a protected virtual Dispose(Boolean disposing) method.

  • The Dispose() method must call Dispose(true) and should suppress finalization for performance.

  • The base type should not include any finalizers.

The following code fragment reflects the dispose pattern for base classes.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.
         //
      }

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

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

Subclasses should implement the disposable pattern as follows:

  • They must override Dispose(Boolean) and call the base class Dispose(Boolean) implementation.

  • They can provide a finalizer if needed.The finalizer must call Dispose(false).

Note that derived classes do not themselves implement the IDisposable interface and do not include a parameterless Dispose method.They only override the base class Dispose(Boolean) method.

The following code fragment reflects the dispose pattern for derived classes.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);
   }
}

The following example demonstrates how to create a resource class that implements the IDisposable interface.

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

Universal Windows Platform
Доступно с 4.5
.NET Framework
Доступно с 1.1
Portable Class Library
Поддерживается в версиях: portable .NET platforms
Silverlight
Доступно с 2.0
Windows Phone Silverlight
Доступно с 7.0
Windows Phone
Доступно с 8.1
Вернуться в начало
Показ:
© 2016 Microsoft