Bright Lee Bright Lee - 2 months ago 11
C# Question

Added object on List<T> can be gather from GC? (xamarin forms)

I'm facing weird situation.

As I know if object is added to Array(like a list), reference count will be increased, so it can't be gathered from GC.

So If I have IList variable(= new List of course) in singletone and it has objects, the objects can not be gathered from GC.

Is this correct?

Answer

Reference count is not the way to think about it, the GC doesn't work that way; its smart enough to know it can collect two objects that reference each other but have no other live references pointing at them.

public void Blah()
{
    var foo1 = new Foo();
    var foo2 = new Foo();
    foo1.OtherFoo = foo2;
    foo2.OtherFoo = foo1;
} //at this point, both foo1 and foo2 are eligible for collection

Just checking if the reference count of an object is equal to zero wouldn't cut it in this simple case. Think of an object as eligible for collection when there is no live (or reachable) references pointing at it.

Concerning your question, as long as your List is reachable, the objects contained within it are reachable and therefore they wont be collected. Do notice however, based on what I explained before, that if your list is not reachable, then the list itself, and all objects contained within it that are not reachable through some other reference, are elegible for collection:

public void Blah()
{
    var list = new List<Foo>();
    var foo1 = new Foo();
    var foo2 = new Foo();
    list.AddRange(new[] { foo1, foo2 });
} //at this point, foo1, foo2 and list are eligible for collection

The list itself can be collected even if references exist to objects contained with in it! For example, consider the following code:

static void Main(string[] args)
{
    var o = new object();
    Foo(o);
    //At this point the list created in Foo(o) is eligible for collection, even if
    //o is not! Collecting the list does not mean that its contents are collected too. 
    Console.WriteLine(o.ToString());
}

private static void Foo(object o)
{
    var list = new MyList<object>();
    list.Add(o);
} //at this point list is eligible for collection!

The point being that although a list will hold a reference to the objects it contains, in general, these objects hold no reference to the container.

One other subtlety; my previous examples might make you identify collection eligibility with scope. That would be a false belief. The runtime is smart enough to collect objects that are still in scope if its absolutely sure nobody will write to or read from them. To be formally correct, the previous examples should be rewritten to:

public void Blah()
{
    var list = new List<Foo>();
    var foo1 = new Foo();
    var foo2 = new Foo();
    list.AddRange(new[] { foo1, foo2 });
    //at this point, foo1, foo2 and list are eligible for collection
}
Comments