Using "using"
-
I've seen a lot of code that looks something like the following:
using (using (FileStream fs = new FileStream(path, FileMode.Create, FileAccess.ReadWrite, FileShare.None))
I realize that this ensures that everything will be properly closed and disposed without you having to do anything, but doesn't the same thing happen when the object goes out of scope? Further, what about exception handling? Is that automatically handled as well? Is it wrong to not want to sue this construct in favor of more obvious code?
"Why don't you tie a kerosene-soaked rag around your ankles so the ants won't climb up and eat your candy ass..." - Dale Earnhardt, 1997
-----
"...the staggering layers of obscenity in your statement make it a work of art on so many levels." - Jason Jystad, 10/26/2001What's with the extra
using (
? -
John Simmons / outlaw programmer wrote:
but doesn't the same thing happen when the object goes out of scope?
Yes but garbage collection is non-deterministic and
using
offers deterministic resource clean up. I'm just the messenger, don't shoot me!led mike
GC and dispose are also doing different stuff. GC frees the memory allocated by the managed object. Dispose is supposed to release native resources allocated by an object. So even if you call dispose, the managed object is still present untill it gets eaten by the GC.
Blog: http://www.rogeralsing.com Projects: http://www.puzzleframework.com
-
John Simmons / outlaw programmer wrote:
I realize that this ensures that everything will be properly closed and disposed without you having to do anything, but doesn't the same thing happen when the object goes out of scope?
No, it doesn't. The memory management doesn't use reference counting, which means that nothing happens because of an object going out of scope. Because there is no possibility to add any code that will run when the object goes out of scope, the IDisposable interface was created, so that the lifetime of an object could be controlled from the code. Ordinary objects that doesn't have a specific need for any cleanup, doesn't have a Dispose method. They will just be removed when the garbage collector notices that the can be.
Despite everything, the person most likely to be fooling you next is yourself.
>>so that the lifetime of an object could be controlled from the code. rather: Lifetime of resources used by an object could be controlled from the code. The disposable object itself will not be removed from memory when you call dispose on it..
Blog: http://www.rogeralsing.com Projects: http://www.puzzleframework.com
-
Nitpicking here, but you forgot
if (fs != null)
:). The finally block looks likeif (fs != null)
((IDisposable)fs).Dispose();Regards Senthil [MVP - Visual C#] _____________________________ My Blog | My Articles | My Flickr | WinMacro
Spot on. Sorry and all that. ;)
Deja View - the feeling that you've seen this post before.
-
See http://www.codeproject.com/KB/cs/tinguusingstatement.aspx[^]
John Simmons / outlaw programmer wrote:
Is it wrong to not want to sue this construct in favor of more obvious code?
Do you want to type out all the try-finally-dispose things again and again, or understand
using
once and save the typing (AND reading)? edit: omfg, it took me 30min to write this and find a link :~ there wasnt any replies when i started typing...
[My Blog]
"Visual studio desperately needs some performance improvements. It is sometimes almost as slow as eclipse." - RĂ¼diger Klaehn
"Real men use mspaint for writing code and notepad for designing graphics." - Anna-Jayne Metcalfednh wrote:
edit: omfg, it took me 30min to write this and find a link there wasnt any replies when i started typing...
Sorry - I just typed my answer from memory which was why I missed a null check. ;)
Deja View - the feeling that you've seen this post before.
-
>>so that the lifetime of an object could be controlled from the code. rather: Lifetime of resources used by an object could be controlled from the code. The disposable object itself will not be removed from memory when you call dispose on it..
Blog: http://www.rogeralsing.com Projects: http://www.puzzleframework.com
Roger Alsing wrote:
rather: Lifetime of resources used by an object could be controlled from the code.
Good point. I should have said that it's for controlling the life cycle of the object rather than the lifetime.
Despite everything, the person most likely to be fooling you next is yourself.
-
What's with the extra
using (
?Wasn't this the OP's question?
-Spacix All your skynet questions[^] belong to solved
I dislike the black-and-white voting system on questions/answers. X|
-
Wasn't this the OP's question?
-Spacix All your skynet questions[^] belong to solved
I dislike the black-and-white voting system on questions/answers. X|
I can't tell.
-
John using is a convenience that hides the following pattern:
FileStream fs = null;
try
{
fs = new FileStream(path, FileMode.Create, FileAccess.ReadWrite, FileShare.None);
}
finally
{
((IDisposable)fs).Dispose();
}Basically, this guarantees that the Dispose method is called regardless of whether an exception happens or not, thus freeing up unmanaged resources in this case. If a class has a Dispose method, then it should always be called because (presumably) the developers have identified that particular items have to be freed up probably because they are expensive to maintain. The added bonus here is that most implementations of Dispose call
GC.SuppressFinalize(...);
so the finalizer (if any) is suppressed.Deja View - the feeling that you've seen this post before.
I don't call dispose on streams, but I do call close(). Isn't that the same thing?
"Why don't you tie a kerosene-soaked rag around your ankles so the ants won't climb up and eat your candy ass..." - Dale Earnhardt, 1997
-----
"...the staggering layers of obscenity in your statement make it a work of art on so many levels." - Jason Jystad, 10/26/2001 -
The object will be freed, but any unmanaged resources will linger unless freed up. Implementing the IDisposable interface is the recommended way to do that. And as someone mentioned using is just a shorthand way to call it safely. Eventually the garbage collector will collect the object; however, that doesn't necessarily free resources. The finalizer will be called unless suppressed, but that will only call Dispose if you specifically do so in your finalizer code.
N a v a n e e t h wrote:
Just wondering why this cast ? fs.Dispose() will do it, Right ?
The object may not directly implement the interface, but may have explictly implemented it. In that case its necessary to cast the object to IDisposable.
>>Eventually the garbage collector will collect the object; however, that doesn't necessarily free resources. The finalizer will be called unless suppressed, but that will only call Dispose if you specifically do so in your finalizer code.<< The using command, especially when applied to IO resources, is more complex than just calling Dispose. For example take this segment of code:
using ( FileStream list = Text.OpenWrite( path ) ) { foreach ( UniqueObject item in myArrayOfObject ) { list.Write( UniqueObject.Message, UniqueObject.GetAverage() ); } }
When you exit the using block, three things will happen. The buffer will be flushed, the file will be closed, and the object will be disposed of. Likewise (and more importantly) if UniqueObject.GetAverage() blew a divide by zero exception your code would leave this execution block. When that happens....using will flush the buffer, close the file, dispose of the object. This process first and formost protects long-running application from creating memory leaks leaving these streams and rare resources around. Secondly it ensures that any unmanaged resources (like file handles) are released. Finally it ensures that even an exception will not cause your file to get corrupted by early interuptus.
-
>>Eventually the garbage collector will collect the object; however, that doesn't necessarily free resources. The finalizer will be called unless suppressed, but that will only call Dispose if you specifically do so in your finalizer code.<< The using command, especially when applied to IO resources, is more complex than just calling Dispose. For example take this segment of code:
using ( FileStream list = Text.OpenWrite( path ) ) { foreach ( UniqueObject item in myArrayOfObject ) { list.Write( UniqueObject.Message, UniqueObject.GetAverage() ); } }
When you exit the using block, three things will happen. The buffer will be flushed, the file will be closed, and the object will be disposed of. Likewise (and more importantly) if UniqueObject.GetAverage() blew a divide by zero exception your code would leave this execution block. When that happens....using will flush the buffer, close the file, dispose of the object. This process first and formost protects long-running application from creating memory leaks leaving these streams and rare resources around. Secondly it ensures that any unmanaged resources (like file handles) are released. Finally it ensures that even an exception will not cause your file to get corrupted by early interuptus.
LongRange.Shooter wrote:
The using command, especially when applied to IO resources, is more complex than just calling Dispose.
Nope. It's not. It just calls Dispose. Dispose is responsible for calling Dispose(true), which performs the following code:
protected override void Dispose(bool disposing)
{
try
{
if (((this._handle != null) && !this._handle.IsClosed) && (this._writePos > 0))
{
this.FlushWrite(!disposing);
}
}
finally
{
if ((this._handle != null) && !this._handle.IsClosed)
{
this._handle.Dispose();
}
this._canRead = false;
this._canWrite = false;
this._canSeek = false;
base.Dispose(disposing);
}
}So, the using block is still about predictably calling Dispose. Don't confuse the effect with the implementation. BTW - there are conditions where the Dispose is not called - in an out of memory or stack overflow, the application bombs straight out (and doesn't hit the Dispose).
Deja View - the feeling that you've seen this post before.
modified on Wednesday, May 7, 2008 3:39 PM
-
I don't call dispose on streams, but I do call close(). Isn't that the same thing?
"Why don't you tie a kerosene-soaked rag around your ankles so the ants won't climb up and eat your candy ass..." - Dale Earnhardt, 1997
-----
"...the staggering layers of obscenity in your statement make it a work of art on so many levels." - Jason Jystad, 10/26/2001John Simmons / outlaw programmer wrote:
I don't call dispose on streams, but I do call close(). Isn't that the same thing?
Yes, as long as you guarantee that
Close()
is called. As I stated earlier, the using statement wraps a try/finally block, so you need to ensure that Close is called in the finally portion.Deja View - the feeling that you've seen this post before.
-
I don't call dispose on streams, but I do call close(). Isn't that the same thing?
"Why don't you tie a kerosene-soaked rag around your ankles so the ants won't climb up and eat your candy ass..." - Dale Earnhardt, 1997
-----
"...the staggering layers of obscenity in your statement make it a work of art on so many levels." - Jason Jystad, 10/26/2001If you do call dispose on most stream classes it will translate that into a .Close() see: http://www.codeproject.com/script/Forums/View.aspx?fid=1649&select=2532987&fr=883#xx2532987xx[^]
-Spacix All your skynet questions[^] belong to solved
I dislike the black-and-white voting system on questions/answers. X|