繁体   English   中英

奇怪的数组行为

[英]Strange array behavior

我观察到一种非常奇怪的行为,也许你可以帮助我看看会发生什么。

这里的课程:

public sealed class Sudoku
{
    private SudokuCell[] _grid = new SudokuCell[81];

    // ctor {}

    private IEnumerable<SudokuCell> Grid
    {
        get { return _grid; }
    }

    private SudokuRow[] _rows;
    public IEnumerable<SudokuRow> Rows
    {
        get
        {
            if (_rows == null)
            {
                _rows = new SudokuRow[9];

                for (int i = 0, length = 9; i < length; i++)
                {
                    _rows[i] = new SudokuRow(from cell in Grid
                                             where cell.Row == i
                                             select cell);

                    // Always print 9 (GOOD)
                    Trace.WriteLine("First Loop " + i + " : " + _rows[i].Cells.Count());
                }
            }

            for (int i = 0; i < 9; i++)
            {
                // Always print 0 ! Huh !?
                Trace.WriteLine("Second Loop " + i + " : " + _rows[i].Cells.Count());
            }

            return _rows;
        }
    }
}

public abstract class SudokuPart
{
    public SudokuPart(IEnumerable<SudokuCell> cells)
    {
        Cells = cells;
    }

    public int Index
    { get; protected set; }

    public IEnumerable<SudokuCell> Cells
    { get; protected set; }
}

public sealed class SudokuRow : SudokuPart
{
    public SudokuRow(IEnumerable<SudokuCell> cells)
        : base(cells)
    {
        base.Index = cells.First().Row;
    }
}

谁能告诉我为什么在第二个循环中它跟踪0而不是9! 我在两个循环之间都没有改变!

谢谢...

这就是问题:

_rows[i] = new SudokuRow(from cell in Grid
                         where cell.Row == i
                         select cell);

这是捕获循环变量( i )... 循环内,它有一个合理的值,这就是你看到9个匹配的原因。

但是,当您计算第二个循环中的匹配值时,该单个捕获的变量将具有值9.现在没有 cell.Row的值为9,因此您没有获得任何匹配。 有关这方面的更多信息,请参阅Eric Lippert的精彩博文, “关闭循环变量被视为有害”。

三个修复:

  • 捕获循环变量的副本

     int copy = i; _rows[i] = new SudokuRow(from cell in Grid where cell.Row == copy select cell); 

    循环的每次迭代都将获得一个单独的副本。

  • 在循环中实现查询:

     _rows[i] = new SudokuRow((from cell in Grid where cell.Row == i select cell).ToList()); 

    甚至:

     _rows[i] = new SudokuRow(Grid.Where(cell => cell.Row == i).ToList()); 
  • 根本不要使用LINQ! 为什么不只是有一个数组数组来表示网格? 这是一种更自然的方法,IMO。

我认为Jon Skeet的答案很棒,但我只是想通过Deferred LINQ Queries的例子添加一些内容。 一旦我看到这一点,它帮助我更多地了解了你遇到的这种代码问题的一些细微差别。

试试这个代码。

var numbers = new List<int> {1, 2, 3, 4, 5};
//Lets create an IEnumerable<int> with the values in our numbers list greater then 3.
var bignumbers = numbers.Where(n => n > 3);

//You may assume our variable bignumbers now contains the numbers 4 and 5

//now lets add another number to our original list that fits the criteria of our LINQ Where statement   
numbers.Add(6);


foreach (var big in bignumbers) {
  Console.WriteLine(big.ToString());
}

我们foreach循环的输出将是4,5,6! 这是因为我们的查询不会运行,直到foreach导致我们的bignumbers变量中的项的枚举。

当您的建筑物在循环中列出并且您在循环之外查询这些列表时,还需要考虑其他事项。 你经常会得到一些不同于你期望的东西。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM