سؤال

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. Please, 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; // <- note 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.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top