简体   繁体   English

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

[英]Why is foreach loop Read-Only in C#

Why is foreach loop a read only? 为什么foreach循环只读? I mean you can fetch the data but can't increase++ or decrease--. 我的意思是你可以获取数据,但不能增加++或减少 - 。 Any reason behind it? 它背后的任何原因? Yes I am a beginner :) 是的我是初学者:)

Exmaple: 〔实施例:

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

That is because foreach is meant to iterate over a container, making sure each item is visited exactly once, without changing the container, to avoid nasty side effects. 这是因为foreach意味着迭代一个容器,确保每个项目只访问一次,而不更改容器,以避免令人讨厌的副作用。

See: foreach in MSDN 请参阅: MSDN中的foreach

If you meant why would changes to an element like an integer not affect a container of integers, well this is because the variable of iteration in this case would be a value type and is copied, eg: 如果你的意思是为什么像整数这样的元素的更改不会影响整数的容器,那么这是因为在这种情况下迭代的变量将是一个值类型并被复制,例如:

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

Even if the variable of iteration was a reference type, whose operations returned a new object, you wouldn't be changing the original collection, you would just be reassigning to this variable most of the time: 即使迭代变量是一个引用类型,其操作返回一个新对象,你也不会改变原始集合,你只需要在大多数时间重新分配给这个变量:

// 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
}

The following example has the potential to actually modify the object in the original collection by calling a mutating method: 以下示例可能通过调用mutating方法实际修改原始集合中的对象:

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

To avoid confusion with regard to value vs reference types and the scenarios mentioned above (along with some reasons related to optimization), MS chose to make the variable of iteration readonly . 为了避免在值与引用类型和上述场景(以及与优化相关的一些原因)方面的混淆,MS选择只readonly迭代变量。

Because the current element is returned by value(ie copied). 因为当前元素是按值返回的(即复制)。 And modifying the copy is useless. 修改副本是没用的。 If it is a reference type you can modify the content of that object, but can't replace the reference. 如果它是引用类型,则可以修改该对象的内容,但不能替换引用。

Perhaps you should read the documentation of IEnumerable<T> and IEnumerator<T> . 也许您应该阅读IEnumerable<T>IEnumerator<T>的文档。 That should make it clearer. 这应该让它更清晰。 The most important bit is that IEnumerable<T> has a property Current of type T . 最重要的一点是IEnumerable<T>具有类型为T的属性Current And this property has only a getter, but no setter. 而这个属性只有一个吸气剂,但没有二传手。

But what would happen if it had a setter? 但如果它有一个二传手会怎么样?

  • It would work well with arrays and Lists 它适用于数组和列表
  • It wouldn't work well with complex containers like hashtables, ordered list because the change causes larger changes in the container(for example a reordering), and thus invalidates the iterator. 它不适用于复杂的容器,如哈希表,有序列表,因为更改会导致容器中的更大更改(例如重新排序),从而使迭代器无效。 (Most collections invalidate the iterators if they get modified to avoid inconsistent state in the iterators.) (如果迭代器被修改以避免迭代器中的状态不一致,则大多数集合都会使迭代器失效。)
  • In LINQ it does make no sense at all. 在LINQ中它完全没有任何意义。 For example with select(x=>f(x)) the values are results of a function and have no permanent storage associated. 例如,使用select(x=>f(x)) ,值是函数的结果,并且没有关联的永久存储。
  • With iterators written with the yield return syntax it doesn't make sense either 使用yield return语法编写的迭代器也没有意义

foreach is designed to visit each item in a collection exactly once, and does not use an explicit "loop index"; foreach旨在仅访问集合中的每个项目一次,并且不使用显式的“循环索引”; if you want more control over the loop and have a loop index, use for . 如果你想要更多地控制循环并有一个循环索引,请使用for

EDIT: You can change the items in the collection being iterated on inside a foreach loop. 编辑:您可以更改在foreach循环内迭代的集合中的项目。 For example: 例如:

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

You cannot, however, add or remove items to/from the collection. 但是,您无法在集合中添加或删除项目。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM