ozgur
ozgur

Reputation: 2719

Is a statement recalculated in every iteration when used in LINQ?

For instance

myEnumerable.Where(v => v != myDictionary["someKey"])

when this query is called is myDictionary["someKey"] statement executed (meaning that dictionary is queried for the key) or the result of myDictionary["someKey"] is used after the first iteration?

Upvotes: 3

Views: 140

Answers (4)

Xiaoy312
Xiaoy312

Reputation: 14477

The result of myDictionary["someKey"] will not be cached(*see edit below), it will be accessed on every item of myEnumerable. However, you can still cache it manually :

var someValue = myDictionary["someKey"];
myEnumerable.Where(v => v != someValue)

Also take note that, if you plan to iterate/access that IEnumerable multiple time, it is best to actualize it via ToList(). Or, the execution will be deferred every single time.

var query = myEnumerable.Where(v => v != myDictionary["someKey"]);

foreach (var item in query) { /* ... */}
foreach (var item in query) { /* ... */}

In the above example, the Where clause is executed twice.


EDIT: As @LucasTrzesniewski has pointed out, this is only stands true for LINQ-to-Objects. This is because the query is evaluated in memory. However, for LINQ-to-Entities, it gets a little bit different, as the query will be converted into SQL query and then executed in the database in order to avoid round trips.

Upvotes: 6

adam0101
adam0101

Reputation: 30995

It depends on the QueryProvider implementation. For example, the ObjectQueryProvider used by Linq-to-objects will access it on every iteration. For Linq-to-entities, it will access it once and then send that value to the database server.

Upvotes: 0

Matt Burland
Matt Burland

Reputation: 45135

Here's a really simple demo (and please, don't try this at home):

var myDictionary = new Dictionary<string,string>() { { "someKey", "someValue" } };
var myEnumerable = new List<string> { "someValue", "someOtherValue" };

var test = myEnumerable.Where(v => v == myDictionary["someKey"]);

foreach (var t in test)
{
    Console.WriteLine(t);
    myDictionary["someKey"] = "someOtherValue";
}

If myDictionary["someKey"] was only evaulated once, then changing the value of myDictionary["someKey"] wouldn't change anything. But if you run the code, you will see that it will echo both someValue and someOtherValue. If you comment out the line that changes the dictionary value, then you will only see someValue

As @Lucas Trzesniewski points out in the comments to the other answer, this applies to LINQ-to-objects. There are a number of important differences between LINQ-to-objects and LINQ-to-SQL.

Upvotes: 1

DVK
DVK

Reputation: 2792

The Lambda expression you supply to the Linq Where extension is simply a Func<> delegate. The method is executed for each item in the IEnumerable(of T), receiving the current item as a parameter. It doesn't do anything special other than that. Your code is somewhat similar similar to:

var myTempCollection = new List<MyClass>();

foreach(MyClass item in myEnumerable)
{
   if (item != myDictionary["someKey"])
   {
        myTempCollection.Add(item);
    }
}

var result = myTempCollection;

Upvotes: 0

Related Questions