Allright, here it goes a good piece of bad code:
public class Log : CachingProxyList<Event> {
public static Log FromFile(String fullPath) {
using (FileStream fs = new FileStream(fullPath, FileMode.Open, FileAccess.Read)) {
using (StreamReader sr = new StreamReader(fs)) {
return new Log(sr);
}
}
}
public Log(StreamReader stream)
: base(Parser.Parse(Parser.Tokenize(stream))) {
/* Here goes some "magic", the whole reason for this
* class to exist, but not really relevant to the issue */
}
}
And now some context into the issue:
CachingProxyList is an implementation of IEnumerable<T> that provides a custom "caching" enumerator: it takes an IEnumerable<T> on its constructor, and initially enumerates through it, but saves each item on a private List<T> field so further iterations run through that before going on with the actual parsing (rather than parsing every now and again; or having to parse a huge log just to query a small portion of it).
Note that this optimization was actually needed, and most of it is already working (if I remove the using statements, everything goes fine except for the leaking file handles).
Both Parse and Tokenize are iterator blocks (AFAIK, the only sane way I could have deferred execution and clean code at the same time); their signatures are IEnumerable<Event> Parse(IEnumerable<Token>) and IEnumerable<Token> Tokenize(StreamReader). Their logics are unrelated to the issue.
The logical flow is quite clear; and the intent of each part of the code rather obvious; but those using blocks don't get along with the whole deferred execution thing (by the time I'm enumerating through my Log object, the using have already been exited and the stream disposed, so Tokenize's attempts to read from it miserably crash).
I can afford having a lock on the file (the open stream) for a relatively long time, but sooner or later I'll have to close it. Since I can't really use the usings, I'll have to explicitly dispose of the streams.
The question is: where should I put the calls to Dispose()? Is there any common idiom to deal with scenarios like these? I wouldn't like to do this the "old way" (releasing resources at several places, having to review each release anytime a tiny bit of the code changes somewhere, and so on).
My first idea was making the Log class disposable, so its constructor could take a file-name and have all the resource-management within the class (requiring only the consumer to dispose of the Log itself when done), but I can see no way of creating and saving the stream before calling the base constructor (the stream is required for the calls that yield the argument for that constructor).
Note: the CachingProxyList shouldn't be touched unless strictly needed (I want to keep it generic enough to make it reusable). Specially, the constructor is essential to enforce some invariants the rest of the implementation heavily relies in (such as the internal enumerator objects never being null). Everything else, OTOH, should be fair game.
Thanks for your patience if you have read this, and also thanks in advance for any help provided ;).
Classes that encapsulate unmanaged resources need to implement dispose pattern (IDisposable interface). For example stream, database connection, etc
Every resource must have one owner
Owner is responsible for calling Dispose() on the resource
If owner cannot immediately call Dispose() on its resource or does not know when to call it, then it needs to implement IDisposable interface itself and call Dispose() on its resource in there.
Above statements could have exceptions but that is the general rule. Example is StreamWriter which takes in a stream (which implement IDisposable interface) and that forces it to implement IDisposable interface itself - since it does not know when to dispose it.
It is the same in your case. Your class uses a disposable resource while it does not know when to dispose it - or that is what I assume. This would make it to implement IDisposable interface. Client of your Log class will have to call Dispose() on your class.
So as you can see, this becomes a chain while the non-disposable client will have to call dispose on the resource it uses and that resource will dispose its resource, etc...
Related
TL;DR -- Is it ever appropriate to execute business logic in IDisposable.Dispose?
In my search for an answer, I read through the question: Is it abusive to use IDisposable and "using" as a means for getting "scoped behavior" for exception safety? It came very close to addressing this issue, but I'd like to attack it dead on. I recently encountered some code that looked like this:
class Foo : IDisposable
{
public void Dispose()
{
ExecuteSomeBusinessBehavior();
NormalCleanup();
}
}
and is used in a context such as:
try
{
using (var myFoo = new Foo())
{
DoStuff();
foo.DoSomethingFooey();
...
DoSomethingElse();
Etc();
}
}
catch (Exception ex)
{
// Handle stuff
}
Upon seeing this code I immediately began to itch. Here's what I see when I look at this code:
First, looking at just the usage context, it's not remotely apparent that actual business logic, not just cleanup code, will be executed when the code leaves the using scope.
Second, if any of the code within the "using" scope throws an exception, the business logic in the Dispose method will still execute and does so before the Try/Catch can handle the exception.
My questions to the StackOverflow community are these: Does it ever make sense to put business logic in the IDisposable.Dispose method? Is there a pattern that achieves similar results without making me itch?
(Sorry, this is more of a comment, but it exceeds the comment length limit.)
Actually, there is an example in the .NET framework where IDisposable is used to create a scope and do useful work when disposing: TransactionScope.
To quote from TransactionScope.Dispose:
Calling this method marks the end of the transaction scope. If the TransactionScope object created the transaction and Complete was called on the scope, the TransactionScope object attempts to commit the transaction when this method is called.
If you decide to take that route, I would suggest that
you make it blatantly obvious that your object creates a scope, e.g., by calling it FooScope instead of Foo and
you think very hard about what should happen when an exception causes the code to leave your scope. In TransactionScope, the pattern of calling Complete at the end of the block ensures that Dispose can distinguish between the two cases.
The real meaning of IDisposable is that an object knows of something, somewhere which has been put into a state that should be cleaned up, and it has the information and impetus necessary to perform such cleanup. Although the most common "states" associated with IDisposable are things like files being open, unmanaged graphic objects being allocated, etc. those are only examples of uses, and not a definition of "proper" use.
The biggest issue to consider when using IDisposable and using for scoped behavior is that there is no way for the Dispose method to distinguish scenarios where an exception is thrown from a using block from those where it exits normally. This is unfortunate, since there are many situations where it would be useful to have scoped behavior which was guaranteed to have one of two exit paths depending upon whether the exit was normal or abnormal.
Consider, for example, a reader-writer lock object with a method that returns an IDisposable "token" when the lock is acquired. It would be nice to say:
using (writeToken = myLock.AcquireForWrite())
{
... Code to execute while holding write lock
}
If one were to manually code the acquisition and release of the lock without a try/catch or try/finally lock, an exception thrown while the lock was held would cause any code that was waiting on the lock to wait forever. That is a bad thing. Employing a using block as shown above will cause the lock to be released when the block exits, whether normally or via exception. Unfortunately, that may also be a bad thing.
If an unexpected exception is thrown while a write-lock is held, the safest course of behavior would be to invalidate the lock so that any present or future attempt to acquire the lock will throw an immediate exception. If the program cannot usefully proceed without the locked resource being usable, such behavior would cause it to shut down quickly. If it can proceed e.g. by switching to some alternate resource, invalidating the resource will allow it to get on with that much more effectively than would leaving the lock uselessly acquired. Unfortunately, I don't know of any nice pattern to accomplish that. One could do something like:
using (writeToken = myLock.AcquireForWrite())
{
... Code to execute while holding write lock
writeToken.SignalSuccess();
}
and have the Dispose method invalidate the token if it's called before success has been signaled, but an accidental failure to signal the success could cause the resource to become invalid without offering indication as to where or why that happened. Having the Dispose method throw an exception if code exits a using block normally without calling SignalSuccess might be good, except that throwing an exception when it exits because of some other exception would destroy all information about that other exception, and there's no way Dispose can tell which method applies.
Given those considerations, I think the best bet is probably to use something like:
using (lockToken = myLock.CreateToken())
{
lockToken.AcquireWrite(Describe how object may be invalid if this code fails");
... Code to execute while holding write lock
lockToken.ReleaseWrite();
}
If code exits without calling ReleaseWrite, other threads that try to acquire the lock will receive exceptions that include the indicated message. Failure to properly manually pair the AcquireWrite and ReleaseWrite will leave the locked object unusable, but not leave other code waiting for it to become usable. Note that an unbalanced AcquireRead would not have to invalidate the lock object, since code inside the read would never put the object into an invalid state.
Business logic code should never be written in any circumstances to Dispose method reason is, you are relying on a unreliable path. What if user does not call your dispose method? You missed to call a complete functionality ? What if there was an exception thrown in the method call of your dispose method? And why would you perform a business operation when user is asking to dispose the object itself. So logically, technically it should not be done.
I'm currently reading Introduction to Rx, by Lee Campbell, and it has a chapter called IDisposable, where he explicitly advocates taking advantage of the integration with the using construct, in order to "create transient scope".
Some key quotations from that chapter:
"If we consider that we can use the IDisposable interface to effectively create a scope, you can create some fun little classes to leverage this."
(...see examples below...)
"So we can see that you can use the IDisposable interface for more than just common use of deterministically releasing unmanaged resources. It is a useful tool for managing lifetime or scope of anything; from a stopwatch timer, to the current color of the console text, to the subscription to a sequence of notifications.
The Rx library itself adopts this liberal usage of the IDisposable interface and introduces several of its own custom implementations:
BooleanDisposable
CancellationDisposable
CompositeDisposable
ContextDisposable
MultipleAssignmentDisposable
RefCountDisposable
ScheduledDisposable
SerialDisposable
SingleAssignmentDisposable"
He gives two fun little examples, indeed:
Example 1 - Timing code execution. "This handy little class allows you to create scope and measure the time certain sections of your code base take to run."
public class TimeIt : IDisposable
{
private readonly string _name;
private readonly Stopwatch _watch;
public TimeIt(string name)
{
_name = name;
_watch = Stopwatch.StartNew();
}
public void Dispose()
{
_watch.Stop();
Console.WriteLine("{0} took {1}", _name, _watch.Elapsed);
}
}
using (new TimeIt("Outer scope"))
{
using (new TimeIt("Inner scope A"))
{
DoSomeWork("A");
}
using (new TimeIt("Inner scope B"))
{
DoSomeWork("B");
}
Cleanup();
}
Output:
Inner scope A took 00:00:01.0000000
Inner scope B took 00:00:01.5000000
Outer scope took 00:00:02.8000000
Example 2 - Temporarily changing console text color
//Creates a scope for a console foreground color. When disposed, will return to
// the previous Console.ForegroundColor
public class ConsoleColor : IDisposable
{
private readonly System.ConsoleColor _previousColor;
public ConsoleColor(System.ConsoleColor color)
{
_previousColor = Console.ForegroundColor;
Console.ForegroundColor = color;
}
public void Dispose()
{
Console.ForegroundColor = _previousColor;
}
}
Console.WriteLine("Normal color");
using (new ConsoleColor(System.ConsoleColor.Red))
{
Console.WriteLine("Now I am Red");
using (new ConsoleColor(System.ConsoleColor.Green))
{
Console.WriteLine("Now I am Green");
}
Console.WriteLine("and back to Red");
}
Output:
Normal color
Now I am Red
Now I am Green
and back to Red
Regarding the Microsoft built classes that inherit IDisposable, do I explicitly have to call Dispose to prevent memory leaks?
I understand that it is best practice to call Dispose (or better yet use a using block), however when programming, typically I don't always immediately realise that a class inherits from IDisposable.
I also understand that Microsoft implementation of IDisposable is a bit borked, which is why they created the article explaining the correct usage of IDisposable.
Long story short, in which instances is it okay to forget to call Dispose?
There are a couple of issues in the primary question
Do I explicitly have to call Dispose to prevent memory leaks?
Calling Dispose on any type which implements IDisposable is highly recomended and may even be a fundamental part of the types contract. There is almost no good reason to not call Dispose when you are done with the object. An IDisposable object is meant to be disposed.
But will failing to call Dispose create a memory leak? Possibly. It's very dependent on what exactly that object does in it's Dispose method. Many free memory, some unhook from events, others free handles, etc ... It may not leak memory but it will almost certainly have a negative effect on your program
In which instances is it okay to forget to call Dispose?
I'd start with none. The vast majority of objects out there implement IDisposable for good reason. Failing to call Dispose will hurt your program.
It depends on two things:
What happens in the Dispose method
Does the finalizer call Dispose
Dispose functionlity
Dispose can do several type of actions, like closing a handle to a resource (like file stream), change the class state and release other components the class itself uses.
In case of resource being released (like file) there's a functionality difference between calling it explicitly and waiting for it to be called during garbage collection (assuming the finalizer calls dispose).
In case there's no state change and only components are released there'll be no memory leak since the object will be freed by the GC later.
Finalizer
In most cases, disposable types call the Dispose method from the finalizer. If this is the case, and assuming the context in which the dispose is called doesn't matter, then there's a high chance that you'll notice no difference if the object will not be disposed explicitly. But, if the Dispose is not called from the finalizer then your code will behave differently.
Bottom line - in most cases, it's better to dispose the object explicitly when you're done with it.
A simple example to where it's better to call Dispose explicitly: Assuming you're using a FileStream to write some content and enable no sharing, then the file is locked by the process until the GC will get the object. The file may also not flush all the content to the file so if the process crashes in some point after the write was over it's not guaranteed that it will actually be saved.
It can be safe to not call Dispose, but the problem is knowing when this is the case.
A good 95% of IEnumerator<T> implementations have a Dispose that's safe to ignore, but the 5% is not just 5% that'll cause a bug, but 5% that'll cause a nasty hard to trace bug. More to the point, code that gets passed an IEnumerator<T> will see both the 95% and the 5% and won't be able to dynamically tell them apart (it's possible to implement the non-generic IEnumerable without implementing IDisposable, and how well that turned out can be guessed at by MS deciding to make IEnumerator<T> inherit from IDisposable!).
Of the rest, maybe there's 3 or 4% of the time it's safe. For now. You don't know which 3% without looking at the code, and even then the contract says you have to call it, so the developer can depend on you doing so if they release a new version where it is important.
In summary, always call Dispose(). (I can think of an exception, but it's frankly too weird to even go into the details of, and it's still safe to call it in that case, just not vital).
On the question of implementing IDisposable yourself, avoid the pattern in that accursed document.
I consider that pattern an anti-pattern. It is a good pattern for implementing both IDisposable.Dispose and a finaliser in a class that holds both managed and unmanaged resources. However holding both managed IDisposable and unmanaged resources is a bad idea in the first place.
Instead:
If you have an unmanaged resource, then don't have any unmanaged resources that implement IDisposable. Now the Dispose(true) and Dispose(false) code paths are the same, so really they can become:
public class HasUnmanaged : IDisposable
{
IntPtr unmanagedGoo;
private void CleanUp()
{
if(unmanagedGoo != IntPtr.Zero)
{
SomeReleasingMethod(unmanagedGoo);
unmanagedGoo = IntPtr.Zero;
}
}
public void Dispose()
{
CleanUp();
GC.SuppressFinalize(this);
}
~HasUnmanaged()
{
CleanUp();
}
}
If you have managed resources that need to be disposed, then just do that:
public class HasUnmanaged : IDisposable
{
IDisposable managedGoo;
public void Dispose()
{
if(managedGoo != null)
managedGoo.Dispose();
}
}
There, no cryptic "disposing" bool (how can something be called Dispose and take false for something called disposing?) No worrying about finalisers for the 99.99% of the time you won't need them (the second pattern is way more common than the first). All good.
Really need something that has both a managed and an unmanaged resource? No, you don't really, wrap the unmanaged resource in a class of your own that works as a handle to it, and then that handle fits the first pattern above and the main class fits the second.
Only implement the CA10634 pattern when you're forced to because you inherited from a class that did so. Thankfully, most people aren't creating new ones like that any more.
It is never OK to forget to call Dispose (or, as you say, better yet use using).
I guess if the goal of your program is to cause unmanaged resource leaks. Then maybe it would be OK.
The implementation of IDisposable indicates that a class uses un-managed resources. You should always call Dispose() (or use a using block when possible) when you're sure you're done with the class. Otherwise you are unnecessarily keeping un-managed resources allocated.
In other words, never forget to call Dispose().
Yes, always call dispose. Either explicitly or implicitly (via using). Take, for example, the Timer class. If you do not explicitly stop a timer, and do not dispose it, then it will keep firing until the garbage collector gets around to collecting it. This could actually cause crashes or unexpected behavior.
It's always best to make sure Dispose is called as soon as you are done with it.
Microsoft (probably not officially) says it is ok to not call Dispose in some cases.
Stephen Toub from Microsoft writes (about calling Dispose on Task):
In short, as is typically the case in .NET, dispose aggressively if
it's easy and correct to do based on the structure of your code. If
you start having to do strange gyrations in order to Dispose (or in
the case of Tasks, use additional synchronization to ensure it's safe
to dispose, since Dispose may only be used once a task has completed),
it's likely better to rely on finalization to take care of things. In
the end, it's best to measure, measure, measure to see if you actually
have a problem before you go out of your way to make the code less
sightly in order to implement clean-up functionality.
[bold emphasize is mine]
Another case is base streams
var inner = new FileStrem(...);
var outer = new StreamReader(inner, Encoding.GetEncoding(1252));
...
outer.Dispose();
inner.Dispose(); -- this will trigger a FxCop performance warning about calling Dispose twice.
(I have turned off this rule)
I was reading about this scenario where making use of the C# using statement can cause problems. Exceptions thrown within the scope of the using block can be lost if the Dispose function called at the end of the using statement was to throw an exception also. This highlights that care should be taken in certain cases when deciding whether to add the using statement.
I only tend to make use of using statements when using streams and the classes derived from DbConnection. If I need to clean up unmanaged resources, I would normally prefer to use a finally block.
This is another use of the IDisposable interface to create a performance timer that will stop the timer and log the time to the registry within the Dispose function.
http://thebuildingcoder.typepad.com/blog/2010/03/performance-profiling.html
Is this good use of the IDisposable interface? It is not cleaning up resources or disposing of any further objects. However, I can see how it could clean up the calling code by wrapping the code it is profiling neatly in a using statement.
Are there times when the using statement and the IDisposable interface should never be used? Has implementing IDisposable or wrapping code in a using statement caused problems for you before?
Thanks
I would say, always use using unless the documentation tells you not to (as in your example).
Having a Dispose method throw exceptions rather defeats the point of using it (pun intended). Whenever I implement it, I always try to ensure that no exceptions will be thrown out of it regardless of what state the object is in.
PS: Here's a simple utility method to compensate for WCF's behaviour. This ensures that Abort is called in every execution path other than when Close is called, and that errors are propogated up to the caller.
public static void CallSafely<T>(ChannelFactory<T> factory, Action<T> action) where T : class {
var client = (IClientChannel) factory.CreateChannel();
bool success = false;
try {
action((T) client);
client.Close();
success = true;
} finally {
if(!success) {
client.Abort();
}
}
}
If you find any other funny behaviour cases elsewhere in the framework, you can come up with a similar strategy for handling them.
The general rule of thumb is simple: when a class implements IDisposable, use using. When you need to catch errors, use try/catch/finally, to be able to catch the errors.
A few observations, however.
You ask whether situations exist where IDisposable should not be used. Well: in most situations you shouldn't need to implement it. Use it when you want to free up resources timely, as opposed to waiting until the finalizer kicks in.
When IDisposable is implemented, it should mean that the corresponding Dispose method clears its own resources and loops through any referenced or owned objects and calls Dispose on them. It should also flag whether Dispose is called already, to prevent multiple cleanups or referenced objects to do the same, resulting in an endless loop. However, all this is no guarantee that all references to the current object are gone, which means it will remain in memory until all references are gone and the finalizer kicks in.
Throwing exceptions in Dispose is frowned upon and when it happens, state is possibly not guaranteed anymore. A nasty situation to be in. You can fix it by using try/catch/finally and in the finally block, add another try/catch. But like I said: this gets ugly pretty quickly.
Using using is one thing, but don't confuse it with using try/finally. Both are equal, but the using-statement makes life easier by adding scoping and null-checks, which is a pain to do by hand each time. The using-statement translates to this (from C# standard):
{
SomeType withDispose = new SomeType();
try
{
// use withDispose
}
finally
{
if (withDispose != null)
{
((IDisposable)withDispose).Dispose();
}
}
}
There are occasions where wrapping an object into a using-block is not necessary. These occasions are rare. They happen when you find yourself inheriting from an interface that inherits from IDisposable just in case a child would require disposing. An often-used example is IComponent, which is used with every Control (Form, EditBox, UserControl, you name it). And I rarely see people wrapping all these controls in using-statements. Another famous example is IEnumerator<T>. When using its descendants, one rarely sees using-blocks either.
Conclusion
Use the using-statement ubiquitously, and be judicious about alternatives or leaving it out. Make sure you know the implications of (not) using it, and be aware of the equality of using and try/finally. Need to catch anything? Use try/catch/finally.
I think the bigger problem is throwing exceptions in Dispose. RAII patterns usually explicitly state that such should not be done, as it can create situations just like this one. I mean, what is the recovery path for something not disposing correctly, other than simply ending execution?
Also, it seems like this can be avoided with two try-catch statements:
try
{
using(...)
{
try
{
// Do stuff
}
catch(NonDisposeException e)
{
}
}
}
catch(DisposeException e)
{
}
The only problem that can occur here is if DisposeException is the same or a supertype of NonDisposeException, and you are trying to rethrow out of the NonDisposeException catch. In that case, the DisposeException block will catch it. So you might need some additional boolean marker to check for this.
The only case I know about is WCF clients. That's due to a design bug in WCF - Dispose should never throw exceptions. They missed that one.
One example is the IAsyncResult.AsyncWaitHandle property. The astute programmer will recognize that WaitHandle classes implement IDisposable and naturally try to greedily dispose them. Except that most of the implementations of the APM in the BCL actually do lazy initialization of the WaitHandle inside the property. Obviously the result is that the programmer did more work than was necessary.
So where is the breakdown? Well, Microsoft screwed up the IAsyncResult inteface. Had they followed their own advice IAsyncResult would have derived from IDisposable since the implication is that it holds disposable resources. The astute programmer would then just call Dispose on the IAsyncResult and let it decide how best to dispose its constituents.
This is one of the classic fringe cases where disposing of an IDisposable could be problematic. Jeffrey Richter actually uses this example to argue (incorrectly in my opinion) that calling Dispose is not mandatory. You can read the debate here.
This seems like a fairly straightforward question, but I couldn't find this particular use-case after some searching around.
Suppose I have a simple method that, say, determines if a file is opened by some process. I can do this (not 100% correctly, but fairly well) with this:
public bool IsOpen(string fileName)
{
try
{
File.Open(fileName, FileMode.Open, FileAccess.Read, FileShare.None);
}
catch
{
// if an exception is thrown, the file must be opened by some other process
return true;
}
}
(obviously this isn't the best or even correct way to determine this - File.Open throws a number of different exceptions, all with different meanings, but it works for this example)
Now the File.Open call returns a FileStream, and FileStream implements IDisposable. Normally we'd want to wrap the usage of any FileStream instantiations in a using block to make sure they're disposed of properly. But what happens in the case where we don't actually assign the return value to anything? Is it still necessary to dispose of the FileStream, like so:
try
{
using (File.Open(fileName, FileMode.Open, FileAccess.Read, FileShare.None));
{ /* nop */ }
}
catch
{
return true;
}
Should I create a FileStream instance and dispose of that?
try
{
using (FileStream fs = File.Open(fileName, FileMode.Open, FileAccess.Read, FileShare.None));
}
...
Or are these totally unnecessary? Can we simply call File.Open and not assign it to anything (first code example), and let the GC dispose of it right away?
Yes, you should definitely dispose of the FileStream. Otherwise the stream will remain open and the file won't be usable until a finalizer happens to clean it up.
The important thing here is ownership: for File.Open, the caller is assumed to "own" the stream returned to it - and if you own something which implements IDisposable, it's your responsibility to dispose of it.
Compare this with the situation of Image.FromStream: in that case, you pass in a stream and the Image then assumes that it owns that stream. You mustn't close the stream yourself, in that case - you have to dispose of the image when you're done, and it will dispose of the stream.
Calling a static method which returns something disposable almost always assumes that the caller takes ownership of the resource. Ditto constructors (which are effectively static methods.)
The irony in this case is that if you don't dispose of the stream returned by File.Open, you'll have found that the file is usable - at the same time as making it unusable until some indeterminate time.
If a method returns an IDisposable, I personally would always put it in a using block. Even if I don't assign the return value to anything.
Even if you don't assign it to a variable, the disposable object is still created. Dispose is not going to be called automatically. The only difference will be that the returned object will become immediately eligible for garbage collection, because there are no (strong) references to it.
The garbage collector does not call Dispose automatically when it reclaims an object. However, most IDisposable types provide a finalizer (which will be called just before the GC reclaims an object) that invokes Dispose as a fallback strategy (safety net) — study the IDisposable pattern to see how this is done:
~SomeClass // <-- the finalizer method will usually call Dispose;
{ // but you have no control over when it will be called!
Dispose(false);
}
Remember that you don't know when the garbage collector will run (because it's non-deterministic). Therefore, you also don't know when the finalizer method will be called. And because of that -- if you haven't called Dispose explicitly (either yourself, or with a using block) -- you don't know when it will be called by the finalizer.
That's the advantage of calling Dispose explicitly: You can free resources -- or at least allow the GC to free managed resources -- as soon as you're done with them, instead of holding on to resources until the finalizer gets called sometime in the future.
Yes, you don't want to leave the FileStream opened. For one, you won't even be able to open the file yourself after that. Calling Close() is good enough, but using using is probably the preferred pattern.
There's a much bigger problem with your code however. It cannot possibly work reliably on Windows. A typical scenario:
The File.Open() call succeeds. You close it
Your thread gets pre-empted by the Windows scheduler
Another thread in another process gets a chance to run, it opens the file
Your thread regains the CPU and continues after the File.Open() call
You open the file, trusting that it will work since IsOpen() returned false.
Kaboom.
Never write code like this, failure is extremely hard to diagnose. Only ever open a file when you are ready to start reading or writing to it. And don't close it until you are done.
Extra bonus: it is now obvious that you want to use a using statement.
When you call any method that returns something, an instance of that something is being created. Just because you're not actually capturing it, doesn't make it any less "there". Therefore, in the case of an IDisposable object, the object is being created by the method you're calling in spite of the fact that you're doing nothing with it. So yes, you still need to dispose of it somehow. The first approach with the using statement seems like it should work.
I've been debugging some code recently that was a bit memory leaky. It's a long running program that runs as a Windows service.
If you find a class wearing an IDisposable interface, it is telling you that some of the resources it uses are outside the abilities of the garbage collector to clean up for you.
The reason it is telling you this is that you, the user of this object, are now responsible for when these resources are cleaned up. Congratulations!
As a conscientious developer, you are nudged towards calling the .Dispose() method when you've finished with the object in order to release those unmanaged resources.
There is the nice using() pattern to help clean up these resources once they are finished with. Which just leaves finding which exact objects are causing the leakyness?
In order to aid tracking down these rogue unmanaged resources, is there any way to query what objects are loitering around waiting to be Disposed at any given point in time?
There shouldn't be any cases where you don't want to call Dispose, but the compiler cannot tell you where you should call dispose.
Suppose you write a factory class which creates and returns disposable objects. Should the compiler bug you for not calling Dispose when the cleanup should be the responsibility of your callers?
IDisposable is more for making use of the using keyword. It's not there to force you to call Dispose() - it's there to enable you to call it in a slick, non-obtrusive way:
class A : IDisposable {}
/// stuff
using(var a = new A()) {
a.method1();
}
after you leave the using block, Dispose() is called for you.
"Is there any way to detect at the end of the program which objects are loitering around waiting to be Disposed?"
Well, if all goes well, at the end of the program the CLR will call all object's finalizers, which, if the IDisposable pattern was implemented properly, will call the Dispose() methods. So at the end, everything will be cleared up properly.
The problem is that if you have a long running program, chances are some of your IDiposable instances are locking some resources that shouldn't be locked. For cases like this, user code should use the using block or call Dispose() as soon as it is done with an object, but there's really no way for a anyone except the code author to know that.
You are not required to call the Dispose method. Implementing the IDisposable interface is a reminder that your class probably is using resources such as a database connection, a file handle, that need to be closed, so GC is not enough.
The best practice AFAIK is to call Dispose or even better, put the object in a using statement.
A good example is the .NET 2.0 Ping class, which runs asynchronously. Unless it throws an exception, you don't actually call Dispose until the callback method. Note that this example has some slightly weird casting due to the way Ping implements the IDisposable interface, but also inherits Dispose() (and only the former works as intended).
private void Refresh( Object sender, EventArgs args )
{
Ping ping = null;
try
{
ping = new Ping();
ping.PingCompleted += PingComplete;
ping.SendAsync( defaultHost, null );
}
catch ( Exception )
{
( (IDisposable)ping ).Dispose();
this.isAlive = false;
}
}
private void PingComplete( Object sender, PingCompletedEventArgs args )
{
this.isAlive = ( args.Error == null && args.Reply.Status == IPStatus.Success );
( (IDisposable)sender ).Dispose();
}
Can I ask how you're certain that it's specifically objects which implement IDisposable? In my experience the most-likely zombie objects are objects which have not properly had all their event handlers removed (thereby leaving a reference to them from another 'live' object and not qualifying them as unreachable during garbage collection).
There are tools which can help track these down by taking a snapshot of the managed heap and stacks and allowing you to see what objects are considered in-use at a given point in time. A freebie is windbg using sos.dll; it'll take some googling for tutorials to show you the commands you need--but it works and it's free. A more user-friendly (don't confused that with "simple") option is Red Gate's ANTS Profiler running in Memory Profiling mode--it's a slick tool.
Edit: Regarding the usefulness of calling Dispose--it provides a deterministic way to cleanup objects. Garbage Collection only runs when your app has ran out of its allocated memory--it's an expensive task which basically stops your application from executing and looks at all objects in existance and builds a tree of "reachable" (in-use) objects, then cleans up the unreachable objects. Manually cleaning up an object frees it before GC ever has to run.
Because the method creating the disposable object may be legitimately returning it as a value, that is, the compiler can't tell how the programming is intending to use it.
What if the disposable object is created in one class/module (say a factory) and is handed off to a different class/module to be used for a while before being disposed of? That use case should be OK, and the compiler shouldn't badger you about it. I suspect that's why there's no compile-time warning---the compiler assumes the Dispose call is in another file.
Determining when and where to call Dispose() is a very subjective thing, dependent on the nature of the program and how it uses disposable objects. Subjective problems are not something compilers are very good at. Instead, this is more a job for static analysis, which is the arena of tools like FxCop and StyleCop, or perhaps more advanced compilers like Spec#/Sing#. Static analysis uses rules to determine if subjective requirements, such as "Always ensure .Dispose() is called at some point.", are met.
I am honestly not sure if any static analyzers exist that are capable of checking whether .Dispose() is called. Even for static analysis as it exists today, that might be a bit on the too-subjective side of things. If you need a place to start looking, however, "Static Analysis for C#" is probably the best place.