myCars.TakeWhile(car => !myCondition(car)).Count();
It works! Think about it. The index of the first matching item equals the number of (not matching) item before it.
I too dislike the horrible standard solution you already suggested in your question. Like the accepted answer I went for a plain old loop although with a slight modification:
public static int FindIndex<T>(this IEnumerable<T> items, Predicate<T> predicate) {
int index = 0;
foreach (var item in items) {
if (predicate(item)) break;
index++;
}
return index;
}
Note that it will return the number of items instead of -1
when there is no match. But let's ignore this minor annoyance for now. In fact the horrible standard solution crashes in that case and I consider returning an index that is out-of-bounds superior.
What happens now is ReSharper telling me Loop can be converted into LINQ-expression. While most of the time the feature worsens readability, this time the result was awe-inspiring. So Kudos to the JetBrains.
new
ing anonymous objectsTherefore I consider it optimal in time and space while remaining readable.
-1
when there is no matchOf course you can always hide it behind an extension method. And what to do best when there is no match heavily depends on the context.