score:11

Accepted answer

You're being bitten by a captured variable:

var query = color.Where(c => c.Contains(s));

Lifts s into a closure and reads the value of s at the time of execution. In this case, this happens after you re-assign s to something else.

What you end up having as your query is:

var query = color.Where(c => c.Contains(s)).Where(c => c.Contains(s));

Rather than what you're probably expecting:

var query = color.Where(c => c.Contains("g")).Where(c => c.Contains("a"));

This will produce the result you're expecting:

string s = "g";
string[] color = { "greena", "browna", "bluea" };
var query = color.Where(c => c.Contains(s));
Console.WriteLine(query.Count());
var b = "a";
query = query.Where(c => c.Contains(b));
Console.WriteLine(query.Count()); // <-- This is where the entire expression is evaluated

score:0

Your colors aren't spelled correctly.

Greena, browna, bluea all have the character 'a' in them. Your linq expression is working as intended.

score:0

Because firstly you are looking for letter 'g', which only 'greena' contains. Afterwards, you change the value of s = "a" and then run a query and look for all words with letter 'a' in them, in this case all 3 of them have 'a', therefore you are getting 1 and 3 as an output. Everything is correct. Why are you intending to get 1 and 1?

score:0

On the first part, it says, you query all colors with the letter g inside which is only 1, that's why it outputs 1:

string s = "g";
string[] color = { "greena", "browna", "bluea" };
var query = color.Where(c => c.Contains(s));

On the second part, it says, you query all colors which contains letter a inside which is every index on your array has letter a inside so it outputs 3:

 s = "a";
 query = query.Where(c => c.Contains(s));
 Console.WriteLine(query.Count());

score:3

The first line for the query:

var query = color.Where(c => c.Contains(s));

Does not put the results in the query. It generates a query that has a source of string[] color with a predicate (filter) of .Contains(s). This doesn't get executed until .Count() is executed.

What this means is on the next execution of query.Contains() it's working on the original source of items. So, while you would expect the first result:

s = "g";
color.Where(c => c.Contains(s));

to return a count of 1 which is "greena", and then

s = "a";
query.Where(c => c.Contains(s)); //  Where query now contains only: "greena" and hence return 1 for a count

What's really happening is this:

s = "g";
string[] color = { "greena", "browna", "bluea" };
query = color;
Console.WriteLine(query.Where(c => c.Contains(s)).Count());
// Outputs 1 because g appears only in greena

s = "g";
// query still contains the original color list
Console.WriteLine(query.Where(c => c.Contains(s)).Count());   
// Outputs 3 because a appears in all three

In order to function as you are expecting you have to force the execution of the linq in the first query:

string s = "g";
string[] color = { "greena", "browna", "bluea" };
var query = color.Where(c => c.Contains(s)).Select(x => x).ToArray();
// Notice the ToArray() -- it forces execution of the linq which returns the results, not the query itself.
Console.WriteLine(query.Count());
s = "a";
var query2 = query.Select(x => x).Where(c => c.Contains(s));
Console.WriteLine(query2.Count());
Console.ReadKey();

Related Articles