Это интересная ошибка, с которой я столкнулся при реализации IEnumerable в классе.Похоже, что это похоже на проблему «доступа к измененному закрытию», но я не знаю, как ее исправить.
Вот простой пример, демонстрирующий проблему:
void Main()
{
var nodeCollection = new NodeCollection();
nodeCollection.MyItems = new List<string>() { "a", "b", "c" };
foreach (var node in nodeCollection)
{
node.Dump();
}
}
public class NodeCollection : IEnumerable<Node>
{
public List<string> MyItems;
public IEnumerator<Node> GetEnumerator()
{
// This isn't necessary, but it should prove that it's not an "access to modified closure" issue.
var items = MyItems;
for (var i = 0; i < 3; i++)
{
var node = new Node();
// I want the node to contains the items in MyItems.
node.Items = items;
// Plus an additional item. Note that I am adding the item to the node, NOT to MyItems.
node.Items.Add(string.Format("iteration: {0}", i));
yield return node;
}
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
public class Node
{
public List<string> Items;
}
Как вы можете видеть из оператора Dump()
, я запускаю это в LINQPad, но проблема возникает в любой IDE.
Когда я запускаю сниппет, я получаю следующий вывод:
Поскольку я добавляю элемент в Items
во вновь созданном Node
, я НЕ ожидаю, что элемент будет добавлен в MyItems
, но этоочевидно, что происходит.
Кажется, что Items
в Node
указывает на MyItems
в NodeCollection
.
Может кто-нибудь сказать мне:
- Почему этопроисходит?
- Как сделать так, чтобы этого не произошло?