Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does List.Count() and IEnumerable.Count() return different results?

We have this array in LINQ.

string[] colors = { "green", "brown", "blue", "red" };

and this code return 0.

var list = new List<string>(colors);
IEnumerable<string> q3 = list.Where(c => c.Length == 3);
list.Remove("red");
listBox1.Items.Add("Oh! That is : " + q3.Count());

and other return 1.

var list = new List<string>(colors);
List<string> q3 = list.Where(c => c.Length == 3).ToList();
list.Remove("red");
listBox1.Items.Add("Oh! That is : " + q3.Count());

Why it happen? What is the diffrence between list and Ienumerable?

like image 424
Reza Mohammady Avatar asked Sep 26 '14 09:09

Reza Mohammady


1 Answers

The Where method doesn't execute your query - it just builds a query, which is then executed when the data is requested. This is known as deferred execution. So in your first snippet, the filter is only applied when Count() is called - which is after the red item has been removed.

In the second snippet, your call to ToList() forces the query to be executed immediately to build a new list. This is then completely independent of the original list - so removing an item from the original list doesn't affect the results.

This is not dependent on the declaration type of q3 - the important difference is just the call to ToList(). So if you change the second snippet to:

var list = new List<string>(colors);
IEnumerable<string> q3 = list.Where(c => c.Length == 3).ToList();
list.Remove("red");
listBox1.Items.Add("Oh! That is : " + q3.Count());

... you'll see the same effect. The query will be executed before the item is removed, at which point the original list is irrelevant to the contents of q3.

For more details on the ins and outs of LINQ, you might want to read my Edulinq blog series.

like image 131
Jon Skeet Avatar answered Oct 27 '22 11:10

Jon Skeet