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.Lazy1..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?
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?
C# initializes members in the order in which they are declared.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With