7

Suppose you have a Collection<B>, and you're about to remove an item. Instance of B is referenced from an instance of A, and references an instance of C, as shown in the first picture:

Figure A

Now, since there was a reference pointing to B, there's no question about the object being "deleted", or garbage collected. It simply gets removed from the collection, like this, right?

Figure B

Now, let's have a Collection<A> with the same referencing hierarchy as before, and let's remove an instance of A.

Figure C

If there's no other reference to A, not only it gets removed from the collection, it is marked as garbage. Am I right? And what about B and C? Do they become garbage too, provided there's no other references except B referencing an instance of C?

This is a simplification of what I'm facing. I want to remove an A instance from a collection and I want to make sure B and C go with it. At the point where A is no longer in my collection, all the "children" that are still alive are a memory leak for me.

When I look at these pictures I made, it seems too stupid of a question. But my situation is a little less trivial. It looks something like this:

figure 4

  • In the picture, Model layer is yellow, ViewModel layer is green
  • The 'A ViewModel' class references its A Model
  • The A Model has a collection of B Model instances (B is kind of the child of A, both in Model and ViewModel layers)
  • each B Model "knows its parent' - references its parent 'A Model' instance
  • back to VM layer, the 'A ViewModel' holds a collection of 'B ViemModel' items
  • as any good ViewModel, 'B ViewModel' references 'B Model'

I have a Collection of those A ViewModel instances. When I delete one, I need everything other to go with it. Provided there's no other "outside reference" to any of the instances involved (basically, no other arrow pointing coming in from outside of the picture), will the removed 'A ViewModel' instance take all the children with it? If so, are there any "gotchas" that could make this simplification misleading? And if I'm completely wrong, why? :)

Thanks for reading this far!

Community
  • 1
  • 1
oli.G
  • 1,300
  • 2
  • 18
  • 24
  • 1
    Be aware of memory leaks. For instance, a badly written `Dispose` method on the `B` class (throwing, say, a `NullReferenceException`) could prevent a `B` instance (and all its referenced objects, including the `C` instance) from being garbage collected. There are some interesting scenarios on [this](http://stackoverflow.com/questions/20386/memory-leaks-in-net) answer. – rsenna Nov 05 '13 at 00:57
  • 1
    @rsenna That is describing a leak in *unmanaged* resources, not a leak in *managed* resources. `A` having a finalizer that throws doesn't prevent it from being GCed, nor does it prevent B or C from being GCed. If the finalizer blocks forever *then* it could do that. – Servy Nov 05 '13 at 01:36

1 Answers1

10

Provided there's no other "outside reference" to any of the instances involved (basically, no other arrow pointing coming in from outside of the picture), will the removed 'A ViewModel' instance take all the children with it?

Yes, provided there are no references from your code to the child, it will be eligible for garbage collection, and should eventually be collected.

If there's no other reference to A, not only it gets removed from the collection, it is marked as garbage. Am I right?

That is not actually how this works. The GC doesn't "track garbage" - instead, it checks all of the object references from currently executing code, and walks out to find references that are currently "alive". Anything left over at that point is not alive, and then becomes eligible for collection. If the only way to reach "B" or "C", in your graph, is through that instance of "A", and you remove "A" from the collection, all of those will become eligible for GC and be found in the next appropriate GC collection.

Reed Copsey
  • 554,122
  • 78
  • 1,158
  • 1,373