Myself and a colleague are having a difference of opinion on when an object can be garbage collected in .NET. Take the following code:
Stream stream=getStream();
using(var request=new Request(stream))
{
Stream copy=request.Stream;
// From here on can "request" be garbage collected?
DoStuff1();
DoStuff2(copy);
}
My colleague claims that when a release build is run using the server garbage collector that it is valid for the request
object to be garbage collected after the call to request.Stream
. He asserts that this only happens with the server garbage collector, and never with the workstation garbage collector.
The reason this is that the Request
class had a finalizer that was closing the Stream
given to the request. As a result, when DoStuff2
went to use the stream it got an "object disposed" exception. Since the finalizer can only be run by the garbage collector my colleague says that a garbage collection must have taken place before the end of the finally block, but after the last use of request
However, it's my belief that since the above code is just shorthand for something like this:
Stream stream=getStream();
Request request=null;
try
{
Stream copy=request.Stream;
// From here on can "request" be garbage collected?
DoStuff1();
DoStuff2(copy);
}
finally
{
if(request!=null)
request.Dispose();
}
Then request
cannot be garbage collected after the call to request.Stream
at it is still reachable from the finally
block.
Also, if it were possible for the garbage collector to collect the object then the finally
block would potentially exhibit undefined behavior as Dispose
would be called on a GC'd object, which doesn't make sense. Likewise, it isn't possible to optimize away the finally
block as an exception could be thrown within the try
/using
block before any garbage collection had taken place, which would require the finally
block to execute.
Ignoring the issue of closing the stream in the finalizer, is it ever possible for the garbage collector to collect the object before the end of the finally
block, and in effect optimize away the logic in the finally
block?
Dispose
method is doing stuff! – Seanrequest
object before the end of theusing
/finally
block? The ODE is caused by a badly coded finalizer in theRequest
object, but my point is it should never run the finalizer until the end of theusing
block and then only afterDispose
. – Sean