C# 集合被修改;从 LIstBox 中删除 ListItem 时,枚举可能不会执行错误
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/808006/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Collection was modified; enumeration may not execute error when removing a ListItem from a LIstBox
提问by Xaisoft
I have two ListBoxes, lstAvailableColors and lstSelectedColors. Between each listbox are two buttons, Add and Remove. When a color or colors is selected in lstAvailableColors and the Add button is clicked, I want to remove them from lstAvailableColors and display them in lstSelectedColors. Also, if colors are selected in lstSelectedColors and the Remove button is clicked, I want to remove the colors from lstSelectedColors and add them back to lstAvailableColors. When I do this, I get the following error when it removes the item:
我有两个列表框,lstAvailableColors 和 lstSelectedColors。每个列表框之间有两个按钮,添加和删除。当在 lstAvailableColors 中选择一种或多种颜色并单击“添加”按钮时,我想从 lstAvailableColors 中删除它们并在 lstSelectedColors 中显示它们。此外,如果在 lstSelectedColors 中选择了颜色并单击了删除按钮,我想从 lstSelectedColors 中删除颜色并将它们添加回 lstAvailableColors。执行此操作时,删除项目时出现以下错误:
Collection was modified; enumeration operation may not execute.
集合被修改;枚举操作可能无法执行。
Here is the code for the Add Button and the Remove Button:
这是添加按钮和删除按钮的代码:
Add:
添加:
protected void btnAdd_Click(object sender, EventArgs e)
{
foreach (ListItem item in lstAvailableColors.Items)
{
if (item.Selected)
{
lstSelectedColors.Items.Add(item);
lstAvailableColors.Items.Remove(item);
}
}
}
Remove:
消除:
protected void btnRemove_Click(object sender, EventArgs e)
{
foreach (ListItem item in lstSelectedColors.Items)
{
if (item.Selected)
{
lstAvailableColors.Items.Add(item);
lstSelectedColors.Items.Remove(item);
}
}
}
采纳答案by JaredPar
It's not possible to modify a collection while you're enumerating it in .Net. You need to separate out your enumeration and remove code into different blocks. Here is a quick sample on how to do that in without LINQ
在 .Net 中枚举集合时无法修改集合。您需要分离您的枚举并将代码删除到不同的块中。这是一个关于如何在没有 LINQ 的情况下执行此操作的快速示例
protected void btnAdd_Click(object sender, EventArgs e)
{
var selected = new List<ListItem>();
foreach (ListItem item in lstAvailableColors.Items)
{
if (item.Selected)
{
selected.Add(item);
lstSelectedColors.Items.Add(item);
}
}
foreach (ListItem item in selected)
{
lstAvailableColors.Items.Remove(item);
}
}
And here's a more concise version using LINQ
这是一个使用 LINQ 的更简洁的版本
var selected = lstAvailableColors.Cast<ListItem>().Where(i => i.Selected).ToList();
selected.ForEach( x => { lstSelectedColors.Items.Add(x); });
selected.ForEach( x => { lstAvailableColors.Items.Remove(x);});
EDIT
编辑
The LINQ version works in two parts. The first part is the first line which finds the currently selected items and stores the value in a List<ListItem>
. It's very important that the line contain the .ToList() call because that forces the query to execute immediately vs. being delayed executed.
LINQ 版本分为两部分。第一部分是第一行,它查找当前选定的项目并将值存储在 a 中List<ListItem>
。该行包含 .ToList() 调用非常重要,因为这会强制查询立即执行而不是延迟执行。
The next two lines iterate through each value which is selected and remove or add it to the appropriate list. Because the selected list is already stored we are no longer enumerating the collection when we modify it.
接下来的两行遍历每个选定的值并将其删除或添加到适当的列表中。因为选定的列表已经存储,所以我们在修改它时不再枚举该集合。
回答by Shea
You can't modify a collection while you're iterating over it. Either iterate over a copy or use for, iterate in reverse and remove as you go down.
迭代时不能修改集合。迭代一个副本或用于,反向迭代并在您向下时删除。
回答by Daniel Brückner
You cannot modify an collection while you are using an Enumerator for this collection, what the for each statement does.
当您为此集合使用枚举器时,您不能修改集合,for each 语句的作用是什么。
You have to loop over the data with a normal for loop and then you can modify the collection, but you must be careful to correctly update the current index if you insert or remove elements. If you just add or remove elements and don't insert some, iterating from the last element to the first will do.
您必须使用普通的 for 循环遍历数据,然后才能修改集合,但是如果插入或删除元素,则必须小心正确更新当前索引。如果您只是添加或删除元素而不插入一些元素,则从最后一个元素迭代到第一个元素即可。
protected void btnAdd_Click(object sender, EventArgs e)
{
for (Int32 i = lstAvailableColors.Items.Count; i >= 0; i--)
{
ListItem item = lstAvailableColors.Items[i];
if (item.Selected)
{
lstSelectedColors.Items.Add(item);
lstAvailableColors.Items.Remove(item);
}
}
}
回答by mqp
As the other answer mentioned, you can't remove items until you've completed the iteration. So perhaps something like this will be cleanest for you:
正如另一个答案所提到的,在完成迭代之前,您无法删除项目。所以也许这样的事情对你来说是最干净的:
var itemsToRemove =
lstAvailableColors.Items.Cast<ListItem>().Where(i => i.IsSelected).ToArray();
foreach(ListItem item in itemsToRemove) lstAvailableColors.Remove(item);
回答by Paul Sonier
You cannot modify a collection you are iterating on. In general, a good solution for this type of problem is to create an empty collection, and in your iterator, copy over all of the elements you do NOT want to remove; after the iteration is complete, replace the original collection with your new collection.
您不能修改正在迭代的集合。通常,解决此类问题的一个好方法是创建一个空集合,并在您的迭代器中复制您不想删除的所有元素;迭代完成后,用您的新集合替换原始集合。
回答by dhinesh
Example on how to remove the selected Items. Here only the selected indices are taken and removed.
关于如何删除所选项目的示例。这里只取和删除选定的索引。
public void RemoveSelectedItems(ListBox listbox)
{
List<ListItem> items = GetSelectedItems(listbox);
foreach (var listItem in items)
{
listbox.Items.Remove(listItem);
}
}
public List<ListItem> GetSelectedItems(ListBox listbox)
{
int[] selectedIndices = listbox.GetSelectedIndices();
return selectedIndices.Select(index => listbox.Items[index]).ToList();
}
回答by Naveen
Maybe this is what you need
也许这就是你所需要的
protected void btnAdd_Click(object sender, EventArgs e)
{
while(listBox1.SelectedIndex!=-1)
{
listBox1.Items.Remove(listBox1.SelectedItem);
}
}
回答by Ali
This might help you;
这可能对你有帮助;
To Remove:
去除:
protected void btnRemove_Click(object sender, EventArgs e)
{
{
for (int i = 0; i < lstAvailableColors.Items.Count; i++)
{
if(lstAvailableColors.Items[i].Selected)
lstAvailableColors.Items.RemoveAt(i);
}
}
}
回答by Luc
The problem you face is that you can't modify the collection you itterate thru. You could solve this by using a single linq:
您面临的问题是您无法修改您遍历的集合。您可以通过使用单个 linq 来解决此问题:
protected void btnAdd_Click(object sender, EventArgs e)
{
lstAvailableColors.Items.RemoveAll(ac => ac.Selected);
}