静的変数に関するC#ドキュメントから引用するには:
静的メンバーは、静的メンバーに初めてアクセスする前、および静的コンストラクター(存在する場合)が呼び出される前に初期化されます。
たとえば、次のサンプルプログラムを実行します。
using System;
namespace ScrapCSConsole
{
class ScrapCSConsole
{
public static void Main()
{
Console.WriteLine("Create StaticDemo A");
StaticDemo a = new StaticDemo();
Console.WriteLine("Create StaticDemo B");
StaticDemo b = new StaticDemo();
Console.WriteLine("Done");
}
}
class StaticDemo
{
private static int staticDemo1;
private static int staticDemo2 = 0;
private static int staticDemo3 = default(int);
private static int staticDemo4;
private static int classNumber;
/// <summary>
/// Static Constructor
/// </summary>
static StaticDemo()
{
Console.WriteLine("Static Constructor");
Console.WriteLine("staticDemo1 {0}", staticDemo1);
staticDemo4 = (new DateTime(1999, 12, 31)).DayOfYear;
}
/// <summary>
/// Instance Constructor
/// </summary>
public StaticDemo()
{
classNumber++;
Console.WriteLine("classNumber {0}", classNumber);
Console.WriteLine("staticDemo2 {0}", staticDemo2);
Console.WriteLine("staticDemo3 {0}", staticDemo3);
Console.WriteLine("staticDemo4 {0}", staticDemo4);
}
}
}
そして、次の出力が得られます。
Create StaticDemo A
Static Constructor
staticDemo1 0
classNumber 1
staticDemo2 0
staticDemo3 0
staticDemo4 365
Create StaticDemo B
classNumber 2
staticDemo2 0
staticDemo3 0
staticDemo4 365
Done
ここで注意すべきいくつかの興味深いことがあります:
- 行'Console.WriteLine( "Create StaticDemo A")'は、StaticDemoの静的コンストラクターの前に呼び出されます。
- 行'Console.WriteLine( "Static Constructor")'は1回だけ呼び出されます。
- 行'Console.WriteLine( "staticDemo1 {0}"、staticDemo1)'は、staticDemo1が明示的に初期化されていない場合でも機能します。
- staticDemo1、staticDemo2、およびstaticDemo 3はすべて、値が0として始まります。
最後に、サブノートとして、複数のスレッドでオブジェクトを作成する場合は注意が必要です。これは、classNumber++が不可分操作ではないためです。これは、読み取りと書き込みの2つの別々の操作としてカウントされます。そのため、2つの別々のスレッドは、どちらかが増分値を書き出す前に、両方とも変数を読み取ることができます。この状況を回避するには、代わりに次の行を使用してください。
System.Threading.Interlocked.Increment(ref classNumber);