Say I have the following:
public abstract class ControlLimitBase : IDisposable
{
}
public abstract class UpperAlarmLimit : ControlLimitBase
{
}
public cl
.Dispose
on it.No, IDisposable
won't be called just automatically. You'd normally call Dispose
with a using
statement, like this:
using (ControlLimitBase limit = new UpperAlarmLimit())
{
// Code using the limit
}
This is effectively a try/finally block, so Dispose
will be called however you leave the block.
CdsUpperAlarmLimit
already implements IDisposable
indirectly. If you follow the normal pattern for implementing IDisposable in non-sealed classes, you'll override void Dispose(bool disposing)
and dispose your composed resources there.
Note that the garbage collector does not call Dispose
itself - although it can call a finalizer. You should rarely use a finalizer unless you have a direct handle on unmanaged resources though.
To be honest, I usually find it's worth trying to change the design to avoid needing to keep hold of unmanaged resources in classes - implementing IDisposable
properly in the general case is frankly a pain. It's not so bad if your class is sealed (no need for the extra method; just implement the Dispose()
method) - but it still means your clients need to be aware of it, so that they can use an appropriate using
statement.
IDisposable is implemented when you want to indicate that your resource has dependencies that must be explicitly unloaded and cleaned up. As such, IDisposable is never called automatically (like with Garbage Collection).
Generally, to handle IDisposables, you should wrap their usage in a using block
using(var x = new CdsUpperAlarmLimit()) { ... }
this compiles to:
CdsUpperAlarmLimit x = null;
try
{
x = new CdsUpperAlarmLimit();
...
}
finally
{
x.Dispose();
}
So, back to topic, if your type, CdsUpperAlarmLimit, is implementing IDisposable, it's saying to the world: "I have stuff that must be disposed". Common reasons for this would be:
The best practice recommend when you implement Dispose()
method in non sealed class you should have a virtual method for your derived classes to override.
Read more on Dispose pattern here http://www.codeproject.com/KB/cs/idisposable.aspx
Dispose()
is never called automatically - it depends on how the code is actually used.
1.) Dispose()
is called when you specifically call Dispose()
:
myAlarm.Dispose();
2.) Dispose()
is called at the end of a using
block using an instance of your type.
using(var myAlarm = new CdsUpperAlarmLimit())
{
}
The using
block is syntactic sugar for a try/finally
block with a call to Dispose()
on the object "being used" in the finally block.
I'm a little confused on when my IDisposable members would actually get called. Would they get called when an instance of CdsUpperAlarmLimit goes out of scope?
No. Its get called when you use using
construct as:
using(var inst = new CdsUpperAlarmLimit())
{
//...
}//<-------- here inst.Dispose() gets called.
But it doesn't get called if you write this:
{
var inst = new CdsUpperAlarmLimit();
//...
}//<-------- here inst.Dispose() does NOT get called.
However, you can write this as well:
var inst = new CdsUpperAlarmLimit();
using( inst )
{
//...
}//<-------- here inst.Dispose() gets called.