简体   繁体   English

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

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

On statement var list = Foo(); 在语句中var list = Foo(); CLR executing Library = null; CLR执行Library = null; after stepping in debug mode on line GC.Collect(2) ; GC.Collect(2)行上进入调试模式后; list is still have 10 elements. 列表仍然有10个元素。 Why it does no set to null? 为什么不将其设置为null? For which object it executing Library = 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() returns a reference to the list of books created in Controller , and that reference is stored in the variable list . Foo()返回对在Controller创建的书籍列表的引用,并且该引用存储在变量list The garbage collector will not collect the list of books because it is still being referred to by your program. 垃圾收集器不会收集书籍列表,因为程序仍在引用该列表。 The list of books will be garbage collected when there are no variable containing a reference to it. 如果没有包含对书的引用的变量,则该书列表将被垃圾回收。

If you call Foo() without storing the return value, then the list of books will be marked for garbage collection, and will be collected eventually when the garbage collector runs. 如果在不存储返回值的情况下调用Foo() ,则书籍列表将被标记为垃圾收集,并且在垃圾收集器运行时最终将被收集。

"For which object it executing Library = null; ?" “它对哪个对象执行Library = null; ?”

Dispose is called automatically at the end of a using block, so this code is where Library is set to null : Dispose是在结束时自动调用using块,所以这个代码是其中Library被设置为null

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

Note that this is called after a reference is obtained to Library for the return statement, so the method still returns a valid reference. 请注意,这是获得对Libraryreturn语句的引用之后调用的,因此该方法仍然返回有效的引用。

And because a reference to the list was returned (and not a null reference), that is why list is not null . 并且因为返回了对列表的引用(而不是null引用),所以这就是list不是null


If you purposefully called Dispose before getting the reference, then Library will be 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