1

我想删除集合中的所有元素,因为我没有看到.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。当然,我遇到了一个例外。

我在这张照片中缺少什么?我知道这不是一个错误,因为会在很久以前被报告和解决......

4

4 回答 4

3

IEnumerator 只能在基础集合保持不变的情况下使用。一旦它发生变化(例如通过从中删除元素),枚举器就会不可恢复地失效。

您只是不能在修改集合时使用一个枚举器来浏览集合,而 Reset 也无济于事。您只需要每次都创建一个新的枚举器。例如,类似的东西可能会起作用:

while (addressBook.Items.Count > 0)
{
    foreach(Outlook.ContactItem target in ...)
    {
        target.Delete();
        break; // <-- !
    }
}
于 2012-09-07T12:53:15.860 回答
1

请参阅Marc Gravell 的回答

复位是多余的;以至于在语言规范中要求迭代器块在重置时抛出异常。正确的做法是简单地处理和释放旧的迭代器,然后再次调用 GetEnumerator。或者更好:避免阅读两次,因为并非所有数据都是可重复的。

请参考以下链接:

当调用 IEnumerator.Reset() 方法时,当foreach 对其进行迭代时,无法从集合中添加/删除项目?

使用 IEnumerator 删除项目

希望这有帮助..

于 2012-09-07T12:52:07.437 回答
1

两件事情。

  1. 只要在删除每个项目后重新实例化它,您就应该能够使用枚举器删除所有项目。使用 LINQ,它应该如下所示:

    while (addressBook.Items.Count > 0)
    {
        addressBook.Items
            .OfType<Outlook.ContactItem>()
            .Last()
            .Delete();
    }
    
  2. 根据 MSDN,您实际上必须删除从最后一项开始的项目:http : //msdn.microsoft.com/en-us/library/microsoft.office.interop.outlook._contactitem.delete.aspx

于 2012-09-07T13:20:43.537 回答
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 调用)或者如果列表是大,那么性能差异可能很大。唯一确定的方法是测试/配置文件。

于 2012-09-08T17:29:31.060 回答