问题
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.
回答1:
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();
}
回答2:
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.
回答3:
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();
}
回答4:
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.
回答5:
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.
回答6:
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