开发者

Technical inside : why does this iteration not find my item

Hey people yesterday i was working on some code and thought that i would save a foreach iteration and use the find extension on the List<> object, but i never got it to work. later i refactored the the code to use a foreach with a lamda where statement and that found my item evrytime.

my 2 versions of code are posted below:

Not working version:

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;
    }

working version :

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;

could someone plx explain why the first bit of code dont get the job done, msdn says that the find method returns the开发者_开发问答 first instance it finds in the list.

i even encountered some "Collection was modified; enumeration operation may not execute" errors, why ?


Because the next iteration will make your variable currentCell null again when Find didn't find the cell with the matching ID. In the second piece of code you return the found cell immediately.

In the first piece of code try this:

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


When you find your cell with the specified ID, the currentCell is set to this specific object. However, on the next iteration in the foreach loop, currentCell is set to nothing, because Find returns nothing :)

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


The 2 versions of code are different - second one returns from all nested loops as soon as it finds a matching cell, while first one returns presence of the cell in the last row of the last block.

Fix - add check for finding the cell in inner loop and retrun as soon one found:

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;

    }
} 
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