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