當設計引用另一個對象的類時,僅在第一次使用引用對象時創建引用對象可能會有所幫助。使用延遲加載。延遲加載和Thread.MemoryBarrier的使用
我經常用這個模式來創建一個延遲加載屬性:據我可以
Encoding Utf8NoBomEncoding {
get {
if (this.utf8NoBomEncoding == null) {
var encoding = new UTF8Encoding(false);
Thread.MemoryBarrier();
this.utf8NoBomEncoding = encoding;
}
return this.utf8NoBomEncoding;
}
}
:
Encoding utf8NoBomEncoding;
Encoding Utf8NoBomEncoding {
get {
return this.utf8NoBomEncoding ??
(this.utf8NoBomEncoding = new UTF8Encoding(false));
}
}
那時,我發現這個代碼瀏覽了BCL的源代碼時就告訴這些都不是線程安全的。例如。可能會創建多個Encoding
對象。我完全明白,並且知道如果創建額外的Encoding
對象,這不是問題。它是不可變的,很快就會被垃圾收集。
但是,我很想知道爲什麼Thread.MemoryBarrier
是必要的,以及第二種實現與多線程場景中的第一種實現不同。
顯然,如果線程安全性是一個問題最好的實現可能使用Lazy<T>
:
Lazy<Encoding> lazyUtf8NoBomEncoding =
new Lazy<Encoding>(() => new UTF8Encoding(false));
Encoding Utf8NoBomEncoding {
get {
return this.lazyUtf8NoBomEncoding.Value;
}
}
創建多個'Encoding'對象不成問題,因爲所有副本的行爲都是相同的。 (還請注意,在編寫代碼時,'懶惰'不可用。) –