懒惰评价不是那么懒惰?

时间:2012-10-28 09:30:52

标签: c# lazy-evaluation

我一直听说C#使用懒惰评估。因此,对于某些代码,if (true || DoExpensiveOperation()将返回true而不执行DoExpensiveOperation()

在面试测试中,我看到了以下问题,

static bool WriteIfTrue(bool argument)
{
    if (argument)
    {
        Console.WriteLine("argument is true!");
    }

    return argument;
}

static void Main()
{
    // 1              0                       0                 1
    WriteIfTrue((WriteIfTrue(false) & WriteIfTrue(true)) || WriteIfTrue(true));

    // 1               1                     0                      1
    WriteIfTrue((WriteIfTrue(true) || WriteIfTrue(false)) & WriteIfTrue(true));

    //  0                 0                  0                    0
    WriteIfTrue((WriteIfTrue(false) & WriteIfTrue(true)) & WriteIfTrue(false));

    // 1                1                      0                   1
    WriteIfTrue((WriteIfTrue(true) || WriteIfTrue(false)) & WriteIfTrue(true));
}

打印多少次“论证是真的!”到屏幕?

我会说7是正确答案。现在,如果我坚持使用编译器并运行它,它会打印10次!懒惰评价哪里出错?

1 个答案:

答案 0 :(得分:37)

  

我一直听说C#使用懒惰评估。

对于我同意的评论,这太过模糊了。如果您说C#中的||&&运算符是短路的,那么只评估第二个操作数,如果不能仅从第一个操作数确定整体结果,那么 我同意。延迟评估是一个更广泛的概念 - 例如,LINQ查询使用延迟(或延迟)评估,而不是在使用结果之前实际获取任何数据。

您使用的是& operator,其中短路:

  

&无论第一个运算符的值如何,运算符都会对运算符求值。

&& operator 短路:

  

操作x && y对应于操作x & y,但如果x为假,则不评估y,因为AND操作的结果为假,无论如何y的价值是什么。

&替换为代码中的&&,您会看到“参数是真的!”打印8次(不是7次 - 再次计算您的评论)。