Most of the examples of the using statement in C# declare the object inside the brackets like this:
using (SqlCommand cmd = new SqlCommand(\"SELECT * FROM Cu
I wrote a little code along with some unit tests. I like it when I can validate statements about the question at hand. My findings:
using
statement doesn't matter. It must implement IDisposable
and Dispose()
will be called upon leaving the using statement block (closing brace).Dispose()
will not be invoked. This is reasonable as the object has not been successfully constructed when an exception is thrown in the constructor. Therefore no instance exists at that point and calling instance members (non-static members) on the object doesn't make sense. This includes Dispose()
.To reproduce my findings, please refer to the source code below.
So bottom line you can - as pointed out by others - instantiate an object ahead of the using statement and then use it inside the using statement. I also agree, however, moving the construction outside the using statement leads to code that is less readable.
One more item that you may want to be aware of is the fact that some classes can throw an exception in the Dispose()
implementation. Although the guideline is not to do that, even Microsoft has cases of this, e.g. as discussed here.
So here is my source code include a (lengthy) test:
public class Bar : IDisposable {
public Bar() {
DisposeCalled = false;
}
public void Blah() {
if (DisposeCalled) {
// object was disposed you shouldn't use it anymore
throw new ObjectDisposedException("Object was already disposed.");
}
}
public void Dispose() {
// give back / free up resources that were used by the Bar object
DisposeCalled = true;
}
public bool DisposeCalled { get; private set; }
}
public class ConstructorThrows : IDisposable {
public ConstructorThrows(int argument) {
throw new ArgumentException("argument");
}
public void Dispose() {
Log.Info("Constructor.Dispose() called.");
}
}
[Test]
public void Foo() {
var bar = new Bar();
using (bar) {
bar.Blah(); // ok to call
}// Upon hitting this closing brace Dispose() will be invoked on bar.
try {
bar.Blah(); // Throws ObjectDisposedException
Assert.Fail();
}
catch(ObjectDisposedException) {
// This exception is expected here
}
using (bar = new Bar()) { // can reuse the variable, though
bar.Blah(); // Fine to call as this is a second instance.
}
// The following code demonstrates that Dispose() won't be called if
// the constructor throws an exception:
using (var throws = new ConstructorThrows(35)) {
}
}