Note

Access to this page requires authorization. You can try signing in or .

Access to this page requires authorization. You can try .

IDisposable Interface

Definition

Namespace:
System
Assemblies:
mscorlib.dll, System.Runtime.dll
Assemblies:
netstandard.dll, System.Runtime.dll
Assembly:
System.Runtime.dll
Assembly:
mscorlib.dll
Assembly:
netstandard.dll
Source:
IDisposable.cs
Source:
IDisposable.cs
Source:
Base64UrlEncoder.cs

Important

Some information relates to prerelease product that may be substantially modified before it’s released. Microsoft makes no warranties, express or implied, with respect to the information provided here.

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
Derived
Attributes

Examples

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(disposing: true);
 // This object will be cleaned up by the Dispose method.
 // Therefore, you should call GC.SuppressFinalize 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# finalizer syntax for finalization code.
 // 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 finalizer in types derived from this class.
 ~MyResource()
 {
 // Do not re-create Dispose clean-up code here.
 // Calling Dispose(disposing: false) is optimal in terms of
 // readability and maintainability.
 Dispose(disposing: false);
 }
 }
 public static void Main()
 {
 // Insert code here to create
 // and use the MyResource object.
 }
}
// The following example demonstrates how to create
// a resource class that implements the IDisposable interface
// and the IDisposable.Dispose method.
open System
open System.ComponentModel
open System.Runtime.InteropServices

// Use interop to call the method necessary
// to clean up the unmanaged resource.
[<DllImport "Kernel32">]
extern Boolean CloseHandle(nativeint handle)

