IDisposable
is nothing special. It's just an interface that makes you have a Dispose()
function. IDisposable
won't clear anything or destroy objects. A call to Dispose()
does nothing if that function does nothing.
The use of IDisposable
is a pattern. It's so important that it gets its own language construct (the using
block), but it's just a pattern.
The difference with a destructor, is that in .NET, the destructor is non-deterministic. You never know when the garbage collector will collect your object. You don't even know if it even will (unlike using delete
in C++, which is deterministic).
So IDisposable
is there for deterministically releasing unneeded references (and releasing unmanaged resources). The "disposed" object will remain in memory after you call Dispose
until the garbage collector decides to collect it (at which point, the "destructor" will be called, unless you explicitly tell it not-to), if it ever decides to.
That's the main difference to using "destructors" (or finalizers, as they are called in C#).
As for the why do we need it:
- Managed references to other objects prevent objects to be collected by the garbage collector. So you need to "release" those references (by, for example, setting the variables that reference those objects to
null
).
- Objects in .NET can use unmanaged resources, if they use native libraries. For example, every control or bitmap in a
Windows.Forms
application uses a Win32 handler
, which is unmanaged. If you don't release those resources, you may reach the handle limit in Windows if using any big application, easily. Also, if you need interoperability with any non-.NET API, you'll more likely have to allocate unmanaged memory (with the use of, for example, Marshal.AllocHGlobal
), which will need to be released at some point: that point is generally the Dispose()
function of the IDisposable
, which must be called explicitly (or by using a using
block).
As for the using
block, it's more equivalent to:
var myObject = new MyDisposableClass();
try
{
...
}
finally {
myObject.Dispose();
}
So it does indeed save typing