C# 垃圾收集器不再引用

C# 垃圾收集器不再引用,c#,.net,garbage-collection,clr,C#,.net,Garbage Collection,Clr,我一直在读C#中关于GC的内容,我发现一些陈述是真实的,非常有趣 假设我有以下方法: public void Foo() { Animal eAnimal = new Animal(); eAnimal.Name = "Matthew"; GC.Collect(); ...more code not using eAnimal... return; } 据推测,在GC.Collect()语句中,GC发现与新的Animal()对象相对应的内存地址不再在代码中引

我一直在读C#中关于GC的内容,我发现一些陈述是真实的,非常有趣

假设我有以下方法:

public void Foo()
{
   Animal eAnimal = new Animal();
   eAnimal.Name = "Matthew";

   GC.Collect();

   ...more code not using eAnimal...

   return;
}
据推测,在GC.Collect()语句中,GC发现与新的Animal()对象相对应的内存地址不再在代码中引用,因此适合处理

据我所知,即使在GC.Collect()语句中,堆栈中也有对新Animal()的引用(甚至可能存储在某个CPU注册表中)。我知道,如果我检查代码,尽管该值存在于堆栈中,但代码的逻辑中不再使用,但我猜这种分析可以在编译时完成,而不是在运行时完成

GC如何知道,即使堆栈中有对堆的引用,该引用也不会以任何方式在程序的未来语句中使用

我最好的猜测是编译会考虑到这一点,并创建适当的指令来清除堆栈中的引用,然后使GC工作更容易。但这似乎给生成的代码增加了很多开销

编辑:我正在读一本关于70-483考试的书,书上说:

StreamWriter stream = File.CreateText(“temp.dat”);
stream.Write(“some data”);
GC.Collect()
在发布模式下运行这段代码时,垃圾收集器将看到 不再引用流,它将释放与流关联的所有内存- 作家的例子


您没有从方法返回对该对象的引用,因此当您调用
GC.Collect()
时,它会查看该对象正在使用的位置,并发现在集合调用之后没有其他对象会引用它。正如您所指出的,调用后的所有代码都没有使用该对象,因此GC将安全地处理它

这个例子很好地解释了与您所处的情况类似的情况


对垃圾收集操作的全面解释:

但是您描述的方式是它工作的唯一方式。这有什么奇怪的?在函数返回之前,需要在某个点“释放”所有这些引用。为什么不在调用
GC.Collect()
据推测,在GC.Collect()语句中,GC发现新的Animal()对象对应的内存地址不再在代码中引用,因此适合处理。
根据谁?@Kyle,我编辑了我的问题。@JonathonReinhart,不要假设Collect()和return之间没有代码。我将在我的问题中解决这个问题。在MSDN示例中,被调用方法的堆栈已死亡,因此当调用Collect()时,这些引用不存在。在我的示例中,当前堆栈仍然处于活动状态,因此情况不同。我的问题是它如何知道调用后的代码没有使用该对象。@MatthewAzkimov从某种意义上说,在集合调用后您没有使用代码是一样的。为什么GC不会删除一个不再被引用的对象?这对你来说是一本好书:我不是说它不应该。我想问的是,如果(我猜)堆栈中仍然存在对动物对象堆中内存地址的内存引用,它如何知道该对象不再被引用。@MatthewAzkimov查看我更新答案中的链接。这是对垃圾收集器工作原理的非常透彻的解释。他们的解释是“活动根目录列表由即时(JIT)编译器和公共语言运行库维护,并可供垃圾收集器的算法访问。”。我想我得问问微软真的“怎么做”。。。。