Compartir a través de


Instrucciones de iteración: for, foreach, doy while

Las instrucciones de iteración ejecutan repetidamente una instrucción o un bloque de instrucciones. La instrucción for ejecuta su cuerpo mientras una expresión booleana especificada se evalúa como true. La instrucción foreach enumera los elementos de una colección y ejecuta su cuerpo para cada elemento de la colección. La instrucción do ejecuta condicionalmente su cuerpo una o varias veces. La instrucción while ejecuta condicionalmente su cuerpo cero o varias veces.

En cualquier punto del cuerpo de una instrucción de iteración, se puede salir del bucle mediante la instrucción break. Puede avanzar a la siguiente iteración en el bucle utilizando la continue sentencia.

Instrucción for

La for instrucción ejecuta una instrucción o un bloque de instrucciones mientras una expresión booleana especificada se evalúa como true. En el ejemplo siguiente se muestra la instrucción for, que ejecuta su cuerpo mientras que un contador entero sea menor que tres:

for (int i = 0; i < 3; i++)
{
    Console.Write(i);
}
// Output:
// 012

En el ejemplo anterior se muestran los elementos de la for declaración.

  • La sección de inicializador que se ejecuta solo una vez, antes de entrar en el bucle. Normalmente, se declara e inicializa una variable de bucle local en esa sección. No se puede tener acceso a la variable declarada desde fuera de la for instrucción .

    La sección initializer del ejemplo anterior declara e inicializa una variable de contador entero:

    int i = 0
    
  • Sección de condición que determina si se debe ejecutar la siguiente iteración del bucle. Si se evalúa como true o no está presente, se ejecuta la siguiente iteración; de lo contrario, se sale del bucle. La sección condition debe ser una expresión booleana.

    La sección condition del ejemplo anterior comprueba si un valor de contador es menor que tres:

    i < 3
    
  • Sección iterador que define lo que sucede después de cada ejecución del cuerpo del bucle.

    La sección iterador del ejemplo anterior incrementa el contador:

    i++
    
  • El cuerpo del bucle, que es una instrucción o un bloque de instrucciones.

La sección iterador puede contener cero o más de las siguientes expresiones de instrucción, separadas por comas:

Si no declara una variable de bucle en la sección de inicializador, puede usar cero o más de las expresiones de la lista anterior también en la sección de inicializador. En el ejemplo siguiente se muestran varios usos menos comunes de las secciones de inicializador e iterador: asignar un valor a una variable externa en la sección inicializador, invocar un método en las secciones inicializador y iterador, y cambiar los valores de dos variables en la sección iterador:

int i;
int j = 3;
for (i = 0, Console.WriteLine($"Start: i={i}, j={j}"); i < j; i++, j--, Console.WriteLine($"Step: i={i}, j={j}"))
{
    //...
}
// Output:
// Start: i=0, j=3
// Step: i=1, j=2
// Step: i=2, j=1

Todas las secciones de la for instrucción son opcionales. Por ejemplo, el código siguiente define el bucle infinito for :

for ( ; ; )
{
    //...
}

Instrucción foreach

La foreach instrucción ejecuta una instrucción o un bloque de instrucciones para cada elemento de una instancia del tipo que implementa la System.Collections.IEnumerable interfaz o System.Collections.Generic.IEnumerable<T> , como se muestra en el ejemplo siguiente:

List<int> fibNumbers = new() { 0, 1, 1, 2, 3, 5, 8, 13 };
foreach (int element in fibNumbers)
{
    Console.Write($"{element} ");
}
// Output:
// 0 1 1 2 3 5 8 13

La foreach declaración no se limita a esos tipos. Puede usarlo con una instancia de cualquier tipo que cumpla las condiciones siguientes:

  • Un tipo tiene el método público GetEnumerator sin parámetros. El GetEnumerator método puede ser el método de extensión de un tipo.
  • El tipo de valor devuelto del GetEnumerator método tiene la propiedad pública Current y el método público sin MoveNext parámetros cuyo tipo de valor devuelto es bool.

En el ejemplo siguiente se usa la instrucción foreach con una instancia del tipo System.Span<T>, que no implementa ninguna interfaz.

Span<int> numbers = [3, 14, 15, 92, 6];
foreach (int number in numbers)
{
    Console.Write($"{number} ");
}
// Output:
// 3 14 15 92 6

Si la propiedad del Current enumerador devuelve un valor de retorno por referencia (ref T donde T es el tipo de un elemento de colección), puede declarar una variable de iteración con el modificador ref o ref readonly, como se muestra en el ejemplo siguiente.

