Reputation: 7585
I was talking with a person about using() statement.
He said if we do NOT use using() statement for something like a StreamWriter, if any exception happens, the resource will NEVER get collected.
I do understand to use using() statement, but I don't agree that the resource will never be collected. I think using() statement will call dispose() method at the end, which can make the collection much faster. However, even if we don't use using(), we don't call dispose(), the resource can still be collected by gabage collection, although it may take much longer time.
Who do you agree with?
ps. I know what you all are saying. It's important to use using() statement. I just want to find out if the resource will definitely never get collected if we don't do it?
Upvotes: 5
Views: 1354
Reputation: 81149
If a StreamWriter is created with a Stream that will be used by other code even after the StreamWriter has been abandoned, one must not call Dispose on the StreamWriter. If the stream will be abandoned by its owner after being given to a StreamWriter, then for correctness one must call Dispose on the StreamWriter.
In retrospect, StreamWriter should probably have had a do-nothing IDisposable implementation, but had an descendant class StreamOwningWriter whose implementation would dispose the passed-in stream. Alternatively, it could have had a constructor parameter and property to indicate whether it should dispose the stream when its own Dispose method is called. Had either of these approaches been taken, then the correct behavior would always have been to call Dispose on a StreamWriter (and let the "StreamWriter" (which could be either a StreamWriter or a StreamOwningWriter) worry about whether the Dispose should actually do anything).
Upvotes: 0
Reputation: 59463
I was talking with a person about using() statement. He said if we do NOT use using() statement for something like a StreamWriter, if any exception happens, the resource will NEVER get collected.
The using
statement has nothing to do with garbage collection. As soon as an object has no live references it becomes eligible for garbage collection.
I do understand to use using() statement, but I don't agree that the resource will never be collected.
Oh, then you're right.
I think using() statement will call dispose() method at the end, which can make the collection much faster.
It may or may not make the collection faster. It is typical for a dispose method to call GC.SupressFinalize(object)
, which means that the finalizer will not be called when the object is garbage collected. Instead, the object will simply be collected. So this could make the collection faster.
If you intend to say that it causes the object to be collected immediately rather than later, then that would be incorrect. Eligible objects are collected whenever the garbage collector gets around to it, never before, and an object become eligible as soon as it has no live references, which the using
statement has little effect on. Actually, since the finally block of the using statement contains a live reference, I can imagine scenerios in which it might increase the lifetime of the object, but this effect is not a consideration, since controlling an object's lifetime is not the point of a using. Deterministic disposal of unmanaged resources is the point of a using statement.
However, even if we don't use using(), we don't call dispose(), the resource can still be collected by gabage collection, although it may take much longer time.
Again, using and Dispose do not typically effect the lifetime of an object. It only affects the state of unmanaged resources (assuming the Dispose method is implemented correctly). You are correct that the object will still be collected.
Upvotes: 1
Reputation: 660024
Let's be clear on this. Suppose the resource in question is a file handle. The garbage collector knows nothing about the file handle or how to free it. The file handle is just an integer.
If the StreamWriter that is holding on to the file handle gets garbage collected then the garbage collector will put the object onto the finalization queue. When the finalization queue runs, it will call the finalizer of the object, and that is what releases the file handle.
Is that all clear? The garbage collector does not free the resource; the only resource the garbage collector knows about is objects in memory. Before the object is freed it is finalized, so it is the object itself that knows how to free the resource.
Upvotes: 10
Reputation: 23876
You should always call Dispose()
when you are done using an IDisposable
object. A using
statement is a great tool for making sure you obide by this rule.
The purpose of IDisposable
is to allow classes to dispose of allocated unmanaged resources which will not be automatically cleaned up by garbage collection.
If you use an IDisposable
object without calling Dispose()
when you are done, you run the risk of never disposing of the resource properly, even after it has been garbage collected.
This is the reason why the using
statement exists; it provides a convenient syntax for using IDisposable
objects and defines a clear scope in which these objects are usable.
Note also that the garbage collector never calls Dispose()
itself, but note also that it is recommended to follow the Finalize/Dispose pattern as documented on MSDN. If an object follows the Finalize/Dispose pattern, Dispose()
will be called when the GC calls the finalizer.
Upvotes: 1
Reputation: 16651
using(x)
is a deterministic pattern. It ensures that Dispose()
is called on the implementor when a particular point in the execution flow is passed. The GC on the other hand is not deterministic, because you don't know exactly when the object will be actually disposed. using
ensures that the object will execute its cleanup code (whatever that is) when you expect it to, rather than some time in the future.
Upvotes: 4
Reputation: 17010
using is essentially the same as the following (Check the IL of both if you doubt it):
try
{
IDisposable o = new Object();
}
finally
{
o.Dispose();
}
As long as the object in question implements IDisposable, the Dispose() method will be called and the resource, pending something stupid coded in Dispose() will be Garbage Collected. When? Not a question I can answer.
Is it possible that an item will never be GCed. Well, never is a long time, but theoretically possible if it gets beyond the first generation and just sits there. A problem? No, if the memory is eventually needed, it will be cleaned. Often seen, incorrectly, as a memory leak? Most certainly.
Upvotes: 0
Reputation: 160882
If there's no reference to that StreamWriter
anymore it will eventually be garbage collected, but it depends on the Garbage Collector when that is - it's not deterministic, so you should always use using
blocks when you can.
Upvotes: 2