Is there any difference between these two code samples and if not, why does using
exist?
StreamWriter writer;
try {
writer = new StreamWriter(...)
writer.blahblah();
} finally {
writer.Dispose();
}
vs:
using (Streamwriter writer = new Streamwriter(...)) {
writer.blahblah
}
I mean in the second example you really should be putting it in a try block anyway so adding the finally block really doesn't use much more effort. I get that the entire thing might be encompassed in a bigger try block but yeah, just seems superfluous to me.
There're some issues with your code. Never write like this (put using instead), and that's why:
StreamWriter writer;
try {
// What if you failed here to create StreamWriter?
// E.g. you haven't got permissions, the path is wrong etc.
// In this case "writer" will point to trash and
// The "finally" section will be executed
writer = new StreamWriter(...)
writer.blahblah();
} finally {
// If you failed to execute the StreamWriter's constructor
// "writer" points to trash and you'll probably crash with Access Violation
// Moreover, this Access Violation will be an unstable error!
writer.Dispose();
}
When you put "using" like that
using (StreamWriter writer = new StreamWriter(...)) {
writer.blahblah();
}
It's equal to the code
StreamWriter writer = null; // <- pay attention to the assignment
try {
writer = new StreamWriter(...)
writer.blahblah();
}
finally {
if (!Object.ReferenceEquals(null, writer)) // <- ... And to the check
writer.Dispose();
}
Is there any difference between these two code samples
Yes, using
checks for null
before calling Dispose
(i.e. the actual code it is expanded to introduces a null check).
why does using exist?
Because the code is more concise. Just a syntactic sugar.
What you've written is pretty much the pattern that using
wraps up. And therefore that is the point of using
to save having to write the same try....finally
block every time you use a Disposable object.
As for your edited question
[...] in the second example you really should be putting it in a try block anyway so adding the finally block really doesn't use much more effort
Chances are you cant (or dont want to) handle that error from blahblah
explicitly and you just want it to bubble up to the calling code... but still cleaning up your StreamWriter resources along the way!
So you would end up with this:
StreamWriter writer;
try{
writer = new StreamWriter(...)
writer.blahblah();
}catch{
throw; // pointless!
} finally [
writer.Dispose();
}
The latter is just syntactic sugar for the former. They should do the same thing, but the latter requires less boilerplate code.
I would recommend using the using
one as one is less likely to make a mistake.
They're not entirely the same. The try
/finally
block does not protect against silly mistakes.
StreamWriter writer = new StreamWriter(...);
try {
...
writer = new StreamWriter(...);
...
} finally {
writer.Dispose();
}
Note that only the second writer gets disposed. In contrast,
using (StreamWriter writer = new StreamWriter(...)) {
...
writer = new StreamWriter(...);
...
}
will give a compile-time error.
First of all, using using
is safer than your code - it properly handles errors in the Disposable
object construction, and will not call dispose on a null object.
The second difference is in code readability - look at your example. The first version takes 7 lines. The second - only 3.
来源:https://stackoverflow.com/questions/20703500/try-finally-block-vs-calling-dispose