I struck up a conversation with my colleague today, who said she'd just learned the reason behind using the using
statement.
//Using keyword is used to clean up resources that require disposal (IDisposable interface). using (StreamReader reader = new StreamReader(@"C:\test.txt")) { string line = reader.ReadLine(); }
I pointed out that the object is marked as "Can be disposed" but not actually disposed and garbage-collected unless GC decides to do so.
She responded that the object will be disposed automatically once that using statement ends because the using statement is translated to try-catch-finally block. So, the object must get disposed at the very end of the using statement.
I was confused by this, because I know that using a using
statement does not guarantee that the object gets GC-collected. All that happens is that the Dispose()
method would be called. The GC decides when to GC it regardless. But when she asked for proof, I could not find any.
Does anyone know how this works, and how to prove it?
The GC does not call Dispose , it calls your finalizer (which you should make call Dispose(false) ).
Finalize is the backstop method, called by the garbage collector when it reclaims an object. Dispose is the "deterministic cleanup" method, called by applications to release valuable native resources (window handles, database connections, etc.)
In the context of C#, dispose is an object method invoked to execute code required for memory cleanup and release and reset unmanaged resources, such as file handles and database connections.
You're talking about two very different things.
The object will be disposed as soon as the using
-block ends. That doesn't say anything about when it is garbage collected. The only time heap memory is released is when a garbage collection occurs - which only happens under memory pressure (unless you use GC.Collect
explicitly).
Disposing an object simply means calling its Dispose
method. That most often means releasing either a scarce resource, or a native resource (in practice, all scarce resources are native - sockets, files, ...). Now, it's handy that the lifetime of the disposable object in your case is limited in scope, so it could theoretically be collected as soon as the using
-block ends - however, that doesn't really happen in practice, since the .NET runtime tries to avoid collections - they're expensive. So until you cross a memory allocation threshold, no collection is going to happen, even though you have a dead object on the heap.
So what's the point of Dispose
? Nothing to do with managed memory. You don't really care about managed memory, and you shouldn't expect that Dispose
will actually be called - it doesn't have to be. The only thing that has to be called by the runtime is the finalizer, and you can only ever use that for disposing of native resources - in fact, there's no guarantee if the objects you have a reference to still exist by the time the finalizer runs - the managed memory might have already been reclaimed by then. That's why you never handle managed resources in a finalizer.
So yes, she was completely right. The point is that IDisposable
has nothing to do with the garbage collector. Disposed does not mean garbage collected.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With