Unexpected behavior in zip method

I have the following code:

[TestMethod()]
public void Test_Changed()
{
    var All = repository.GetProducts().Select(c => c.Price).ToList();
    var Original = All.ToList();
    //The following line updates all prices but should has no effect
    //Because I've used ToList already in All query
    reducer.ReducePrice(amount);
    All.Zip(Original, (f, s) =>
    {
        if (f == s)
        {
            Assert.Fail();
        }
        return f;
    });
}

I'd expected that my test would failed but it is passed successfully. I'm really wondering how is this possible? As clearly shown below the All and Original variables have same values so why Assert.Fail(); never executed?

enter image description here

If I remove the ToList from All query the test should passed as expected because of deferred execution but when I use ToList the later changes should has no effect. So why my test is passes?

Please also see this:

var res = All.Zip(Original, (f, s) =>
{
    if (f == s)
    {
        Assert.Fail();
    }
    return f;
});

The result:

enter image description here

But the test result:

enter image description here

Jon Skeet
people
quotationmark

Like many LINQ operations, Zip is lazy - your lambda expression is never being executed, because you're calling Zip but never using the results.

If you changed your test to do something like:

var list = All.Zip(...).ToList();

Then I suspect you'll see the assertion fail. (Or call Count(), or anything else that iterates over the whole sequence.)

Or as Jamiec says, add an assertion. It could be as simple as:

Assert.IsFalse(All.Zip(Original, (f, s) => f == s).Any(x => x));

(It really depends on what you're trying to check - different assertions will give you different kinds of information.)

people

See more on this question at Stackoverflow