When building applications for a mobile operating system such as Windows Phone 7 (WP7) you might want (at times) to defer the creation of large objects, specifically when this creation is going to increase memory consumption.
While in the desktop CLR there is the Lazy(Of T) Class, when working on WP7 this class does not exist (at least not at the time of this writing).
I find it a very repetitive task to manually produce a single instance object:
While you can not avoid step 2, it is possible to create a generic class that produces step 1 and step 3. Then, from the class constructor, you can pass the code that creates the object using a Func(TResult) Delegate.
SingleInstance(Of T) Class
using System; using System.Threading; internal sealed class SingleInstance<T> where T : class { private readonly object lockObj = new object(); private readonly Func<T> @delegate; private bool isDelegateInvoked; private T @value; public SingleInstance() : this(() => default(T)) { } public SingleInstance(Func<T> @delegate) { this.@delegate = @delegate; } public T Instance { get { if (!this.isDelegateInvoked) { T temp = this.@delegate(); Interlocked.CompareExchange<T>(ref this.@value, temp, null); bool lockTaken = false; try { // WP7 does not support the overload with the // Boolean indicating if the lock was taken. Monitor.Enter(this.lockObj); lockTaken = true; this.isDelegateInvoked = true; } finally { if (lockTaken) { Monitor.Exit(this.lockObj); } } } return this.@value; } } }
The code inside the “T Instance” public property uses interlocked constructs to produce a single T object. It has been discussed in the book CLR via C#, 3rd Edition, Microsoft Press, page 846.
The SingleInstance(Of T) class has many differences from the System.Lazy(Of T) class in the desktop CLR.
Keep in mind that the SingleInstance(Of T) class uses a Func(TResult) Delegate. There is a known performance hit when calling delegates compared to direct method calls. (See the Delegates section here).