【问题标题】:Why do both j-- and --j throw exceptions in this LINQ code, but j - 1 does not?为什么在此 LINQ 代码中 j-- 和 --j 都会抛出异常,而 j - 1 不会?
【发布时间】:2022-11-21 00:08:03
【问题描述】:

我是 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

【问题讨论】:

  • 在索引超出范围之前需要澄清的重要一点:增量运算符在 (--j) 之前或之后 (j--) 转换为 j = j - 1,变量 j 在语句中使用。 j - 1 == j - 1 关键区别在于没有对 j 进行赋值

标签: c# linq increment indexoutofboundsexception


【解决方案1】:

据我了解,在所有情况下,--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]

在你的在职的代码中,您对两个索引都使用了 j - 1,而根本没有修改 j,因此当 j 从 1 变为 100 时,您使用的数组索引从 0 变为 99,这是有效的。

【讨论】:

    猜你喜欢
    • 2014-02-11
    • 2018-09-06
    • 2022-01-14
    • 1970-01-01
    • 1970-01-01
    • 2014-06-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多