views:

157

answers:

5

"File and Font are examples of managed types that access unmanaged resources (in this case file handles and device contexts). There are many other kinds of unmanaged resources and class library types that encapsulate them. All such types must implement the IDisposable interface. As a rule, when you use an IDisposable object, you should declare and instantiate it in a using statement." - MSDN

Is there a list of such cases (managed types that access unmanaged resources like FILE and FONT, ...) where USING statement should be employed?

+2  A: 

Whenever you have a resource that needs deterministic cleanup, i.e. you want it to have a chance to be ``destroyed'' as soon as you're done with it.

In more detail, the IDisposible interface mainly tries to solve the lack of a ``delete'' keyword in .net languages. Because the CLR is garbage collected, you never know when the finalizer (destructor) for an object will be run. The GC is at liberty to wait for as long as you it likes before getting around to releasing the managed resource.

However, many managed resources wrap underlying finite resources - memory is not the only thing that must be allocated and deallocated. As mentioned, file handles are one; database handles another - there are myriad examples. To avoid an inconsistent mess of cleanup idioms, the IDisposible pattern is used to say "Please release your finite resources, I'm done with them". Because it's built into the framework, it gets special language support via "using", to help ensure you never forget to call the Dispose methods, and hence "leak" unmanaged resource.

This does not mean all IDisposible implementers should be wrapped in a using - if you're retaining a reference, and need them in the future, you should certainly not wrap them, as you'd cause premature release of the underlying resource. Call Dispose only when you're finished with the object and thus wrap in "using" only if you know you're done with it after the using scope ends.

So as we'd expect, languages which have deterministic destruction, such as C++/CLI, don't need "using". Non-heap C++/CLI objects have their Dispose method called automatically when they fall out of scope, mimicking the destructor behaviour the pattern tries to capture.

Adam Wright
+2  A: 

No. The MSDN article just told you that you should consider employing it when you use an IDisposable object. There are many framework classes implementing IDisposable, and you will surely define many of your own as well.

mquander
+5  A: 

Any type that implements IDisposable, should use using.

Update (in response to comments): using should surround an instance of an IDisposable type, assuming it is not required in a larger scope.

Mitch Wheat
would the down voter please leave a comment. Thanks
Mitch Wheat
2 downvotes and no comments. what gives?
Mitch Wheat
Assuming the IDisposable is a local variable. If it is a class member you should implement IDisposable yourself to clean these objects up.
Matthew Whited
I'll vote this up, but I think for completeness this should include that `using` may not always be a feasible solution due to differing scope of allocation and de-allocation. (And then a design should be preferred where the object is owned by another class during its lifetime that implements `IDisposable` if possible ;)
jerryjvl
Because you should only call Dispose when you are completely finished with the resource. Wrapping any type implementing IDisposable in using is wrong in general; you (or another) may have retained a reference to the object for later use.
Adam Wright
Sometimes you might nest an IDisposable in another type that also implements IDisposable, but then the parent type should dispose the child it's in own dispose event and should itself be created in a using block. Bottom line, you put it in a using somewhere up the chain.
Joel Coehoorn
@jerryjvl: true. I was assuming that people would understand that, but I should have been explicit.
Mitch Wheat
+2  A: 

The correct approach is always to use the using statement when the type implements the IDisposable interface, but know exceptions of the rule.

Known Exceptions:

  • Main form (Windows Forms application, because it's managed by the Application class)
  • SystemPens.*, SystemBrushes.* (these static instances are cached internally)
  • Icons.* (these static instances are cached internally)
  • Registry.* (these static instances are cached internally)
  • AutoResetEvent, ManualResetEvent (should actually be disposed, but if you do it make it very carefully as it may cause racing conditions)

The list of known exceptions is surely not complete.

Michael Damatov
Registry does not implement IDisposable.Icon implements so Dispose() should be called...
Mitch Wheat
Datasets and Datatables are disposable, but don't hold any unmanaged resources.
Joel Coehoorn
@Joel Coehoorn: I think if you Reflecter into Datasets and Datatables, the Dispose() call does nothing.
Mitch Wheat
@Joel, @Mitch. Whether DataSets and DataTables handle unmanaged resources or not is an implementation detail and could (in theory) change at some point in the future. In general, best practice is to ensure that any IDisposable is disposed.
LukeH
@ Luke: I realise that. That's what my answer basically says...
Mitch Wheat
@Mitch. Yep, that's why I already upvoted your answer ;)
LukeH
MemoryStream is disposable, but doesn't hold any unmanaged resources too.
Michael Damatov
A: 

The simple rule is "any time you have a resource that should be freed immediately after use, rather than at some unknown point in the future, when the garbage collector gets around to freeing it".

All limited resources, basically, unmanaged or managed. Files, network sockets, database connections, registry handles, anything that shouldn't be left floating around indefinitely.

jalf