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

Jas*_*lad 13 c# loops

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

〔实施例:

int[] myArray={1,2,3};
foreach (int num in myArray)
{
  num+=1;
}
Run Code Online (Sandbox Code Playgroud)

Mic*_*eyn 11

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

请参阅:MSDN中的foreach

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

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

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

// 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
}
Run Code Online (Sandbox Code Playgroud)

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

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

为避免混淆价值与参考类型和上述情景(以及与优化相关的一些原因),MS选择制作迭代变量readonly.


Cod*_*aos 9

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

也许你应该阅读的文档IEnumerable<T>IEnumerator<T>.这应该让它更清晰.最重要的一点是IEnumerable<T>具有Current类型的属性T.而这个属性只有一个吸气剂,但没有二传手.

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

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