foreach is a loop or iterator? Or could it be both?

18

In a video tutorial the instructor said not to fall into foolish to think that the foreach loop is one, and was vehement that he was an iterator.

There are cases where we can scroll through the items in an array using foreach as a "compact for" version.

  

That is, when we use foreach for arrays or arrays, in the background   we are using it as a compact version of the for loop. When we use it   to iterate collections, it is indeed a TRUE iterator because   "access" IEnumerator methods

Is the statement correct? Can anyone add anything to this?

Following example code:

//foreach com Arrays
    int[] array = new int[]{1, 2, 3, 4, 5, 6};
    foreach (int item in array) 
    {
      Console.WriteLine(item);
    }

However, the compiler generates C # C # equivalent to the generated CIL:

//Código C# equivalente ao CIL gerado
    int[] tempArray;
    int[] array = new int[]{1, 2, 3, 4, 5, 6};
    tempArray = array;
     for (int counter = 0; (counter < tempArray.Length); counter++) {
       int item = tempArray[counter];
       Console.WriteLine(item);
    }

The above code was taken from the book: Essential C-6.0, 5th Edition [Author Mark Michaelis] page 582

    
asked by anonymous 05.03.2017 / 23:34

3 answers

21

In general videotapes are made by people who misunderstand the language, let alone programming languages. I will not speak of a specific case, but always bear this in mind. There are even good things, usually in English and are paid for, like those of Pluralsight .

All that is executed in repetition is a loop , or loop in Portuguese. So both are loops.

If the intention was to say that foreach does not do the traditional process that is usually done in for , it is also wrong.

foreach is an iterate mechanism with a collection of data. How this will be done depends on a few factors. The most common way is to use an iterator provided by the collection, but you can use the same algorithm as for in cases like array and string . Although it does not exist, nothing prevents it from having other mechanisms or other objects that iterate without a ready iterator in the future.

Let's look at the code using both ways:

using static System.Console;
using System.Collections.Generic;
public class C {
    public static void Main() {
        int[] array = new int[]{1, 2, 3, 4, 5, 6};
        foreach (int item in array) {
            WriteLine(item);
        }
        var lista = new List<int>{1, 2, 3, 4, 5, 6};
        foreach (int item in lista) {
            WriteLine(item);
        }
        var texto = "123456";
        foreach (char item in texto) {
            WriteLine(item);
        }
    }
}

See working on .NET Fiddle . And see descompilando in TryRoslyn . Also put it on GitHub for future reference .

Of course, the way the decompiler will sort the font depends on the quality of the font, but it is clear that in the case of array it transforms into something with no iterator provided by it, as well as string in>, and with a list a ready iterator is used, so it can rebuild itself foreach . But the foreach with iterator is actually equivalent to this code:

IEnumerator<int> enumerator = lista.GetEnumerator();
try {
    while (enumerator.MoveNext()) {
        int item = enumerator.Current;
        WriteLine(item);
    }
} finally {
    IDisposable disposable = enumerator as IDisposable;
    if (disposable != null) disposable.Dispose();
}

So it's a loop as well.

Note that even for uses an iterator, but it is a manual that the programmer himself controls as he likes.

See what iteration .

    
06.03.2017 / 00:58
7

As was said in @bigown's response, foreach is a loop because it executes a block of code repeatedly, non-recursively, such as while , for or do-while , or even goto in some scenarios.

I do not know what the tutor wanted to explain, but if I were the tutor I would explain that foreach is a simplified way to use a IEnumerable<T> .

As you can see IEnumerable<T> has only one method IEnumerator<T> GetEnumerator() . If foreach did not exist, you would have to write a code like this to go through the elements:

IEnumerable<string> values = new[]{"olá"};
var it = values.GetEnumerator();
while(it.MoveNext()){
    Console.WriteLine(it.Current);
}

foreach allows you to have a simpler code. In fact whenever using foreach it actually generates code similar to what I showed.

But the story does not end here. If you look closely you see that IEnumerator<T> implements the interface IDisposable . And in reality when you use foreach the platform also generates code to call Dispose .

In other words, something is missing from the code I showed earlier:

IEnumerable<string> values = new[]{"olá"};
var it = values.GetEnumerator();
using(it){
    while(it.MoveNext()){
        Console.WriteLine(it.Current);
    }
}

Now, you have a general idea of how foreach works. The code generated by .NET should not be very different from that.

Note - The .NET platform is evolving and it is normal that they have found a way to generate more efficient code depending on the data structure being used. It seems that according to the book quoted by the questioner, they have found a way to optimize the generated code to go through any array, or even any%     

06.03.2017 / 11:50
4

Hello, I found this discussion somewhat interesting, and just to complement what @Bigown and @bigown said, note that the following code below also works normally:

IEnumerable<string> itens = new string[1] { "meu texto" };

for (IEnumerator<string> it = itens.GetEnumerator(); it.MoveNext();)
{
    Console.WriteLine(it.Current);
}

Note that I also gave foreach Syntax Sugar permission here, making it possible to iterate with an IEnumerable collection.

  

Note: The code generated above is intended for disciplinary purposes only, to show that both foreach and loop characteristics are present, as well as to iterate collections. I do not recommend using this approach, precisely because we have the foreach itself to do it.

I hope this can help you.

    
06.03.2017 / 14:24