GC.Collect 后 C# 引用对象仍然存在
C# reference object still alive after GC.Collect
On statement var list = Foo();
CLR 在行 GC.Collect(2)
进入调试模式后执行 Library = null;
;列表仍然有 10 个元素。为什么它没有设置为空?它为哪个对象执行 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()
return 是对 Controller
中创建的图书列表的引用,该引用存储在变量 list
中。垃圾收集器将不会收集书籍列表,因为您的程序仍在引用它。当没有包含对其的引用的变量时,书籍列表将被垃圾收集。
如果你调用Foo()
而不存储return值,那么书籍列表将被标记为垃圾收集,并最终在垃圾收集器运行时被收集。
"For which object it executing 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'
}
请注意,在 为 return
语句获得对 Library
的引用后,这被称为 ,因此该方法仍然是 returns有效参考。
并且因为返回了对列表的引用(而不是空引用),这就是为什么 list
不是 null
。
如果您在 获取引用之前有意调用Dispose
,那么Library
将是null
:
private static List<Book> Foo()
{
using (var lib = new Controller())
{
lib.Dispose();
return lib.Library; // Now 'Library' is null
}
}
On statement var list = Foo();
CLR 在行 GC.Collect(2)
进入调试模式后执行 Library = null;
;列表仍然有 10 个元素。为什么它没有设置为空?它为哪个对象执行 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()
return 是对 Controller
中创建的图书列表的引用,该引用存储在变量 list
中。垃圾收集器将不会收集书籍列表,因为您的程序仍在引用它。当没有包含对其的引用的变量时,书籍列表将被垃圾收集。
如果你调用Foo()
而不存储return值,那么书籍列表将被标记为垃圾收集,并最终在垃圾收集器运行时被收集。
"For which object it executing
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'
}
请注意,在 为 return
语句获得对 Library
的引用后,这被称为 ,因此该方法仍然是 returns有效参考。
并且因为返回了对列表的引用(而不是空引用),这就是为什么 list
不是 null
。
如果您在 获取引用之前有意调用Dispose
,那么Library
将是null
:
private static List<Book> Foo()
{
using (var lib = new Controller())
{
lib.Dispose();
return lib.Library; // Now 'Library' is null
}
}