Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In C#, why can't I modify the member of a value type instance in a foreach loop?

I know that value types should be immutable, but that's just a suggestion, not a rule, right? So why can't I do something like this:

struct MyStruct {     public string Name { get; set; } }   public class Program {     static void Main(string[] args)     {         MyStruct[] array = new MyStruct[] { new MyStruct { Name = "1" }, new MyStruct { Name = "2" } };         foreach (var item in array)         {             item.Name = "3";         }         //for (int i = 0; i < array.Length; i++)         //{         //    array[i].Name = "3";         //}          Console.ReadLine();     } } 

The foreach loop in the code doesn't compile while the commented for loop works fine. The error message:

Cannot modify members of 'item' because it is a 'foreach iteration variable'

Why is that?

like image 323
Cui Pengfei 崔鹏飞 Avatar asked Apr 13 '11 14:04

Cui Pengfei 崔鹏飞


People also ask

What does << mean in C?

<< is the left shift operator. It is shifting the number 1 to the left 0 bits, which is equivalent to the number 1 .

What does %d do in C?

In C programming language, %d and %i are format specifiers as where %d specifies the type of variable as decimal and %i specifies the type as integer.


1 Answers

Because foreach uses an enumerator, and enumerators can't change the underlying collection, but can, however, change any objects referenced by an object in the collection. This is where Value and Reference-type semantics come into play.

On a reference type, that is, a class, all the collection is storing is a reference to an object. As such, it never actually touches any of the object's members, and couldn't care less about them. A change to the object won't touch the collection.

On the other hand, value types store their entire structure in the collection. You can't touch its members without changing the collection and invalidating the enumerator.

Moreover, the enumerator returns a copy of the value in the collection. In a ref-type, this means nothing. A copy of a reference will be the same reference, and you can change the referenced object in any way you want with the changes spreading out of scope. On a value-type, on the other hand, means all you get is a copy of the object, and thus any changes on said copy will never propagate.

like image 114
Kyte Avatar answered Oct 08 '22 01:10

Kyte