Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why use Lazy<T> instead of static factory class for singletons?

Tags:

c#

singleton

Before I found the Lazy<T> type, I was using the following pattern for implementing global singletons:

class DataModel
{
    public static XmlSerializer Serializer
    {
        get { return SerializerFactory.instance; }
    }

    static class SerializerFactory
    {
        internal static readonly XmlSerializer instance =
            new XmlSerializer(typeof(DataModel));
    }    
}

This pattern provides the following advantages:

  1. Type initialization is lazy.
  2. Type initialization is thread-safe.
  3. Singleton access is simply a direct field access with no method calls.

Recently I've come across a lot of posts suggesting Lazy<T> for implementing similar singleton access patterns. Is there any benefit that Lazy<T> (or LazyInitializer) would bring to this implementation?

like image 547
glopes Avatar asked Sep 15 '17 09:09

glopes


2 Answers

Readability

This is how your code would look like when implemented with Lazy<T>:

class DataModel
{
    private static readonly Lazy<XmlSerializer> lazySerializer = 
       new Lazy<XmlSerializer>(() => new XmlSerializer(typeof(DataModel)));

    public static XmlSerializer Serializer
    {
        get { return lazySerializer.Value; }
    }
}
  1. You need less boilerplate code (no inner class),
  2. the purpose of your code is immediately obvious to everyone reading it,
  3. it is much easier to verify that the code is correct and thread-safe (no knowledge of subtle type initialization details required, a look at Lazy<T>'s documentation suffices),
  4. people reading your code won't wonder why you reinvented the wheel and whether there might be some subtle difference to the built-in feature.
like image 194
Heinzi Avatar answered Oct 17 '22 14:10

Heinzi


Lazy<T> is much more expressive. It is immediately clear that the value utilizes deferred initialization.

For example I use it in situations when the intialization of some resource is too heavy to put in the constructor and I don't want the API-consumer to call some explicit Initialize routine.

like image 3
mbnx Avatar answered Oct 17 '22 16:10

mbnx