gpt4 book ai didi

c# - 在 foreach 循环中修改集合时出现异常

转载 作者:行者123 更新时间:2023-11-30 22:07:45 25 4
gpt4 key购买 nike

我知道在 foreach 中不修改集合的基本原则,这就是我这样做的原因:

    public void UpdateCoverages(Dictionary<PlayerID, double> coverages)
{
// TODO: temp
var keys = coverages.Select(pair => pair.Key);
foreach (var key in keys)
{
coverages[key] = 0.84;
}
}

和:

class PlayerID : IEquatable<PlayerID>
{
public PlayerID(byte value)
{
Value = value;
}

public byte Value { get; private set; }

public bool Equals(PlayerID other)
{
return Value == other.Value;
}
}

首先,我保存了所有 key ,以免发生 Collection modified 异常,然后我检查它。但是我仍然得到我无法理解的异常。

如何解决这个问题以及导致问题的原因是什么?

最佳答案

First I save all my keys

不,你不知道; keys 是一个实时序列,它在被 foreach 迭代时主动迭代集合。要创建 key 的独立副本,您需要将 .ToList() (或类似的)添加到末尾:

var keys = coverages.Select(pair => pair.Key).ToList();

虽然我个人可能会选择:

var keys = new PlayerID[coverages.Count];
coverages.Keys.CopyTo(keys, 0);

(允许正确的长度分配和内存复制)


What is a live sequence actually?

Select 方法在另一个之上创建非缓冲假脱机迭代器...这是一个真的理解起来很复杂的事情,但基本上:当你第一次开始迭代时 var key in keys,它获取 coveragesinner 序列(又名 coverages.GetEnumerator()),然后每个foreach 请求下一个项目时, 请求下一个项目。是的,这听起来很复杂。好消息是 C# 编译器自动内置了这一切,并为您生成状态机等。所有主要使用 yield return 语法完成。 Jon Skeet 在 C# in Depth 的第 6 章中对此进行了精彩的讨论。 IIRC 这曾经是“免费章节”,但现在不是了。

但是,请考虑以下几点:

static IEnumerable<int> OneTwoOneTwoForever()
{
while(true) {
yield return 1;
yield return 2;
}
}

您可能会惊讶地发现您可以使用上述内容,使用相同的非缓冲“当您请求另一个值时,它会运行足够的代码来为您提供下一个值”方法:

var firstTwenty = OneTwoOneTwoForever().Take(20).ToList(); // works!

关于c# - 在 foreach 循环中修改集合时出现异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22771670/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com