3

いくつかのクラスへのハンドルを保持する静的コンテナー クラスがあります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(); }

理論的には、この割り当てを無視するようにコンパイルを最適化できますか、またはメソッドを呼び出すときに常にAインスタンス化されることを 100% 確信できますか?Init

次のコードを実行すると:

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

Container._a常に定義され、メソッドからの出力がDoItコンソールに書き込まれますか?

4

1 に答える 1

7

コンパイラーは一般に、Aのコンストラクターに観察可能な副作用があるかどうかを知らないため、常にそれを呼び出します。ただし、変数「a」は保持されない場合があります。

したがって、コンストラクターが呼び出されますが、結果が変数に割り当てられない場合があります。代わりに、他に何も参照されていない場合、Aオブジェクトはすぐにガベージコレクションに登録される可能性があります。(あなたの場合、他の何かがそれを参照します-つまり、Containerクラス-したがって、ガベージコレクションされません!)

あなたの場合、コンストラクターには明らかに副作用があります(したがって、コンストラクター呼び出しを最適化することはコンパイラーにとって大きなエラーになります)。

要約すれば:

  • コンストラクターは常に呼び出されます。
  • 結果のローカル変数への割り当ては、コンパイラが観察可能な副作用がないことを認識しているため、実行されない場合があります。
  • あなたのコードでは、他の何かが構築されたオブジェクトへの参照を保持しているので、それはGCされません。
于 2013-01-29T08:39:41.233 に答える