![](/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.