Question

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) ?

Was it helpful?

Solution

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.

OTHER TIPS

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top