Let's say I have code like:
if (someEnumerable.Count() < 2) {
// Do something
}
Would this result in someEnumerable
being iterated over fully, or would evaluation complete if Count()
reaches a second item in the enumerable?
Let's say I have code like:
if (someEnumerable.Count() < 2) {
// Do something
}
Would this result in someEnumerable
being iterated over fully, or would evaluation complete if Count()
reaches a second item in the enumerable?
There is no compiler optimization regarding the behavior of methods. If at all that would be a runtime optimization of the method itself. But since Enumerable.Count
doesn't know in which context it is used, it cannot change it's behavior.
If you don't want to count something but just want to know if there is not more than one use:
if (!someEnumerable.Skip(1).Any()) {
// Do something
}
However, if someEnumerable
is implementing ICollection<TSource>
or ICollection
(like arrays, lists or dictionaries) the method is optimized to simply use the Count
property, so doesn't need to enumerate all items(source). Then it would be a micro optimization which hurts readability and i'd probably prefer Count() < 2
.
In general, the optimizations compilers do are quite conservative because they have to work for all cases.
From the compiler's point of view there are two discrete operations here. 1) counting the elements of the sequence represented by someEnumerable
and 2) comparing that count to a specific value. The compiler has no way to know if there are any side effects of enumerating the sequence (I guess it could find out, but it gets hairy pretty quickly), so an optimization like this would change the semantics of someEnumerable.Count()
.
For what it is worth some implementations of Count
can and do use properties if available, but that's controlled by the class implementing the interface and not in general by the compiler.
© 2022 - 2024 — McMap. All rights reserved.
Skip(1).Any()
is about the same length... – Flocculent(x, y, z) = (a, b, c)
it doesn't actually create the ValueTuple - but I would never expect it to change this code. – InchwormCount
only iterates over the enumerable as a last resort. source.dot.net/#System.Linq/System/Linq/Count.cs,11 – SubeditICollection
of any kind. So depends where you got yourIEnumerable
from. – HoarySkip(1).Any()
should be equivalent here, but it is not always. When using Entity Framework, enumerating the source would cause all entries to be loaded into memory. Reordering that statement would mean that a successive call toFind()
would be a cache miss instead of a hit. That's potentially introducing bugs – WillytsomeEnumerable.Count()
is just a method which is called and the compiler will not change the behavior of a method. Use the right method if you don't want to count something but just want to know if there is not more than one:!someEnumerable.Skip(1).Any()
– Conglobate