c# - 内部范围内嵌套引用类型对象对垃圾回收没有影响 : True or False?

标签 c# scope garbage-collection

我一直在阅读 Jeffrey Richter 的好书“CLR via C#”中的垃圾收集章节。在那里,他通过引用从 JIT 编译器发出的 native 代码的反汇编列表,说明了 GC 在概念上如何工作(如何标记根)的示例。从那个例子中,我想到在范围内嵌套引用类型似乎对加速嵌套变量的垃圾收集有零影响。我想知道我是否理解正确。无论如何,请考虑这两个版本的代码:

A) 在内部范围内嵌套引用类型变量 (y):

namespace scope
{
    class A { public void foo() { } }
    class Program
    {
        static void Main(string[] args)
        {
            A x = new A();
            x.foo();
            {
                A y = new A();
                y.foo();
            }
        }
    }
}

B) 同上,只是 x 和 y 在同一范围内。

namespace scope
{
    class A { public void foo() { } }
    class Program
    {
        static void Main(string[] args)
        {
            A x = new A();
            x.foo();

            A y = new A();
            y.foo();
        }
    }
}

出于好奇,我检查了两个版本生成的 IL 代码,它们是一样的!

Q1:所以,这似乎暗示,范围界定确实不会以任何方式加速垃圾收集。这样对吗? (注意:我知道“using”语句 - 但我只对上面 2 个示例中所示的“普通旧范围”的 GC 行为感到好奇。)

问题 2:如果问题 1 的答案是“正确”,那么我对“对象生命周期不是由作用域决定”的情况如何可能发生感到非常困惑,如下所述: http://www.curly-brace.com/favorite.html

最佳答案

垃圾收集部分取决于您是否在调试器中运行。我假设我们不是。

它实际上可能比您想象的更具侵略性。例如:

object o = new object();
Console.WriteLine(o);   
Console.WriteLine("hi");
o = new object();

对象可以在第二行之后立即被垃圾回收——即在变量 o 退出作用域之前很久。如果没有最后一行,这也是正确的。

换句话说,作用域不会加速垃圾收集 - 因为 GC 已经比您想象的更聪明。

事实上,垃圾收集器可以甚至更激进。考虑这段代码:

Foo f = new Foo();
f.SomeMethod();
Console.WriteLine("Hello");

Foo 看起来像这样:

public class Foo
{
    int x = 10;

    public void SomeMethod()
    {
        Console.WriteLine(x);
        for (int i = 0; i < 100; i++)
        {
            Console.WriteLine("Hello");
            Thread.Sleep(100);
        }
    }
}

理论上,垃圾收集器可以在 SomeMethod 运行时收集 Foo 对象,只要它越过第一行,其中它实际上是从 x 读取的。如果 Foo 有终结器,您可以让终结器在一个线程中运行,而 SomeMethod 在另一个线程中运行。可怕的东西。

关于c# - 内部范围内嵌套引用类型对象对垃圾回收没有影响 : True or False?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3101530/

相关文章:

java - 错误java.lang.OutOfMemoryError:超出了GC开销限制

c# - 调整图像大小,同时保持纵横比

java - 没有抽象方法的抽象类

c++ - 什么C++在内存地址处做一个变量到 "deallocate"呢?

javascript - C++/CX : Defining public void at namespace scope

Java:增加YoungGen大小以提高GC性能

compiler-construction - 为什么要收集垃圾?为什么编译器不自动插入 free() 呢?

c# - 在gridview上获取两次点击事件

c# - WPF/Xaml 有类似 Flex/MXML 的 ViewStack 的东西吗

scope - 未捕获闭包范围? — CoffeeScript