到目前已知的:
- foreach是通过枚举器实现遍历的语法糖实现
- foreach遍历不能修改元素或者增删元素
无法修改元素
表面上来说是因为current设置为只读
1 | public interface IEnumerator<out T> : IDisposable, IEnumerator |
但就算设为set,也没用。
对于引用类型,current是当前遍历元素的深拷贝复制品,
对于值类型,current只是栈上另起的一块位置,有着相同值罢了
如Dictionary内的引用类型current返回
1
2
3
4
5
6
7
8
9
10 while ((uint)_index < (uint)_dictionary._count)
{
ref Entry entry = ref _dictionary._entries![_index++];
if (entry.next >= -1)
{
_current = new KeyValuePair<TKey, TValue>(entry.key, entry.value);
return true;
}
}
无法增删元素
代码上来说
在容器类中都有一个字段,名为
_version,其作用是:维持枚举器的一致性。在容器进行增删改的时候,它都会自增一,在迭代器结构中保存了调用时的version,每次MoveNext时都会判断是否相同则报错
ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumFailedVersion()从数据结构来说
如果增删元素,容器结构就会被改变,就可能对遍历结果造成或多或少的影响,这个要根据情况具体分析。
例如链表linkedlist 在当前遍历节点之前增删就有影响,在其之后就无影响。