为什么在这个LINQ代码中j--和--j都抛出异常,而j - 1不抛出异常?

xienkqul  于 2022-12-06  发布在  其他
关注(0)|答案(1)|浏览(154)

我是C#新手,通过编写一个经典的100扇门问题的解决方案来练习。下面的代码(可能是糟糕的)解决了这个问题:

internal class Program
{
    private static void Main(string[] args)
    {
        var doors = new bool[100];
        var ints = new int[100];
        ints = Enumerable.Range(1, 100).ToArray();
        for (int i = 1; i <= 100; i++)
        {
           ints.Where(j => j % i == 0)
               .Select(j => j)
               .ToList()
               .ForEach(j => doors[j - 1] = !doors[j - 1]); //This is the relevant line.
        }
        Array.ForEach(doors, i => Console.WriteLine(i));
    }
}

我把注解放在上面的行让我很惊讶。它工作得非常好,但是用下面的任何一个替换它都会抛出System.IndexOutOfRangeException

.ForEach(j => doors[--j] = !doors[--j]);
.ForEach(j => doors[j--] = !doors[j--]);

尽管j - 1是完全正确的,为什么这两个都是无效的呢?我的理解是,在所有情况下,--jj--中只有一个等价于j - 1

lb3vh1jj

lb3vh1jj1#

我的理解是,在任何情况下,j和j中,只有一个等价于j - 1.
不,绝对不是。
这两个函数失败的原因不同-一个是当j初始为1时,另一个是当j初始为100时。
首先考虑一下:

.ForEach(j => doors[--j] = !doors[--j]);

这将j * 递减两次 *,并且在每种情况下,都使用递减发生后的j * 的值。
首先计算左手操作数,因此当j为1时,数组索引的计算结果为:

doors[0] = !doors[-1];

显然,doors[-1]是无效的。
现在让我们考虑第二种选择:

.ForEach(j => doors[j--] = !doors[j--]);

这再次将j递减两次,但在每次数组索引操作中使用递减前的j的值。因此,当j为100时,它将数组索引计算为:

doors[100] = !doors[99];

这次是doors[100],这是无效的。
在您的 working 代码中,您将j - 1用于两个索引,而根本不修改j,因此当j从1到100时,您使用的数组索引从0到99,这是有效的。
我强烈建议不要在任何表达式或语句中使用前/后增量/减量,因为您在多个位置使用了修改后的变量-并且 * 绝对 * 避免在同一表达式或语句中多次使用同一变量的前/后增量/减量。

相关问题