modified closure warning in ReSharper - c#

I was hoping someone could explain to me what bad thing could happen in this code, which causes ReSharper to give an 'Access to modified closure' warning:
bool result = true;
foreach (string key in keys.TakeWhile(key => result))
{
result = result && ContainsKey(key);
}
return result;
Even if the code above seems safe, what bad things could happen in other 'modified closure' instances? I often see this warning as a result of using LINQ queries, and I tend to ignore it because I don't know what could go wrong. ReSharper tries to fix the problem by making a second variable that seems pointless to me, e.g. it changes the foreach line above to:
bool result1 = result;
foreach (string key in keys.TakeWhile(key => result1))
Update: on a side note, apparently that whole chunk of code can be converted to the following statement, which causes no modified closure warnings:
return keys.Aggregate(
true,
(current, key) => current && ContainsKey(key)
);

In that particular code nothing, take the following as an example:
int myVal = 2;
var results = myDatabase.Table.Where(record => record.Value == myVal);
myVal = 3;
foreach( var myResult in results )
{
// TODO: stuff
}
It looks like result will return all records where the Value is 2 because that's what myVal was set to when you declared the query. However, due to deferred execution it will actually be all records where the Value is 3 because the query isn't executed until you iterate over it.
In your example the value isn't being modified, but Resharper is warning you that it could be and that deferred execution could cause you problems.

When you modify the result variable, the closure (the use of the variable inside the lambda expression) will pick up the change.
This frequently comes as an unexpected surprise to programmers who don't fully understand closures, so Resharper has a warning for it.
By making a separate result1 variable which is only used in the lambda expression, it will ignore any subsequent changes to the original result variable.
In your code, you're relying on the closure picking up the changes to the original variable so that it will know when to stop.
By the way, the simplest way to write your function without LINQ is like this:
foreach (string key in keys) {
if (ContainsKey(key))
return true;
}
return false;
Using LINQ, you can simply call Any():
return keys.Any<string>(ContainsKey);

See
http://ericlippert.com/2009/11/12/closing-over-the-loop-variable-considered-harmful-part-one/
for an extensive discussion of this issue and what we might do in hypothetical future versions of C# to mitigate it.

I'm not sure if ReSharper will give the exact same warning for this, but the following illustrates a similar situation. The iterator for a loop is used in a LINQ clause, but the clause isn't actually evaluated until after the loop has finished, by which time the iterator variable has changed. The following is a contrived example that looks like it should print all odd numbers from 1 to 100, but actually prints all numbers from 1 to 99.
var notEven = Enumerable.Range(1,100);
foreach (int i in Enumerable.Range(1, 50))
{
notEven = notEven.Where(s => s != i * 2);
}
Console.WriteLine(notEven.Count());
Console.WriteLine(string.Join(", ", notEven.Select(s => s.ToString()).ToArray()));
This can be quite an easy mistake to make. I've heard people say that if you truly understand closures/functional programming/etc. you should never make this mistake. I've also seen professional developers who certainly do have a good grasp of those concepts make this exact mistake.

Well, the warning is because result could be changed before the closure is executed (variables are taken at execution, not defition). In your case, you are actually taking advantage of that fact. If you use the resharper reccomodation, it will actually break your code, as key => result1 always returns true.

Related

Why am I able to edit a LINQ list while iterating over it?

