1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

C#のモジュール初期化子が呼ばれる前に

Last updated at Posted at 2026-01-11

C#のモジュール初期化子は

「モジュールが読み込まれたタイミングで呼ばれるメソッド」

という表現は正しいのだけれど、

「モジュールが読み込まれたタイミングでまず最初に呼ばれるメソッド」

という表現は適切ではなさそう。

「モジュール初期化子は、モジュールが読み込まれたタイミングで呼ばれる。
ただし、その前に呼ぶ必要があるメソッドを、すべて呼び出した後に呼ばれる点に注意が必要。」

くらいの表現が、適切な気がする。

具体的には、モジュール初期化子が呼び出される前に、そのクラスの静的コンストラクターがあれば、呼び出されるはず。また、その静的コンストラクターの呼び出しに必要な処理やメソッドがあれば、それも呼ばれるはず。


具体的なコード例とその実行結果を示す。
コメント中の数字は実行される順番。
これは極端な例であることに注意。

using System.Runtime.CompilerServices;

public class Program
{
    public static void Main(string[] args)
    {
        // 12. 最後に、「Hello World!」と表示
        Console.WriteLine("Hello World!");
    }
}

public class ModuleInitializerCaller
{
    // 1. ModuleInitializerCallerの静的フィールドの初期化を行おうとする。
    // そのためにAnotherClassの初期化が必要
    // 6. その後、AnotherClassのインスタンスを生成する
    static AnotherClass _anotherClassInstance = new AnotherClass("in ModuleInitializerCaller");

    // 8.  ModuleInitializerCallerの静的フィールドの初期化を行おうとする。
    // そのために、ModuleInitializerCallerのインスタンスを生成する
    static ModuleInitializerCaller _instance = new ModuleInitializerCaller();

    // 10. ModuleInitializerCallerの静的コンストラクターが呼ばれる
    // 「static ModuleInitializerCaller」と表示    
    static ModuleInitializerCaller()
    {
        Console.WriteLine("static ModuleInitializerCaller");
    }

    // 0. ModuleInitializer属性がついているから、モジュールが読み込まれたタイミングでModuleInitializerCaller#InitializeModuleを呼び出そうとする。
    // その前に、必要なメソッドや処理を呼び出す。
    // 11. 必要なメソッドや処理の呼び出しが終わったので、InitializeModuleメソッドを呼び出し
    // 「ModuleInitializerCaller#InitializeModule」と表示
    [ModuleInitializer]
    public static void InitializeModule()
    {
        Console.WriteLine("ModuleInitializerCaller#InitializeModule");
    }

    // 9. ModuleInitializerCallerの静的フィールドの初期化のために、ModuleInitializerCallerのコンストラクターが呼ばれる
    // 「constructor ModuleInitializerCaller」と表示    
    ModuleInitializerCaller()
    {
        Console.WriteLine("constructor ModuleInitializerCaller");
    }
}

// 2. AnotherClassの初期化をする
public class AnotherClass
{
    // 3. AnotherClassの静的フィールドの初期化を行おうとする。
    // そのためにAnotherClassのインスタンスを生成する
    static AnotherClass _instance = new AnotherClass("in AnotherClass");

    // 5. AnotherClassの静的コンストラクターが呼ばれる
    // 「static AnotherClass」と表示
    static AnotherClass()
    {
        Console.WriteLine("static AnotherClass");
    }

    // 4. AnotherClassの静的フィールドの初期化のために、AnotherClassのコンストラクターが呼ばれる
    // 「constructor AnotherClass AnotherClass」と表示
    // 7. ModuleInitializerCallerの静的フィールドの初期化のために、AnotherClassのコンストラクターが呼ばれる
    // 「constructor AnotherClass ModuleInitializerCaller」と表示
    public AnotherClass(string message)
    {
        Console.WriteLine($"constructor AnotherClass {message}");
    }
}

上記のコードを「.NET 10.0.100」で実行した結果は、次の通り。

constructor AnotherClass in AnotherClass
static AnotherClass
constructor AnotherClass in ModuleInitializerCaller
constructor ModuleInitializerCaller
static ModuleInitializerCaller
ModuleInitializerCaller#InitializeModule
Hello World!

処理は次のような順番で行われる。

  1. ModuleInitializer属性がついているから、モジュールが読み込まれたタイミングでModuleInitializerCaller#InitializeModuleを呼び出そうとする。
    その前に、必要なメソッドや処理を呼び出す。

  2. ModuleInitializerCallerの静的フィールドの初期化を行おうとする。そのためにAnotherClassの初期化が必要。

  3. AnotherClassの初期化をする

  4. AnotherClassの静的フィールドの初期化を行おうとする。そのためにAnotherClassのインスタンスを生成する。

  5. AnotherClassの静的フィールドの初期化のために、AnotherClassのコンストラクターが呼ばれる
    「constructor AnotherClass in AnotherClass」と表示

  6. AnotherClassの静的コンストラクターが呼ばれる
    「static AnotherClass」と表示

  7. その後、AnotherClassのインスタンスを生成する

  8. ModuleInitializerCallerの静的フィールドの初期化のために、AnotherClassのコンストラクターが呼ばれる
    「constructor AnotherClass in ModuleInitializerCaller」と表示

  9. ModuleInitializerCallerの静的フィールドの初期化を行おうとする。
    そのために、ModuleInitializerCallerのインスタンスを生成する

  10. ModuleInitializerCallerの静的フィールドの初期化のために、ModuleInitializerCallerのコンストラクターが呼ばれる
    「constructor ModuleInitializerCaller」と表示

  11. ModuleInitializerCallerの静的コンストラクターが呼ばれる
    「static ModuleInitializerCaller」と表示

  12. 必要なメソッドや処理の呼び出しが終わったので、InitializeModuleメソッドを呼び出し
    「ModuleInitializerCaller#InitializeModule」と表示

  13. 最後に、「Hello World!」と表示

実行順序を理解するために、抑えるべきポイントは次の通り。

  • モジュール初期化子の前に、そのメソッドが定義されているクラスの静的コンストラクターが呼び出される
  • 静的コンストラクターが呼び出される前に、静的フィールドの初期化が終わる
  • 静的フィールドの初期化順序は定義順

というわけで、

モジュール初期化子は、モジュールが読み込まれたタイミングで呼ばれる。
ただし、その前に呼ぶ必要があるメソッドを、すべて呼び出した後に呼ばれる点に注意が必要。

1
0
0

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
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?