As a java developer getting into .NET I\'d like to understand the IDisposable interface. Could somebody please try to explain this and how it differs from what happens in Java?
There're situations when you need reliable disposal for resources owned by your class. E.g., opened connection should be closed in proper time, not when GC decides to collect memory. In .NET method Dispose
is used by convention for this. It can be called in try ... finally
block, e.g.:
IConnection conn = OpenConnection();
try{
...
}finally{
conn.Dispose();
}
Because this pattern is so widely used, there's a syntactic sugar for this:
using(IConnection conn = OpenConnection()){
} // Dispose is called at the end.
As this syntax is very concise, sometimes it's useful to implement IDisposable
on objects that don't own resources, but need some operation be executed at the end of its usage. E.g. consider class
class TimeMeasure: IDisposable{
public void Measure(string operation) { ... } // recourds operation time
public void Dispose(){
... // print timings for all operations
}
}
Usage:
using(TimeMeasure m = new TimeMeasure())
{
DoFoo();
m.Measure("Foo");
DoBar();
m.Measure("Bar");
} // timings for 'Foo' and 'Bar' are printed here
In Java more or less equivalent interface is Closeable
. But there's no simple syntax to ensure its calls.
How IDisposable
should be implemented? This is a bit tricky:
Dispose
call or by GC but not by both. So, you need a flag indicating fact of disposal. For less code duplication, the disposal code is moved to separate method.Example:
bool disposed;
public void Dispose(){
Dispose(true);
GC.SuppressFinalize(this); // tell GC not to call Finalizer() for this object
}
~MyObject(){
Dispose(false);
}
void Dispose(bool manualDisposing){
if(!disposed){
disposed = true;
if(manualDisposing)
... // call Dispose on all IDisposable fields
... // dispose all native resources
}
}
TimeMeasure
class, no need for Finalizer, you just do necessary logic in Dispose
.