// A base class that implements IDisposable.
// By implementing IDisposable, you are announcing that
// instances of this type allocate scarce resources.
type MyResource(handle: nativeint) =
 // Pointer to an external unmanaged resource.
 let mutable handle = handle

 // Other managed resource this class uses.
 let comp = new Component()
 
 // Track whether Dispose has been called.
 let mutable disposed = false

 // Implement IDisposable.
 // Do not make this method virtual.
 // A derived class should not be able to override this method.
 interface IDisposable with
 member this.Dispose() =
 this.Dispose true
 // This object will be cleaned up by the Dispose method.
 // Therefore, you should call GC.SuppressFinalize 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.
 abstract Dispose: bool -> unit
 override _.Dispose(disposing) =
 // Check to see if Dispose has already been called.
 if not disposed then
 // If disposing equals true, dispose all managed
 // and unmanaged resources.
 if disposing then
 // Dispose managed resources.
 comp.Dispose()

 // Call the appropriate methods to clean up
 // unmanaged resources here.
 // If disposing is false,
 // only the following code is executed.
 CloseHandle handle |> ignore
 handle <- IntPtr.Zero

 // Note disposing has been done.
 disposed <- true


 // 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 finalizer in types derived from this class.
 override this.Finalize() =
 // Do not re-create Dispose clean-up code here.
 // Calling Dispose(disposing: false) is optimal in terms of
 // readability and maintainability.
 this.Dispose false
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(disposing:=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(disposing:=False) is optimal in terms of
 ' readability and maintainability.
 Dispose(disposing:=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

Remarks

The primary use of the IDisposable interface is to release unmanaged resources. The garbage collector automatically releases the memory allocated to a managed object when that object is no longer used. However, it's not possible to predict when garbage collection will occur. Furthermore, the garbage collector has no knowledge of unmanaged resources such as window handles, or open files and streams.

Use the Dispose method of this interface to explicitly release unmanaged resources in conjunction with the garbage collector. The consumer of an object can call this method when the object is no longer needed.

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.

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.

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.

Use an object that implements IDisposable

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. 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, and the use statement or using function in F#.
  • By wrapping the call to the IDisposable.Dispose implementation in a try/finally block.

Note

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

The C#, F#, and Visual Basic Using statement

If your language supports a construct such as the using statement in C#, the Using statement in Visual Basic, or the use statement in F#, 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; } }
}
open System.IO
open System.Text.RegularExpressions

type WordCount(filename) =
 let txt = 
 if File.Exists filename |> not then
 raise (FileNotFoundException "The file does not exist.")

 use sr = new StreamReader(filename)
 sr.ReadToEnd()

 let pattern = @"\b\w+\b"
 
 let nWords = Regex.Matches(txt, pattern).Count

 member _.FullName = filename

 member _.Name = Path.GetFileName filename

 member _.Count = 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

The using statement (use expression in F#) is actually a syntactic convenience. At compile time, the language compiler implements the intermediate language (IL) for a try/finally block.

For more information about the using statement, see the Using Statement or using Statement topics.

The Try/Finally block

If your programming language does not support a construct like the using statement in C# or Visual Basic, or the use statement in F#, or if you prefer not to use it, you can call the IDisposable.Dispose implementation from the finally block of a try/finally statement. 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 WordCount2
{
 private String filename = String.Empty;
 private int nWords = 0;
 private String pattern = @"\b\w+\b";

 public WordCount2(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; } }
}
open System.IO
open System.Text.RegularExpressions

type WordCount2(filename) =
 let txt = 
 if File.Exists filename |> not then
 raise (FileNotFoundException "The file does not exist.")

 let sr = new StreamReader(filename)
 try
 sr.ReadToEnd()
 finally
 sr.Dispose()

 let pattern = @"\b\w+\b"
 
 let nWords = Regex.Matches(txt, pattern).Count

 member _.FullName = filename

 member _.Name = Path.GetFileName filename

 member _.Count = nWords
Imports System.IO
Imports System.Text.RegularExpressions

Public Class WordCount2
 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

For more information about the try/finally pattern, see Try...Catch...Finally Statement, try-finally, try...finally Expression, or try-finally Statement.

Implement IDisposable

You should implement IDisposable if your type uses unmanaged resources directly or if you wish to use disposable resources yourself. 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. For more information about implementing IDisposable.Dispose, see the Dispose(bool) method overload.

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.

IDisposable and the inheritance hierarchy

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 System;
using System.IO;
using System.Runtime.InteropServices;

class BaseClass1 : IDisposable
{
 // Flag: Has Dispose already been called?
 bool disposed = false;
 // Instantiate a FileStream instance.
 FileStream fs = new FileStream("test.txt", FileMode.OpenOrCreate);

 // Public implementation of Dispose pattern callable by consumers.
 public void Dispose()
 {
 Dispose(disposing: true);
 GC.SuppressFinalize(this);
 }

 // Protected implementation of Dispose pattern.
 protected virtual void Dispose(bool disposing)
 {
 if (disposed)
 return;

 if (disposing)
 {
 fs.Dispose();
 // Free any other managed objects here.
 //
 }

 disposed = true;
 }
}
open System
open System.IO

type BaseClass1() =
 // Flag: Has Dispose already been called?
 let mutable disposed = false

 // Instantiate a FileStream instance.
 let fs = new FileStream("test.txt", FileMode.OpenOrCreate)

 interface IDisposable with
 // Public implementation of Dispose pattern callable by consumers.
 member this.Dispose() =
 this.Dispose true
 GC.SuppressFinalize this

 // Implementation of Dispose pattern.
 abstract Dispose: bool -> unit
 override _.Dispose(disposing) =
 if not disposed then
 if disposing then
 fs.Dispose()
 // Free any other managed objects here.
 disposed <- true
Imports System.IO
Imports System.Runtime.InteropServices

Class BaseClass1 : Implements IDisposable
 ' Flag: Has Dispose already been called?
 Dim disposed As Boolean = False
 ' Instantiate a FileStream instance.
 Dim fs As FileStream = New FileStream("test.txt", FileMode.OpenOrCreate)

 ' Public implementation of Dispose pattern callable by consumers.
 Public Sub Dispose() _
 Implements IDisposable.Dispose
 Dispose(disposing:=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
 fs.Dispose()
 ' Free any other managed objects here.
 '
 End If

 disposed = True
 End Sub
End Class

If you do override the Object.Finalize method, your class should implement the following pattern.

using System;

class BaseClass2 : IDisposable
{
 // Flag: Has Dispose already been called?
 bool disposed = false;

 // Public implementation of Dispose pattern callable by consumers.
 public void Dispose()
 {
 Dispose(disposing: 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;
 }

 ~BaseClass2()
 {
 Dispose(disposing: false);
 }
}
open System

type BaseClass2() =
 // Flag: Has Dispose already been called?
 let mutable disposed = false

 interface IDisposable with
 // Public implementation of Dispose pattern callable by consumers.
 member this.Dispose() =
 this.Dispose true
 GC.SuppressFinalize this

 // Implementation of Dispose pattern.
 abstract Dispose: bool -> unit
 override _.Dispose(disposing) =
 if not disposed then
 if disposing then
 // Free any other managed objects here.
 ()

 // Free any unmanaged objects here.
 disposed <- true

 override this.Finalize() =
 this.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(disposing:=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(disposing:=False)
 End Sub
End Class

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 System;
using System.IO;
using System.Runtime.InteropServices;

class MyDerivedClass : MyBaseClass
{
 // Flag: Has Dispose already been called?
 bool disposed = false;
 // Instantiate a FileStream instance.
 FileStream fs = new FileStream("test.txt", FileMode.OpenOrCreate);

 // Protected implementation of Dispose pattern.
 protected override void Dispose(bool disposing)
 {
 if (disposed)
 return;

 if (disposing)
 {
 fs.Dispose();
 // Free any other managed objects here.
 //
 }

 // Free any unmanaged objects here.
 //

 disposed = true;
 // Call base class implementation.
 base.Dispose(disposing);
 }
}
open Microsoft.Win32.SafeHandles
open System

type MyDerivedClass() =
 inherit MyBaseClass()
 
 // Flag: Has Dispose already been called?
 let mutable disposed = false
 // Instantiate a FileStream instance.
 let fs = new FileStream("test.txt", FileMode.OpenOrCreate)

 // Implementation of Dispose pattern.
 override _.Dispose(disposing) =
 if not disposed then
 if disposing then
 fs.Dispose()
 // Free any other managed objects here.

 // Free any unmanaged objects here.
 disposed <- true
 // Call base class implementation.
 base.Dispose disposing
Imports System.IO
Imports System.Runtime.InteropServices

Class DerivedClass2 : Inherits BaseClass2
 ' Flag: Has Dispose already been called?
 Dim disposed As Boolean = False
 ' Instantiate a FileStream instance.
 Dim fs As FileStream = New FileStream("test.txt", FileMode.OpenOrCreate)

 ' Protected implementation of Dispose pattern.
 Protected Overrides Sub Dispose(disposing As Boolean)
 If disposed Then Return

 If disposing Then
 fs.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

Methods

Name Description
Dispose()

Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.

Applies to

See also


Feedback

Was this page helpful?