C# Sentencias de Control

Descargar como docx, pdf o txt
Descargar como docx, pdf o txt
Está en la página 1de 24

Psy3com - Cuentos de terror

Tipos de instrucciones (Referencia de C#)


Visual Studio 2005

Otras versiones

Personas que lo han encontrado útil: 5 de 10 - Valorar este tema

Este capítulo describe las instrucciones de C# que se pueden utilizar en un programa. Salvo que se
indique otra cosa, las instrucciones se ejecutan secuencialmente. C# dispone de las siguientes categorías
de instrucciones:

Categoría Palabras clave de C#

Instrucciones de selección if, else, switch, case


Instrucciones de iteración do, for, foreach, in, while
Instrucciones de salto break, continue, default, goto, return, yield
Instrucciones de control de excepciones throw, try-catch, try-finally, try-catch-finally
Checked y unchecked checked, unchecked
Instrucción fixed fixed
Instrucción lock lock

Sentencias de Control en C#

Hay tres categorías de sentencias de control en C#: Las instrucciones de selección, que son los if y
switch, las instrucciones de iteración o ciclos, que consisten en el for, while, do-while y los bucles
foreach, y las instrucciones de salto, que incluyen break, continue, goto, return y throw. Explicaremos
cada uno de ellos a excepción del throw que forma parte de un mecanismo de excepción que lo
postearemos después.

La Sentencia if

La forma completa de esta sentencia es la siguiente:

if (condición) sentencia;
else sentencia;

- Pág. 1 de 24 -
Psy3com - Cuentos de terror

donde los objetivos de el if y el else son simples sentencias o declaraciones. La cláusula else es
opcional. Los objetivos de ambos el if y el else puede ser un bloque se sentencias (recuerde que los
bloques de sentencia en C# van entre llaves.

if (condición)
{
secuencia de expresiones
}
else
{
secuencia de expresiones
}

Si la expresión de condición es verdadera, se ejecutarán las secuencias de expresiones del if, en caso contrario

si existe la parte del else, estas serán ejecutadas. No se ejecutarán las dos al mismo tiempo. La expresión

condicional debe dar como resultado un valor booleano (bool).

// Determinar si un valor es positivo o negativo


using System;
class PosNeg
{
static void Main()
{
int i;
for(i = -5; i <= 5; i++)
{
Console.Write("Probando " + i + " : ");
if (i < 0) Console.WriteLine("Negativo");
else Console.WriteLine("Positivo");
}
}
}

El resultado mostrará el resultado siguiente:

Probando –5 : Negativo
Probando –4 : Negativo
Probando –3 : Negativo
Probando –2 : Negativo
Probando –1 : Negativo
Probando 0 : Positivo
Probando 1 : Positivo

- Pág. 2 de 24 -
Psy3com - Cuentos de terror

Probando 2 : Positivo
Probando 3 : Positivo
Probando 4 : Positivo
Probando 5 : Positivo

If anidados

Las instrucciones if pueden estar anidadas, es decir un if dentro de otro if. Esto es muy común en la
programación diaria. Por ejemplo la siguiente instrucción muestra un if anidado

if (i == 10)
{
if (j < 20)
a = b;
if (k > 100)
c = d;
else // este else se refiere al if(k>100)
a = c;
}
else
a = d; // este else se refiere al if( i == 10)

La escalera if-eslse-if

Una estructura común en programación es la escalera if-else-if. Esto luciría de la siguiente manera:

if (condición)
instruccion;
else if (condición)
instrucción;
else if (condición)
instucción;

- Pág. 3 de 24 -
Psy3com - Cuentos de terror

.
.
.
else
instrucción;

Las expresiones condicionales son evaluadas de arriba hacia abajo. Tan pronto como la condición
verdadera se encuentra, la instrucción o instrucciones asociadas son ejecutadas. y el resto de la escalera es
omitido. Si no se encuentra una condición verdadera la clausula else es ejecutada. En este caso la
claúsula else funciona como una expresión default. Si no existiera una cláusula else y ninguna condición
es verdadera, no se tomaría ninguna acción.

El siguiente programa demuestra el uso de la sentencia if-else-if

// Determinar el factor más pequeño


using System;
class Escalera {
static void Main() {
int num;
for(num = 2; num < 12; num++) {
if((num % 2) == 0)
Console.WriteLine("El factor más pequeño de " + num + " es 2.");
else if((num % 3) == 0)
Console.WriteLine("El factor más pequeño de " + num + " is 3.");
else if((num % 5) == 0)
Console.WriteLine("El factor más pequeño de " + num + " is 5.");
else if((num % 7) == 0)
Console.WriteLine("El factor más pequeño de " + num + " is 7.");
else
Console.WriteLine(num + " no es divisible por 2, 3, 5, o 7.");
}
}
}

El programa anterior mostraría la siguiente salida:

El factor más pequeño de 2 es 2.


El factor más pequeño de 3 es 3.
El factor más pequeño de 4 es 2.
El factor más pequeño de 5 es 5.

- Pág. 4 de 24 -
Psy3com - Cuentos de terror

El factor más pequeño de 6 es 2.


El factor más pequeño de 7 es 7.
El factor más pequeño de 8 es 2.
El factor más pequeño de 9 es 3.
El factor más pequeño de 10 es 2.
11 no es divisible por 2, 3, 5, o 7.

Sentencias de Control en C# – II Parte

La instrucción Switch

La segunda de las instrucciones de selección en C # es switch. El switch proporciona una rama múltiple
de selección, por lo tanto, permite a un programa seleccionar entre varias alternativas. Funciona así: El
valor de una expresión se prueba sucesivamente con una lista de las constantes. Cuando se encuentra una
coincidencia, la secuencia de instrucciones asociada con esa concordancia es ejecutado. La forma general
de la sentencia switch es:

switch(expresión)
{
case constant1:
statement sequence
break;
case constant2:
statement sequence
break;
case constant3:
statement sequence
break;
.
.
.
default:
statement sequence
break;
}

La expresión switch debe ser de un tipo entero, como char, byte, short o int, del un tipo de enumeración, o
de tipo cadena. Otras expresiones no están permitidas, como por ejemplo las de punto flotante. Con
frecuencia, la expresión de control del switch es simplemente una variable. En el caso de las constantes
deben ser de un tipo compatible con la expresión. No pueden haber dos constantes con el mismo valor en
la instrucción. La secuencia por defecto ( default ) se ejecuta si ningún caso (case) la expresión coincide
con la expresión constante. el valor por defecto es opcional, si no está presente, ninguna acción se lleva a
cabo si no hay coincidencias. Cuando un coincidencia es encontrada, las instrucciones asociadas a ese
case se ejecutan hasta que la rotura (break) se encuentra

// Demonstrate the switch.


using System;
class SwitchDemo {

- Pág. 5 de 24 -
Psy3com - Cuentos de terror

static void Main() {


int i;
for(i=0; i<10; i++)
switch(i) {
case 0:
Console.WriteLine("i es cero");
break;
case 1:
Console.WriteLine("i es uno");
break;
case 2:
Console.WriteLine("i es dos");
break;
case 3:
Console.WriteLine("i es tres");
break;
case 4:
Console.WriteLine("i es cuatro");
break;
default:
Console.WriteLine("i es cinco o más");
}
}
}
}

El programa produce la salida siguiente

i es cero
i es dos
i es tres
i es cuatro
i es cinco o más
i es cinco o más
i es cinco o más
i es cinco o más
i es cinco o más
i es cinco o más

Las sentencias switch también pueden ser anidadas al igual que el if.

Sentencias de Control en C# – III Parte

- Pág. 6 de 24 -
Psy3com - Cuentos de terror

El ciclo for

El instrucción for es una de las sentencias más poderosas y flexibles para los ciclos. En su forma general
la instrucción para repetir una simple instrucción es:

for(inicialización; condición; iteración) sentencia;

Para repetir un bloque de instrucciones la forma general es:

for(inicialización; condición; iteración)


{
secuencia de instrucciones;
}

La Inicialización es normalmente una sentencia de asignación que fija el valor inicial de la variable que
controlará la iteraciones en el ciclo, actuando como contador. La condición es una expresión booleana
que determina si el ciclo se repetirá. La expresión iteración define la cantidad por la cual la variable de
control cambia cada vez que el ciclo es repetido. Nótese que cada expresión del for debe ser separado por
punto y coma. El ciclo for se repite mientras la condición es verdadera. Una vez que la condición llega a
ser falsa el ciclo se detiene y se sigue ejecutando la siguiente sentencia después del bloque for. El ciclo
puede iniciar de forma positiva o negativa e incrementar los valores en cualquier cantidad entera. Por
ejemplo el siguiente programa imprime los números del –100 al 100 con incrementos de –5

// A negatively running for loop.


using System;
class DecrFor {
static void Main() {
int x;
for(x = 100; x > -100; x -= 5)
Console.WriteLine(x);
}
}
}

