I have a class that contains a pointer to an object inheriting off IDisposable
class Foo
{
private Bar bar;
private test()
{
bar = CreateBarFactory();
}
};
bar never is used beyond when it is set, in test();
I'm wondering if the GC is permitted to dispose of bar even if the Foo instance is still around?
if so is there a way I can prevent this? bar is a pointer to an object that contains a ref count, if it's Disposed() then the ref is released causing some functionality to be disabled
If the instance of foo is still around (i.e. someone is holding a reference to it.. keeping it alive), bar will not be collected. It will be treated as 'reachable' by the GC i.e. in use.
Members of reachable objects are also considered to be reachable.
Please don't mix up terminology. C# does have pointers, but that's not what you have there. You have a reference. Importantly, references do affect the garbage collector, whereas pointers, in and of themselves, do not.(*)
So long as the instance of Foo
is reachable, it's reference to bar
will keep that object reachable too. If Foo
and Bar
have finalizers, then, in the finalizer of Foo
is the one circumstance where you shouldn't assume anything about bar
- it may have already been finalized itself.
Even though, as you've indicated, no other method will be called that accesses bar
, the GC and JIT don't perform this sort of analysis. For object references, the entire object is considered to be reachable, and any references it contains are followed and the objects located similarly are marked as reachable. This has to be done so that Reflection based access to an object will never obtain an invalid reference. This is also why, if your object has allocated a large helper object that you will no longer use, it can be (in this limited circumstance) useful to set the reference to null
.
The only lifetime analysis that does consider what future code will run is the code within a single method body, with respect to the local variables. A local reference variable within a method is not sufficient to keep an object alive if no further references to that variable will occur. This is worked out collaboratively between the JIT and GC.
(*) people sometimes think that pointers keep objects alive. This is not strictly true. The act of pinning, which can yield a pointer, will keep an object alive, but there's nothing stopping you from keeping a pointer beyond the time that the object was pinned. Of course, de-referencing the pointer at any such time would be unsafe...
And, another terminology issue:
I'm wondering if the GC is permitted to dispose of bar
The GC doesn't dispose of anything. Disposal occurs when an object implements IDisposable and the user of the object calls Dispose
on it (either directly or via e.g. a using
block).
The GC doesn't call Dispose
. It may call a finalizer, if one is defined on an object (and so my warning above would apply) and it then collects the object.
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