我想要删除集合中的所有元素,因为我没有看到.RemoveAll
或者之后我使用了下面的代码。
int number = addressBook.Items.Count;
System.Collections.IEnumerator enumerator = ...
while (enumerator.MoveNext())
{
target = enumerator.Current as Outlook.ContactItem;
target.Delete();
}
但是,我注意到集合中剩余元素的数量大约是每次运行程序的一半。我的结论是.Delete()
单独跳到下一个元素,这意味着.MoveNext()
循环的条件会在之后跳转到元素。
所以我尝试按如下方式重置枚举器。
int number = addressBook.Items.Count;
System.Collections.IEnumerator enumerator = ...
while (enumerator.MoveNext())
{
target = enumerator.Current as Outlook.ContactItem;
target.Delete();
enumerator.Reset();
}
但是,当我检查.Count
时,我看到在删除最后一个元素并重置枚举数之后剩余的元素数仍为1。当然,我的脸上有一个例外。
这张照片中我错过了什么?我知道这不是一个错误,因为 会在很久以前报告和解决...
答案 0 :(得分:3)
只要基础集合保持不变,IEnumerator只能用于。一旦它发生变化(例如通过从中删除元素),枚举器就会无法恢复。
在修改集合时,您无法使用一个枚举器来浏览集合,而重置不会对此有所帮助。您只需每次都创建一个新的枚举器。例如。类似的东西可能有用:
while (addressBook.Items.Count > 0)
{
foreach(Outlook.ContactItem target in ...)
{
target.Delete();
break; // <-- !
}
}
答案 1 :(得分:1)
重置是多余的;以至于它是一个必需品 迭代器块的语言规范在重置时抛出异常。该 正确的做法是简单地处理并释放旧的迭代器, 并再次调用GetEnumerator。或者更好:避免阅读它 两次,因为并非所有数据都是可重复的。
请参阅以下链接:
Can't add/remove items from a collection while foreach is iterating over it
When IEnumerator.Reset() method is called?
using IEnumerator to removing items
希望这有帮助..
答案 2 :(得分:1)
两件事。
只要在删除每个项目后重新实例化,您就应该能够删除枚举器中的所有项目。使用LINQ,它应该如下所示:
while (addressBook.Items.Count > 0)
{
addressBook.Items
.OfType<Outlook.ContactItem>()
.Last()
.Delete();
}
根据MSDN,您实际上必须删除从最后一个开始的项目:http://msdn.microsoft.com/en-us/library/microsoft.office.interop.outlook._contactitem.delete.aspx
答案 3 :(得分:1)
我希望使用Enumerable.Reverse扩展程序可以改进while...Last().Delete()
解决方案。这可能是这样的:
foreach(var target in addressBook.Items
.OfType<Outlook.ContactItem>()
.Reverse())
{
target.Delete();
}
我经常不使用Reverse
;事实上,我不记得曾经在生产代码中使用它,但我也没有必要与Outlook互操作。这样做的好处是,在每个项目删除后,您不会像while...Last().Delete()
方法那样重复遍历整个列表余数。当项目列表很小时,可能没有太多(任何?)性能上的差异,但是如果遍历是昂贵的(并且我想这是因为这可能归结为COM iterop在引擎盖下调用)或者如果列表是大,那么性能差异可能很大。唯一可以确定的方法是测试/配置文件。