我尝试了MSDN的Lazy Initialization sample code。我试图用静态Func<模拟静态InitLargeObject()方法。 T>委托使用lambda表达式,因为Lazy< lazy< T>构造
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();
}
如果我在 lazyLargeObject 声明 声明之前将 InitWithLambda 委托,那么一切都很好。
如果我在 lazyLargeObject 声明之后将 InitWithLambda 委托,我收到此错误:
未处理的异常:System.TypeInitializationException:类型 “计划”的初始化程序&#39;抛出一个例外。 ---&GT; System.ArgumentNullException:值不能为null。参数名称: System.Lazy
1..ctor(Func
1 valueFactory的valueFactory, LazyThreadSafetyMode模式)在System.Lazy1..ctor(Func
1 program..cctor()中的valueFactory) E:\ myCode \ Misc \ LazyWithLambda \ LazyWithLambda \ Class1.cs:第10行--- 内部异常堆栈跟踪结束---在Program.Main()
似乎lambda表达式无法被赋值给valueFactory参数。
但似乎该位置不会影响 InitLargeObject()方法,它不使用Lambda表达式。
为什么?
根据Billy ONeal,我用一个更简单的代码重新解决了这个问题:
这个没问题:
class FieldInitInOrder
{
static string s1 = "abc";
static Int32 s1_length = s1.Length;
static void Main()
{
Console.WriteLine(s1_length);
}
}
这个抛出相同的NullReference异常:
class FieldInitInOrder
{
static Int32 s1_length = s1.Length; // Order switched
static string s1 = "abc"; // Order switched
static void Main()
{
Console.WriteLine(s1_length);
}
}
我不知道为什么C#编译器是这样设计的。它可能导致非常微妙的错误。 有任何设计考虑因素吗?
答案 0 :(得分:6)
C#按照声明的顺序初始化成员。
答案 1 :(得分:3)
这是设计,根据C#规范:
声明名称的文字顺序通常为no 意义。特别是,文本顺序并不重要 声明和使用命名空间,常量,方法,属性, 事件,索引器,运算符,实例构造函数,析构函数, 静态构造函数和类型。声明顺序很重要 以下方式:
•字段声明和局部变量的声明顺序 声明确定其初始化程序(如果有)的顺序 被执行。
•必须在使用本地变量之前定义它们 (第3.7节)。
•枚举成员声明(第14.3节)的声明顺序是 当省略常量表达式值时显着。
将按照声明的顺序初始化值。