How do you create a counter that returns (theoretically) an infinite number of elements?

I am writing code similar to this:

public IEnumerable<T> Unfold<T>(this T seed) { while (true) { yield return [next (T)object in custom sequence]; } } 

Obviously, this method will never return. (The C # compiler silently resolves this, while R # gives me the warning "The function never returns.")

Generally speaking, does poor design provide an enumerator that returns an infinite number of elements without providing a way to stop the enumeration?

Are there any special considerations for this scenario? Mem? Perf? Other bugs?

If we always provide an exit condition, what are the parameters? For example:

  • an object of type T that represents an inclusive or exclusive border
  • a Predicate<T> continue (as TakeWhile )
  • account (like Take )
  • ...

Should we rely on users calling Take(...) / TakeWhile(...) after Unfold(...) ? (Perhaps the preferred option, as it uses existing Linq knowledge.)

Could you answer this question differently if the code published a public API, either as it is (general) or as a specific implementation of this template?

+6
c # enumerator
source share
4 answers

As long as you clearly document that the method will never complete the iteration (the method itself returns very quickly, of course), then I think this is normal. In fact, this can make some algorithms much neater. I do not believe that there are significant memory / performance problems, although if you reference an "expensive" object inside your iterator, this link will be fixed.

There are always ways to abuse the API: as long as your documents are clear, I think this is normal.

+7
source share

"Generally speaking, is it bad to provide an enumerator that returns an infinite number of items without providing a way to stop the enumeration?"

The consumer of the code can always stop the enumeration (using a gap, for example, or other means). If your counter returns and an infinite sequence, this does not mean that the client of the enumerator is somehow forced to never interrupt the enumeration, in fact, you cannot make an enumerator that is guaranteed to be completely enumerated by the client.

Should we rely on the challenge of users Take (...) / TakeWhile (...) after Open (...)? (Perhaps preferred, as it uses existing Link.)

Yes, if you clearly indicate in your documentation that the enumerator is returning, and the endless sequence and violation of the enumeration is the responsibility of the caller, everything should be fine.

Returning infinite sequences is not a bad idea; functional programming languages ​​have done this a long time ago.

+6
source share

I agree with John. The compiler will convert your method to a class that implements a simple state machine that references the current value (i.e., the value that will be returned through the current property). I have used this approach several times to simplify the code. If you clearly document the behavior of the method, it should work fine.

+2
source share

I would not use an infinite enumerator in a public API. The C # programmers included by me are too accustomed to the foreach loop. This will also comply with the .NET Framework; notice how the Enumerable.Range and Enumerable.Repeat methods take an argument to limit the number of elements in Enumerable. Microsoft chose to use Enumerable.Repeat (", 10) instead of Enumerable.Repeat (" ") .Take (10) to avoid endless enumeration, and I would stick to their design options.

0
source share

All Articles