[英]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'
}
请注意,这是在获得对Library
的return
语句的引用之后调用的,因此该方法仍然返回有效的引用。
并且因为返回了对列表的引用(而不是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.