【问题标题】:I don't think I'm modifying this collection我不认为我在修改这个集合
【发布时间】:2012-02-22 16:44:48
【问题描述】:

代码:

    List<Item> Contents = ObjectHandler.player.Contents.ToList<Item>() //Was HashTable
    List<int> IDS = new List<int>(); //Holds Item IDs for later counting
    foreach (Item I in Contents) 
    {
        IDS.Add(I.ID); // Add ID to IDS
    }
    List<Item> newContents = Contents;
    foreach (Item I in Contents)
    {
        if (IDS.Contains(I.ID)) //Check if the ID has already been used in Contents
        {
            newContents.Remove(I); //Remove it
        }
    }
    Contents = newContents;

此代码 sn-p 应准备一个 ID 列表以供以后计数,并从项目列表中删除重复项。但是,一旦 Contents 中出现项目,我就会收到 InvalidOperationException。我相当确定我没有修改 foreach 正在循环的内容,因此我很困惑。有人可以向我解释一下吗?谢谢。

【问题讨论】:

  • 顺便说一句,这将删除所有项,而不仅仅是重复项。

标签: c# list object collections


【解决方案1】:

虽然@SLaks 指出了复制列表并避免两个对象指向同一个地方的好方法,但首先不需要两个列表。

如果您使用传统的 for 循环(而不是 foreach)并向后计数,则可以从原始列表中删除项目而不会产生任何抱怨。

以下内容应该可行:

for (int i = Contents.Count - 1; i >= 0; i--)
{
    if (IDS.Contains(Contents[i].ID)) //Check if the ID has already been used in Contents
    {
        Contents.RemoveAt(i);
    }
}

【讨论】:

  • 顺便说一句,任何人都可以指出在回复中引用其他人的最佳方式吗?我没有看到任何像块引用或类似的按钮可以做到这一点。
【解决方案2】:
var Contents = ObjectHandler.player.Contents.ToList<Item>();
var IDs = new HashSet<int>();
var filtered = Contents.Where( i =>
  {
      bool result = !IDs.Contains(i.ID);
      IDs.Add(i.ID);
      return result;
  }).ToList();

【讨论】:

    【解决方案3】:
    newContents = Contents;
    

    您现在有两个变量指向同一个集合。

    你可能想通过写new List&lt;Item&gt;(Contents)来复制集合。

    【讨论】:

    • 我明白了,这很有道理,谢谢。
    猜你喜欢
    • 1970-01-01
    • 2013-02-20
    • 1970-01-01
    • 2020-10-04
    • 2019-12-17
    • 1970-01-01
    • 2022-01-01
    • 2023-03-24
    • 1970-01-01
    相关资源
    最近更新 更多