Variable of foreach loop

8

When we use a foreach loop, does the local variable we create to receive the content of the list in question pass by value or reference?

Ex:

foreach (var item in listItems)
{
   //TODO
}

Does item receive content by value or reference?

    
asked by anonymous 24.08.2017 / 16:31

2 answers

12

The item is by value, so it is not allowed to change its value.

It only has one detail if the item is an object by reference this value I am talking about is pointer and not the object itself, so can modify object the object normally, just can not change the constant reference in the collection, you can not change the object as a whole to a new one, but you can modify the existing one.

There is a proposal to say that the item should be by reference and bring all the good and bad consequences of this .

using static System.Console;
using System.Collections.Generic;

public class Program {
    public static void Main() {
        var ints = new List<int> { 1, 2, 3 };
        var lists = new List<List<int>> { new List<int> { 1, 2, 3 }, new List<int> { 4, 5, 6 } };
        foreach (var item in ints) {
//          item = 9; //não compila
        }
        foreach (var item in lists) {
            item[0] = 9;
        }
        foreach (var item in lists) {
//          item = new List<int> { 7, 8, 9 }; //não compila
        }
        foreach (var lista in lists) {
            foreach (var item in lista) {
                WriteLine(item);
            }
        }
    }
}

See running on .NET Fiddle . And no Coding Ground . Also I placed GitHub for future reference .

See Memory Allocation in C # - Value Types and Reference Types . And also: What are and where are the "stack" and "heap"? . It will also help What's the difference between Struct and Class? .

There is a lot of confusion among programmers, and especially in the .NET world, about memory usage, so it would be interesting to deepen the concepts about types by value and reference, where they are allocated, what can be done with it, and about immutability that people generally associate with types by value (which some call primitives, but this concept does not exist in C #), but these types may be immutable, or associate which types by reference are mutable and they may be immutable, see more at use of immutability .

    
24.08.2017 / 16:42
2

It depends on the type of the list.

If it is a complex type list - class - will be by reference.

If it is a list of primitive type - string , int , bool , decimals , etc - will be by value. However, you can not change the value of this variable, because it is an iteration variable of foreach .

TL; DR;

This is due to the fact that, primitive variables are allocated in memory different from complex types. There are two types of memory that you should worry about as you develop:

  • Stack memory : Fast access memory and simple value allocation;
  • Heap memory : Not so fast access memory for complex value allocation;

When you create a primitive type variable - int, long, string, decimal, float, double, etc - this is addressed to an address in stack , and that address has a < strong> value simple.

When you instantiate an object to a variable - new class(); - the following occurs: the variable will reference an address in stack , but this address will < strong> to an address in heap memory, and that's where all the values of your complex type will be.

See the image below:

Whenyoumakeaforeachinalistofcomplextype,ithappensthatanewvariableiscreatedinmemorystackcalleditemthatonlyhasitsreferencechangedforthelistitems.Therefore,foreachisbyreference.

Butifitisalistofprimitivetype,thisisnotpossible,andyouendupdoingforeachforvalue.

IhopeIhaveclarifiedeverythingonthisissue.Ifsomethingelsewasmissing,comment.:)

Simplification

Loopasbelow:

foreach(variteminlist){/*aquivaiseucódigo*/}

Italmostisthesameasdoing(thisalmostisrelevant):

for(vari=0;i<list.Length;i++){varitem=list[i];/*aquivaiseucódigo*/}

Butforeachismuchmoreelegant.:)

MicrosoftDocumentation-foreach-in(C#reference)

link

    
24.08.2017 / 16:41