I recently came across an issue where I was able to change the IEnumerable object that I was iterating over in a foreach loop. It's my understanding that in C#, you aren't supposed to be able to edit the list you're iterating over, but after some frustration, I found that this is exactly what was happening. I basically looped through a LINQ query and used the object IDs to make changes in the database on those objects and those changes affected the values in the .Where() statement.
Does anybody have an explanation for this? It seems like the LINQ query re-runs every time it's iterated over
NOTE: The fix for this is adding .ToList() after the .Where(), but my question is why this issue is happening at all i.e. if it's a bug or something I'm unaware of
using System;
using System.Linq;
namespace MyTest {
class Program {
static void Main () {
var aArray = new string[] {
"a", "a", "a", "a"
};
var i = 3;
var linqObj = aArray.Where(x => x == "a");
foreach (var item in linqObj ) {
aArray[i] = "b";
i--;
}
foreach (var arrItem in aArray) {
Console.WriteLine(arrItem); //Why does this only print out 2 a's and 2 b's, rather than 4 b's?
}
Console.ReadKey();
}
}
}
This code is just a reproducible mockup, but I'd expect it to loop through 4 times and change all of the strings in aArray into b's. However, it only loops through twice and turns the last two strings in aArray into b's
EDIT: After some feedback and to be more concise, my main question here is this: "Why am I able to change what I'm looping over as I'm looping over it". Looks like the overwhelming answer is that LINQ does deferred execution, so it's re-evaluating as I'm looping through the LINQ IEnumerable.
EDIT 2: Actually looking through, it seems that everyone is concerned with the .Count() function, thinking that is what the issue here is. However, you can comment out that line and I still have the issue of the LINQ object changing. I updated the code to reflect the main issue
Why am I able to edit a LINQ list while iterating over it?
All of the answers that say that this is because of deferred "lazy" execution are wrong, in the sense that they do not adequately address the question that was asked: "Why am I able to edit a list while iterating over it?" Deferred execution explains why running the query twice gives different results, but does not address why the operation described in the question is possible.
The problem is actually that the original poster has a false belief:
I recently came across an issue where I was able to change the IEnumerable object that I was iterating over in a foreach loop. It's my understanding that in C#, you aren't supposed to be able to edit the list you're iterating over
Your understanding is wrong, and that's where the confusion comes from. The rule in C# is not "it is impossible to edit an enumerable from within an enumeration". The rule is you are not supposed to edit an enumerable from within an enumeration, and if you choose to do so, arbitrarily bad things can happen.
Basically what you're doing is running a stop sign and then asking "Running a stop sign is illegal, so why did the police not prevent me from running the stop sign?" The police are not required to prevent you from doing an illegal act; you are responsible for not making the attempt in the first place, and if you choose to do so, you take the chance of getting a ticket, or causing a traffic accident, or any other bad consequence of your poor choice. Usually the consequences of running a stop sign are no consequences at all, but that does not mean that it's a good idea.
Editing an enumerable while you're enumerating it is a bad practice, but the runtime is not required to be a traffic cop and prevent you from doing so. Nor is it required to flag the operation as illegal with an exception. It may do so, and sometimes it does do so, but there is not a requirement that it does so consistently.
You've found a case where the runtime does not detect the problem and does not throw an exception, but you do get a result that you find unexpected. That's fine. You broke the rules, and this time it just happens that the consequence of breaking the rules was an unexpected outcome. The runtime is not required to make the consequence of breaking the rules into an exception.
If you tried to do the same thing where, say, you called Add on a List<T> while enumerating the list, you'd get an exception because someone wrote code in List<T> that detects that situation.
No one wrote that code for "linq over an array", and so, no exception. The authors of LINQ were not required to write that code; you were required to not write the code you wrote! You chose to write a bad program that violates the rules, and the runtime is not required to catch you every time you write a bad program.
It seems like the LINQ query re-runs every time it's iterated over
That is correct. A query is a question about a data structure. If you change that data structure, the answer to the question can change. Enumerating the query answers the question.
However, that is an entirely different issue than the one in the title of your question. You really have two questions here:
Why can I edit an enumerable while I am enumerating it?
You can do this bad practice because nothing stops you from writing a bad program except your good sense; write better programs that do not do this!
Does a query re-execute from scratch every time I enumerate it?
Yes; a query is a question, not an answer. An enumeration of the query is an answer, and the answer can change over time.
The explanation to your first question, why your LINQ query re-runs every time it's iterated over is because of Linq's deferred execution.
This line just declares the linq exrpession and does not execute it:
var linqLIST = aArray.Where(x => x == "a");
and this is where it gets executed:
foreach (var arrItem in aArray)
and
Console.WriteLine(linqList.Count());
An explict call ToList() would run the Linq expression immediately. Use it like this:
var linqList = aArray.Where(x => x == "a").ToList();
Regarding the edited question:
Of course, the Linq expression is evaluated in every foreach iteration. The issue is not the Count(), instead every call to the LINQ expression re-evaluates it. As mentioned above, enumerate it to a List and iterate over the list.
Late edit:
Concerning #Eric Lippert's critique, I will also refer and go into detail for the rest of the OP's questions.
//Why does this only print out 2 a's and 2 b's, rather than 4 b's?
In the first loop iteration i = 3, so after aArray[3] = "b"; your array will look like this:
{ "a", "a", "a", "b" }
In the second loop iteration i(--) has now the value 2 and after executing aArray[i] = "b"; your array will be:
{ "a", "a", "b", "b" }
At this point, there are still a's in your array but the LINQ query returns IEnumerator.MoveNext() == false and as such the loop reaches its exit condition because the IEnumerator internally used, now reaches the third position in the index of the array and as the LINQ is re-evaluated it doesn't match the where x == "a" condition any more.
Why am I able to change what I'm looping over as I'm looping over it?
You are able to do so because the build in code analyser in Visual Studio is not detecting that you modify the collection within the loop. At runtime the array is modified, changing the outcome of the LINQ query but there is no handling in the implementation of the array iterator so no exception is thrown.
This missing handling seems by design, as arrays are of fixed size oposed to lists where such an exception is thrown at runtime.
Consider following example code which should be equivalent with your initial code example (before edit):
using System;
using System.Linq;
namespace MyTest {
class Program {
static void Main () {
var aArray = new string[] {
"a", "a", "a", "a"
};
var iterationList = aArray.Where(x => x == "a").ToList();
foreach (var item in iterationList)
{
var index = iterationList.IndexOf(item);
iterationList.Remove(item);
iterationList.Insert(index, "b");
}
foreach (var arrItem in aArray)
{
Console.WriteLine(arrItem);
}
Console.ReadKey();
}
}
}
This code will compile and iterate the loop once before throwing an System.InvalidOperationException with the message:
Collection was modified; enumeration operation may not execute.
Now the reason why the List implementation throws this error while enumerating it, is because it follows a basic concept: For and Foreach are iterative control flow statements that need to be deterministic at runtime. Furthermore the Foreach statement is a C# specific implementation of the iterator pattern, which defines an algorithm that implies sequential traversal and as such it would not change within the execution. Thus the List implementation throws an exception when you modify the collection while enumerating it.
You found one of the ways to modify a loop while iterating it and re-eveluating it in each iteration. This is a bad design choice because you might run into an infinite loop if the LINQ expression keeps changing the results and never meets an exit condition for the loop. This will make it hard to debug and will not be obvious when reading the code.
In contrast there is the while control flow statement which is a conditional construct and is ment to be non-deterministic at runtime, having a specific exit condition that is expected to change while execution.
Consider this rewrite base on your example:
using System;
using System.Linq;
namespace MyTest {
class Program {
static void Main () {
var aArray = new string[] {
"a", "a", "a", "a"
};
bool arrayHasACondition(string x) => x == "a";
while (aArray.Any(arrayHasACondition))
{
var index = Array.FindIndex(aArray, arrayHasACondition);
aArray[index] = "b";
}
foreach (var arrItem in aArray)
{
Console.WriteLine(arrItem); //Why does this only print out 2 a's and 2 b's, rather than 4 b's?
}
Console.ReadKey();
}
}
}
I hope this should outline the technical background and explain your false expectations.
Enumerable.Where returns an instance that represents a query definition. When it is enumerated*, the query is evaluted. foreach allows you to work with each item at the time it is found by the query. The query is deferred, but it also pause-able/resume-able, by the enumeration mechanisms.
var aArray = new string[] { "a", "a", "a", "a" };
var i = 3;
var linqObj = aArray.Where(x => x == "a");
foreach (var item in linqObj )
{
aArray[i] = "b";
i--;
}
At the foreach loop, linqObj is enumerated* and the query is started.
The first item is examined and a match is found. The query is paused.
The loop body happens: item="a", aArray[3]="b", i=2
Back to the foreach loop, the query is resumed.
The second item is examined and a match is found. The query is paused.
The loop body happens: item="a", aArray[2]="b", i=2
Back to the foreach loop, the query is resumed.
The third item is examined and is "b", not a match.
The fourth item is examined and is "b", not a match.
The loop exits and the query concludes.
Note: is enumerated* : this means GetEnumerator and MoveNext are called. This does not mean that the query is fully evaluated and results held in a snapshot.
For further understanding, read up on yield return and how to write a method that uses that language feature. If you do this, you'll understand what you need in order to write Enumerable.Where
IEnumerable in c# is lazy. This means whenever you force it to evaluate you get the result. In your case Count() forces the linqLIST to evaluate every time you call it. by the way, linqLIST is not a list right now
You could upgrade the «avoid side-effects while enumerating an array» advice to a requirement, by utilizing the extension method below:
private static IEnumerable<T> DontMessWithMe<T>(this T[] source)
{
var copy = source.ToArray();
return source.Zip(copy, (x, y) =>
{
if (!EqualityComparer<T>.Default.Equals(x, y))
throw new InvalidOperationException(
"Array was modified; enumeration operation may not execute.");
return x;
});
}
Now chain this method to your query and watch what happens. 😃
var linqObj = aArray.DontMessWithMe().Where(x => x == "a");
Of course this comes with a cost. Now every time you enumerate the array, a copy is created. This is why I don't expect that anyone will use this extension, ever!

