Orcun Iyigun Ответов: 3

Список элементов изменился. Операция перечисления не удалось продолжить.


Привет,

Я пытаюсь удалить дочерние узлы узла. Во время выполнения цикла foreach у меня возникает ошибка- "список элементов изменился. Операция перечисления не удалось продолжить." Я думаю, что из-за того, что я изменяю XMLfile, у меня есть эта ошибка, но я не знаю, как ее исправить. Может ли кто - нибудь исправить мой код?

XmlDocument xmlDocument = new XmlDocument();
           xmlDocument.Load(@"C:\Users\Orcun Iyigun\Desktop\Projects\Rules.xml");

           XmlNodeList ratingNodes = xmlDocument.GetElementsByTagName("Rule/Rating");
           XmlNodeList mailtoNodes = xmlDocument.GetElementsByTagName("Rule/Mailto");
           XmlNodeList ruleNodes = xmlDocument.GetElementsByTagName("Rule");
           
           foreach (ListViewItem item in lvRules.Items)
           {
               if (item.Selected)
               {
                   string ratingVal = item.SubItems[0].Text;
                   string mailtoVal = item.SubItems[1].Text;
                   string ratmailNode = ratingVal + mailtoVal;


                   foreach (XmlNode deleteXMLnode in ruleNodes)
                   {
                       if (deleteXMLnode.InnerText == ratmailNode)
                       {
                           deleteXMLnode.ParentNode.RemoveChild(deleteXMLnode);
                       }
                   }
                   lvRules.Items.Remove(item);
               }
           }
           xmlDocument.Save(@"C:\Users\Orcun Iyigun\Desktop\Projects\Rules.xml");

3 Ответов

Рейтинг:
28

Nish Nishant

Вы можете конвертировать foreach в for петля, но даже тогда каждый раз, когда вы звоните RemoveChild, вы должны настроить переменную цикла, если вы используете условие кэшированной длины для выхода из цикла. for петля.

На самом деле, даже если вы не кэшируете for-условие, вам все еще нужно настроить переменную цикла. Пример см. В приведенном ниже фрагменте кода:

var list = new int[] { 1, 2, 3, 4, 8, 6, 7, 5 }.ToList();
for (int i = 0; i < list.Count; i++)
{
    if (list[i] % 2 == 0)
        list.RemoveAt(i--); // <-- see what I did here!
}

foreach (var item in list)
{
    Console.WriteLine(item);
}


Hiren solanki

Хорошее Объяснение, Ниш.

Orcun Iyigun

спасибо, я попробую и посмотрю, сработает ли это.

Рейтинг:
1

Rod Kemp

Ваша проблема заключается в том, что вы получаете ListViewItemCollection в самом начале игры foreach петля.
Вам нужно получить ListViewItemsCollection перед началом цикла.

ListView.ListViewItemCollection lvIC = lvRules.Items;
foreach (ListViewItem item in lvIC)
{
    .
    .
    .
    lvRules.Items.Remove(item);
}

Вот почему при циклическом просмотре коллекций элементов вы не делаете вызов, чтобы получить коллекцию частью цикла.

Для второго foreach цикл вам нужно изменить способ использования узлов правил SelectNodes с помощью запроса XPath вместо этого типа;
XmlNodeList ruleNodes = xmlDocument.SelectNodes("doc/Rule");


Orcun Iyigun

Тем не менее, у меня есть та же ошибка во внутреннем(втором) цикле foreach. Я изменил первый цикл foreach, как вы сказали, но он не работает.

hatelove420

у меня такая же проблема может ли кто-нибудь ясно объяснить вышеприведенную проблему

Рейтинг:
1

hilvarenbeek

Изменение выбора с GetElementsByTagName на SelectNodes сработало для меня. По-видимому, метод GetElementsByTagName изменяет результат IEnumerable во время цикла (если вы отладите, то увидите, что количество элементов уменьшается), но результат SelectNodes остается прежним.

private XmlDocument RemoveDrawingNodes(XmlDocument xmlDocument)
{
    var drawingNodes = xmlDocument.SelectNodes("//w:drawing", XmlNamespaceManager);

    foreach (XmlElement element in drawingNodes)
    {
        element.ParentNode.RemoveChild(element);
    }
    return xmlDocument;
}