Span<int> storage = stackalloc int[10];
int num = 0;
foreach (ref int item in storage)
{
    item = num++;
}
foreach (ref readonly var item in storage)
{
    Console.Write($"{item} ");
}
// Output:
// 0 1 2 3 4 5 6 7 8 9

Si la colección de origen de la foreach instrucción está vacía, el bloque de la foreach instrucción no se ejecuta y se omite. Si la foreach instrucción se aplica a null, se lanza un objeto NullReferenceException.

await foreach

Puede usar la await foreach instrucción para consumir un flujo asincrónico de datos, es decir, el tipo de colección que implementa la IAsyncEnumerable<T> interfaz. Cada iteración del bucle se puede suspender mientras el elemento siguiente se recupera de forma asincrónica. En el ejemplo siguiente se muestra cómo usar la await foreach instrucción :

await foreach (var item in GenerateSequenceAsync())
{
    Console.WriteLine(item);
}

También puede usar la await foreach instrucción con una instancia de cualquier tipo que cumpla las condiciones siguientes:

  • Un tipo tiene el método público GetAsyncEnumerator sin parámetros. Ese método puede ser el método de extensión de un tipo.
  • El tipo de valor devuelto del método GetAsyncEnumerator tiene la propiedad pública Currenty el método público MoveNextAsync sin parámetros cuyo tipo de valor devuelto es Task<bool>, ValueTask<bool>, o cualquier otro tipo que se puede esperar cuyo método GetResult de awaiter devuelve un valor bool.

De forma predeterminada, los elementos de secuencia se procesan en el contexto capturado. Si desea deshabilitar la captura del contexto, use el TaskAsyncEnumerableExtensions.ConfigureAwait método de extensión . Para obtener más información sobre los contextos de sincronización y la captura del contexto actual, consulte Consumo del patrón asincrónico basado en tareas. Para obtener más información sobre las secuencias asincrónicas, consulte el tutorial Secuencias asincrónicas.

Tipo de una variable de iteración

Puede usar la var palabra clave para permitir que el compilador infiera el tipo de una variable de iteración en la foreach instrucción , como se muestra en el código siguiente:

foreach (var item in collection) { }

Nota:

El compilador puede inferir el tipo de var como un tipo de referencia anulable, dependiendo de si el contexto de referencia nulable está habilitado y si el tipo de la expresión de inicialización es un tipo de referencia. Para obtener más información, consulte Variables locales con tipo implícito.

También puede especificar explícitamente el tipo de una variable de iteración, como se muestra en el código siguiente:

IEnumerable<T> collection = new T[5];
foreach (V item in collection) { }

En el formato anterior, el tipo T de un elemento de colección debe convertirse implícita o explícitamente en el tipo V de una variable de iteración. Si una conversión explícita de T a V falla en tiempo de ejecución, la instrucción foreach lanza una InvalidCastException. Por ejemplo, si T es un tipo de clase no sellado, V puede ser cualquier tipo de interfaz, incluso el que T no implementa. En tiempo de ejecución, el tipo de un elemento de colección puede ser el que deriva de T y realmente implementa V. Si ese no es el caso, se produce InvalidCastException.

Instrucción do

La do instrucción ejecuta una instrucción o un bloque de instrucciones mientras una expresión booleana especificada se evalúa como true. Dado que esa expresión se evalúa después de cada ejecución del bucle, un do bucle se ejecuta una o varias veces. El do bucle difiere del while bucle , que ejecuta cero o más veces.

En el ejemplo siguiente se muestra el uso de la declaración do:

int n = 0;
do
{
    Console.Write(n);
    n++;
} while (n < 5);
// Output:
// 01234

Instrucción while

La while instrucción ejecuta una instrucción o un bloque de instrucciones mientras una expresión booleana especificada se evalúa como true. Dado que esa expresión se evalúa antes de cada ejecución del bucle, un while bucle ejecuta cero o más veces. El while bucle difiere del do bucle , que se ejecuta una o varias veces.

En el ejemplo siguiente se muestra el uso de la declaración while:

int n = 0;
while (n < 5)
{
    Console.Write(n);
    n++;
}
// Output:
// 01234

Especificación del lenguaje C#

Para más información, vea las secciones siguientes de la Especificación del lenguaje C#:

Para obtener más información sobre estas características, consulte las siguientes notas de propuesta de características:

Consulte también