为什么foreach循环在C#中只读

为什么foreach循环只读? 我的意思是你可以获取数据,但不能增加++或减少 – 。 它背后有什么原因吗? 是的我是初学者:)

〔实施例:

int[] myArray={1,2,3}; foreach (int num in myArray) { num+=1; } 

这是因为foreach意味着迭代一个容器,确保每个项目只访问一次,而不更改容器,以避免令人讨厌的副作用。

请参阅: MSDN中的foreach

如果你的意思是为什么像整数这样的元素的更改不会影响整数的容器,那么这是因为在这种情况下迭代的变量将是一个值类型并被复制,例如:

 // Warning: Does not compile foreach (int i in ints) { ++i; // Would not change the int in ints } 

即使迭代变量是一个引用类型,其操作返回一个新对象,你也不会改变原始集合,你只需要在大多数时间重新分配给这个变量:

 // Warning: Does not compile foreach (MyClass ob in objs) { ob=ob+ob; // Reassigning to local ob, not changing the one from the original // collection of objs } 

以下示例可能通过调用mutating方法实际修改原始集合中的对象:

 // Warning: Does not compile foreach (MyClass ob in objs) { ob.ChangeMe(); // This could modify the object in the original collection } 

为了避免在值与引用类型和上述场景(以及与优化相关的一些原因)方面的混淆,MS选择只readonly迭代变量。

因为当前元素是按值返回的(即复制)。 修改副本是没用的。 如果它是引用类型,则可以修改该对象的内容,但不能替换引用。

也许您应该阅读IEnumerableIEnumerator的文档。 这应该更清楚。 最重要的一点是IEnumerable具有类型为T的属性Current 。 而这个属性只有一个吸气剂,但没有二传手。

但如果它有一个二传手会怎么样?

  • 它适用于数组和列表
  • 它不适用于复杂的容器,如哈希表,有序列表,因为更改会导致容器中的更大更改(例如重新排序),从而使迭代器无效。 (如果迭代器被修改以避免迭代器中的不一致状态,则大多数集合都会使迭代器失效。)
  • 在LINQ中它完全没有任何意义。 例如,使用select(x=>f(x)) ,值是函数的结果,并且没有关联的永久存储。
  • 使用yield return语法编写的迭代器也没有意义

foreach旨在仅访问集合中的每个项目一次,并且不使用显式的“循环索引”; 如果你想要更多地控制循环并有一个循环索引,请使用for

编辑:您可以更改在foreach循环内迭代的集合中的项目。 例如:

 foreach(Chair ch in mychairs) { ch.PaintColour = Colour.Green; //this alters the chair object *in* the collection. } 

但是,您无法在集合中添加或删除项目。