Algo importante de recalcar es que la condición se evalúa siempre en la parte superior del for. Esto significa que

el código dentro del ciclo for puede no ejecutarse si la condición es falsa desde el inicio. Por ejemplo:

int count;
for(count=10; count < 5; count++)
x += count; // Esta instrucción nunca se ejecutará

- Pág. 7 de 24 -
Psy3com - Cuentos de terror

Note que en los ejemplos anteriores la parte de la inicialización, es decir, donde se define el contador del ciclo, la

variable utilizada x = 100, se asume que ya fue declarada anteriormente como una variable del tipo entero. Esto

también se puede hacer al momento del ciclo.

// Sumar números del 1 al 100


using System;
class Sumar100 {
static void Main() {
int sum = 0;
for(int i = 1; i <= 100; i++)
sum += i;
Console.WriteLine("La Suma es " + sum);
}
}

En el ejemplo anterior se suman los números del 1 al 100. La variable i se ha declarado e inicializado dentro del

ciclo.

El ciclo infinito

Usted puede crear un ciclo infinito (un ciclo que nunca termina) usando el for dejando la expresión de
condición vacía. Por ejemplo :

for(;;) // ciclo intencionalmente infinito


{
//...
}

Ciclo sin cuerpo

En C#, el cuerpo asociado con el ciclo for puede ser vacío. Esto es porque un el cuerpo vacío de un for es
sintácticamente válido. Los ciclos sin cuerpo son muy útiles. Por ejemplo para el programa usado para
sumar los números del 1 al 100 podemos resumirlo como se muestra a continuación:

