2

I made an extension which adds ForEach() method on ObservableCollection :

public static void ForEach<T>(this ObservableCollection<T> enumerable, Action<T> action)
{
    foreach (var item in enumerable)
        action(item);
}

When I use it, like this :

private bool Bar(int i)
{
    return i % 2 == 1;
}

private void Foo()
{
    Boolean ok = true;
    ObservableCollection<int> oc = new ObservableCollection<int> { 1, 2, 3, 4 };

    oc.ForEach(i => ok &= Bar(i));
    //ok is now false
}

I don't understand how does the ok Boolean take the value returned by the Bar() method which is executed by action(item) ?

Onur
  • 5,017
  • 5
  • 38
  • 54

2 Answers2

2

Lambdas are allowed to modify variables that are in the scope of the code inside their bodies. You need to be very careful with this sort of code, because you do not always have full control over the timing of executing the lambdas.

For example, if you add an assignment to a lambda that you pass to a method with deferred execution, the side effect of that lambda (i.e. the assignment) would not be visible until the code of that lambda has actually executed.

Here is an example:

bool ok = true;
IEnumerable<int> res = new[] {1, 2, 3}.Where(i => ok &= (i == 2));
// ok is true here
IList<int> listRes = res.ToList();
// ok is false here

If you run this code, ok would remain true, even though the very first item of the source list would trigger an assignment of false to the ok variable. This wouldn't happen, however, until you enumerate res.

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
  • While this is true and really very good information, the majority of it does not apply to this question because `foreach` is not deferred. This answer is very valuable - I'd just suggest making a note of that. – Magus Mar 17 '14 at 15:49
  • @Magus You are right - the part that is relevant to the OP's question is in the very first sentence. However, I wanted to make sure that whoever reads this answer does not get too carried away by the new exciting possibilities, because they need to be handled with care. – Sergey Kalinichenko Mar 17 '14 at 15:53
0

You are applying &= which will and each result with the previos value of ok (as ok is not local to a single loop iteration, it is declared outside of the loop). In other words,

as the condition is only true for two values (1 and 3)

ok = true && false && true && false

which is false.

Justin Harvey
  • 14,446
  • 2
  • 27
  • 30