実はLazy<T>を調べたのは寄り道。最初に目に付いたのはこっちの方です。LazyInitializerクラスです。これも遅延初期化用のクラスですが、明示的な初期化に使います。
サンプルソース §
using System;
using System.Threading;
class Sample
{
public string Message;
public Sample()
{
Message = "Created on " + DateTime.Now;
}
}
class Program
{
private static void dump( Sample sample )
{
if( sample == null ) Console.WriteLine("sample not initialized");
else Console.WriteLine(sample.Message);
}
static void Main(string[] args)
{
Sample sample = null;
dump(sample);
LazyInitializer.EnsureInitialized(ref sample);
dump(sample);
}
}
実行結果 §
sample not initialized
Created on 2011/05/12 9:35:22
解説 §
LazyInitializer.EnsureInitializedメソッドを使うと以下のような特徴のある初期化ができます。
- null値の変数を、引数の無いコンストラクタで初期化してくれる
- バリエーションで、初期化が実行されたかを示す値を受け取れる
- バリエーションで、マルチスレッドでロックするためのオブジェクトを渡せる
- 初期化の実行は明示的であり、Lazy<T>クラスのように使ったら自動的に初期化してくれるわけではない
- 初期化は必ず1回だけ実行される。既に初期化済みなら重ねて初期化しない
感想 §
結局、位置づけはSystem.Threading名前空間にあることから明瞭ですね。ロックオブジェクトを渡して、排他制御しながら確実に遅延初期化するためのメソッドでしょう。複数のスレッドからこのメソッドを呼んでもコンストラクタは一回しか走りません。どのスレッドから初期化する場合でもこれを呼べば確実に初期化されます。