C# 无限循环中创建的对象的垃圾回收
我有一个非常基本的问题 我写了这样一个循环:C# 无限循环中创建的对象的垃圾回收,c#,garbage-collection,C#,Garbage Collection,我有一个非常基本的问题 我写了这样一个循环: while(true) { MyTestClass myObject = new MyTestClass(); } 何时在中创建对象 循环,垃圾收集 而且,对于每一次迭代,都是这样吗 新的内存位置是 是否已分配给myObject引用 如果我写myObject=null在每次迭代结束时 坦白地说,只要GC愿意;变量永远不会被读取,因此它总是合格的 myObject是一个变量,它在堆栈上有一个固定的位置作为参考;但是,每个新MyTestClass
while(true)
{
MyTestClass myObject = new MyTestClass();
}
myObject=null代码>在每次迭代结束时
myObject
是一个变量,它在堆栈上有一个固定的位置作为参考;但是,每个新MyTestClass()
都是一个不同的对象,在可用堆空间的某个地方创建;每次都不一样(而)存在一些复杂性,但这只有在退出循环后才会显示出来。因为在每次迭代中您都会立即分配它,所以这里没有明显的区别
myObject=null代码>在每次迭代结束时
这没什么区别。设置myObject=null
删除对对象的引用,但在下一次循环迭代中重新分配myObject
变量时,引用仍然会被删除。让我们来澄清一些事情。每次点击循环的内部,myObject
将被分配到一个新地址。所以这个循环所做的就是为一个变量名分配新的内存地址。因此:
GC将垃圾收集所有以前的分配,可能几乎是立即进行的,因为从未使用过该变量
对
没关系。该变量仍然未使用
作为所有其他答案的补充:
你可以把你的类变成一个结构。然后它将在堆栈上,并在每次迭代中被丢弃。如果您的结构生成了新类,那么您就回到了原点。如果结构较大,则可能会对性能产生负面影响;如果结构较小,则可能会对性能产生正面影响 让我们添加一些实际使用对象的代码,以便更清楚地了解实际发生的情况:
while(true) {
// Here a new instance is created in each iteration:
MyTestClass myObject = new MyTestClass();
// Here the instance is still in use
// until here:
myObject.CallSomething();
// Here the instance isn't used any more,
// so the GC can collect it if it wants to.
// Setting the reference to null here:
myObject = null;
// is useless, as the GC already knows that the
// instance is unused before that time.
}
这是你的最后一点;在IL级别(这是GC关心的),作用域不存在,并且在IL前导中声明了myObject
(假设它没有被捕获),因此在方法的整个持续时间内都存在(作为带有值的“局部”)。离开(C#)范围时,它不会被明确清除。简单地说:它永远不会超过这一点。您确定变量在每次传递时都必须有一个固定的位置吗?既然变量声明在循环中,那么这不是一个更动态的场景吗?如果您在循环中使用myObject的不同“实例”构造一个Lambda表达式,并且该表达式的生命周期超出了循环,那么您就能够捕获它们了?或者这是一个编译器技巧?myObject变量在堆栈上的位置固定是否正确?我认为,每次在堆栈上创建名为“myObject”的新变量时(在上一次迭代中创建的变量显然会被删除)。我说的对吗?@Tormod在这种情况下,将动态创建lambda闭包中字段的存储,并通过复制变量中的值填充字段,但这不会影响变量在堆栈上的位置。@Tormod-如@Pete所示;如果你捕获它,它就不再是“本地”;本地堆栈将具有对引用变量(现在是字段)的对象的引用。每个循环是否获得不同的捕获对象取决于变量的确切定义位置;在这种情况下,每个循环将获得一个新的捕获对象。而且每次捕获实例也会被收集(当GC感觉像的时候)。+1如果你认为null是空的,那么一旦GC不再使用,运行时会使这些实例对GC来说是可省略的,这意味着即使在声明大量对象变量的大方法中,在方法中部分地将它们置零(虽然可读),不会导致行为上的差异。@Adam:如果是这样,那么我们应该在什么时候为对象指定null值?当我们知道变量在某些代码行之后(例如myObject.CallSomething()之后)不会使用时,不将其设置为null可以吗?@Amey是的,对不起,我不是很清楚-不需要将其设置为null,运行时有智能为您解决此问题。这是不正确的。如果它是一个结构,那么每次迭代都不会丢弃它,每次迭代都会是同一个实例,并且在方法退出之前不会丢弃它。但是,每次迭代都会得到一个新的值。这是否意味着,在struct的情况下,将使用相同的变量,但在每次迭代中它的属性将有不同的值?i、 e.在循环中声明的struct变量不会在每次迭代结束时从堆栈中移除。我说的对吗?循环变量是否被弹出取决于编译器,但这些变量的行为是在每次迭代中被重置(全新的)。如果你想让一个变量值在iTraion上继续存在,你需要在循环之外声明它。我说的“丢弃”只是意味着你不能访问以前的数据。它是清除堆栈上的数据,还是弹出堆栈,然后推送堆栈,对于GC来说并不重要。第一个是有点