![](/img/trans.png)
[英]Strange “Collection was modified after the enumerator was instantiated” exception
[英]Strange `Collection was modified` exception though it never gets modified
如果我有一个预定义的集合并且它的值仅通过索引访问和更新,为什么我会得到Collection was modified
异常。 没有线程向集合中删除或添加项目。 异常发生在行var values = new List<double> { amount.Values[0], amount.Values[1] };
System.InvalidOperationException: Collection was modified; enumeration operation may not execute.
at System.ThrowHelper.ThrowInvalidOperationException(ExceptionResource resource)
at System.Collections.Generic.List`1.Enumerator.MoveNextRare()
at System.Collections.Generic.List`1.Enumerator.MoveNext()
at System.Linq.Enumerable.<SkipIterator>d__31`1.MoveNext()
at System.Collections.Generic.List`1.InsertRange(Int32 index, IEnumerable`1 collection)
at MyProject.Exensions.ToFixed(Amount amount) in ...\Amount.cs:line 43 ...
代码
private List<double> _currentAmount = new List<double>(...);
public async Task<Amount> GetAmount(bool fromCache = true)
{
if(!fromCache)
{
_currentAmount = await _service.GetAmount();
}
return new Amount(_currentAmount).ToFixed();
}
// Called every 100ms by other thread
private void OnAmountChanged(AmountChangedEventArgs args)
{
_currentAmount[args.Index] = args.Value;
AmountChanged?.Invoke(new Amount(_currentAmount));
}
public static Amount ToFixed(this Amount amount)
{
var values = new List<double> { amount.Values[0], amount.Values[1] };
values.Add(amount.Values[2] * 0.1);
values.AddRange(amount.Values.Skip(3));
return new Amount(values);
}
public sealed class Amount
{
public ReadOnlyCollection<double> Values { get; }
public Amount(IList<double> values)
{
Values = new ReadOnlyCollection<double>(values);
}
...
}
您正在通过修改列表使迭代器无效。 在评论中,你说:
但是“更改集合”仅表示添加或删除项目时,而不是索引修改值时,不是吗?
但不,这不是它的意思。 从List<T>.GetEnumerator
的文档(强调我的):
只要集合保持不变,枚举器就一直有效。 如果对集合进行了更改,例如添加、修改或删除元素,则枚举器将不可恢复地失效,并且下一次调用
MoveNext
或IEnumerator.Reset
将引发InvalidOperationException
。
这很容易在一个最小的例子中证明:
using System;
using System.Collections.Generic;
using System.Linq;
var list = new List<int> { 0, 1, 2 };
foreach (var element in list)
{
list[1] = 5;
}
这会引发InvalidOperationException
异常,这与您的预期相反。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.