Foreach in C sharp

2018-10-06

Today I would like to talk about the way the foreach loop works inside.

We all know that a foreach loop is - a loop that iterates through all the elements of the collection. Its greatest advantage in the ease of use - we do not need to worry about how many elements in the collection. However, many do not know that this is just syntactic “sugar”, which facilitates the work of the programmer. Therefore, we simply have to know in what the resulting compiler will convert.

The foreach loop works differently, depending on the collection you want to sort through.

1)      If it has to deal with the banal array, we can always know its length. Therefore, foreach will eventually be converted to a for loop. For example:

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

 The compiler converts the loop into this construct:

1
2
3
4
5
6
7
8
int[] temp;
int[] array = new int[]{1, 2, 3, 4, 5, 6};
temp = array;
for (int i = 0; i < temp.Length; i++)
{
 int item = temp[i];
 Console.WriteLine(item);
}

 2) However, many collections do not support indexed access to elements, for example: Dictionary, Queue, Stack. In this case, the iterator template will be used.

This template is based on the interfaces System.Collections.Generic.IEnumerator <T> and nongeneric System.Collections.IEnumerator, which allow you to iterate the elements in the set.

The IEnumerator contains:

  • MoveNext () method - moves the enumerator to the next element of the collection;
  • Reset () method - restarts the enumeration, sets the enumerator to the starting position;
  • Current property - returns the current element of the collection.

IEnumirator <T> is inherited from two interfaces - IEnumirator and IDisposable. It contains an overload of the Current property, providing its implementation by type.

Since we mentioned the interface IDisposable, then we'll tell a couple of words about it. It contains the only Dispose () method that is needed to free resources. Every time the loop terminates or when it exits, IEnumirator <T> clears the resources.

Let's look at this loop:

1
2
3
4
5
6
7
8
9
System.Collections.Generic.Queue<int> queue = new System.Collections.Generic.Queue<int>();
 queue.Enqueue(1);
 queue.Enqueue(2);
 queue.Enqueue(3);
 
 foreach (int item in queue)
 {
 Console.WriteLine(item);
 }

 The compiler converts it into a similar code:

1
2
3
4
5
6
7
8
9
10
11
System.Collections.Generic.Queue<int> queue = new System.Collections.Generic.Queue<int>();
 queue.Enqueue(1);
 queue.Enqueue(2);
 queue.Enqueue(3);
 
int num;
while (queue.MoveNext())
{
 num = queue.Current;
 Console.WriteLine(num);
}

 In this example, MoveNext replaces the need to count elements during the loop. When it does not receive the next element, it returns fasle and the loop terminates.

But, nevertheless, this code is only approximate to what the compiler really produces. The problem is that if you have two or more overlapping cycles that work with the same collection, then each MoveNext call will affect all the cycles. This course of events will not suit anyone. And so came up with the second interface IEnumirator.

It contains the only method GetEnumerator (), which returns an enumerator. Thus IEnumerable <T> and its generic version of IEnumerable allow you to render the logic of enumerating elements from the collection class. Usually this is a nested class that has access to the collection's elements and supports IEnumerator <T>. Having each enumerator, different consumers will not interfere with each other, performing the enumeration of the collection at the same time.

Thus, the above example should take into account two points - obtaining an enumerator and releasing resources. Here's how the compiler actually translates the foreach loop code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
System.Collections.Generic.Queue<int> queue = new System.Collections.Generic.Queue<int>();
 System.Collections.Generic.Queue<int>.Enumerator enumirator;
 
 IDisposable disposable;
 
 enumirator = queue.GetEnumerator();
 queue.Enqueue(1);
 queue.Enqueue(2);
 queue.Enqueue(3);
 
 try
 {
 int num;
 while (enumirator.MoveNext())
 {
 num = enumirator.Current;
 Console.WriteLine(num);
 }
 }
 finally
 {
 disposable = (IDisposable)enumirator;
 disposable.Dispose();
 }

 You probably think that for the iteration of the collection, you need to implement the IEnumerable and IEnumerable <T> interfaces. However, this is not quite true. To compile foreach, you just need to implement the GetEnumerator () method, which will return another object with the Current property and the MoveNext () method.

Here we use duck typing - a well-known approach:

  "If something goes like a duck, and quacks like a duck, it's a duck."

That is, if there is an object with the GetEnumerator () method, which returns an object with the MoveNext () method and the Current property, then this is the enumerator.

Otherwise, if the necessary objects, with the necessary methods are not found, the interfaces IEnumerable and IEnumerable <T> will be searched.

Thus foreach is really a universal loop that works fine with both arrays and collections. I use it constantly. However, there is one disadvantage for foreach - it allows only to read the elements, and does not allow them to be changed. Therefore, the old good “for” never will be lost from our code.

.NET .NET C# C#
08 de abril de 2026

Novos recursos para trabalhar com bandas no Designer do FastReport .NET

Na versão 2026.2 do FastReport .NET foi adicionado o recurso de alterar a ordem das bandas diretamente no Designer, simplesmente arrastando e soltando-as com o mouse.
07 de abril de 2026

Como conectar um plugin ao Google Planilhas no FastReport .NET

Neste artigo, veremos como começar a usar o Google Sheets (Planilhas) no FastReport .NET. você aprenderá como configurar o acesso à API por meio do Console do Google Cloud, criar e conectar o plug-in.
06 de abril de 2026

Como configurar novos modos de renderização de QR code no FastReport .NET

Neste artigo, veremos como substituir os módulos de código QR padrão em FastReport .NET em formas decorativas: círculos, estrelas, hexágonos e outros.

© 1998-2026 Fast Reports Inc.