块结束后
{
}
块中的变量会发生什么变化?
{
int a;
a=2;
int b = 3;
}
//What happened now???
以及此块后发生的事情
{
int a=2;
int b = 3;
}
GC.Collect();
清楚吗? 如果我选择的标签有误,请编辑它,或者如果您可以编辑我的问题,请编辑它。
答案 0 :(得分:4)
块内的引用变量将超出范围。当被垃圾收集标记时,它们将保持标记,因为它们不再具有任何引用。由于您没有任何参考变量,因此GC不会参与。
在某一点上,垃圾收集器将运行并决定是否可以清除引用变量使用的内存。这取决于它们的生成,因此它们可能不会立即被删除。
调用GC.Collect();
只会强制GC运行,但收集不确定。对于大多数应用来说,这不是必需的。
答案 1 :(得分:4)
在一个块结束时,所有变量都在'超出范围'内声明。
很可能它们会被堆叠掉,但细节可以通过优化器来实现。
由于您的示例变量都是int
s(ValueTypes),因此它们与垃圾收集无关。
如果我们将最后一个示例更改为:
{
int a=2;
var b = new StringBuilder();
...
}
GC.Collect();
然后将在GC.Collect()中收集StringBuilder的内存。请注意,正常程序永远不需要调用GC.Collect()。
答案 2 :(得分:2)
在块结束时,块内声明的变量超出范围。如果它们是值类型(如int),它们只会从堆栈中弹出。如果它们是引用类型(像大多数其他对象,例如StringBuilder
)那么它们将不再被引用(除非你将它传递给仍在范围内的块之外的东西),垃圾收集器将获取它过了一会儿。
如果你有对象访问稀缺资源,比如各种基于Stream
的类(或任何实现IDisposable
的类),那么你应该把它放在这样的using语句中:
using (Stream s = GetStream())
{
// Do something with the stream.
}
在使用块结束时,调用Dispose
方法并释放所有资源(例如文件处理程序,数据库连接,大块内存等)
通常,您无需了解垃圾收集器何时运行或释放内存。当我在2002年从C ++迁移到.NET时,这是我最难理解的事情之一,因为我习惯于在堆上创建的任何对象上调用delete
。
你不再需要担心这一点。即使您忘记调用dispose,垃圾收集器也会最终到达它(尽管您可能不希望保留该文件的句柄超过必要的时间,因此IDisposable
)