意外的Foreach行为C#

CRK*_*CRK -1 c# xml linq foreach loops

foreach loop当条件是有一个意外的行为true其实都是指令后内if statement,循环中断.我试着评论if语句并且一切正常(将所有元素迭代到ienumerable中).有人能解释我为什么吗?

var allRef = projDefinition
    .Element(msbuild + "Project")
    .Elements(msbuild + "ItemGroup")
    .Elements(msbuild + "COMReference")
    .Where(refElem => find.Any(f => refElem.FirstAttribute.Value.ToLower().Contains(f)))
    .Select(refElem => refElem);


foreach (var xElement in allRef)
{
    var name = xElement.FirstAttribute.Value;
    var dllPath = dllFiles.FirstOrDefault(dll => dll.ToLower().Contains(name.ToLower()));

    if (dllPath != null)
    {
        var dllName = dllPath.Substring(dllPath.LastIndexOf('\\') + 1, dllPath.LastIndexOf('.') - dllPath.LastIndexOf('\\') - 1);
        xElement.Remove();
        XElement elem = new XElement(msbuild + "Reference", new XAttribute("Include", dllName));
        elem.Add(new XElement(msbuild + "HintPath", HintPath.GetHintPath(dllPath)));
        elem.Add(new XElement(msbuild + "EmbedInteropTypes", "False"));
        projDefinition.Root.Elements(msbuild + "ItemGroup").ElementAt(0).Add(elem);
    }

}

projDefinition.Save(fullProjectPath);
Run Code Online (Sandbox Code Playgroud)

Zbi*_*iew 5

你在循环过程中allRef同时从中移除它xElement.Remove,这与循环迭代器混淆.

Basicaly 在引擎盖下foreach创建IEnumerator并使用它从当前元素移动到下一个元素.通过从集合中删除元素同时仍然覆盖它来扰乱它.

它不会导致异常,但是你的循环会导致意外的行为,比如不会遍历所有元素.

您可能想要了解foreach的工作原理

这种问题的简单解决方案是添加.ToList()(正如@Ivan Stoev在评论中指出的那样).它的工作原理是因为它创建了新的列表,所以foreach迭代器被创建到新的列表而不是你的allRef.这意味着您可以安全地从中删除元素allRef.