C#
 Computer >> コンピューター >  >> プログラミング >> C#

C#の静的コンストラクターとは?特徴・実行タイミング・注意点を解説

静的コンストラクターとは

静的コンストラクター(static constructor)は、静的なデータを初期化したり、一度だけ実行すればよい特定の処理を行うために使用されます。最初のインスタンスが生成される前、またはいずれかの静的メンバーが参照される前に、自動的に呼び出されるのが大きな特徴です。

静的コンストラクターは、アンマネージコード用のラッパークラスを作成する際に特に有用です。この場合、コンストラクター内でLoadLibraryメソッドを呼び出すことができます。また、制約(constraints)ではコンパイル時にチェックできない型パラメーターに対して、実行時の検証を行う場所としても適しています。

静的コンストラクターの主な特徴

  • アクセス修飾子を持たず、パラメーターも受け取りません。

  • 1つのクラスまたは構造体に定義できる静的コンストラクターは1つだけです。

  • 継承やオーバーロードはできません。

  • コードから直接呼び出すことはできません。呼び出しは共通言語ランタイム(CLR)が担当し、自動的に実行されます。

  • プログラム内のどの時点で実行されるかを、開発者が制御することはできません。

  • 最初のインスタンスが作成される前、または静的メンバーが参照される前に、クラスを初期化するために自動的に呼び出されます。静的コンストラクターは必ずインスタンスコンストラクターよりも先に実行されます。なお、イベントやデリゲートに割り当てられた静的メソッドの場合、そのメソッドが実際に呼び出されたときに静的コンストラクターが実行され、割り当てた時点では実行されません。静的コンストラクターが存在するクラスに静的フィールド変数初期化子がある場合、それらは静的コンストラクターの実行直前に、クラス宣言内で記述されている順序(テキスト上の順序)どおりに実行されます。

  • 静的フィールドを初期化する静的コンストラクターを定義しなかった場合、すべての静的フィールドは「C#の型の既定値」に従った既定値で初期化されます。

  • 静的コンストラクターが例外をスローした場合、ランタイムは二度とそれを呼び出さず、プログラムが動作しているアプリケーションドメインの有効期間中、その型は未初期化のままになります。最もよく見られるのは、静的コンストラクターが型のインスタンス化に失敗した場合や、静的コンストラクター内でハンドルされていない例外が発生した場合にスローされるTypeInitializationExceptionです。ソースコードに明示的に定義されていない暗黙的な静的コンストラクターの場合、トラブルシューティングには中間言語(IL)コードの調査が必要になることがあります。

  • 静的コンストラクターが存在すると、BeforeFieldInit型属性が付与されなくなります。その結果、ランタイムの最適化が制限される点にも注意が必要です。

  • static readonlyとして宣言されたフィールドは、宣言時または静的コンストラクター内でのみ代入できます。明示的な静的コンストラクターが不要な場合は、静的コンストラクターを使う代わりに宣言時に静的フィールドを初期化する方が、ランタイムの最適化の観点から有利です。

例1:静的コンストラクターの基本的な動作

using System;
namespace DemoApplication{
    public class Program{
        static void Main(string[] args){
            Car user = new Car();
            Car user1 = new Car();
            Console.ReadLine();
        }
    }
    public class Car{
        static Car(){
            Console.WriteLine("Static constructor called");
        }
        public Car(){
            Console.WriteLine("Default constructor called");
        }
    }
}

出力結果

Static constructor called
Default constructor called
Default constructor called

上記の例では、Carクラスのインスタンスを2つ生成しましたが、静的コンストラクターのメッセージ「Static constructor called」は最初の1回しか表示されていません。このことから、静的コンストラクターが型ごとに一度だけ実行されることが確認できます。

例2:static readonlyフィールドとの組み合わせ

using System;
using System.Threading;
namespace DemoApplication{
    public class Car{
        protected static readonly DateTime globalStartTime;
        protected int RouteNumber { get; set; }
        static Car(){
            globalStartTime = DateTime.Now;
            Console.WriteLine($"Static constructor called. Global start time:
            {globalStartTime.ToLongTimeString()}");
        }
        public Car(int routeNum){
            RouteNumber = routeNum;
            Console.WriteLine($"Car {RouteNumber} is created.");
        }
        public void Drive(){
            TimeSpan elapsedTime = DateTime.Now - globalStartTime;
            Console.WriteLine($"Car {this.RouteNumber} is starting its route
            {elapsedTime.Milliseconds} minutes after global start time
            {globalStartTime.ToShortTimeString()}.");
        }
    }
    class TestCar{
        static void Main(){
            Car car1 = new Car(1);
            Car car2 = new Car(2);
            car1.Drive();
            Thread.Sleep(25);
            car2.Drive();
            Console.ReadLine();
        }
    }
}

出力結果

Static constructor called. Global start time:
7:09:06 AM
Car 1 is created.
Car 2 is created.
Car 1 is starting its route25 minutes after global start time7:09 AM.
Car 2 is starting its route50 minutes after global start time7:09 AM.

この例では、静的コンストラクター内でstatic readonlyフィールドであるglobalStartTimeに現在時刻を設定しています。このように、静的コンストラクターはアプリケーション全体で共有される静的な状態(開始時刻など)を初期化するのに非常に役立ちます。


  1. Javaのパラメータ化コンストラクタとは?使い方と具体例を解説

    Javaのコンストラクタとはコンストラクタはメソッドに似た特別な仕組みで、クラスのオブジェクトが生成されるタイミングで自動的に呼び出されます。主にクラスのインスタンス変数を初期化するために使用されます。コンストラクタにはクラス名と同じ名前を付けなければならず、戻り値の型は持ちません。コンストラクタには大きく分けて「引数なし(デフォルト)コンストラクタ」と「パラメータ化(引数付き)コンストラクタ」の2種類があります。このうち、パラメータ化コンストラクタは1つ以上の引数を受け取ることができるのが特徴です。パラメータ化コンストラクタの役割コンストラクタの主な目的は、クラスのインスタンス変数を初期化す

  2. Javaのコンストラクタとは?役割と使い方を実例付きで解説

    コンストラクタとは コンストラクタはメソッドに似た仕組みで、クラスのオブジェクトが生成されるタイミングで自動的に呼び出されます。主な用途は、クラスのインスタンス変数を初期化することです。 コンストラクタには以下のような特徴があります。 クラス名と同じ名前を持つ 戻り値の型を持たない(voidも指定しない) newキーワードによるオブジェクト生成時に自動的に実行される コンストラクタの種類 Javaのコンストラクタには、大きく分けて次の2種類があります。 引数なしコンストラクタ:引数を受け取らず、固定値などでフィールドを初期化します。 引数付きコンストラクタ:呼び出し側から渡された値を使っ