Is this leaky
No. This is good coding practice for almost any object implementing IDisposable because it ensures that the dispose method is called as soon as the variable being 'used' goes out of scope (eg. the code leaves the using block). There are a few exceptions (WCF clients, custom code that doesn't follow good IDisposable practices), but it is a good idea to wrap ANY IDisposable in a using block unless you have a specific reason not to.
Is it possible that the return value is invalid as a result of foo being disposed
This depends on what the Dispose
method in Foo does. For example, if you try to invoke a SQLCommand that references a SQLConnection that has already been closed/disposed, you are going to get an exception. Lets look at an example that makes this behavior obvious.
public class Foo : IDisposable
{
public Foo()
{
ComplexType = new ComplexType();
}
public ComplexType ComplexType { get; set; }
public void Dispose()
{
ComplexType = null;
GC.Collect();
}
}
Now this piece of code that accesses our Foo:
static void Main(string[] args)
{
Foo foo;
ComplexType complexType;
using (var newFoo = new Foo())
{
foo = newFoo;
complexType = newFoo.ComplexType;
}
Console.WriteLine(complexType.SomeProperty); // This works :)
Console.WriteLine(foo.ComplexType.SomeProperty); // Throws an exception because ComplexType is NULL
Console.ReadKey();
}
Weird right? The reason this happens is because in the Foo constructor we create a new ComplexType and store it at a memory address. The Foo.ComplexType property contains a reference to the memory address. When we call dispose, we set the reference to null, but the actual object is not garbage collected because we have other references to it in our calling code, so we can't access it through the foo.ComplexType
property anymore, but it is still accessible via the complexType
variable. Note as well that foo
is NOT null even though it has been assigned to an object that has been disposed. Because a reference still exists to our Foo
instance, despite being outside of the using block, it is still alive since it can't be collected while that reference exists.
Now, if the Dispose
method changed SomeProperty, it is possible (depending on how it was changed), that the change COULD propagate out and invalidate results.
I guess the moral of the story is that you could experience (or create) all sorts of weird behavior if you start playing around with objects that have been disposed, but that depends on what the disposed objects are doing during disposal. I wouldn't recommend it as a practice since most objects aren't intended to be used after disposal. Perform your "work" as an atomic unit inside the using block, and then let the object die.