通过溢出从MinValue迭代到MaxValue

时间:2017-05-05 08:31:07

标签: c# for-loop

我有一个简单的循环,看起来应该是这样的

for (sbyte i = sbyte.MinValue; i <= sbyte.MaxValue; i++)
{
    Console.WriteLine(i);
}

遗憾的是sbyte.MaxValue +1 = sbyte.MinValue所以这永远不会满足结束条件。我的解决方法是使用int中的-128127,但是还有一种原生的sbyte方法吗?

4 个答案:

答案 0 :(得分:5)

没有考虑到明显的

  

输出除MaxValue以外的所有内容,然后输出MaxValue

接近,我看到一个解决方案 它很有效,但看起来很奇怪,只有在OverflowException:)

时才会抛出checked
sbyte i = sbyte.MinValue;
do
{
    Console.WriteLine(i++);
} while (i != sbyte.MinValue);

答案 1 :(得分:2)

您可以仅使用int作为条件,并使用sbyte

int checkVal = sbyte.MinValue;
for (sbyte i = sbyte.MinValue; checkVal <= sbyte.MaxValue; i++, checkVal++)
{
    Console.WriteLine(i);
}

答案 2 :(得分:1)

如果将其更改为do ... while循环,则可以获得正确的范围:

sbyte i = sbyte.MinValue;
do
{
    Console.WriteLine(i);
    i++;
}
while(i != sbyte.MaxValue);
Console.WriteLine(i);

答案 3 :(得分:1)

最简单的方法可能是使用Enumerable.Range(int start, int count)方法:

foreach (var i in Enumerable.Range(sbyte.MinValue, 256))
{
    Console.WriteLine((sbyte)i);
}

由于魔术数为256,所以这有点难看,并且枚举当然不是基于本机sbyte

一种更丑陋的方法是使用Nullable<sbyte>作为本地循环变量:

for (sbyte? i = sbyte.MinValue;
    i.HasValue && i <= sbyte.MaxValue;
    i = unchecked(i < ++i ? i : null))
{
    Console.WriteLine(i);
}

不仅丑陋而且缓慢。因此,我最终写了一个Loop方法,该方法接受包含性的sbyte参数,并且也可以用负数step进行调用以进行向后枚举:

public static void Loop(sbyte fromInclusive, sbyte toInclusive,
    sbyte step, Action<sbyte> action)
{
    var index = fromInclusive;
    while (true)
    {
        action(index);
        sbyte nextIndex = unchecked((sbyte)(index + step));
        if (step > 0)
        {
            if (nextIndex < index) break; // Overflow
            if (nextIndex > toInclusive) break;
        }
        else if (step < 0)
        {
            if (nextIndex > index) break; // Overflow
            if (nextIndex < toInclusive) break;
        }
        index = nextIndex;
    }
}
public static void Loop(sbyte fromInclusive, sbyte toInclusive,
    Action<sbyte> action) => Loop(fromInclusive, toInclusive, 1, action);

用法示例:

Loop(sbyte.MinValue, sbyte.MaxValue, (i) =>
{
    Console.WriteLine(i);
});

输出:

  

-128
  -127
  -126
  -125
  -124
  ...
  123
  124
  125
  126
  127

它比带有for循环变量的int语句慢,但比带有Enumerable<int>枚举foreach的语句快。