1

If I use any integer variable in a LINQ where clause, and after query execution if I modify / initialize the integer variable, then the result set of the LINQ query changes. For example:

static void Main(string[] args)
{    
     int startPos = 0;          
     List<string> intList = new List<string>();
     for (int i = 0; i < 10; i++)
     {
        intList.Add(i.ToString());
     }

     var qResult = from c in intList
                   where Convert.ToInt32(c) >= startPos
                   select c;

     // prints count as 10
     Console.WriteLine("List count is :"+qResult.Count());

     startPos = 5;

     // prints count as 5
     Console.WriteLine("List count is :" + qResult.Count());
}

Output:

List count is :10
List count is :5

In above example you can see that after startPos = 5;, the qResult has changed. I don't understand how this has happened; as far as I know, int is value type.

Is the Linq query again executed at line startPos = 5;? If yes, then will it be a performance impact? And most importantly, am I missing anything here?

4

5 回答 5

2

qResult is enumerated every time you call .Count(), so when you change startPos in between calls to .Count(), you are really changing the code being executed.

To avoid this, enumerate your list once by calling .ToList(), .ToArray(), or similar:

List<string> qResult = (from c in intList
                   where Convert.ToInt32(c) >=startPos
                   select c).ToList();

This is a very good article on deferred execution in LINQ.

于 2013-07-31T10:16:35.200 回答
1

那是因为每次调用qResult都会被执行。如果您希望结果永远不会改变,只需像这样使用:IEnumerable<T>.Count()ToList()

var qResult = (from c in intList
               where Convert.ToInt32(c) >=startPos
               select c).ToList();
于 2013-07-31T10:19:37.867 回答
0

是的,这是因为qResult每次调用时都会枚举Count(),并且您正在将修改后的闭包访问到 linq 查询中。您应该使用第三个变量来避免这种行为:

        int pos = startPos;
        var qResult = from c in intList
                      where Convert.ToInt32(c) >= pos
                      select c;

或就地枚举:

        var qResult = (from c in intList
                      where Convert.ToInt32(c) >= startPos
                      select c).ToArray();

它被称为延迟执行

于 2013-07-31T10:19:34.150 回答
0

.Count() 在调用时会进行枚举。它不像变量值,因此结果与预期的行为一致。

于 2013-07-31T10:18:20.960 回答
0

linq 查询在调用时执行,因为它使用延迟加载,在您的情况下qResult.Count(),如果您希望强制执行调用ToList()或类似功能,您的查询将在 中执行

于 2013-07-31T10:19:16.157 回答