Object.Finalize()重写和GC.Collect()

Ale*_*ell 0 c# garbage-collection finalizer

在覆盖Object.Finalize()的类的存在下,我似乎无法理解GC.Collect()的行为.这是我的基本代码:

namespace test
{
 class Foo
 {
  ~Foo() { Console.WriteLine("Inside Foo.Finalize()"); }
 }

 static class Program
 {

  static void Main()
  {
   {
    Foo bar = new Foo();
   }

   GC.Collect();
   GC.WaitForPendingFinalizers();

   Console.ReadLine();
  }
 }

}
Run Code Online (Sandbox Code Playgroud)

与我期望的相反,我只在程序终止时获得控制台输出而不是之后 GC.WaitForPendingFinalizers()

Eri*_*ert 12

编译器和运行时都不需要保证超出范围的本地实际上会截断其内容的生命周期.出于计算生命周期的目的,编译器或运行时将其视为不存在大括号是完全合法的.如果需要基于大括号的清理,则实现IDisposable并使用"using"块.

更新:

关于你的问题"为什么这在优化与未经优化的构建中有所不同",好吧,看看codegen的不同之处.

未优化:

.method private hidebysig static void  Main() cil managed
{
  .entrypoint
  // Code size       28 (0x1c)
  .maxstack  1
  .locals init (class test.Foo V_0)
  IL_0000:  nop
  IL_0001:  nop
  IL_0002:  newobj     instance void test.Foo::.ctor()
  IL_0007:  stloc.0
  IL_0008:  nop
  IL_0009:  call       void [mscorlib]System.GC::Collect()
  IL_000e:  nop
  IL_000f:  call       void [mscorlib]System.GC::WaitForPendingFinalizers()
  IL_0014:  nop
  IL_0015:  call       string [mscorlib]System.Console::ReadLine()
  IL_001a:  pop
  IL_001b:  ret
} // end of method Program::Main
Run Code Online (Sandbox Code Playgroud)

优化:

.method private hidebysig static void  Main() cil managed
{
  .entrypoint
  // Code size       23 (0x17)
  .maxstack  8
  IL_0000:  newobj     instance void test.Foo::.ctor()
  IL_0005:  pop
  IL_0006:  call       void [mscorlib]System.GC::Collect()
  IL_000b:  call       void [mscorlib]System.GC::WaitForPendingFinalizers()
  IL_0010:  call       string [mscorlib]System.Console::ReadLine()
  IL_0015:  pop
  IL_0016:  ret
} // end of method Program::Main
Run Code Online (Sandbox Code Playgroud)

显然是一个巨大的差异.显然,在未经优化的构建中,引用存储在本地插槽零中,并且在方法结束之前永远不会被删除.因此,在方法结束之前,GC无法回收内存.在优化的构建中,引用存储在堆栈中,立即弹出堆栈,GC可以自由回收它,因为堆栈上没有剩余的有效引用.