別のオブジェクトへの参照を持つクラスを設計する場合、参照されるオブジェクトを最初に使用するときにのみ作成することが有益な場合があります。たとえば、遅延読み込みを使用します。
私はよくこのパターンを使用して、遅延ロードされたプロパティを作成します。
Encoding utf8NoBomEncoding;
Encoding Utf8NoBomEncoding {
get {
return this.utf8NoBomEncoding ??
(this.utf8NoBomEncoding = new UTF8Encoding(false));
}
}
次に、BCL のソース コードを参照しているときに、次のコードを見つけました。
Encoding Utf8NoBomEncoding {
get {
if (this.utf8NoBomEncoding == null) {
var encoding = new UTF8Encoding(false);
Thread.MemoryBarrier();
this.utf8NoBomEncoding = encoding;
}
return this.utf8NoBomEncoding;
}
}
私が知る限り、これらはどれもスレッドセーフではありません。たとえば、複数のEncoding
オブジェクトを作成できます。Encoding
私はそれを完全に理解しており、余分なオブジェクトが作成されても問題ないことを知っています。これは不変であり、まもなくガベージ コレクションになります。
Thread.MemoryBarrier
ただし、なぜが必要なのか、またマルチスレッド シナリオで 2 番目の実装が最初の実装とどのように異なるのかを理解したいと思っています。
明らかに、スレッドの安全性が懸念される場合、最適な実装はおそらく次を使用することLazy<T>
です。
Lazy<Encoding> lazyUtf8NoBomEncoding =
new Lazy<Encoding>(() => new UTF8Encoding(false));
Encoding Utf8NoBomEncoding {
get {
return this.lazyUtf8NoBomEncoding.Value;
}
}