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:
- Make its constructor private.
- Write the code for initialization.
- Provide a getter method that returns the one and only instance.
While you cannot 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.
Update: The first version of the SingleInstance(Of T)
class provided an option to create an instance (Of T)
using the thread pool. This option is removed in the current version.
SingleInstance(Of T) Class
using System;
using System.Threading;
public sealed class SingleInstance<T> where T : class
{
private readonly Object m_lockObj = new Object();
private readonly Func<T> m_delegate;
private Boolean m_isDelegateInvoked;
private T m_value;
public SingleInstance()
: this(() => default(T)) { }
public SingleInstance(Func<T> @delegate)
{
m_delegate = @delegate;
}
public T Instance
{
get
{
if (!m_isDelegateInvoked)
{
T temp = m_delegate();
Interlocked.CompareExchange<T>(ref m_value, temp, null);
Boolean lockTaken = false;
try
{
Monitor.Enter(m_lockObj); lockTaken = true;
m_isDelegateInvoked = true;
}
finally
{
if (lockTaken) { Monitor.Exit(m_lockObj); }
}
}
return m_value;
}
}
}
The SingleInstance(Of T)
class has many differences from the System.Lazy(Of T)
class in the desktop CLR.
- The
System.Lazy(Of T)
class takes a LazyThreadSafetyMode enumeration. This enumeration contains 3 members (None
, PublicationOnly
, ExecutionAndPublication
). The SingleInstance(Of T)
class uses the interlocked constructs to produce a single instance. This is similar with passing LazyThreadSafetyMode.ExecutionAndPublication
in the System.Lazy(Of T)
class.
- The
System.Lazy(Of T)
class works with classes (reference types) and structs (value types). The value types are boxed internally. The SingleInstance(Of T)
class works only with reference types.
- Finally, the
System.Lazy(Of T)
class is written, tested and supported by Microsoft, while the SingleInstance(Of T)
is not.
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.)
CodeProject