Predicate inside a Where<> query not hit?

I need to call the method for each item in the list. So, I have used Where<> query as follows,
List<string> list = new List<string>();
list.Add("Name1");
list.Add("Name2");
list.Add("Name3");
var name = list.Where(n =>
{
return CheckName(n);
});
But in the above case, CheckName() is not hit. The same method is triggered if I use FirstOrDefault<>. I don't know whether it is a framework break or I am going in a wrong way.
As additional info, I am using.NET Framework 4.5.
Has anyone experienced this error? If so, is there any solution to overcome this issue?
You are understanding incorrectly the result of the Where condition. As linq is deffered executed it will only enter the where condition when materialized (by a ToList/FirstOrDefault/Sum and such).
The Where is never actually materialized in your current code (It did as you experienced when using FirstOrDefault) and as such it will never enter the CheckName method. Then, as Where will never return null but "worst case" an empty collection, which is not null, the result is true.
If you debug you will see that name equals true at the end of this. To "overcome" this depends on what is your desired output:
If you want to know if you have any item that matched the predicate then:
var result = list.Any(CheckName);
If you want to retrieve those that match the predicate:
var result = list.Where(CheckName);
If later you want to query and check if results contains anything then:
if(result.Any()) { /* ... */ }
If you only want the results (and thus materializing the query):
list.Where(CheckName).ToList();
Read more about linq being deffered executed here:
Linq and deffered execution
What are the benefits of a Deferred Execution in LINQ?
Just as a side note see how you can change your current code from:
var name = list.Where(n =>
{
return CheckName(n);
})
To:
var name = list.Where(n => CheckName(n));
And eventually to:
var name = list.Where(CheckName);
LINQ has a Deferred Execution principal which means the query will not be executed until and unless you access name variable. If you want to execute it immediately, (just for example) add .ToList() in the end, which is exactly what FirstOrDefault does. It does immediate execution instead of deferred execution.
var name = list.Where(n =>
{
return CheckName(n);
}).ToList() != null;
Also where condition result will never be null. Even if there is no object in list satisfying your condition(s) in CheckName, where will return an empty collection.
The CheckName() method is not executed because of Deferred execution of Linq. The actual statement is not executed till you actually access it. So in your case, for the CheckName(), you should do something like:
var name = list.Where(n =>
{
return CheckName(n);
}).ToList();
When you look at the Where-Method source code you can easily see why:
internal static IEnumerable<T> Where<T>(this IEnumerable<T> enumerable, Func<T, bool> where) {
foreach (T t in enumerable) {
if (where(t)) {
yield return t;
}
}
}
The yield will cause the execution to only happen once the returned IEnumerable<T> is actually accessed. That is what is called deferred execution.
If you need to call a method for each item in a list then you should use a simple for loop:
foreach var name in list
CheckName(name);
Just because LINQ is available, doesn't mean it should be used everywhere there is a collection. It is important to write code that makes sense and is self commenting and using it here has simultaneously introduced a flaw into your logic and made your code harder to read, understand and maintain. It's the wrong tool for the stated purpose
Doubtless you have additional requirements not stated here, like "I want to check every name in a list and make sure that none are null". You can and possibly should use linq for this but it looks more like
bool allNamesOK = list.All(n => n != null);
This code is compact and reads well; we can clearly see the intention (though I wouldn't call the list "list" - "names" would better)

Replacing a foreach with LINQ expression

So I have a code like this:
foreach (var optionValues in productOption.ProductOptionValues)
{
if (optionValues.ProductOptionValueID > 0)
{
unitOfWork.ProductContext.Entry(optionValues).State = EntityState.Modified;
}
else
{
unitOfWork.ProductContext.Entry(optionValues).State = EntityState.Added;
}
}
The code review for this was that I should look at using LINQ to do this.
Can someone please point me to a resource that can explain using LINQ to change the object properties?
You don't. Simple as that.
The code review for this was that I should look at using LINQ to do this and avoid the foreach.
Tell the code reviewer he is wrong. LinQ is for Querying data. You are updating data. Stay with your foreach loop, it's fine.
LINQ is for querying. You are modifying values, so foreach is perfectly fine here.
The best you could do is this:
var query =
from optionValues in productOption.ProductOptionValues
select new
{
entry = unitOfWork.ProductContext.Entry(optionValues),
value = optionValues.ProductOptionValueID > 0
? EntityState.Modified
: EntityState.Added
};
foreach (var x in query)
{
x.entry.State = x.value;
}
But I don't think that this really gives you much in terms of readability.
The only reasonable use of LINQ here (and it depends on the type of ProductOptionValues) is to filter the results using Where, which essentially replaces your if statement, but it's not better than your current code:
foreach (var option in productOption.ProductOptionValues.Where(x => x.ProductOptionValueID > 0)
unitOfWork.ProductContext.Entry(optionValues).State = EntityState.Modified;
foreach (var option in productOption.ProductOptionValues.Where(x => x.ProductOptionValueID <= 0)
unitOfWork.ProductContext.Entry(optionValues).State = EntityState.Added;
You should not use the LINQ ForEach extension. Let me explain why:
The LINQ foreach violates the functional programming principles that all the other sequence operators are based upon.
Clearly the sole purpose of a call to this method is to cause side effects. The purpose of an expression is to compute a value, not to cause a side effect.
The purpose of a statement is to cause a side effect. The call site of this thing would look an awful lot like an expression
The second reason is that using it adds zero representational value to your code. Doing this lets you rewrite this perfectly clear code:
foreach(Foo foo in foos){ statement involving foo; }
into this code:
foos.ForEach((Foo foo)=>{ statement involving foo; });
which uses almost exactly the same characters in slightly different order. And yet the second version is harder to understand, harder to debug, and introduces closure semantics, thereby potentially changing object lifetimes in subtle ways.
The above is in parts a summary of a blog Post from Eric Lippert. Read the full post here.
What is more the Extension has been removed by the BCL Team in Windows 8:
List.ForEach has been removed in Metro style apps. While the method seems simple it has a number of potential problems when the list gets mutated by the method passed to ForEach.
Instead it is recommended that you simply use a foreach loop.
Assuming productOption.ProductOptionValues is an IList<>() (if it isn't you might need to do a .ToList() before the .ForEach), it would be something like this:
productOption.ProductOptionValues.ForEach(x =>
unitOfWork.ProductContext.Entry(x).State = (
(x.ProductOptionValueID > 0) ? EntityState.Modified : EntityState.Added)
)
... but I don't think that's really an improvement. Quite the opposite, in fact.
Really, don't do this.
Tricky, just for the humor, it is possible in several ways, such as:
var sum = productOption.ProductOptionValues.Select(
optionValues => unitOfWork.ProductContext.Entry(optionValues).State = (optionValues.ProductOptionValueID > 0 ? EntityState.Modified : EntityState.Added).Sum();

Access to modified closure... but why?

Saw several similar questions here, but none of them seemed to quite be my issue...
I understand (or thought I understood) the concept of closure, and understand what would cause Resharper to complain about access to a modified closure, but in the below code I don't understand how I'm breaching closure.
Because primaryApps is declared within the context of the for loop, primary isn't going to change while I'm processing primaryApps. If I had declared primaryApps outside the for loop, then absolutely, I have closure issues. But why in the code below?
var primaries = (from row in openRequestsDataSet.AppPrimaries
select row.User).Distinct();
foreach (string primary in primaries) {
// Complains because 'primary' is accessing a modified closure
var primaryApps = openRequestsDataSet.AppPrimaries.Select(x => x.User == primary);
Is Resharper just not smart enough to figure out it's not an issue, or is there a reason closure is an issue here that I'm not seeing?
The problem is in the following statement
Because primaryApps is declared within the context of the for loop, primary isn't going to change while I'm processing primaryApps.
There is simply no way for Resharper to 100% verify this. The lambda which references the closure here is passed to function outside the context of this loop: The AppPrimaries.Select method. This function could itself store the resulting delegate expression, execute it later and run straight into the capture of the iteration variable issue.
Properly detecting whether or not this is possible is quite an undertaking and frankly not worth the effort. Instead ReSharper is taking the safe route and warning about the potentially dangerous capture of the iteration variable.
Because primaryApps is declared within the context of the for loop, primary isn't going to change while I'm processing primaryApps. If I had declared primaryApps outside the for loop, then absolutely, I have closure issues. But why in the code below?
Jared is right; to demonstrate why your conclusion does not follow logically from your premise, let's make a program that declares primaryApps within the context for the for loop, and still suffers from a captured loop variable problem. Easy enough to do that.
static class Extensions
{
public IEnumerable<int> Select(this IEnumerable<int> items, Func<int, bool> selector)
{
C.list.Add(selector);
return System.Enumerable.Select(items, selector);
}
}
class C
{
public static List<Func<int, bool>> list = new List<Func<int, bool>>();
public static void M()
{
int[] primaries = { 10, 20, 30};
int[] secondaries = { 11, 21, 30};
foreach (int primary in primaries)
{
var primaryApps = secondaries.Select(x => x == primary);
// do something with primaryApps
}
C.N();
}
public static void N()
{
Console.WriteLine(C.list[0](10)); // true or false?
}
}
Where "primaryApps" is declared is completely irrelevant. The only thing that is relevant is that the closure might survive the loop, and therefore someone might invoke it later, incorrectly expecting that the variable captured in the closure was captured by value.
Resharper has no way to know that a particular implementation of Select does not stash away the selector for later; in fact, that is exactly what all of them do. How is Resharper supposed to know that they happen to stash it away in a place that won't be accessible later?
As far as I know Resharper generates the warning every time you access the foreach variable even if it does not really cause closure.
Yes it's just warning,
Look :
http://devnet.jetbrains.net/thread/273042

IEnumerable -- how non-empty collection can be empty at the same time?

I cannot figure this out. The workflow of passing IEnumerable<T> (T is some my class, but it is not relevant here) basically looks like this:
var a = GetEntireCollection(); // so I get IEnumerable<T>
...
var b = a.Where(condition1);
...
var c = b.Where(condition2);
...
So I filter out more and more items from the collection, finally I call:
if (z.IsEmpty())
throw new Exception();
Foo(z);
and Foo is
public void Foo(IEnumerable<T> p)
{
pool = p.OrderByDescending(it => it.MyProperty).ToList();
if (pool.IsEmpty())
throw new Exception(pool.Count().ToString() + ", " + p.Count().ToString());
...
All I do, is order the collection.
Now, my program crashes with exception -- it says that p has Count = 1, and pool has Count = 0. What's more when I point out p and require the results (I run program using Visual Studio) it says, the collection yielded with no results (or somethig similar, not verbatim quote).
Questions:
how can non-empty collection become empty just by reordering?
how can collection Count can be > 0, when there are no items in it?
I am asking because I would like to know how to avoid this situation, but honestly, when I am looking at the code it seems 100% legit for me.
Technical background:
it is pure C# code, no asm inlines, or anything like this
no threads
no external libraries, except for Where (which comes from Linq) this is all my code
Edits
Edit 1
public static bool IsEmpty<T>(this IEnumerable<T> coll)
{
var iter = coll.GetEnumerator();
return !iter.MoveNext();
}
Edit 2
Just before I call Foo(z) I check if the z is empty, so the code looks like this:
if (z.IsEmpty())
throw new Exception();
Foo(z);
SOLVED
As Jon suggested (C# sharpshooting I would say) one of the conditions was time dependent. So when the collection evaluation was forced the condition changed and I get in fact another collection.
One possibility is that evaluating the conditions twice is effectively changing the results.
Each time you iterate through p, it will re-evaluate the data, including the Where clauses. So you're doing that once to populate pool, and then again to print out p.Count().
Without any more information about what GetEntireCollection does or what the Where conditions are, it's hard to say what's going on... but that's one possible explanation. If you can post a short but complete program demonstrating the problem, that would help a lot.
It's empty because of Deferred Execution, most query operators execute not when
constructed, but when enumerated (in other words, when MoveNext is called on its
enumerator).
So if you change it to :
var c = b.Where(condition2).ToList();
And then call Foo(c) it will work.
I think the code you show will call GetEntireCollection multiple times.
So maybe this method is returning different results on successive invocations.

Categories