[英]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.