Strange .Where() behaviour. Somebody has an explanation?
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 >= D开发者_如何学CateTime.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?
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.
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
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.
精彩评论