When designing a class that refers to another object, it may turn out to be useful only to create the object that is referenced at first use, for example. use lazy loading.
I often use this template to create a lazy loaded property:
Encoding utf8NoBomEncoding; Encoding Utf8NoBomEncoding { get { return this.utf8NoBomEncoding ?? (this.utf8NoBomEncoding = new UTF8Encoding(false)); } }
Then I came across this code while looking at the source code for BCL:
Encoding Utf8NoBomEncoding { get { if (this.utf8NoBomEncoding == null) { var encoding = new UTF8Encoding(false); Thread.MemoryBarrier(); this.utf8NoBomEncoding = encoding; } return this.utf8NoBomEncoding; } }
As far as I can tell, none of them are thread safe. For instance. Multiple Encoding objects can be created. I fully understand this and know that this is not a problem if an additional Encoding object is created. It is unchanged and will soon be garbage collection.
However, I am very interested to understand why Thread.MemoryBarrier necessary and how the second implementation differs from the first in scripts with multiple threads.
Obviously, if thread safety is an issue, a better option would probably be to use Lazy<T> :
Lazy<Encoding> lazyUtf8NoBomEncoding = new Lazy<Encoding>(() => new UTF8Encoding(false)); Encoding Utf8NoBomEncoding { get { return this.lazyUtf8NoBomEncoding.Value; } }
source share