【问题标题】:Lazy Evaluation not so Lazy?懒评估不那么懒?
【发布时间】:2012-10-28 09:30:51
【问题描述】:

我一直听说 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));
}

它会打印多少次“argument is true!”到屏幕上?

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

【问题讨论】:

  • 这些是 & 还是 && 运算符?
  • 这不是懒惰的评估,而是短路。此外,您将按位运算符 (&) 与逻辑运算符 (||) 混合使用。

标签: c# lazy-evaluation


【解决方案1】:

我一直听说 C# 使用惰性求值。

这个评论太模糊了,我无法同意。如果您说 C# 中的 ||&& 运算符是短路的,则仅在无法仅从第一个操作数确定总体结果时才评估第二个操作数,那么我会同意的。惰性求值是一个范围更广的概念 - 例如,LINQ 查询使用惰性(或延迟)求值,在使用结果之前不会实际获取任何数据。

您正在使用& operator,这没有短路:

& 运算符计算两个运算符,而不考虑第一个运算符的值。

&& operator短路了:

运算x && y对应于运算x & y,只是如果x为假,则不计算y,因为无论y的值是多少,AND运算的结果都是假.

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

【讨论】:

  • 老实说现在不记得测试中是 & 还是 &&。会在我测试时解释意外的行为,谢谢!
猜你喜欢
  • 2015-09-06
  • 2019-01-07
  • 1970-01-01
  • 2016-12-14
  • 2021-12-25
  • 2018-04-01
  • 2018-03-31
  • 2017-04-30
  • 1970-01-01
相关资源
最近更新 更多