繁体   English   中英

GC.Collect之后,C#参考对象仍然有效

[英]C# reference object still alive after GC.Collect

在语句中var list = Foo(); CLR执行Library = null; GC.Collect(2)行上进入调试模式后; 列表仍然有10个元素。 为什么不将其设置为null? 它针对哪个对象执行Library = null;

public class Book
{
    public string FirstName { get; set; }

    public string LastName { get; set; }
}

public class Controller : IDisposable
{
    public List<Book> Library = null;

    public Controller()
    {
        Console.WriteLine("Controller created.");
        Console.WriteLine("List created.");
        Library = new List<Book>();
        for (int i = 0; i < 10; i++)
        {
            Library.Add(new Book { FirstName = "FirstName" + i.ToString(), LastName = "LastName" + i.ToString() });
        }
    }
    public void Dispose()
    {
        Library = null; // Just for check
        Console.WriteLine("List disposed.");
    }
}

class Program
{
    private static List<Book> Foo()
    {
        using (var lib = new Controller())
        {
            return lib.Library;
        }
    }
    static void Main(string[] args)
    {
        var list = Foo();
        GC.Collect(0);
        GC.Collect(1);
        GC.Collect(2);
    }
}

Foo()返回对在Controller创建的书籍列表的引用,并且该引用存储在变量list 垃圾收集器不会收集书籍列表,因为程序仍在引用该列表。 如果没有包含对书的引用的变量,则该书列表将被垃圾回收。

如果在不存储返回值的情况下调用Foo() ,则书籍列表将被标记为垃圾收集,并且在垃圾收集器运行时最终将被收集。

“它对哪个对象执行Library = null; ?”

Dispose是在结束时自动调用using块,所以这个代码是其中Library被设置为null

private static List<Book> Foo()
{
    using (var lib = new Controller())
    {
        return lib.Library;
    } // <-- Dispose is called here on 'lib'
}

请注意,这是获得对Libraryreturn语句的引用之后调用的,因此该方法仍然返回有效的引用。

并且因为返回了对列表的引用(而不是null引用),所以这就是list不是null


如果获取引用之前有意调用Dispose ,则Library将为null

private static List<Book> Foo()
{
    using (var lib = new Controller())
    {
        lib.Dispose();
        return lib.Library;  // Now 'Library' is null
    } 
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM