As pointed out by commenters and illustrated in this answer, the int
type has max and min bounds, so you can't actually use it as the value type of an infinite sequence. However, you can compromise as follows:
- Sacrifice the
int
type for something like BigInteger
- as is done in this answer.
- Sacrifice "infinity" so that you can keep the
int
type.
Since the former has been covered, I'll cover the latter. Below is a class I used to provide enumeration over int
values, which will throw an exception if that enumeration gets out of range, either too high or too low. I've unit tested the upper/lower edge cases and it all seems to work fine.
internal class SequentialIntProviderImpl : ISequentialIntProvider
{
public int Start { get; }
public int Step { get; }
private int _current;
public SequentialIntProviderImpl(int start, int step)
{
Start = start;
Step = step;
_current = start;
}
public int Next()
{
AssertNextIsInBounds();
_current += Step;
return _current;
}
private void AssertNextIsInBounds()
{
AssertNextLeqIntMax();
AssertNextGeqIntMin();
}
private void AssertNextGeqIntMin()
{
if (Step < 0)
{
int MinAllowableCurrent = int.MinValue - Step;
if (_current < MinAllowableCurrent)
{
throw new IndexOutOfRangeException($"Current index {_current} plus step {Step} will exceed int Min value");
}
}
}
private void AssertNextLeqIntMax()
{
if(Step > 0)
{
int maxAllowableCurrent = int.MaxValue - Step;
if(_current > maxAllowableCurrent)
{
throw new IndexOutOfRangeException($"Current index {_current} plus step {Step} will exceed int Max value");
}
}
}
}
/// <summary>
/// Provides iteration over an arithmetic sequence of ints, starting at the given value & increasing by the given step
/// </summary>
public interface ISequentialIntProvider
{
/// <summary>
/// Value to start at
/// </summary>
int Start { get; }
/// <summary>
/// Value by which to increase the sequence at each successive term
/// </summary>
int Step { get; }
/// <returns>The next successive term in the sequence</returns>
int Next();
}