views:

141

answers:

3

Original

I don't get why the Where() clause doesn't give me the right results in the last example.
It isn't any different is it? Why does C# behaves differently?

transactions = IEnumerable<Transaction> //pseudocode 

//This works: It gives me the transaction I need.
DateTime startDate = DateTime.Parse(parameter.Constraint); 
transactions = transactions.Where(T => T.date >= startDate);  

//This doesn't work... No actual code changed, only the way of writing it...
//I get 0 results.
 transactions = transactions.Where(T => T.date >= DateTime.Parse(parameter.Constraint));

Edit

Ok, it is indeed relevant to mention that transactions is loaded using Entity Framework.

transactions = this.db.Include("blablabla").OrderByDescending(T => T.date);

Maybe that's why it's doing weird? Because of the way Entity Linq works?

+5  A: 

The only way this could actually be happening is if you were modifying parameter or parameter.Constraint somehow while you're enumerating through transactions. So if you're not doing that, look at whether you're actually observing what you think you're observing.

In principle, this should work fine.

EDIT: One obvious way you could be confused about your observation is if you didn't check the results of (actually evaluate) the lazy Where enumeration until later on, when parameter had changed. If you put a ToArray on the end to evaluate it immediately, you might find that it "magically" fixes itself.

mquander
I am thinking that this is indeed the case. I will make it a ToList() so it evaluates immediately and I guess my problems are over.
Peterdk
I indeed used multiple Where's and multiple parameters all which used a lazy Where. I now added everywhere a .ToList() and voila, it's fixed.
Peterdk
+4  A: 

Undoubtedly a variation of

http://lorgonblog.spaces.live.com/blog/cns!701679AD17B6D310!689.entry

http://blogs.msdn.com/ericlippert/archive/2009/11/12/closing-over-the-loop-variable-considered-harmful.aspx

Brian
I don't see how this would be connected to his issue. Perhaps his problem is a simple misunderstanding of lazy evaluation, but it doesn't seem related to the closure-reference gotcha you cite.
mquander
+1  A: 

I just tried this and it works fine:

class Program
{
    public class Transaction { public DateTime date { get; set; } }
    public class Parameter { public string Constraint { get; set; } }
    public static void Main()
    {
        IEnumerable<Transaction> transactions = new List<Transaction> {
            new Transaction { date = new DateTime(2009, 10, 5) },
            new Transaction { date = new DateTime(2009, 11, 3) }
        };
        Parameter parameter = new Parameter { Constraint = "2009-11-01" };
        DateTime startDate = DateTime.Parse(parameter.Constraint);

        // Version 1.
        transactions = transactions.Where(T => T.date >= startDate);

        // Version 2.
        transactions = transactions.Where(T => T.date >= DateTime.Parse(parameter.Constraint));

    }
}

You must be omitting an important detail. Perhaps you could try reducing your code to the simplest possible example that still reproduces the bug. In doing so, you will probably discover the solution. If you still can't see the problem you can post the short, compiling, non-working version here and I'm sure someone will spot the problem quickly.

Mark Byers