// El cuerpo del ciclo puede estar vacío


using System;

- Pág. 8 de 24 -
Psy3com - Cuentos de terror

class Empty3 {
static void Main() {
int i;
int sum = 0;
// Suma los números del 1 al 100.
for(i = 1; i <= 5; sum += i++) ;
Console.WriteLine("La Suma es " + sum);
}
}

En este caso la instrucción de la suma se hace dentro de la instrucción for. ( sum += i++), aquí se acumula
el valor de i a la variable sum y además se incrementa la variable. Fíjese además que al terminar la linea
del for se colocaron el punto y como para definir que no hay cuerpo,

Sentencias de Control en C# - IV Parte

El ciclo while

Otro ciclo dentro del C# es el while. La forma general del while es:

while (condición) sentencia;

donde sentencia puede ser una simple sentencia o un bloque de sentencias y condición define la condición
que controla el ciclo y puede ser cualquier expresión booleana válida. Las sentencias son ejecutadas
mientras la condición es verdadera. Cuando la condición llega a ser falsa, el control del programa pasa a
la línea inmediata que sigue el ciclo (si son más de una sentencias se debe usar un bloque con llaves para
que el while sepa que tiene que hacer todas las instrucciones en cada vuelta del ciclo).

// Calcular el orden de magnitud de un número


using System;
class WhileDemo {
static void Main() {
int num;
int mag;
num = 435679;
mag = 0;
Console.WriteLine("Número: " + num);
while(num > 0) {
mag++;
num = num / 10;
};
Console.WriteLine("Magnitud: " + mag);
}
}

La salida del sistema anterior es:

- Pág. 9 de 24 -
Psy3com - Cuentos de terror

Número : 435679
Magnitud : 6

El ciclo trabaja de la siguiente manera: El valor de num es examinado. Si num es mayor que 0, la
variable mag es incrementada y num es divido entre 10. Mientras el valor num sea mayor que 0 el ciclo
se repite. Cuando num es igual a cero el ciclo se detiene y mag contiene el orden (cantidad de dígitos ) del
valor original.

El ciclo do-while

El tercer ciclo del C# es el ciclo do-while. A diferencia del ciclo for y el ciclo while, en los cuales la
condición es examinada y evaluada al inicio del ciclo, el ciclo do-while chequea la condición al final del
ciclo. Esto significa que el ciclo do-while siempre se ejecutará al menos una vez. La forma general del
ciclo do-while es la siguiente:

