Does the location of a lambda expression matter in Lazy Initialization?
.net, c#
Solution
C# initializes members in the order in which they are declared.
Problem
I tried the Lazy Initialization sample code from MSDN. And I tried to mimic the static InitLargeObject() method with a static Func< T > delegate using a lambda expression since it's acceptable by the Lazy< T > constructor. ``` static Lazy<LargeObject> lazyLargeObject = new Lazy<LargeObject>(InitWithLambda); static Func<LargeObject> InitWithLambda = () => { LargeObject large = new LargeObject(Thread.CurrentThread.ManagedThreadId); // Perform additional initialization here. return large; }; static LargeObject InitLargeObject() { LargeObject large = new LargeObject(Thread.CurrentThread.ManagedThreadId); // Perform additional initialization here. return large; } static void Main() { //lazyLargeObject = new Lazy<LargeObject>(InitLargeObject); // <---- This one use the static method. lazyLargeObject = new Lazy<LargeObject>(InitWithLambda); // <---- Thsi one uses the lambda expression. Console.WriteLine( "\r\nLargeObject is not created until you access the Value property of the lazy" + "\r\ninitializer. Press Enter to create LargeObject."); Console.ReadLine(); // Create and start 3 threads, each of which uses LargeObject. Thread[] threads = new Thread[3]; for (int i = 0; i < 3; i++) { threads[i] = new Thread(ThreadProc); threads[i].Start(); } // Wait for all 3 threads to finish. foreach (Thread t in threads) { t.Join(); } Console.WriteLine("\r\nPress Enter to end the program"); Console.ReadLine(); } ``` If I put the InitWithLambda delegate before the lazyLargeObject declaration, everything is fine. If I put the InitWithLambda delegate after the lazyLargeObject declaration, I got this error: Unhandled Exception: System.TypeInitializationException: The type initializer for 'Program' threw an exception. ---> System.ArgumentNullException: Value cannot be null. Parameter name: valueFactory at System.Lazy`1..ctor(Func`1 valueFactory, LazyThreadSafetyMode mode) at System.Lazy`1..ctor(Func`1 valueFactory) at Program..cctor() in E:\myCode\Misc\LazyWithLambda\LazyWithLambda\Class1.cs:line 10 --- End of inner exception stack trace --- at Program.Main() It seems the lambda expression failed to be assinged to the valueFactory parameter. But it seems the location doesn't affect the InitLargeObject() method, which is not using Lambda expression. Why? Update 1 According to Billy ONeal, I reproed this issue with a simpler code: This one is ok: ``` class FieldInitInOrder { static string s1 = "abc"; static Int32 s1_length = s1.Length; static void Main() { Console.WriteLine(s1_length); } } ``` This one throw the same NullReference exception: ``` class FieldInitInOrder { static Int32 s1_length = s1.Length; // Order switched static string s1 = "abc"; // Order switched static void Main() { Console.WriteLine(s1_length); } } ``` I don't know why C# compiler is designed like this. It could cause very delicate bugs. Is there any design consideration?