Lazy Evaluation not so Lazy?

2019-07-15 03:08发布

I've always heard C# uses lazy evaluation. So for certain code like, if (true || DoExpensiveOperation() will return true without executing DoExpensiveOperation().

On an interview test I saw the following questions,

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));
}

How many times would it print "argument is true!" to the screen?

I would say 7 is the correct answer. Now if I stick into the compiler and run it, it prints it 10 times! Where did lazy evaluation all go wrong?

1条回答
Explosion°爆炸
2楼-- · 2019-07-15 03:38

I've always heard C# uses lazy evaluation.

That's far too vague a comment for me to agree with. If you'd said that the || and && operators in C# are short-circuiting, only evaluating the second operand if the overall result couldn't be determined just from the first operand, then I'd agree with it. Lazy evaluation is a more wide-ranging concept - for example, LINQ queries use lazy (or deferred) evaluation, not actually fetching any data until the result is used.

You're using the & operator, which isn't short-circuiting:

The & operator evaluates both operators regardless of the first one's value.

The && operator is short-circuiting:

The operation x && y corresponds to the operation x & y except that if x is false, y is not evaluated, because the result of the AND operation is false no matter what the value of y is.

Replace & with && everywhere in your code, and you'll see "argument is true!" printed 8 times (not 7 - count your comments again).

查看更多
登录 后发表回答