views:

399

answers:

1

Update for future readers: When .NET 4 comes out, LazyInit<T> from the CTP will have been renamed to Lazy<T> and will be changed from a struct to a class, so very little of this will apply, except as an illustration of why mutable structs can be problematic if you're not careful.

I've been experimenting with LazyInit in the Parallel Extensions June CTP, and I would expect the following code to print out the same Guid a thousand times, but instead it prints out a thousand different Guids. Clearly I'm missing something obvious here about how LazyInit is supposed to work, and I'd appreciate if someone would kindly point out what it is.

using System;
using System.Diagnostics;
using System.Threading;

namespace TestApp
{
    class Program
    {
        static void Main(string[] args)
        {
            for (int i=0; i < 1000; i++)
            {
                Console.WriteLine(TestClass.Instance.Id);
            }

            Console.Write("Press any key to continue:");
            Console.ReadKey();
        }

        private class TestClass
        {
            private static readonly LazyInit<TestClass> _instance = new LazyInit<TestClass>(() => new TestClass(), LazyInitMode.EnsureSingleExecution);

            public static TestClass Instance
            {
                get { return _instance.Value; }
            }

            private TestClass()
            {
                Debug.WriteLine("TestClass Constructor");
                Id = Guid.NewGuid();
            }

            public Guid Id { get; private set; }
        }
    }
}
+11  A: 

Short Version: Make the static non-readonly and it will fix the bug you are experiencing.

Long Version: This is a very misunderstood portion of C#. When you access a struct you are accessing a copy of the struct. The underlying call of LazyInit.Value is a mutating operation. Normally a copyback is performed but in the case of a read-only field there is no way to perform the copy back and hence you are still left with an uninitialized value.

Extremely detailed explanation: http://blogs.msdn.com/ericlippert/archive/2008/05/14/mutating-readonly-structs.aspx

JaredPar
Thanks, I came back to answer my own question with the same URL, but you beat me to it!
Joel Mueller