LINQ has 2 methods for counting enumerables: Count
and LongCount
. Practically the only difference between these two is that the first returns an int
, while the second returns a long
.
I'm unclear as to why the second method was added. It seems its only use case would be to handle enumerables of over 2B elements. This seems like a poor decision to me, for a few reasons:
Most BCL collections are backed by single-dimensional arrays, which have lengths that are guaranteed to fit in an int
. Trying to go past that will raise an OverflowException
/ OutOfMemoryException
.
LongCount
is O(n) since IEnumerable
is lazy. If you have a 3B element enumerable, you call LongCount
on it, and then you iterate through it again (which you will have to if you want to use any of the values), you will be adding an extra 3B iterations, which will be extremely slow, and hiding it from the developer.
Other LINQ operations, such as ToArray
/ ToList
, do not support enumerables with 2B+ elements because of (1).
Am I missing something here, or is there a more practical reason why LongCount
was added? Thanks.
I have no first-hand knowledge of this design decision but I can offer an educated guess.
The method is of obvious usefulness for IQueryable
; the query could easily be backed by an enormous database table.
I would expect
IQueryable<Foo> q = whatever;
long result1 = q.LongCount();
long result2 = q.AsEnumerable().LongCount();
to produce the same answer. It seems perverse to require in-memory queries to use a different method that returns a different type, particularly when it is so easy to implement the enumerable version.
But like I said, that's an educated guess; hopefully someone who actually worked on this design might chime in.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With