我的windows phone 7 silverlight应用程序在将图钉放在地图图层上之前会移除之前存在的任何内容。
我在foreach循环中这样做如下:
//Clear previous pins
try
{
foreach (UIElement p in PushPinLayer.Children)
{
if(p.GetType() == typeof(Pushpin))
{
PushPinLayer.Children.Remove(p);
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
//TODO: For some reason the foreach loop above causes an invalid Operation exception.
//Cathing the error here until I can work out why it is happening.
}
此代码根据需要删除任何图钉但在最后一个循环之后会抛出异常“无效操作”我将其重新编写为for循环:
for (int i = 0; i < PushPinLayer.Children.Count; i++)
{
if (PushPinLayer.Children[i].GetType() == typeof(Pushpin))
{
PushPinLayer.Children.RemoveAt(i);
}
}
哪个工作正常,但我不明白为什么foreach会抛出错误。
答案 0 :(得分:7)
这很正常,
您无法从列表中删除仍在foreach列表中使用的项目。 然后删除该项将更好地创建一个新列表,并且每次它不是图钉类型时,将该对象添加到新列表。
这样原始列表不会改变,你也不会得到例外。
我觉得for循环有效,但如果确实如此,那就意味着它们的迭代方式不同了。 for循环将被复制到另一个内存位置并用于for循环,以便for循环中不再使用原始的for循环。 foreach循环将从列表中获取参数,您删除项目,因此列表和参数变为并发。
答案 1 :(得分:3)
您的foreach
循环使用和Enumerator
来迭代集合中的对象。从集合中删除对象时,Enumerator
不再有效,因为它引用了不再存在的对象。这会导致InvalidOperationException
删除它们的最佳方法是使用for
循环,甚至更好地反向执行。
for (int i = PushPinLayer.Children.Count - 1; i >= 0 ; i--)
{
if (PushPinLayer.Children[i].GetType() == typeof(Pushpin))
{
PushPinLayer.Children.RemoveAt(i);
}
}
这样可以确保在删除商品时,Index
i
不会超过您收藏中的商品数量。
答案 2 :(得分:2)
更改集合的内容时,foreach循环中使用的枚举器将变为无效。枚举时无法更改集合。
这是一种解决方法:
List<UIElement> toRemove = new List<UIElement>();
foreach (UIElement p in PushPinLayer.Children)
{
if(p.GetType() == typeof(Pushpin))
{
toRemove.Add(p);
}
}
foreach(UIElement p in toRemove)
{
PushPinLayer.Children.Remove(p);
}
或者,您可以使用RemoveAll方法,该方法将谓词作为参数:
PushPinLayer.Children.RemoveAll(p => p is Pushpin);
答案 3 :(得分:2)
其他人已经告诉你这个问题的原因所以我只是想发布一个LINQ版本的工作
var toRemove = PushPinLayer.Children.OfType<Pushpin>().ToList();
// since toRemove is a separate collection, it's safe to do this now:
foreach (var child in toRemove)
PushPinLayer.Children.Remove(child)
答案 4 :(得分:2)
由于其他人已经回答了您的问题,我只会评论您对xxx.GetType() == typeof(Pushpin)
的使用情况。您只需使用C#保留关键字 即可检查某些内容是否为图钉。 e.g:
if (p is Pushpin) {...}
答案 5 :(得分:1)
在进行预习时,不得更改集合。