在语句list = Foo();
上进入调试模式后,在行Library = null;
上执行CL GC.Collect(2)
时执行CLR;列表仍然有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);
}
}
答案 0 :(得分:1)
Foo()
返回对在Controller
中创建的书籍列表的引用,该引用存储在变量list
中。垃圾收集器不会收集书籍列表,因为程序仍在引用该列表。如果没有包含引用的变量,则该图书列表将被垃圾回收。
如果在不存储返回值的情况下调用Foo()
,则将书籍列表标记为要进行垃圾收集,并且将在运行垃圾收集器时最终对其进行收集。
答案 1 :(得分:1)
“它为哪个对象执行
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'
}
请注意,这在之后称为Library
语句的对return
的引用,因此该方法仍返回有效的引用。
并且由于返回了对列表的引用(而不是空引用),因此list
不是null
的原因。
如果您有意在获得参考之前致电Dispose
,那么Library
将是null
:
private static List<Book> Foo()
{
using (var lib = new Controller())
{
lib.Dispose();
return lib.Library; // Now 'Library' is null
}
}