Reputation: 3367
I saw the post on ways to handle an infinite IEnumerable, but I didn't see a good answer for testing if an enumerable is infinite.
My end goal is to write a function for all collection types in .NET, but to safely traverse the whole collection without the risk of long wait times due to some infinite collection.
OPT1: I thought I might be able tell if an enumerable is infinite and throw an exception. However, I figure this would be the approach for .NET aggregate LINQ expressions (e.g. Max, Count) if it were possible.
OPT2: Is there some other abstraction that supports most all enumerable types, but disallows infinite elements? ICollection
looks promising, supports lists and arrays, but not Queues or many custom IEnumerables.
I'm also having a hard time determining if ICollection can be infinite or not.
Suggestions?
Upvotes: 0
Views: 190
Reputation: 233307
You are literally running into the Halting Problem. There's no general-purpose algorithm that can be used to determine whether or not a Turing-complete computation will ever complete.
You could have an IEnumerable<int>
that enumerates all the digits in π. There's no way of telling if that function just keeps on going (as it should, according to mathematics), or only approximates π to a billion decimals.
Is there some other abstraction that supports most all enumerable types, but disallows infinite elements?
I usually use IReadOnlyCollection<T>
for just that purpose. It's nothing but IEnumerable<T>
with an extra Count property. That property strongly suggests that the collection has a finite length - particularly because int
has a MaxValue.
That said, a malicious implementer could trivially implement IReadOnlyCollection<T>
as an infinite sequence by just lying and setting Count
to, say, 0
, so there are no guarantees. But since any C# method could hypothetically block forever, I consider that par for the course.
I first became aware of IReadOnlyCollection<T>
in 2013 and started using it soon thereafter. Using it is still a bit awkward at times, since so many other APIs return IEnumerable<T>
. You can easily convert them to IReadOnlyCollection<T>
with either ToArray or ToList, but it's still a little inconvenient at times.
Still, I've been bitten by deferred execution enough times that I strongly favour IReadOnlyCollection<T>
.
Upvotes: 1