Now I am not across the inner workings of LINQ and lambda, however the results from doing the following code are not what I would have expected.
{
System.Diagnostics.Debug.WriteLine("Testing:" + DateTime.Now.ToString());
List<Dictionary<int, int>> ld = new List<Dictionary<int, int>>();
ld.Add(new Dictionary<int, int>() { { 1, 10 }, { 2, 20 }, { 3, 30 } });
ld.Add(new Dictionary<int, int>() { { 1, 20 }, { 2, 300000}, { 3, 40000000 }, { 4, 500000000 }});
int indx = 10;
var ds = ld.Where(itm => itm[1] == indx);
if (ds.Count() > 0)
{
System.Diagnostics.Debug.WriteLine("Count=" + ds.First().Count());
indx = ds.First()[2]; //this is a value I want to keep for later
int valueIwant = ds.First()[3]; //this is the value I want from this result
System.Diagnostics.Debug.WriteLine("Value I Want=" + valueIwant);
//oh no ??? that's not the value I wanted ???
System.Diagnostics.Debug.WriteLine("Count=" + ds.First().Count());
//and now the count changed ???
}
}
I would expect the LINQ query to return the first row, (where itm[key==1] == 10).
And valueIwant to equal the third value in that result dictionary (itm[key==3]).
The first count confirms we are working with row 1 with 3 records in the result dictionary.
HOWEVER, changing the indx value prior to getting valueIwant causes the result to change dynamically - thus returning a new result set, which in this case is row 2.
The end result in my variable is 40000000 - big diff. And the final count is 4, as it is the second record now.
This is a real trap - especially when using LINQ/lambda to work down a hierarchy of values.
My suggestion would be to use a pattern where any lambda expressions that use a variable should have the variable assigned to a lambda specific variable prior to creating the expression.
i.e.
int indx = 10;
int tmpidx = intidx;
var ds = ld.Where(itm => itm[1] == tmpidx);
if (ds.Count() > 0)
{
indx = ds.First()[2]; //this is a value I want to keep for later
int valueIwant = ds.First()[3]; //now I get what I wanted !!!!
I can't determine if this is by-design, a feature to support delegates, or a genuine bug, but it is definately something to watch out for!
Update: The legends on the MSDN forum suggest using .ToList() on the end of the Where statement to generate a fixed list result - thus separating the result set from the object query. It is also noted that each call to Count() and First() will cause the expression to re-evaluate!
No comments:
Post a Comment