4
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

C# - staticなフィールドは記述順序に気を付けよう - 順次実行されるが後出でも未定義エラーにならず初期値で代用される

4
Last updated at Posted at 2022-02-09

問題となるソースコード


using System;

class SampleCode
{
    static readonly int Y = X;
    static readonly int X = 10;

    [STAThread]
    static void Main(string[] args)
    {
        Console.WriteLine(Y);
    }
}

このコードをcsc.exeでコンパイルして実行するとどうなるでしょう?

(a). Xが未定義としてコンパイルエラーになる
(b). 10が出力される
(c). (a)でも(b)でもない






実行結果


0

タイトル通りの挙動になっています。
ちなみにreadonlyかどうかは影響はないです。(ユースシーン的にreadonly1を使うときにうっかりしそうなので書いた次第。)

言語仕様

静的フィールドを初期化するための静的コンストラクターを指定しないと、すべての静的フィールドは、「C# 型の既定値」で示されている既定値に初期化されます。

静的コンストラクターは自動的に呼び出されます。 これにより、最初のインスタンスが作成される前、またはそのクラス (基底クラスではない) で宣言された静的メンバーが参照される前に、クラスが初期化されます。 静的コンストラクターは、インスタンス コンストラクターの前に実行されます。 (中略)。 静的フィールド変数初期化子が静的コンストラクターのクラスに存在する場合、それらは、クラス宣言に出現するテキストの順序で実行されます。 初期化子は、静的コンストラクターの実行直前に実行されます。

ildasmによる逆アセンブル結果

参考まで。
名称からして「静的コンストラクター」だと思われますが、言語仕様の章で抜粋した記載中の用語「静的フィールド変数初期化子」を内包しているっぽい。

static宣言部分の初期化処理の中身

.method private hidebysig specialname rtspecialname static 
        void  .cctor() cil managed
{
  // コード サイズ       18 (0x12)
  .maxstack  8
  IL_0000:  ldsfld     int32 SampleCode::X
  IL_0005:  stsfld     int32 SampleCode::Y
  IL_000a:  ldc.i4.s   10
  IL_000c:  stsfld     int32 SampleCode::X
  IL_0011:  ret
} // end of method SampleCode::.cctor

実行環境

コンパイル環境:
Microsoft (R) Visual C# Compiler version 4.8.4084.0
for C# 5

  1. static readonly の代わりに const を推奨するものではありません。

4
2
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?