14

静的フィールドの初期化の動作が異なる場合があることがわかりました。次のコードの場合、

public class Class1
{
  public static void Main()
  {
    Console.WriteLine("Main");
    Test();
    Console.ReadLine();
  }

  public static void Test(){
    Console.WriteLine("Test");
    Singleton.Instance.DoSomething();
  }
}

public class Singleton
{
  private static Singleton sInstance = new Singleton();

  protected Singleton()
  {
    Console.WriteLine("Singleton Constructor");
  }

  public static Singleton Instance
  {
    get
    {
      return sInstance;
    }
  }

  public void DoSomething(){}
}

デバッグビルドでは、印刷されます

Main
Test
Singleton Constructor

リリースビルドでは、印刷されます

Main
Singleton Constructor
Test

これら 2 つのビルドで生成された IL コードを確認しましたが、ほとんど同じです。

これはどうやって起こるのだろうか?また、リリース ビルドでの一種の JIT 最適化である場合、その動機は何ですか?

4

3 に答える 3

7

静的初期化子がいつ実行されるかは、完全に実装に依存します。そのため、順序が異なる場合があります。しかし、静的コンストラクターを提供すると、それらの静的イニシャライザーは常に先に実行されます。したがって、出力は一貫した順序になります。

MSDNから

クラスの静的フィールド変数初期化子は、クラス宣言に現れるテキストの順序で実行される一連の代入に対応します。静的コンストラクター (セクション 10.11) がクラスに存在する場合、静的フィールド初期化子の実行は、その静的コンストラクターを実行する直前に発生します。それ以外の場合、静的フィールド初期化子は、そのクラスの静的フィールドを最初に使用する前に、実装に依存する時点で実行されます。

クラスに静的コンストラクターを追加するSingleton

static Singleton() { }
于 2012-05-27T15:58:36.873 に答える
2

リリースビルドでx86ジッターを再現します。これは仕様によるものであり、静的クラスコンストラクターが実行される正確な瞬間は保証されていません。唯一の要件は、クラス内の他のメソッドが実行される前に実行されることです。したがって、オプティマイザは、より効率的なコードを生成する場合、コードを再配置することが許可されます。そうです、cctor呼び出しをMain()メソッドに戻します。残りのコードを最適化する機会が増えるという利点があります。

一般に、観察可能な副作用がある初期化式でコードを記述しないようにする必要があります。

于 2012-05-27T16:18:16.850 に答える
1

別の回答では、テスト プログラムと、 { Debug, Release }{ x86, x64 }および.NETメジャー バージョンの比較についての説明を提供します。要約された結果は次のとおりです。詳細については、次のリンクを確認してください。

.NET 2.0/3.5

2.0.50727.8825 x86 Debug
2.0.50727.8825 x86 Debug TouchMe fieldinit
2.0.50727.8825 x86 Release fieldinit
2.0.50727.8825 x86 Release TouchMe fieldinit
2.0.50727.8825 x64 Debug
2.0.50727.8825 x64 Debug TouchMe fieldinit
2.0.50727.8825 x64 Release
2.0.50727.8825 x64 Release TouchMe fieldinit

.NET 4.7.1

4.7.2556.0 x86 Debug
4.7.2556.0 x86 Debug TouchMe fieldinit
4.7.2556.0 x86 Release
4.7.2556.0 x86 Release TouchMe
4.7.2556.0 x64 Debug
4.7.2556.0 x64 Debug TouchMe fieldinit
4.7.2556.0 x64 Release
4.7.2556.0 x64 Release TouchMe

于 2017-12-22T01:50:23.140 に答える