簡體   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