do {
sentencias;
} while(condición)

Las llaves no son necesarias si solo hay una sentencia, pero siempre es bueno tenerlas para que la
estructura sea más legible.

Por ejemplo el siguiente programa muestra como se imprimen los números en orden inverso mediante un
ciclo do-while

- Pág. 10 de 24 -
Psy3com - Cuentos de terror

// Mostrar los dígitos de un entero en orden inverso


using System;
class DoWhileDemo {
static void Main() {
int num;
int nextdigit;
num = 198;
Console.WriteLine("Número: " + num);
Console.Write("Número en orden inverso: ");
do {
nextdigit = num % 10;
Console.Write(nextdigit);
num = num / 10;
} while(num > 0);
Console.WriteLine();
}
}

La salida del programa será:

Number: 198
Number in reverse order: 891

El ciclo foreach

El ciclo foreach recorre todos los elementos de una colección. Una colección es un grupo de objetos. C#
define varios tipos de colecciones, una de las cuales son los Arreglos o Matrices. Examinaremos
posteriormente el ciclo foreach cuando describamos los arreglos.

Usando la instrucción break para salir de un ciclo

- Pág. 11 de 24 -
Psy3com - Cuentos de terror

Es posible forzar una salida inmediata del ciclo, sin pasar por el resto de código en el cuerpo del ciclo y la
prueba condición del ciclo,usando la instrucción break. Cuando el ciclo encuentra la instrucción break, el
ciclo es terminado, y el control del programa se pasa a la siguiente instrucción después del ciclo. Aquí un
ejemplo de su uso.

// Usando break para salir de un ciclo


using System;
class BreakDemo {
static void Main() {
// Usar break para salir del ciclo
for(int i=-10; i <= 10; i++) {
if(i > 0) break; // terminar el ciclo cuando i sea positivo
Console.Write(i + " ");
}
Console.WriteLine("Hecho");
}
}

El break se puede usar en cualquier tipo de ciclo.

Usando continue

Es posible forzar una iteración temprana de un ciclo, sin pasar por la estructura del bucle de control
normal. Esto se logra utilizando continue. La sentencia continue obliga a la siguiente iteración de la ciclo
que tendrá lugar, saltándose cualquier código en el medio. Por lo tanto, continue es esencialmente el
complemento de break. Por ejemplo, el siguiente programa utiliza continue ayudando a imprimir los
números pares entre 0 y 100.

// Usar continue.
using System;
class ContDemo {
static void Main() {
// Imprimir número pares del 0 al 100.
for(int i = 0; i <= 100; i++) {
if((i%2) != 0) continue; // iterate
Console.WriteLine(i);
}
}
}

- Pág. 12 de 24 -
Psy3com - Cuentos de terror

Nótese que en el programa anterior se evalúa si el residuo de la división del número almacenado en la
variable i entre 2 es diferente de 0 se fuerza la siguiente iteración, si el valor es cero (el número es par) se
imprime el valor del número.

La instrucción return

Esta instrucción muy usada en los programas de C# se utiliza para salir de un método. Este también
puede ser usado para regresar un valor.

La sentencia goto

El goto es una sentencia de salto incondicional en C#. Cuando se encuentra el programa salta a una
localización definida por el goto. La sentencia cayó en desgracia con muchos programadores años atrás,
ya que fomentó la creación de código spaguetti. Sin embargo, el goto es todavía usado en ocasiones y de
manera eficiente. No se debe juzgar la forma de programar de algunos pero si se puede reducir su uso es
mejor. Un ejemplo de como se utilizaría sería el siguiente fragmento de código. Note que el goto
requiere siempre de un label que funciona como un identificador válido de C#.

x = 1;
loop1:
x++;
if(x < 100) goto loop1;

- Pág. 13 de 24 -
Psy3com - Cuentos de terror

Estructuras de control

Las instrucciones condicionales son instrucciones que permiten ejecutar bloques de instrucciones sólo
si se da una determinada condición. En los siguientes subapartados de este epígrafe se describen cuáles
son las instrucciones condicionales disponibles en C#

Instrucción if

La instrucción if permite ejecutar ciertas instrucciones sólo si de da una determinada condición. Su


sintaxis de uso es la sintaxis:

