3

When an object is created and used only within the scope of a using statement, is it disposed of during the disposal of its enclosing IDisposable instance? If not, why wouldn't it be?

For instance, when using Dapper I've often created an anonymous object within the scope of the SqlConnection with the impression that it will be disposed of sooner - however I recently read something to the contrary.

using (var connection = new SqlConnection("Connection String"))
{
    var parameters = new
    { 
        Message = "Hello world!"
    };

    connection.Execute("INSERT INTO...", parameters);
}
Joseph Woodward
  • 9,191
  • 5
  • 44
  • 63
  • You can declare the `parameters` variable outside of the `using`, then you can access it later. Only `connection` is disposed not everything that you are initializing or using inside the `using`-statement. It doesn't make sense to dispose everything inside of an `using`. – Tim Schmelter Nov 25 '15 at 10:17
  • That would make sense, but in the instances where I didn't need to access the anonymous object I would have thought it would be garbage collected when the scope ends. I'm curious as to the reasoning. – Joseph Woodward Nov 25 '15 at 10:19
  • 6
    Don't confuse garbage collection with disposing. It will be garbage collected when it's no longer referenced (which seems to be the case). `Dispose` on the other hand enables you to cleanup unmanaged resources which won't be cleaned up by the GC. [Garbage Collector Fundamentals](https://msdn.microsoft.com/en-us/library/ee787088(v=vs.110).aspx) ... vs... [Dispose](https://msdn.microsoft.com/en-us/library/fs2xkftw(v=vs.110).aspx) – Tim Schmelter Nov 25 '15 at 10:23

1 Answers1

3

Your using statement is essentially equivalent to:

 var connection = new SqlConnection("Connection String");

 try
 {
     var parameters = new
     { 
         Message = "Hello world!"
     };
 }
 finally
 {
     if (connection != null)
     {
         ((IDisposable)connection).Dispose();
     }
 }

As you can see, there is no reason why any other IDisposable instance created inside the try block be disposed automatically for you. If you do need to ensure other objects are disposed then simply nest using statements:

using (var connection = new SqlConnection("Connection String"))
{
     using (var otherDisposableObject = new ....)
     {
     } //otherDisposableObject disposed
} //connection disposed

If excessive nesting gets in the way of readability, then you can simply write the using statements as follows:

using (var connection = new SqlConnection("Connection String"))
using (var otherDisposableObject = new ....)
using (var anotherDisposableObject = new ....)
using (var andAnotherDisposableObject = new ....)
{
} //andAnotherDisposableObject, anotherDisposableObject, otherDisposableObject and connection all disposed

Do bear in mind though that you seem to be mixing garbage collection with disposing an object. In your example, parameters is elegible for garbage collection once execution has exited the using statement as there is no live refence to it.

When it is garbage collected is up to the GC, it might very well never be, depending on your application's memory pressure. If it is garbage collected, then it will be marked as valid for finalization and the finalizer of the object will be scheduled to run. Again, if and when that happens is entirely up to the GC.

Lastly, if the IDisposable pattern of the object is implemented correctly and the finalizer is run, Dispose() will be called (to be precise, Dispose(false) will be called) and the object will dispose any unmanaged resources it might be holding (managed resources can not be disposed safely in this context but it really doesn't matter, the GC will eventually take care of them too).

See IDisposable Pattern for more details on how it works or even better, check out this excellent SO answer.

Community
  • 1
  • 1
InBetween
  • 32,319
  • 3
  • 50
  • 90
  • +1: A minor correction if you will, "... and the finalizer of the object will be scheduled to run. Again, _when_ that happens", might possibly be "Again **if** and when that happens", as there is no guarentee that a finalizer will ever run. – Binary Worrier Nov 25 '15 at 11:18
  • @BinaryWorrier True! Fixed that. Thanks – InBetween Nov 25 '15 at 11:18
  • Great, thanks for the thorough answer! That certainly explains a lot and fits in with my current understanding of disposable resources and garbage collection. – Joseph Woodward Nov 25 '15 at 11:28