#948 – Using Generic Lazy Class to Implement the Singleton Pattern

The singleton pattern is useful in cases when you only want/need a single instance of a type, e.g. to use in creating instances of some other type (an object factory).

We can make use of the Lazy<T> type to implement a singleton that is created as late as possible, i.e. just before it is used.

    public sealed class DogFactory
    {
        // Instance created when first referenced
        private static readonly Lazy<DogFactory> instance =
            new Lazy<DogFactory>(() => new DogFactory());

        // Prevent instantiation
        private DogFactory() { }

        public static DogFactory Instance
        {
            get { return instance.Value; }
        }

        // Actual methods go here, e.g.:
        public Dog CreateDog(string name)
        {
            return new Dog(name);
        }
    }

Notice that we can access other static members of the DogFactory without forcing the instance object to get created. The instance will only be instantiated when we use the Instance property.

Advertisement

#947 – Specifying Lazy Instantiation Using a Lambda Expression

When you are declaring an object that will be lazily instantiated, you pass a delegate instance to the Lazy<T> constructor, where the delegate instance indicates a method to be called that will instantiate the underlying object.

For example, you could do the following:

        private static Lazy<Dog> dog1 = new Lazy<Dog>(CreateDefaultDog);
        private static Dog CreateDefaultDog()
        {
            return new Dog("Lassie");
        }

Very often, however, you’ll want to pass some parameter value to the delegate or just invoke one of the normal constructors for the object, passing one or more parameters to the constructor.  You can do this by just using a lambda expression, as follows:

        private static Lazy<Dog> dog2 = new Lazy<Dog>(() => new Dog("Lassie"));

#946 – Specifying Whether Lazy Instantiated Object Should Be Thread-Safe

You can use the Lazy<T> class to declare an object that will be lazily instantiated–that is, created just before it is used.

In the example below, we indicate that the listOfAllFamousDogs object should only be created (by calling GenerateBigListOfFamousDogs) just before it is referenced.  The GenerateBigListOfFamousDogs method returns an instance of List<Dog>.

private static Lazy<List<Dog>> listOfAllFamousDogs = new Lazy<List<Dog>> (GenerateBigListOfFamousDogs);

In the Lazy<T> constructor, we specify a delegate that will be called to initialize our object.  By default, this results in a thread-safe implementation that lazily instantiates the specified object.

If we do not need thread-safety, we can pass a second parameter to the Lazy<T> constructor, with a value of false.

        // No need for thread safety
        private static Lazy<List<Dog>> listOfAllFamousDogs = new Lazy<List<Dog>> (GenerateBigListOfFamousDogs, false);

#945 – Lazy Instantiation, an Easier Solution

The previous post showed how to implement lazy instantiation in a thread-safe manner, waiting to initialize an object until it is first used.

.NET 4.0 introduced the Lazy<T> class, which makes lazy instantiation much easier.  If you have an object that you want to instantiate as late as possible, you declare it to be of type Lazy<T>, where is the core type of your object.  You also specify a method to be called to do the actual initialization of the object.

So instead of doing this:

        private static List<Dog> listOfAllFamousDogs = GenerateBigListOfFamousDogs();
        public bool IsFamous
        {
            get { return listOfAllFamousDogs.Contains(this); }
        }

You do this:

        private static Lazy<List<Dog>> listOfAllFamousDogs = new Lazy<List<Dog>> (GenerateBigListOfFamousDogs);
        public bool IsFamous
        {
            get { return listOfAllFamousDogs.Value.Contains(this); }
        }

Note that you also use the Value property of the new Lazy<T> object to get at the underlying object.

#944 – Lazy Instantiation, Solution #2

The previous post showed one way to achieve lazy instantiation–waiting to initialize a data object until just before it’s needed.  The problem with this example, however, was that it wasn’t thread-safe.  Two threads could simultaneously check to see if the object is initialized and both determine that it is not.  Both threads would then try to initialize the object.

The code below updates the earlier example, making it thread-safe.

        private static List listOfAllFamousDogs = null;
        private static readonly object initLock = new object();

        private static List GenerateBigListOfFamousDogs()
        {
            Console.WriteLine("Loading big list of famous dogs!");
            List bigList = new List();
            bigList.Add(new Dog("Lassie"));
            bigList.Add(new Dog("Rin Tin Tin"));
            // load 1,000 more dogs here

            return bigList;
        }

        public bool IsFamous
        {
            get
            {
                lock (initLock)
                {
                    if (listOfAllFamousDogs == null)
                        listOfAllFamousDogs = GenerateBigListOfFamousDogs();
                }

                return listOfAllFamousDogs.Contains(this);
            }
        }

Next time, we’ll see an easier way to do this in .NET 4.0 or later.

#943 – Lazy Instantiation, Solution #1

There are cases when we have a large amount of data to allocate in a class, either in an instance of the class or as static data.  We want to allocate and initialize the data as late as possible, i.e. just before we need to use the data.  This is know as lazy instantiation.

One method for lazy instantiation is to check to see if the data is instantiated, wherever we try to use it.

        private static List<Dog> listOfAllFamousDogs = null;

        private static List<Dog> GenerateBigListOfFamousDogs()
        {
            Console.WriteLine("Loading big list of famous dogs!");
            List<Dog> bigList = new List<Dog>();
            bigList.Add(new Dog("Lassie"));
            bigList.Add(new Dog("Rin Tin Tin"));
            // load 1,000 more dogs here

            return bigList;
        }

        public bool IsFamous
        {
            get
            {
                if (listOfAllFamousDogs == null)
                    listOfAllFamousDogs = GenerateBigListOfFamousDogs();

                return listOfAllFamousDogs.Contains(this);
            }
        }

We get lazy instantiation here–the list isn’t initialized until we use the IsFamous property.  This solution, however, is not thread-safe.

#942 – The Case for Lazy Instantiation

Assume that we create some large data item in an object, e.g. the listofAllFamousDogs object in the sample below:

    public class Dog
    {
        public string Name { get; set; }

        public Dog(string name)
        {
            Name = name;
        }

        public void Bark()
        {
            Console.WriteLine("Woof!");
        }

        private static List<Dog> listOfAllFamousDogs = GenerateBigListOfFamousDogs();

        private static List<Dog> GenerateBigListOfFamousDogs()
        {
            Console.WriteLine("Loading big list of famous dogs!");
            List<Dog> bigList = new List<Dog>();
            bigList.Add(new Dog("Lassie"));
            bigList.Add(new Dog("Rin Tin Tin"));
            // load 1,000 more dogs here

            return bigList;
        }

        public bool IsFamous
        {
            get { return listOfAllFamousDogs.Contains(this); }
        }
    }

The problem with this is that we end up creating the big list when we first use the class–whether or not we’ll later use the IsFamous property.

            Dog bob = new Dog("Bob");
            bob.Bark();

942-001
What we need is to lazily instantiate this list.  That is–wait to create the list until we actually need it.