if (<condición>){
<instruccionesIf>}
else{
<instruccionesElse>}

- Pág. 14 de 24 -
Psy3com - Cuentos de terror

El significado de esta instrucción es el siguiente: se evalúa la expresión <condición>, que ha de


devolver un valor lógico. Si es cierta (devuelve true) se ejecutan las <instruccionesIf>, y si es falsa
(false) se ejecutan las <instruccionesElse> La rama else es opcional, y si se omite y la condición es falsa
se seguiría ejecutando a partir de la instrucción siguiente al if. En realidad, tanto <instruccionesIf> como
<instruccionesElse> pueden ser una única instrucción o un bloque de instrucciones.

Un ejemplo de aplicación de esta instrucción es esta variante del HolaMundo:

using System;
class HolaMundoIf
{
public static void Main(String[] args)
{
if (args.Length > 0){
Console.WriteLine("Hola {0}!", args[0]);}
else{
Console.WriteLine("Hola mundo!");}
}
}

Si ejecutamos este programa sin ningún argumento veremos que el mensaje que se muestra es ¡Hola
Mundo!, mientras que si lo ejecutamos con algún argumento se mostrará un mensaje de bienvenida
personalizado con el primer argumento indicado.

Instrucción switch

La instrucción switch permite ejecutar unos u otros bloques de instrucciones según el valor de una
cierta expresión. Su estructura es:

switch (<expresión>)
{
case <valor1>: <bloque1>
<siguienteAcción>
case <valor2>: <bloque2>
<siguienteAcción>
...
default: <bloqueDefault>
<siguienteAcción>
}

El significado de esta instrucción es el siguiente: se evalúa . Si su valor es se ejecuta el , si es se ejecuta


, y así para el resto de valores especificados. Si no es igual a ninguno de esos valores y se incluye la rama
default, se ejecuta el ; pero si no se incluye se pasa directamente a ejecutar la instrucción siguiente al
switch.

- Pág. 15 de 24 -
Psy3com - Cuentos de terror

Los valores indicados en cada rama del switch han de ser expresiones constantes que produzcan
valores de algún tipo básico entero, de una enumeración, de tipo char o de tipo string. Además, no puede
haber más de una rama con el mismo valor.

En realidad, aunque todas las ramas de un switch son opcionales siempre se ha de incluir al menos una.
Además, la rama default no tiene porqué aparecer la última si se usa, aunque es recomendable que lo
haga para facilitar la legibilidad del código.

El elemento marcado como <siguienteAcción> colocado tras cada bloque de instrucciones indica qué
es lo que ha de hacerse tras ejecutar las instrucciones del bloque que lo preceden. Puede ser uno de estos
tres tipos de instrucciones:

goto case <valori>;


goto default;
break;

Si es un goto case indica que se ha de seguir ejecutando el bloque de instrucciones asociado en el switch a la

rama del <valori> indicado, si es un goto default indica que se ha de seguir ejecutando el bloque de instrucciones

de la rama default, y si es un break indica que se ha de seguir ejecutando la instrucción siguiente al switch.

El siguiente ejemplo muestra cómo se utiliza switch:

