【问题标题】:Will local variable assignment always be executed, even if variable is unused?即使变量未使用,是否总是执行局部变量赋值?
【发布时间】:2013-01-29 08:36:35
【问题描述】:

我有一个静态容器类,它拥有某个类 A 的句柄:

public static class Container
{
    private static A _a;        
    public static void Register(A a) { _a = a; }
    public static void Run() { _a.DoIt(); }
}

容器A实例的注册在A构造函数中进行:

public class A
{
    public A() { Container.Register(this); }        
    public void DoIt() { Console.WriteLine("Running!"); }
}

现在,假设我通过调用仅包含 A 实例化的方法来注册我的 A 实例:

public void Init() { var a = new A(); }

理论上,可以优化编译以忽略此分配,还是我可以 100% 确定 A 在我调用 Init 方法时总是被实例化?

示例当我运行以下代码时:

Init();
...
Container.Run();

是否将始终定义 Container._a 并将 DoIt 方法的输出写入控制台?

【问题讨论】:

    标签: c# variable-assignment compiler-optimization


    【解决方案1】:

    编译器通常不知道 A 的构造函数是否具有可观察到的副作用,因此它总是会调用它。但它可能不会保留变量“a”。

    所以,构造函数会被调用,但结果可能不会赋值给变量;相反,如果没有其他对象引用它,则 A 对象可能会立即注册以进行垃圾收集。 (在您的情况下,其他东西确实引用了它 - 即 Container 类 - 所以它不会被垃圾收集!)

    在您的情况下,构造函数显然在任何情况下都有副作用(因此编译器优化构造函数调用将是一个重大错误)。

    总结:

    • 将始终调用构造函数。
    • 可能无法将结果赋值给局部变量,因为编译器知道它没有可观察到的副作用。
    • 在您的代码中,其他内容保留了对构造对象的引用,因此不会被 GC。

    【讨论】:

    • 它不应该保留变量 'a',这在这里不是问题,因为新对象将被 Container 类引用,所以它不会被 GC'd 直到其他一些 'A ' 向容器注册
    • 好的,我已经更新了我的答案,明确提到了这一点!
    猜你喜欢
    • 2011-05-05
    • 1970-01-01
    • 2019-08-26
    • 2014-04-22
    • 1970-01-01
    • 1970-01-01
    • 2016-06-30
    相关资源
    最近更新 更多