teleball
teleball

Reputation: 4662

LINQ Where clause misunderstanding

I am getting some behavior from a LINQ Where clause that I can't quite grok.

For instance, I am trying to search a list for terms using a AND semantic.

Here is some code:

var items = new List<string>()
{
    "beef",
    "beef soup",
    "beef ribs",
    "chicken soup",
    "soup",
    "pork ribs",
    "ribs"
};

var term = "soup beef";
var terms = term.Split(' ');
var result = items.AsQueryable();
foreach(var t in terms)
{
    result = result.Where( i => i.Contains(t) );
}
result.ToList().Dump();

The result are:

However, I was looking for it to an AND result, returning just:

Now, I CAN GET THE RESULT I WANT by simply adding

.ToList().AsQueryable()

to the end of the Where clause.

Of course, this is not what I want to do if the back end is a database.

What is really odd here is that when I check 'result' in the loop, I get the following:

  1. Before first where clause => full list -> makes sense.
  2. After first where (for 'soup') => ['beef soup', 'chicken soup', 'soup'] -> still looks good
  3. Before second loop (for 'beef') => ['beef', 'beef soup', 'beef ribs'] -> WHOA! Whats up here
  4. After second loop => stays the same

Can someone explain to me what is going on (and how to fix this correctly)?

Upvotes: 1

Views: 185

Answers (2)

teleball
teleball

Reputation: 4662

CLOSURES!!! Arg.... Got it.

    var cTerm = t;

    result = result.Where( i => i.Contains(cTerm) );

Sorry for the randomness...

Upvotes: 0

Jeff
Jeff

Reputation: 36603

Review Access To Modified Closure

http://weblogs.asp.net/fbouma/archive/2009/06/25/linq-beware-of-the-access-to-modified-closure-demon.aspx

Essentially the problem is that t is being modified in your foreach loop, but you are using it within your closure (the Where lambda method), which is accessing t by reference.

Upvotes: 3

Related Questions