Depending on the .NET language more or less of implementing resource management with the interface IDisposable and the finalizer is hidden. Interestingly, with VB nothing is hidden - however all the code is created automatically with Visual Studio 2005 as soon as the interface IDisposable is implemented.
The syntax implementing the Dispose method of the IDisposable interface and overriding the Finalize method of the Object class is shown with this table:
| IL | C++/CLI | C# | VB |
| Dispose | ~ClassName | Dispose | Dispose |
| Finalize | !ClassName | ~ClassName | Finalize |
Visual Basic does not hide Dispose and Finalize. The automatically created code (with Visual Studio 2005) also includes the Dispose(bool) pattern:
Public Class Resource
Implements IDisposable
Private disposed As Boolean = False
' IDisposable
Private Overloads Sub Dispose(ByVal disposing As Boolean)
If Not Me.disposed Then
If disposing Then
' TODO: put code to dispose managed resources
End If
' TODO: put code to free unmanaged resources here
End If
Me.disposed = True
End Sub
#Region " IDisposable Support "
' This code added by Visual Basic to correctly implement the disposable pattern.
Public Overloads Sub Dispose() Implements IDisposable.Dispose
' Do not change this code. Put cleanup code in Dispose(ByVal disposing As Boolean) above.
Dispose(True)
GC.SuppressFinalize(Me)
End Sub
Protected Overrides Sub Finalize()
' Do not change this code. Put cleanup code in Dispose(ByVal disposing As Boolean) above.
Dispose(False)
MyBase.Finalize()
End Sub
#End Region
End Class
Implementing a similar functionality with C#, the destructor syntax is used to override the Finalize method. The IDisposable interface and the Dispose pattern must be implemented traditionally.
class Resource : IDisposable
{
private bool disposed = false;
~Resource()
{
Dispose(false);
}
protected void Dispose(bool disposing)
{
if (disposing)
{
// dispose managed resources
}
// dispose unmanaged resources
disposed = true;
}
#region IDisposable Members
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
#endregion
public void Foo()
{
if (disposed)
throw new ObjectDisposedException("Object already disposed");
//...
}
}
C++/CLI not only hides the implementation of the Finalize method, but also the implementation of the IDisposable interface with the Dispose method. Contrary to C# where the destructor is used to implement the finalizer, here the destructor is used to implement IDisposable. Calling this method is done with the delete operator. The destructor syntax automatically includes code for GC.SuppressFinalize(this).
To override the Finalize method, a new syntax is used: !Class().
The Dispose(bool) pattern still must be done.
ref class Resource
{
private:
bool disposed;
public:
Resource()
{
disposed = false;
}
~Resource() // IDisposable
{
Dispose(true);
}
protected:
!Resource() // Finalize
{
Dispose(false);
}
void Dispose(bool disposing)
{
if (disposing)
{
// dispose managed resources
}
// dispose unmanaged resources
disposed = true;
}
};
Christian