.NET 4では、キャッシュされたプロパティを持つ次のスニペットは、 System.Lazy<T>
クラス。私は両方のアプローチのパフォーマンスを測定しましたが、それはほとんど同じです。なぜ一方を他方の上に使用する必要があるのかについて、本当の利点や魔法はありますか?
キャッシュされたプロパティ
public static class Brushes
{
private static LinearGradientBrush _myBrush;
public static LinearGradientBrush MyBrush
{
get
{
if (_myBrush == null)
{
var linearGradientBrush = new LinearGradientBrush { ...};
linearGradientBrush.GradientStops.Add( ... );
linearGradientBrush.GradientStops.Add( ... );
_myBrush = linearGradientBrush;
}
return _myBrush;
}
}
}
Lazy <T>
public static class Brushes
{
private static readonly Lazy<LinearGradientBrush> _myBrush =
new Lazy<LinearGradientBrush>(() =>
{
var linearGradientBrush = new LinearGradientBrush { ...};
linearGradientBrush.GradientStops.Add( ... );
linearGradientBrush.GradientStops.Add( ... );
return linearGradientBrush;
}
);
public static LinearGradientBrush MyBrush
{
get { return _myBrush.Value; }
}
}
私は一般的にLazy<T>
を使用します:
デリゲートにラムダ式を使用しないことに注意してくださいhave。たとえば、これは少しクリーンなアプローチです。
public static class Brushes
{
private static readonly Lazy<LinearGradientBrush> _myBrush =
new Lazy<LinearGradientBrush>(CreateMyBrush);
private static LinearGradientBrush CreateMyBrush()
{
var linearGradientBrush = new LinearGradientBrush { ...};
linearGradientBrush.GradientStops.Add( ... );
linearGradientBrush.GradientStops.Add( ... );
return linearGradientBrush;
}
public static LinearGradientBrush MyBrush
{
get { return _myBrush.Value; }
}
}
これは、作成プロセスがループなどで複雑になる場合に特に便利です。その外観から、作成コードでGradientStops
のコレクション初期化子を使用できることに注意してください。
別のオプションはnotもちろんこれを怠惰に行うことです...クラスにそのようなプロパティがいくつかあり、関連するオブジェクトを1つずつ作成するだけの場合を除いて、多くの状況でレイジークラスの初期化に依存します。
DoubleDownの回答に記載されているように、これをリセットして再計算を強制する方法はありません(Lazy<T>
フィールドを読み取り専用にしない限り)-しかし、それが重要であるとはめったに見つかりませんでした。
使用する Lazy<T>
、それはあなたがしていることを正確に表現しているので-遅延読み込み。
さらに、それはあなたの財産を非常にきれいに保ち、スレッドセーフです。
通常、レイジーを使用しない唯一の理由は、変数をnullにリセットして、次のアクセスで変数が再度ロードされるようにすることです。レイジーにはリセットがないため、レイジーを最初から再作成する必要があります。
Lazy<T>
は、例にスレッドセーフチェックがない場合でも、並行シナリオを正しく処理します(正しい LazyThreadSafetyMode を渡した場合)。
Lazy<T>
はより単純で、コードの意図を明確に表現しています。
スレッドセーフでもあります。
これを実際に複数のスレッドで使用している場合は、[ThreadStatic]
にする必要があることに注意してください。 GDI +オブジェクトはスレッド間で共有できません。
Lazyには、スレッドセーフを提供するための同期オーバーヘッドがありますが、キャッシュされたプロパティは、他のコードよりも先にCLRによって初期化され、同期コストを支払う必要はありません。
テスト容易性の観点から、Lazyは十分にテストされ、実証済みのアーティファクトです。
ただし、私の意見では、他のオプションよりもわずかなオーバーヘッドがあります