我急切地想知道发生了什么的对象在.NET中,当它超出范围。 事情是这样的:
class A
{
ClassB myObjectB = new ClassB();
}
//what happens to object at this point here?
在内存会发生什么? 当它掉出来的在堆范围和松散它参考GC是否被调用?
我急切地想知道发生了什么的对象在.NET中,当它超出范围。 事情是这样的:
class A
{
ClassB myObjectB = new ClassB();
}
//what happens to object at this point here?
在内存会发生什么? 当它掉出来的在堆范围和松散它参考GC是否被调用?
What happens in the memory? Does GC get called when it falls out of scope and loose it reference in the heap?
No - the GC doesn't get called at this point.
What happens is that the object is left in memory, but is now "unrooted" - basically, there are no references to that object from any other object. As such, the object is now eligible for garbage collection.
At some point in the future, the GC will run. When this happens, the unrooted object will now be eligible for garbage collection. Depending on which generation holds the object, it may or may not be cleaned at that point. Eventually, if the program continues executing and if memory pressure causes the appropriate generation to be collected, the memory for that object will be reclaimed.
There is no definite point in time when this will happen (unless you explicitly call GC.Collect
, which is a bad idea). However, with managed code, you don't really need to worry about when this will happen. Just assume that it will happen when and if appropriate for your specific application.
从PST的评论之后,一个更好的例子可能是这样的:
void M()
{
ClassB myObjectB = new ClassB();
}
//what happens to object at this point here?
在这个例子中, myObjectB
是一个局部变量,而不是一个场。 所以,当局部变量超出范围时,会发生什么? 没有! 范围无关,与C#对象的生命周期。
真正的情况是,JIT编译器决定在某个时候释放对象。 这可以是变量的作用域结束前 ,如果变量是不会在该方法的其余部分使用。 一旦对象不再被引用,因为其他的答案也提到,变得适合收集由GC。 它实际上没有收集直到GC运行(实际上,直至GC收集的对象所居住的产生)。
作为PST暗示,一个字段是差的例子,因为它总是会到达其时包含的对象是可到达的,所以范围和对象的生存期之间的间隔更大的:
class A
{
private object o = //whatever
}
void B()
{
var a = new A();
// here, the field o is not in scope, but the object it refers to is reachable and cannot be collected.
GC.KeepAlive(a);
}
我觉得“闹翻的范围”是一个更加C ++ - 的东西,其中在给定范围内的一端与自动存储一个对象被释放,并呼吁其析构函数思想的具体方式。
在C#世界,没有“跌出的范围”。 变量(读:名)在一定范围存在,仅此而已。 该GC真的有这种不关心; 一个对象可以其名字的范围在年底前这取决于引用它当GC确定的集合是必要的,即使收集退出,或者不久。
然后这两个概念应该离婚,大约分开的理由。 作用域是所有有关的名字,而垃圾收集只关心对象的可达性。 当一个对象不再是从已知的根源之一可达,会定期收集。
如果没有什么引用对象时,它会最终被GC回收。 关键是,你无法预测何时它到底会发生。 你只知道,它会发生。
一般而言,垃圾收集发生在3个不同的世代(0,1或2)。 当每个这些被收集取决于有多少资源被操作系统所需要。
到GC.Collect的()的调用将收集所有可用的资源,但它是可以定义要收集的资源产生。