using System;
class HolaMundoSwitch
{
public static void Main(String[] args)
{
if (args.Length > 0)
switch(args[0])
{
case "José":
Console.WriteLine("Hola José. Buenos días");
break;
case "Paco":
Console.WriteLine("Hola Paco. Me alegro de
verte");
break;
default:
Console.WriteLine("Hola {0}", args[0]);
break;
}
else
Console.WriteLine("Hola Mundo");
}
}

- Pág. 16 de 24 -
Psy3com - Cuentos de terror

Este programa reconoce ciertos nombres de personas que se le pueden pasar como argumentos al lanzarlo

y les saluda de forma especial. La rama default se incluye para dar un saludo por defecto a las personas no

reconocidas.

Para los programadores habituados a lenguajes como C++ es importante resaltarles el hecho de que, a
diferencia de dichos lenguajes, C# obliga a incluir una sentencia break o una sentencia goto case al final
de cada rama del switch para evitar errores comunes y difíciles de detectar causados por olvidar incluir
break; al final de alguno de estos bloques y ello provocar que tras ejecutarse ese bloque se ejecute
también el siguiente.

Instrucciones iterativas

Las instrucciones iterativas son instrucciones que permiten ejecutar repetidas veces una instrucción o
un bloque de instrucciones mientras se cumpla una condición. Es decir, permiten definir bucles donde
ciertas instrucciones se ejecuten varias veces. A continuación se describen cuáles son las instrucciones de
este tipo incluidas en C#.

Instrucción while

La instrucción while permite ejecutar un bloque de instrucciones mientras se de una cierta instrucción.
Su sintaxis de uso es:

while (<condición>)
{
<instrucciones>
}

Su significado es el siguiente: Se evalúa la <condición> indicada, que ha de producir un valor lógico.


Si es cierta (valor lógico true) se ejecutan las <instrucciones> y se repite el proceso de evaluación de
<condición> y ejecución de <instrucciones> hasta que deje de serlo. Cuando sea falsa (false) se pasará a
ejecutar la instrucción siguiente al while. En realidad <instrucciones> puede ser una única instrucción o
un bloque de instrucciones.

Un ejemplo cómo utilizar esta instrucción es el siguiente:

using System;
class HolaMundoWhile
{
public static void Main(String[] args)
{
int actual = 0;

- Pág. 17 de 24 -
Psy3com - Cuentos de terror

if (args.Length > 0)
while (actual < args.Length)
{
Console.WriteLine("¡Hola {0}!",
args[actual]);
actual = actual + 1;
}
else
Console.WriteLine("¡Hola mundo!");
}
}

En este caso, si se indica más de un argumento al llamar al programa se mostrará por pantalla un
mensaje de saludo para cada uno de ellos. Para ello se usa una variable actual que almacena cuál es el
número de argumento a mostrar en cada ejecución del while. Para mantenerla siempre actualizada lo que
se hace es aumentar en una unidad su valor tras cada ejecución de las <instrucciones> del bucle.

Por otro lado, dentro de las <instrucciones> de un while pueden utilizarse las siguientes dos
instrucciones especiales:

 break;: Indica que se ha de abortar la ejecución del bucle y continuarse ejecutando por la instrucción
siguiente al while.

