在Lazy Initialization中,lambda表达式的位置是否重要?

时间:2014-07-05 14:43:47

标签: c# .net

我尝试了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.Lazy 1..ctor(Func 1   program..cctor()中的valueFactory)   E:\ myCode \ Misc \ LazyWithLambda \ LazyWithLambda \ Class1.cs:第10行---   内部异常堆栈跟踪结束---在Program.Main()

似乎lambda表达式无法被赋值给valueFactory参数。

但似乎该位置不会影响 InitLargeObject()方法,它不使用Lambda表达式。

为什么?

更新1

根据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#编译器是这样设计的。它可能导致非常微妙的错误。 有任何设计考虑因素吗?

2 个答案:

答案 0 :(得分:6)

C#按照声明的顺序初始化成员。

答案 1 :(得分:3)

这是设计,根据C#规范:

  

声明名称的文字顺序通常为no   意义。特别是,文本顺序并不重要   声明和使用命名空间,常量,方法,属性,   事件,索引器,运算符,实例构造函数,析构函数,   静态构造函数和类型。声明顺序很重要   以下方式:

     

•字段声明和局部变量的声明顺序   声明确定其初始化程序(如果有)的顺序   被执行。

     

•必须在使用本地变量之前定义它们   (第3.7节)。

     

•枚举成员声明(第14.3节)的声明顺序是   当省略常量表达式值时显着。

将按照声明的顺序初始化值。