技术内部:为什么这个迭代找不到我的项目

时间:2011-03-11 08:32:09

标签: c# lambda

嘿,人们 昨天我正在研究一些代码,并认为我会保存一个foreach迭代并使用List<>上的find扩展名。对象,但我从来没有得到它的工作。后来我重构了代码,使用foreach和lamda where语句,并发现我的项目evrytime。

我的2个版本的代码发布在下面:

不能正常使用版本:

private XmlCell FindCell(string id)
    {
        XmlSection section = new XmlSection(SectionNode);
        XmlCell currentCell = null;

        foreach (XmlBlock block in section.Blocks)
        {
            foreach (XmlRow row in block.Rows)
            {
                currentCell = row.Cells.Find(cell => string.Equals(cell.Id, id));
            }
        }

        Assert.IsNotNull(currentCell, string.Format("Cell with id {0} not found", id));
        return currentCell;
    }

工作版:

XmlSection section = new XmlSection(SectionNode);
XmlCell currentCell = null;

foreach (XmlBlock block in section.Blocks)
{
    foreach (XmlRow row in block.Rows)
    {
        foreach (XmlCell cell in row.Cells.Where(cell => string.Equals(cell.Id, id)))
        {
            return cell;
        }
    }
}

Assert.IsNotNull(currentCell, string.Format("Cell with id {0} not found", id));
return currentCell;

有人可以解释为什么第一部分代码没有完成工作,msdn说find方法返回它在列表中找到的第一个实例。

我甚至遇到过一些“集合被修改;枚举操作可能无法执行”的错误,为什么?

3 个答案:

答案 0 :(得分:2)

因为当currentCell找不到具有匹配ID的单元格时,下一次迭代会再次使变量Find为空。在第二段代码中,您将立即返回找到的单元格。

在第一段代码中试试这个:

foreach (XmlRow row in block.Rows)
{
 currentCell = row.Cells.Find(cell => string.Equals(cell.Id, id));
 //new
 if (currentCell != null)
  return currentCell;
 //end new
}

答案 1 :(得分:1)

当您找到具有指定ID的单元格时,currentCell将设置为此特定对象。但是,在foreach循环的下一次迭代中,currentCell设置为空,因为Find不返回任何内容:)

 foreach (XmlRow row in block.Rows)
  {
     currentCell = row.Cells.Find(cell => string.Equals(cell.Id, id));
  }

答案 2 :(得分:0)

代码的两个版本是不同的 - 第二个版本在找到匹配的单元格后立即从所有嵌套循环返回,而第一个代码返回最后一个块的最后一行中单元格的存在。

修复 - 添加检查以在内循环中找到单元格并在找到后立即重新启动:

foreach (XmlBlock block in section.Blocks)        
{  
    foreach (XmlRow row in block.Rows)             
    {                 
         currentCell = row.Cells.FirstOrDefault(cell => string.Equals(cell.Id, id));             
         if (currentCell != null) 
           return currentCell;

    }
}