When to use the Using statement
I think I may be using the Using statement wrong here. What would be a better way of writing this?
Dim x As New Serialization.XmlSerializer( ... )
Using file As New FileStream(myFile, FileMode.Create)
Using writer As XmlWriter = XmlTextWriter.Create(file)
x.Serialize(writer, myCollection)
End Using
End Using
I've read that you're only supposed to use a using
blo开发者_C百科ck on objects that have a .Dispose()
(i.e. implements IDisposable), which is why I'm thinking there shouldn't be a Using on "writer", but instead a writer.Close()
at the end. But "file" has both a .Dispose()
and a .Close()
, so which do I use? The using
or file.Close()
?
Note: I'm using an XmlWriter because I can customize the output. I removed the settings here, though.
Both FileStream
and XmlWriter
implement IDisposable
- the code is correct. Actually the compiler probably wouldn't let you do this if it was wrong. If there isn't a public .Dispose()
, then it must be using explicit interface implementation - but that doesn't change your responsibility for calling .Dispose()
. For interest, in C# you can avoid the ever-increasing nesting/indenting, i.e.
using(...a...)
using(...b...)
using(...c...)
{
...
}
but fundamentally your current code is correct.
This is indeed confusing and has been the subject of much debate. This is the implementation of the Dispose() method:
Public Sub Dispose()
Me.Close
End Sub
In other words, calling Dispose() does the exact same thing as calling Close(). You definitely want to take advantage of the Using statement here.
Yes, the .Close
and .Dispose
issue is a bit unfortunate.
It is (was?) an official MS guideline though. The Close method is called a Domain Specific Alias.
And like the word Alias suggests, you may assume that they do exactly the same. Usually Close will just call Dispose.
The Using ... End Using
block will only compile with a reference that is IDisposable (has .Dispose)
General advice:
- When a Class has a .Dispose, use a
Using
block Using
is just short-hand forTry ... Finally
and you can fall back on that. But- Don't get creative trying to combine or economize multiple blocks
- When the nesting gets to deep (> 3..5), factor out an extra method.
Your code looks correct. Note that you will get a compile-time error if you attempt to use using
on a data type that does not support IDispose
.
I'd tend to do both, but that could be because I'm a bit old fashioned. If I've opened a file (which you have), I'll explicitly close it. Whether or not the Dispose method does a clean close is up to the implementation of the object, not up to the client. But, as the object still implements IDisposable you still need to call it.
精彩评论