Suppose I have
void foo () {
Bar bar = new Bar(); // bar is never referred to after this line
// (1)
doSomethingWithoutBar();
}
At (1), is the object bar
is pointing to eligible for garbage collection? Or does bar
have to fall out of scope as well? Does it make a difference if GC.Collect
is called by doSomethingWithoutBar
?
This is relevant to know if Bar has a (C#) destructor or something funky like that.
Objects can become eligible for garbage collection as soon as it's certain that they will no longer be used. It's entirely possible that bar
will be garbage collected before the variable goes out of scope.
Proof:
using System;
class Bar
{
~Bar() { Console.WriteLine("Finalized!"); }
}
class Program
{
static void Main(string[] args)
{
Bar bar = new Bar();
GC.Collect();
GC.WaitForPendingFinalizers();
Console.WriteLine("Press any key to exit...");
Console.ReadLine();
}
}
Run in Release Mode (because it doesn't get collected in Debug Mode).
Output:
Finalized! Press any key to exit...
It also works on ideone which uses Mono. The output is the same.
Marc answered the question, but here is the solution:
void foo () {
Bar bar = new Bar(); // bar is never referred to after this line
// (1)
doSomethingWithoutBar();
GC.KeepAlive(bar); // At the point where you no longer need it
}
From a quick reading of the spec, it looks like it's implementation specific. It's allowed to garbage collect it, but not required to.
I get this from a note in section 10.9 "Automatic Memory Management" of the ECMA Spec:
[Note: Implementations might choose to analyze code to determine which references to an object can be used in the future. For instance, if a local variable that is in scope is the only existing reference to an object, but that local variable is never referred to in any possible continuation of execution from the current execution point in the procedure, an implementation might (but is not required to) treat the object as no longer in use. end note]
Emphasis mine.
Without defining what version of the CLR you're referring to, it's impossibledifficult to be definitive about the behaviour that you'll see here.
A hypothetical CLR could, in this example, assuming that the following is true:
Bar
does nothingEntirely disregard the line Bar bar = new Bar();
and optimise it away as it "does nothing".
As far as my memory serves, in current versions of the CLR bar
is eligible for garbage collection the moment after you've constructed it.
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