 continue;: Indica que se ha de abortar la ejecución de las <instrucciones> y reevaluarse la <condición> del
bucle, volviéndose a ejecutar las <instrucciones> si es cierta o pasándose a ejecutar la instrucción
siguiente al while si es falsa.

Instrucción do...while

La instrucción do...while es una variante del while que se usa así:

do {
<instrucciones>
} while(<condición>);

La única diferencia del significado de do...while respecto al de while es que en vez de evaluar primero
la condición y ejecutar <instrucciones> sólo si es cierta, do...while primero ejecuta las <instrucciones> y
luego mira la <condición> para ver si se ha de repetir la ejecución de las mismas. Por lo demás ambas
instrucciones son iguales, e incluso también puede incluirse break; y continue; entre las <instrucciones>
del do...while.

do ... while está especialmente destinado para los casos en los que haya que ejecutar las
<instrucciones> al menos una vez aún cuando la condición sea falsa desde el principio, como ocurre en el
siguiente ejemplo:

- Pág. 18 de 24 -
Psy3com - Cuentos de terror

using System;
class HolaMundoDoWhile
{
public static void Main()
{
String leído;
do
{
Console.WriteLine("Clave: ");
leído = Console.ReadLine();
}
while (leído != "José");
Console.WriteLine("Hola José");
}
}

Este programa pregunta al usuario una clave y mientras no introduzca la correcta (José) no continuará
ejecutándose. Una vez que introducida correctamente dará un mensaje de bienvenida al usuario.

Instrucción for

La instrucción for es una variante de while que permite reducir el código necesario para escribir los
tipos de bucles más comúnmente usados en programación. Su sintaxis es:

for (<inicialización>; <condición>; <modificación>){


<instrucciones>
}

El significado de esta instrucción es el siguiente: se ejecutan las instrucciones de <inicialización>, que


suelen usarse para definir e inicializar variables que luego se usarán en <instrucciones>. Luego se evalúa
<condición>, y si es falsa se continúa ejecutando por la instrucción siguiente al for; mientras que si es
cierta se ejecutan las <instrucciones> indicadas, luego se ejecutan las instrucciones de <modificación> -
que como su nombre indica suelen usarse para modificar los valores de variables que se usen en
<instrucciones>- y luego se reevalúa <condición> repitiéndose el proceso hasta que ésta última deje de
ser cierta.

En <inicialización> puede en realidad incluirse cualquier número de instrucciones que no tienen


porqué ser relativas a inicializar variables o modificarlas, aunque lo anterior sea su uso más habitual. En
caso de ser varias se han de separar mediante comas (,), ya que el carácter de punto y coma (;)
habitualmente usado para estos menesteres se usa en el for para separar los bloques de <inicialización>,
<condición> y <modificación> Además, la instrucción nula no se puede usar en este caso y tampoco
pueden combinarse definiciones de variables con instrucciones de otros tipos.

Con <modificación> pasa algo similar, ya que puede incluirse código que nada tenga que ver con
modificaciones pero en este caso no se pueden incluir definiciones de variables.

- Pág. 19 de 24 -
Psy3com - Cuentos de terror

Como en el resto de instrucciones hasta ahora vistas, en <instrucciones> puede ser tanto una única
instrucción como un bloque de instrucciones. Además, las variables que se definan en <inicialización>
serán visibles sólo dentro de esas <instrucciones>.

La siguiente clase es equivalente a la clase HolaMundoWhile ya vista solo que hace uso del for para
compactar más su código:

using System;
class HolaMundoFor
{
public static void Main(String[] args)
{
if (args.Length > 0)
for (int actual = 0; actual < args.Length;
actual++) {
Console.WriteLine("¡Hola {0}!",
args[actual]);
}
else
Console.WriteLine("¡Hola mundo!");
}
}

Al igual que con while, dentro de las <instrucciones> del for también pueden incluirse instrucciones
continue; y break; que puedan alterar el funcionamiento normal del bucle.

Instrucción foreach

La instrucción foreach es una variante del for pensada especialmente para compactar la escritura de
códigos donde se realice algún tratamiento a todos los elementos de una colección, que suele un uso muy
habitual de for en los lenguajes de programación que lo incluyen. La sintaxis que se sigue a la hora de
escribir esta instrucción foreach es:

foreach (<tipoElemento> <elemento> in <colección>) {


<instrucciones>
}

El significado de esta instrucción es muy sencillo: se ejecutan <instrucciones> para cada uno de los
elementos de la <colección> indicada. <elemento> es una variable de sólo lectura de tipo <tipoElemento>
que almacenará en cada momento el elemento de la colección que se esté procesando y que podrá ser
accedida desde <instrucciones>.

Es importante señalar que <colección> no puede valer null porque entonces saltaría una excepción de
tipo System.NullReferenceException, y que <tipoElemento> ha de ser un tipo cuyos objetos puedan
almacenar los valores de los elementos de <colección>

- Pág. 20 de 24 -
Psy3com - Cuentos de terror

En tanto que una tabla se considera que es una colección, el siguiente código muestra cómo usar for
para compactar aún más el código de la clase HolaMundoFor anterior:

using System;
class HolaMundoForeach
{
public static void Main(String[] args)
{
if (args.Length > 0)
foreach(String arg in args) {
Console.WriteLine("¡Hola {0}!", arg);
}
else
Console.WriteLine("¡Hola mundo!");
}
}

Las tablas multidimensionales también pueden recorrerse mediante el foreach, el cual pasará por sus
elementos en orden tal y como muestra el siguiente fragmento de código:

int[,] tabla = { {1,2}, {3,4} };


foreach (int elemento in tabla)
Console.WriteLine(elemento);

Cuya salida por pantalla es:

1
2
3
4

En general, se considera que una colección es todo aquel objeto que implemente las interfaces
IEnumerable o IEnumerator del espacio de nombres System.Collections de la BCL, que están
definidas como sigue:

interface IEnumerable
{
[C#]
IEnumerator GetEnumerator();
}
interface IEnumerator
{
[C#]
object Current {get;}
[C#]

- Pág. 21 de 24 -
Psy3com - Cuentos de terror

bool MoveNext();
[C#]
void Reset();
}

El método Reset() ha de implementarse de modo que devuelva el enumerador reiniciado a un estado


inicial donde aún no referencie ni siquiera al primer elemento de la colección sino que sea necesario
llamar a MoveNext() para que lo haga.

El método MoveNext() se ha de implementar de modo que haga que el enumerador pase a apuntar al
siguiente elemento de la colección y devuelva un booleano que indique si tras avanzar se ha alcanzado el
final de la colección.

La propiedad Current se ha de implementar de modo que devuelva siempre el elemento de la


colección al que el enumerador esté referenciando. Si se intenta leer Current habiéndose ya recorrido
toda la colección o habiéndose reiniciado la colección y no habiéndose colocado en su primer elemento
con MoveNext(), se ha de producir una excepción de tipo
System.Exception.SystemException.InvalidOperationException

Otra forma de conseguir que foreach considere que un objeto es una colección válida consiste en hacer
que dicho objeto siga el patrón de colección. Este patrón consiste en definir el tipo del objeto de modo
que sus objetos cuenten con un método público GetEnumerator() que devuelva un objeto no nulo que
cuente con una propiedad pública llamada Current que permita leer el elemento actual y con un método
público bool MoveNext() que permita cambiar el elemento actual por el siguiente y devuelva false sólo
cuando se haya llegado al final de la colección.

El siguiente ejemplo muestra ambos tipos de implementaciones:

using System;
using System.Collections;
class Patron
{
private int actual = -1;
public Patron GetEnumerator()
{
return this;
}

public int Current


{
get {return actual;}
}

public bool MoveNext()


{
bool resultado = true;
actual++;
if (actual==10)
resultado = false;
return resultado;

- Pág. 22 de 24 -
Psy3com - Cuentos de terror

}
}

class Interfaz:IEnumerable,IEnumerator
{
private int actual = -1;
public object Current
{
get {return actual;}
}

public bool MoveNext()


{
bool resultado = true;
actual++;
if (actual==10)
resultado = false;
return resultado;
}

public IEnumerator GetEnumerator()


{
return this;
}

public void Reset()


{
actual = -1;
}
}
class Principal
{
public static void Main()
{
Patron obj = new Patron();
Interfaz obj2 = new Interfaz();
foreach (int elem in obj)
Console.WriteLine(elem);
foreach (int elem in obj2)
Console.WriteLine(elem);
}
}

Nótese que en realidad en este ejemplo no haría falta implementar IEnumerable, puesto que la clase
Interfaz ya implementa IEnumerator y ello es suficiente para que pueda ser recorrida mediante foreach.

La utilidad de implementar el patrón colección en lugar de la interfaz IEnumerable es que así no es


necesario que Current devuelva siempre un object, sino que puede devolver objetos de tipos más
concretos y gracias a ello puede detectarse al compilar si el <tipoElemento> indicado puede o no
almacenar los objetos de la colección.

Por ejemplo, si en el ejemplo anterior sustituimos en el último foreach el <tipoElemento> indicado por
Patrón, el código seguirá compilando pero al ejecutarlo saltará una excepción
System.InvalidCastException. Sin embargo, si la sustitución se hubiese hecho en el penúltimo foreach,

- Pág. 23 de 24 -
Psy3com - Cuentos de terror

entonces el código directamente no compilaría y se nos informaría de un error debido a que los objetos
int no son convertibles en objetos Patrón.

También hay que tener en cuenta que la comprobación de tipos que se realiza en tiempo de ejecución
si el objeto sólo implementó la interfaz IEnumerable es muy estricta, en el sentido de que si en el
ejemplo anterior sustituimos el <tipoElemento> del último foreach por byte también se lanzará la
excepción al no ser los objetos de tipo int implícitamente convertibles en bytes sino sólo a través del
operador () Sin embargo, cuando se sigue el patrón de colección las comprobaciones de tipo no son tan
estrictas y entonces sí que sería válido sustituir int por byte en <tipoElemento>.

El problema de sólo implementar el patrón colección es que este es una característica propia de C# y
con las instrucciones foreach (o equivalentes) de lenguajes que no lo soporten no se podría recorrer
colecciones que sólo siguiesen este patrón. Una solución en estos casos puede ser hacer que el tipo del
objeto colección implemente tanto la interfaz IEnumerable como el patrón colección. Obviamente esta
interfaz debería implementarse explícitamente para evitarse conflictos derivados de que sus miembros
tengan signaturas coincidentes con las de los miembros propios del patrón colección.

Si un objeto de un tipo colección implementa tanto la interfaz IEnumerable como el patrón de


colección, entonces en C# foreach usará el patrón colección para recorrerlo.

- Pág. 24 de 24 -

También podría gustarte