Imagine the following class:
public class Checker
{
public async Task Check() { ... }
}
Now, imagine a list of instances of
"Asynchronous sequences" can always cause some confusion. For example, it's not clear whether your desired semantics are:
There's a third possibility (start all checks simultaneously, and evaluate them in sequence order), but that would be silly in this scenario.
I recommend using Rx for asynchronous sequences. It gives you a lot of options, and it a bit hard to learn, but it also forces you to think about exactly what you want.
The following code will start all checks simultaneously and evaluate them as they complete:
IObservable result = checkers.ToObservable()
.SelectMany(c => c.Check()).All(b => b);
It first converts the sequence of checkers to an observable, calls Check
on them all, and checks whether they are all true
. The first Check
that completes with a false
value will cause result
to produce a false
value.
In contrast, the following code will start the checks one at a time, evaluating them in sequence order:
IObservable result = checkers.Select(c => c.Check().ToObservable())
.Concat().All(b => b);
It first converts the sequence of checkers to a sequence of observables, and then concatenates those sequences (which starts them one at a time).
If you do not wish to use observables much and don't want to mess with subscriptions, you can await
them directly. E.g., to call Check
on all checkers and evaluate the results as they complete:
bool all = await checkers.ToObservable().SelectMany(c => c.Check()).All(b => b);