C#引用对象在GC.Collect之后仍处于活动状态
在语句varC#引用对象在GC.Collect之后仍处于活动状态,c#,garbage-collection,C#,Garbage Collection,在语句varlist=Foo()上CLR执行库=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 {
list=Foo()上代码>CLR执行库=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);
}
}
公共课堂教材
{
公共字符串名{get;set;}
公共字符串LastName{get;set;}
}
公共类控制器:IDisposable
{
公共列表库=null;
公共控制员()
{
Console.WriteLine(“控制器已创建”);
Console.WriteLine(“创建列表”);
库=新列表();
对于(int i=0;i<10;i++)
{
添加(新书{FirstName=“FirstName”+i.ToString(),LastName=“LastName”+i.ToString()});
}
}
公共空间处置()
{
Library=null;//仅供检查
Console.WriteLine(“列表已处理”);
}
}
班级计划
{
私有静态列表Foo()
{
使用(var lib=new Controller())
{
返回库;
}
}
静态void Main(字符串[]参数)
{
var list=Foo();
GC.Collect(0);
GC.Collect(1);
GC.Collect(2);
}
}
Foo()
返回对在Controller
中创建的书籍列表的引用,该引用存储在变量list
中。垃圾收集器不会收集书籍列表,因为您的程序仍在引用它。当没有包含引用的变量时,书籍列表将被垃圾收集
如果在不存储返回值的情况下调用Foo()
,则书籍列表将被标记为垃圾收集,并最终在垃圾收集器运行时被收集
“它为哪个对象执行Library=null;
?”
Dispose
在块末尾使用
自动调用,因此此代码是库
设置为null
的地方:
private static List<Book> Foo()
{
using (var lib = new Controller())
{
return lib.Library;
} // <-- Dispose is called here on 'lib'
}
private static List<Book> Foo()
{
using (var lib = new Controller())
{
lib.Dispose();
return lib.Library; // Now 'Library' is null
}
}
当您调用GC.Collect
时,GC(1)不保证遵守您执行收集的请求,并且(2)当您连接了调试器时,其行为会有所不同。删除对该列表的所有引用后,您如何检查该列表?@JoeSewell,好吧,为什么主函数中的列表不为null?我在dispose方法中将他设置为null。@AlexGorbunov如果没有,您将引用列表的属性设置为null,但这不会影响可能获得该引用的任何其他变量或属性。我认为您对引用类型的工作方式感到困惑。如果您执行var x=new List();变量y=x;x=零
,则x
为null
,但y
仍在引用列表。把列表想象成一个在某处占用内存的对象。然后x
和y
只是指内存中的那个位置。如果将其中一个设置为null
,它将不再指向那里,但这不会改变该内存位置上的内容,因此另一个仍然引用列表。如果存在对它的活动引用,GC
将不会处理它。