Помогите с преобразованием цикла foreach в цикл while в c # - PullRequest
1 голос
/ 24 марта 2010

Изучив ваши замечательные ответы, я узнал, что удаление элементов из цикла foreach не является хорошей практикой, так как это (и я цитирую) "Обрезка ветви, на которой вы сидите".

Мой код в настоящее время удаляет текст из выпадающего списка, но фактический элемент остается (только текст не отображается).

Другими словами, он не удаляется, и, вероятно, не может, потому что вы не можете удалить из цикла foreach.

После нескольких часов попыток я не могу понять, как это сделать.

//For each checked box, run the delete code
for (int i = 0; i < this.organizeFav.CheckedItems.Count; i++)
{
    //this is the foreach loop
    foreach (ToolStripItem mItem in favoritesToolStripMenuItem.DropDownItems)
    {
        //This rules out seperators
        if (mItem is ToolStripMenuItem)
        {
            ToolStripMenuItem menuItem = mItem as ToolStripMenuItem;

            //This matches the dropdownitems text to the CheckedItems String
            if (((ToolStripMenuItem)mItem).Text.ToString() == organizeFav.CheckedItems[i].ToString())
            {
                //And deletes the item
                menuItem.DropDownItems.Remove(mItem);
            }
        }
    }
}

Но оно не удаляется, потому что оно внутри цикла foreach! Я был бы очень признателен за вашу помощь и был бы по-настоящему удивлен, если бы кто-нибудь смог разобраться с этим кодом:)

С уважением

Ответы [ 5 ]

5 голосов
/ 24 марта 2010

Веселье с LINQ!

// Loop through the checked items, same as you did.
foreach (var checkedItem in this.organizeFav.CheckedItems)
{
    // Cast from IEnumerable to IEnumerable<T> so we can abuse LINQ
    var matches = favoritesToolStripMenuItem.DropDownItems.Cast<ToolStripItem>()
                  // Only items that the Text match
                  .Where(item => item.Text == checkedItem.Text)
                  // Don't match separators
                  .Where(item => item is ToolStripMenuItem)
                  // Select the keys for the later .Remove call
                  .Select(item => item.Name);

    // Loop through all matches        
    foreach (var key in matches)
    {
        // Remove them with the Remove(string key) overload.
        favoritesToolStripMenuItem.Remove(key);
    }
}
3 голосов
/ 24 марта 2010

Вам не нужен цикл foreach - просто используйте обычный цикл, но идите наоборот, начинайте с конца и переходите к началу.

//For each checked box, run the delete code
for (int i = 0; i < this.organizeFav.CheckedItems.Count; i++)
{
    //this *replaces* the foreach loop
    for(int j = favoritesToolStripMenuItem.DropDownItems.Count - 1; j >= 0; j--)
    {
        ToolStripMenuItem menuItem = favoritesToolStripMenuItem.DropDownItems[j] as ToolStripMenuItem; 

        //This rules out seperators
        if (menuItem != null)
        {
            //This matches the dropdownitems text to the CheckedItems String
            if (menuItem.Text.ToString() == organizeFav.CheckedItems[i].ToString())
            {
                favoritesToolStripMenuItem.DropDownItems.Remove(menuItem);
            }
        }
    }
 }

это был реорганизованный код @ Kurresmack, я просто закодировал его прямо здесь, на странице, так что извините за любую небольшую синтаксическую ошибку или что-либо очевидное, что я упустил (отказ от ответственности: это образец !!)

Вы все еще можете рассматривать favoritesToolStripMenuItem.DropDownItems как коллекцию, как и вы, но вам не нужно перечислять ее, используя foreach. Это сокращает несколько строк кода и работает, потому что вы выполняете его в обратном порядке, вы не получите индекс за исключением исключительной ситуации.

0 голосов
/ 24 марта 2010

Вместо foreach используйте обратную for -Coop:

for(int reverseIndex = myList.Count - 1; reverseIndex >= 0; reverseIndex--)
{
    var currentItem = myList[reverseIndex];
    if(MatchMyCondition(currentItem))
    {
        myList.Remove(currentItem);
    }
}
0 голосов
/ 24 марта 2010

На мой взгляд, способ заставить код работать:
1. Создайте экземпляр типа, * * * * * * * * * * * * * * * * * * *.Вы не хотите быть удалены в эту коллекцию.
3. Сделайте favoritesToolStripMenuItem.DropDownItems, чтобы указать новую коллекцию.Или очистите favoritesToolStripMenuItem.DropDownItems и загрузите в него предметы из новой коллекции.

Надеюсь, это поможет

0 голосов
/ 24 марта 2010

Попробуйте что-то вроде этого:

//For each checked box, run the delete code
for (int i = 0; i < this.organizeFav.CheckedItems.Count; i++)
        {
    List<ToolStripItem> toRemove = new List<ToolStripItem>();
//this is the foreach loop
            foreach (ToolStripItem mItem in favoritesToolStripMenuItem.DropDownItems)
            {

                //This rules out seperators
                if (mItem is ToolStripMenuItem)
                {
                    ToolStripMenuItem menuItem = mItem as ToolStripMenuItem;

             //This matches the dropdownitems text to the CheckedItems String
                    if (((ToolStripMenuItem)mItem).Text.ToString() == organizeFav.CheckedItems[i].ToString())
                    {
                        toRemove.Add(mItem);
                    }
                }
            }
        foreach(var item in toRemove)
        {
        favoritesToolStripMenuItem.DropDownItems.Remove(item);
        }
        }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...