1

块结束后

{
}

块中的变量会发生什么?

{
    int a;
    a=2;
    int b = 3;
}

//What happened now???

以及在这个块之后会发生什么

{
    int a=2;
    int b = 3;
}
GC.Collect();

清楚吗?如果我选择的标签是错误的,请编辑它,或者如果你可以编辑我的问题以明确请编辑它。

4

3 回答 3

4

在块的末尾,所有在内部声明的变量都“超出范围”。

它们很可能会从堆栈中弹出,但细节是优化器的操作。

而且由于您的示例变量都是ints (ValueTypes),因此它们与垃圾收集无关。

如果我们将最后一个示例更改为:

{
  int a=2;
  var b = new StringBuilder();
  ...
}
GC.Collect();

然后 StringBuilder 的内存将在 GC.Collect() 中收集。请注意,普通程序永远不需要调用 GC.Collect()。

于 2011-05-14T12:53:36.043 回答
3

块内的引用变量将超出范围。当被垃圾回收标记时,它们将保持标记,因为它们不再有任何引用。由于您没有任何参考变量,因此 GC 不会参与其中。

在某个时刻,垃圾收集器将运行并决定是否可以清除引用变量使用的内存。这取决于它们所处的世代,因此它们可能不会立即被删除。

调用GC.Collect();只是强制 GC 运行,尽管收集并不确定。对于大多数应用程序来说,这不是必需的。

于 2011-05-14T12:52:01.347 回答
2

在块的末尾,在块内声明的变量超出范围。如果它们是值类型(如 int),它们只会从堆栈中弹出。如果它们是引用类型(像大多数其他对象一样,例如StringBuilder),那么它们将不再被任何东西引用(除非你将它传递给仍在范围内的块之外的东西)并且垃圾收集器将在稍后的某个时间得到它。

如果您有访问稀缺资源的对象,例如各种Stream基于类(或任何实现IDisposable),那么您应该将其放在 using 语句中,如下所示:

using (Stream s = GetStream())
{
    // Do something with the stream.
}

在 using 块结束时,Dispose调用该方法并释放所有资源(例如文件处理程序、数据库连接、大块内存等)

通常,您不需要了解垃圾收集器何时运行或释放内存。当我在 2002 年从 C++ 迁移到 .NET 时,这对我来说是最难理解的事情之一,仅仅是因为我习惯于调用delete我在堆上创建的任何对象。

您不再需要担心这些。即使您忘记调用 dispose,垃圾收集器最终也会得到它(尽管您可能不想让该文件句柄保持比必要的时间更长,因此IDisposable

于 2011-05-14T13:14:16.730 回答