列表< >可以从GC收集?(xamarin的形式)

本文关键字:xamarin 收集 GC 列表 | 更新日期: 2023-09-27 18:09:52

我面临一个奇怪的情况。

据我所知,如果对象被添加到数组(如列表),引用计数将增加,因此它不能从GC收集。

因此,如果我在singletone中有IList变量(当然= new List)并且它有对象,则对象不能从GC中收集。

正确吗?

列表< >可以从GC收集?(xamarin的形式)

引用计数不是考虑它的方式,GC不是这样工作的;它足够聪明,知道它可以收集两个相互引用的对象,但没有其他活动引用指向它们。

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

在这个简单的例子中,仅仅检查对象的引用计数是否等于零并不能解决这个问题。当一个对象没有活动的(或可访问的)引用指向它时,就认为它有资格被收集。

关于你的问题,只要你的List是可达的,它所包含的对象是可达的,因此它们不会被收集。但是,请注意,根据我之前的解释,如果您的列表不可访问,那么列表本身以及其中包含的所有无法通过其他引用访问的对象都适用于集合:

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

列表本身可以被收集,即使对包含在其中的对象存在引用!例如,考虑以下代码:

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!

问题的关键在于,尽管列表将保存对其所包含对象的引用,但通常这些对象不保存对容器的引用。

另一个微妙之处;我前面的例子可能会让您通过作用域确定收集资格。那将是一个错误的信念。运行时足够聪明,可以收集仍然在作用域中的对象,如果绝对确定没有人会对它们进行写入或读取。为了形式上正确,前面的例子应该重写为:

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
}