viernes, 12 de marzo de 2010

Colecciones - List, ArrayList

Las colecciones de clases de C# son un conjunto de clases diseñadas específicamente para agrupar objetos y llevar a cabo tareas con ellos.

Tanto la list‹T› como la ArrayList y otras clases de la Collections tienen propiedades muy similares a los arrays de C# (para más detalles sobre estos busquen nueva el tema Matrices y confirmen). Una ventaja fundamental de estas clases sobre los arrays es que puedan crecer y reducir el número de objetos almacenados.

La clase list‹T› esta contenida en System.Collections.Generic, mientras que la clase ArrayList figura en el System.Collections.

La sintaxis para crear una colección list‹T› es la siguiente:
Listtipo› nombre = new Listtipo›();

ArrayList es un objeto creado de una manera similar, aunque sin el argumento de tipo:
ArrayList nombre = new ArrayList ();

Con esta sintaxis ahora podemos crear una list‹T› denominada listacolores:

using System;
using System.Collections.Generic;

public class Lists
{
static void Main()
{
Liststring› listacolores = new Liststring›();
}
}

Añadir artículos a las listas
Una vez que una lista se ha creado hay una serie de métodos que pueden ser llamados a realizar tareas en la lista. En este caso para agrear elementos a la lista de objetos se utiliza el método Add(). Ejemplo:

Liststring› ListaColores = new Liststring›();

ListaColores.Add ("Azul");
ListaColores.Add ("Rojo");
ListaColores.Add ("Verde");
ListaColores.Add ("Amarillo");
ListaColores.Add ("Morado");



Acceso a los elementos
A los elementos individuales en una lista se puede acceder mediante el índice del valor de la partida (teniendo en cuenta que el primer punto del índice es 0, el segundo índice 1 y así sucesivamente). El valor del índice se encuentra entre corchetes tras el nombre de la lista. Por ejemplo, para acceder al segundo punto del objeto ListaColores:

Console.WriteLine (ListaColores[1]);

Un elemento de la lista puede cambiar su valor de manera similar usando el índice combinado con el operador de asignación. Por ejemplo, para cambiar el color de verde a mamey:

ListaColores[2] = "mamey";

Todos los elementos de una lista se puede acceder mediante un bucle foreach. Por ejemplo:

foreach (string color in ListaColores)
{
Console.WriteLine ( color );
}


Cuando compilado y ejecutado, el código de salida anterior mostrara todos los colores.


Inserción de artículos en una lista
Anteriormente se utilizó el método Add() para añadir elementos a una lista. El método Add(), sin embargo, sólo añade elementos al final de una lista. A veces es necesario añadir un nuevo tema en una ubicación específica en una lista. Insert() es el método para este fin específico. Insert() recibe dos argumentos, un entero que indica el índice de localización de la inserción y el tema que se incluirá en ese lugar. Por ejemplo, para insertar un elemento en la posición 2 de la lista seria:

ListaColores.Insert(2, "Blanco");
Ordenando Listas
No hay manera de decirle a C# que ordene automáticamente una lista de artículos despues de añadir. Si los elementos de una lista deben estar siempre ordenados se debe llamar al metodo Sort una vez se añaden nuevos elementos:

ListaColores.Sort();


Búsqueda de elementos en una lista

Se proveen un buen número de métodos con las clases listas y la ArrayList. El método más básico es el Contains(), en el cual cuando se pide a un objeto ArrayList o List devuelve true si el tema se encuentra en la lista, o false si no se encuentra.

El IndexOf() devuelve el valor de un índice de un elemento de la lista. Por ejemplo, el código siguiente muestra el valor de salida de 2, que es el índice de la posición de "Amarillo" en la cadena:

Liststring› ListaColores = new Liststring›();

ListaColores.Add ("Red");
ListaColores.Add ("Green");
ListaColores.Add ("Amarillo");
ListaColores.Add ("Morado");
ListaColores.Add ("Mamey");

Console.WriteLine(ListaColores.IndexOf("Amarillo"));

Si el elemento no se encuentra en la lista devuelve -1.

Esta técnica podría utilizarse para reemplazar un valor con otro. Por ejemplo, sin conocer de antemano el valor del índice del "Amarillo" cadena podemos cambiar a "Negro":

ListaColores[ListaColores.IndexOf("Amarillo")] = "Negro";

El LastIndexOf() método devuelve el valor del índice del último elemento de la lista para que coincida con el punto especificado. Esto es particularmente útil cuando la lista contiene elementos duplicados.

Obtener informacion de una lista

Hay dos miembros de la clase que son útiles para obtener información acerca de una lista de C # o colección de objetos ArrayList. La propiedad Capacity puede ser utilizada para identificar el número de artículos que puede almacenar una colección sin tener que cambiar el tamaño.

El propiedad Count, por otra parte, identifica cuantos artículos se encuentran actualmente almacenados en la lista. Por razones obvias, Capacity sera siempre superior a Count.

En los casos en que existe una gran diferencia entre el Count y Capacity los elementos pueden ser borrados con el método TrimExcess().

Borrado de elementos

Todos los elementos de una lista podrán ser borrados mediante el método Clear():

ListaColores.Clear();

Clear() elimina los elementos de la lista y establece la propiedad Count a cero. La propiedad Capacity, sin embargo, sigue siendo la misma. Para eliminar la Capacity despues de el método Clear() hay que llamar a TrimExcess().

jueves, 11 de marzo de 2010

Matrices

En las matrices de C#, los índices empiezan en cero. Las matrices de C# funcionan de forma similar a como lo hacen en la mayoría de los lenguajes populares; existen, sin embargo, algunas diferencias que se deben conocer.
Cuando se declara una matriz, los corchetes ([]) deben ir después del tipo, no después del identificador. Colocar los corchetes después del identificador no es sintácticamente válido en C#.


int[] table; // no int table[];Otro detalle es que el tamaño de la matriz no forma parte de su tipo. Esto permite declarar una matriz y asignarle cualquier matriz de objetos int, independientemente de la longitud de la matriz.


int[] numeros; // declare numeros de tipo array int de cualquier tamañonumeros = new int[10]; // numeros es un array de 10 elementosnumeros = new int[20]; // ahora es un array de 20 elementos
Declarar matricesC# admite matrices de una dimensión, matrices multidimensionales (matrices rectangulares) y matrices de matrices (matrices escalonadas). El siguiente ejemplo muestra cómo declarar diferentes tipos de matrices:

Matrices unidimensionales:

int[] numeros;


Matrices multidimensionales:

string[,] nombres;


Matrices de matrices (escalonadas):

byte[][] notas;


La declaración de matrices (como se muestra arriba) no crea realmente las matrices. En C#, las matrices son objetos cuyas instancias deben crearse. Los siguientes ejemplos muestran cómo crear matrices:

Matrices unidimensionales:

int[] numeros = new int[5];


Matrices multidimensionales:

string[,] nombres = new string[5,4];


Matrices de matrices (escalonadas):

byte[][] notas = new byte[5][];
for (int x = 0; x < notas.Length; x++)
{
notas[x] = new byte[4];
}



También se pueden utilizar matrices más grandes. Por ejemplo, se puede utilizar una matriz rectangular de tres dimensiones:


int[,,] buttons = new int[4,5,3];


Incluso, se pueden combinar matrices rectangulares y escalonadas. Por ejemplo, el siguiente código declara una matriz unidimensional que contiene matrices tridimensionales de matrices bidimensionales de tipo int:

int[][,,][,] numeros;


Ejemplo
El siguiente es un programa completo en C# que declara y crea instancias de las matrices comentadas anteriormente.


// arrays.csusing System;
class DeclararArraySimples
{
public static void Main()
{
// array de una dimensionint[] numeros = new int[5];

// Array Multidimensional
string[,] nombres = new string[5,4];

// Array-de-arrays (matriz escalonada)
byte[][] notas = new byte[5][];

// Crear la matriz escalonadafor (int i = 0; i < notas.Length; i++)
{
notas[i] = new byte[i+3];
}

// Imprimir la longitud por cada filafor (int i = 0; i < notas.Length; i++)
{
Console.WriteLine("Longitud de la fila {0} es {1}", i, notas[i].Length);
}
}
}

Resultado

Longitud de la fila 0 es 3
Longitud de la fila 1 es 4
Longitud de la fila 2 es 5
Longitud de la fila 3 es 6
Longitud de la fila 4 es 7


Inicializar matricesC# proporciona métodos simples y sencillos para inicializar matrices en el momento de la declaración encerrando los valores iniciales entre llaves ({}). Los siguientes ejemplos muestran diferentes modos de inicializar diferentes tipos de matrices.
Nota Si no inicializa una matriz en el momento de la declaración, sus miembros se inicializan automáticamente con el valor inicial predeterminado para el tipo de matriz. Además, si declara la matriz como campo de un tipo, se establecerá con el valor predeterminado null cuando cree la instancia del tipo.
Matrices unidimensionales

int[] numeros = new int[5] {1, 2, 3, 4, 5};
string[] nombres = new string[3] {"John", "Fer", "Juan"};
El tamaño de la matriz se puede omitir, como se indica a continuación:


int[] numeros = new int[] {1, 2, 3, 4, 5};
string[] nombres = new string[] {"John", "Fer", "Juan"};
También se puede omitir el operador new si se utiliza un inicializador como el siguiente:

int[] numeros = {1, 2, 3, 4, 5};
string[] nombres = {"John", "Fer", "Juan"};
Matrices multidimensionales

int[,] numeros = new int[3, 2] { {1, 2}, {3, 4}, {5, 6} };
string[,] hermanos = new string[2, 2] { {"John","Willy"}, {"Fer","Juan"} };
El tamaño de la matriz se puede omitir, como se indica a continuación:

int[,] numeros = new int[,] { {1, 2}, {3, 4}, {5, 6} };
string[,] hermanos = new string[,] { {"John","Willy"}, {"Fer","Juan"} };

También se puede omitir el operador new si se utiliza un inicializador como el siguiente:

int[,] numeros = { {1, 2}, {3, 4}, {5, 6} };
string[,] hermanos = { {"John","Willy"}, {"Fer","Juan"} };
Matriz escalonada (matriz de matrices)
Las matrices escalonadas se pueden inicializar como en el siguiente ejemplo:

int[][] numeros = new int[2][] { new int[] {2,3,4}, new int[] {5,6,7,8,9} };

El tamaño de la primera matriz se puede omitir, como se indica a continuación:


int[][] numeros = new int[][] { new int[] {2,3,4}, new int[] {5,6,7,8,9} };
O tambien


int[][] numeros = { new int[] {2,3,4}, new int[] {5,6,7,8,9} };

Observe que no existe sintaxis de inicialización para los elementos de una matriz escalonada.
Acceso a miembros de matrices
El acceso a los miembros de una matriz es sencillo. Por ejemplo, el siguiente código crea una matriz denominada numeros y, a continuación, asigna un 5 al quinto elemento de la matriz:


int[] numeros = {10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0};
numeros[4] = 5;
El siguiente código declara una matriz multidimensional y asigna el valor 5 al miembro ubicado en [1, 1]:


int[,] numeros = { {1, 2}, {3, 4}, {5, 6}, {7, 8}, {9, 10} };
numeros[1, 1] = 5;
La siguiente es una declaración de una matriz escalonada de una sola dimensión que contiene dos elementos. El primer elemento es una matriz de dos enteros, mientras que el segundo es una matriz de tres enteros:


int[][] numeros = new int[][] { new int[] {1, 2}, new int[] {3, 4, 5} };

La siguiente instrucción asigna 58 al primer elemento de la primera matriz y 667 al segundo elemento de la segunda matriz:


numeros[0][0] = 58;
numeros[1][1] = 667;
Las matrices son objetos
En C#, las matrices son realmente objetos. System.Array es el tipo base abstracto de todos los tipos de matrices. Las propiedades y otros miembros de la clase System.Array se pueden utilizar cuando sea necesario. Un ejemplo de esto sería utilizar la propiedad Length para obtener la longitud de una matriz. El siguiente código asigna la longitud de la matriz numeros, que es 5, a una variable denominada LogitudDeNumeros:


int[] numeros = {1, 2, 3, 4, 5};
int LongitudDeNumeros = numeros.Length;

La clase System.Array proporciona muchos otros métodos y propiedades útiles, como métodos para ordenar, buscar y copiar matrices.
Usar foreach con matrices
C# dispone de la instrucción foreach. Esta instrucción proporciona un modo simple y limpio de iterar en los elementos de una matriz. Por ejemplo, el siguiente código crea una matriz denominada numeros y la recorre mediante la instrucción foreach:


int[] numeros = {4, 5, 6, 1, 2, 3, -2, -1, 0};
foreach (int i in numeros)
{
System.Console.WriteLine(i);
}

Con matrices multidimensionales, se puede utilizar el mismo método para recorrer los elementos, por ejemplo:


int[,] numeros = new int[3, 2] {{9, 99}, {3, 33}, {5, 55}};
foreach(int i in numeros)
{
Console.Write("{0} ", i);
}
El resultado de este ejemplo es:
9 99 3 33 5 55

miércoles, 10 de marzo de 2010

Iteradores

Los iteradores son una nueva característica en C# 2.0. Un iterador es un método, descriptor de acceso get u operador que proporciona compatibilidad con una iteración foreach en una clase o estructura sin tener que implementar toda la interfaz IEnumerable. En su lugar, se proporciona sólo un iterador, que simplemente recorre las estructuras de datos de la clase. Cuando el compilador detecte el iterador, generará automáticamente los métodos Current, MoveNext y Dispose de la interfaz IEnumerable o IEnumerable.

Información general sobre los iteradores
Un iterador es una sección de código que devuelve una secuencia ordenada de valores del mismo tipo.

Un iterador se puede utilizar como el cuerpo de un método, operador o descriptor de acceso get.

El código del iterador utiliza la instrucción yield return para devolver a su vez cada elemento. yield break finaliza la iteración.

Se pueden implementar varios iteradores en una clase. Cada iterador debe tener un nombre único como cualquier nombre de clase y se puede invocar mediante código de cliente en una instrucción foreach de la manera siguiente: foreach(int x in ClaseEjemplo.Iterator2){}

El tipo de valor devuelto de un iterador debe ser IEnumerable, IEnumerator, IEnumerable o IEnumerator.

La palabra clave yield se utiliza para especificar el valor o valores devueltos. Cuando se llega a la instrucción yield return, se almacena la ubicación actual. La ejecución se reinicia desde esta ubicación la próxima vez que se llame al iterador.

Los iteradores son especialmente útiles con las clases de colección, ya que proporcionan una manera fácil de recorrer en iteración las estructuras de datos no triviales, por ejemplo, los árboles binarios.



Ejemplo
En este ejemplo, la clase DiasDeLaSemana es una clase de colección simple que almacena los días de la semana como cadenas. Después de cada iteración de un bucle foreach, se devuelve la cadena siguiente en la colección.

public class DiasDeLaSemana : System.Collections.IEnumerable
{
string[] Dias = { "Dom", "Lun", "Mar", "Mie", "Jue", "Vie", "Sab" };

public System.Collections.IEnumerator GetEnumerator()
{
for (int i = 0; i < Dias.Length; i++)
{
yield return Dias[i];
}
}
}

class TestDiasDeLaSemana
{
static void Main()
{
// Crear una clase de la clase coleccion
DiasDeLaSemana semana = new DiasDeLaSemana();

// Iterar con foreach
foreach (string dia in semana)
{
System.Console.Write(dia + " ");
}
}
}

Resultado
Dom Lun Mar Mie Jue Vie Sab

return

La instrucción return termina la ejecución del método en el que aparece y devuelve el control al método que realizó la llamada. También puede devolver un valor opcional. Si el método es del tipo void, la instrucción return se puede omitir.

Ejemplo
En el siguiente ejemplo, el método A() devuelve la variable Area como un valor de tipo double.

//sentencia_return.cs
using System;
class ReturnTest
{
static double CalcularArea(int r)
{
double area = r * r * Math.PI;
return area;
}

static void Main()
{
int radio = 5;
Console.WriteLine("El area es {0:0.00}", CalcularArea(radio));
}
}

Resultados
El area es 78.54

goto

La instrucción goto transfiere el control del programa directamente a una instrucción identificada por una etiqueta.

Comentarios
Un uso habitual de goto consiste en transferir el control a una etiqueta switch-case específica o a la etiqueta predeterminada de una instrucción switch.

La instrucción goto también es útil para salir de bucles de varios niveles de anidamiento.

Ejemplo
El ejemplo siguiente muestra cómo utilizar goto en una instrucción switch.

// sentencias_goto_switch.cs
using System;
class SwitchTest
{
static void Main()
{
Console.WriteLine("Dimensiones del cafe: 1=Small 2=Medium 3=Large");
Console.Write("Especifique su seleccion: ");
string s = Console.ReadLine();
int n = int.Parse(s);
int costo = 0;
switch (n)
{
case 1:
costo += 25;
break;
case
2:
costo += 25;
goto case 1;
case 3:
costo += 50;
goto case 1;
default:
Console.WriteLine("Seleccion Invalida.");
break;
}
if (costo != 0)
{
Console.WriteLine("Inserte {0} pesos.", costo);
}
Console.WriteLine("Negocio concluido.");
}
}


Entrada
2
Resultados del ejemplo
Dimensiones del cafe: 1=Small 2=Medium 3=Large
Entre su seleccion: 2
Inserte 50 pesos.
Negocio concluido.



El siguiente ejemplo muestra el uso de goto para salir de un conjunto de bucles anidados.

// sentencia_goto.cs
// Busqueda de bucles anidados
using System;
public class GotoTest1
{
static void Main()
{
int x = 200, y = 4;
int count = 0;
string[,] array = new string[x, y];

// Inicializo array:
for (int i = 0; i < x; i++)

for (int j = 0; j < y; j++)
array[i, j] = (++count).ToString();

// Pido el valor:
Console.Write("Digite un numero a buscar: ");

string numero = Console.ReadLine();

// Busqueda:
for (int i = 0; i < x; i++)
{
for (int j = 0; j < y; j++)
{
if (array[i, j].Equals(numero))
{
goto Found;
}
}
}

Console.WriteLine("El numero {0} no fue encontrado", numero);
goto Finish;

Found:
Console.WriteLine("El numero {0} fue encontrado.", numero);

Finish:
Console.WriteLine("Fin de la busqueda.");
}
}

Entrada
44

Resultados del ejemplo
Digite el numero a buscar: 44
El numero 44 fue encontrado.
Fin de la busqueda.

continue

La instrucción continue transfiere el control a la siguiente iteración de la instrucción de iteración envolvente donde aparece.

Ejemplo
En este ejemplo, se inicializa un contador que cuenta de 1 a 10. Utilizando la instrucción continue con la expresión (i < 9)continue y el final del cuerpo del bucle for.

// sentencia_continue.cs

class ContinueTest
{
static void Main()
{
for (int i = 1; i <= 10; i++)
{
if (i < 9)
{
continue;
}
Console.WriteLine(i);
}
}
}
Resultados
9
10

break

La instrucción break permite terminar el bucle envolvente más cercano o la instrucción switch en la cual aparece. El control se transfiere a la instrucción que sigue a la instrucción terminada, si existe alguna.

Ejemplo
En este ejemplo, la instrucción condicional contiene un contador que se supone que cuenta de 1 a 100; sin embargo, la instrucción break termina el bucle tras 4 iteraciones.

// sentencias_break.cs
using System;
class BreakTest
{
static void Main()
{
for (int i = 1; i <= 100; i++) { if (i == 5)
{
break;
}
Console.WriteLine(i);
}
}
}


Resultados
1
2
3
4

Este ejemplo muestra el uso de break en una instrucción switch.

// sentencias_break2.cs
// break y switch
using System;
class Switch
{
static void Main()
{
Console.Write("Entre su seleccion (1, 2, or 3): ");
string s = Console.ReadLine();
int n = Int32.Parse(s);

switch (n)
{
case 1:
Console.WriteLine("El valor acutal es {0}", 1);
break;
case 2:
Console.WriteLine("El valor actual es {0}", 2);
break;
case 3:
Console.WriteLine("El valor actual es {0}", 3);
break;
default:
Console.WriteLine("Seleccion Invalida.");
break;
}
}
}


Entrada
1

Resultados del ejemplo
Entre su seleccion (1, 2, o 3): 1
El valor actual es 1

Comentarios
Si se escribió 4, el resultado sería:

Entre su seleccion (1, 2, o 3): 4
Seleccion Invalida.

Instrucciones de salto

La alteración del flujo secuencial normal de un programa se consigue mediante instrucciones de salto, las cuales producen una transferencia inmediata del control del programa. Las siguientes palabras clave se utilizan en instrucciones de salto:

break

continue

goto

return

throw

while

La instrucción while ejecuta una instrucción o un bloque de instrucciones repetidamente hasta que una expresión especificada se evalúa como false.

Ejemplo
//sentencias_while.cs
using System;
class WhileTest
{
static void Main()
{
int n = 1;
while (n < 6)
{
Console.WriteLine("El valor actual de n es: {0}", n);
n++;
}
}
}


Resultados
El valor actual de n es: 1
El valor actual de n es: 2
El valor actual de n es: 3
El valor actual de n es: 4
El valor actual de n es: 5

//sentencias_while_2.cs
using System;
class WhileTest
{
static void Main()
{
int n = 1;
while (n++ < 6)
{
Console.WriteLine("El valor actual de n es: {0}", n);
}
}
}

Resultados
El valor actual de n es: 2
El valor actual de n es: 3
El valor actual de n es: 4
El valor actual de n es: 5
El valor actual de n es: 6

Como la comprobación de la expresión while tiene lugar antes de la ejecución del bucle, las instrucciones internas de un bucle while pueden no llegar a ejecutarse. Esto es diferente del bucle do que se ejecuta una o varias veces.

Un bucle while se puede terminar cuando una instrucción break, goto, return o throw transfiere el control fuera del bucle. Para pasar el control a la siguiente iteración sin salir del bucle, use la instrucción continue. Observe la diferencia en los resultados de los tres ejemplos anteriores con relación a dónde se incrementa int n. En el ejemplo siguiente no se genera ningún resultado.

//sentencias_while_3.cs
// ninguna salida sera generada
using System;
class WhileTest
{
static void Main()
{
int n = 5;
while (++n < 6)
{
Console.WriteLine("El valor actual de n es: {0}", n);
}
}
}

Utilizar foreach con matrices

C# dispone de la instrucción foreach. Esta instrucción proporciona un modo simple y limpio de recorrer en iteración los elementos de una matriz. Por ejemplo, el siguiente código crea una matriz denominada numeros y la recorre mediante la instrucción foreach:

int[] numeros = { 4, 5, 6, 1, 2, 3, -2, -1, 0 };
foreach (int i in numeros)
{
System.Console.WriteLine(i);
}


Con matrices multidimensionales, se puede utilizar el mismo método para recorrer los elementos, por ejemplo:

int[,] numeros2D = new int[3, 2] { { 9, 99 }, { 3, 33 }, { 5, 55 } };
foreach (int i in numeros2D)
{
System.Console.Write("{0} ", i);
}


El resultado de este ejemplo es:

9 99 3 33 5 55

Sin embargo, con matrices multidimensionales, utilizar un bucle for anidado proporciona más control sobre los elementos de la matriz.

foreach, in

La instrucción foreach repite un grupo de instrucciones incluidas en el bucle para cada elemento de una matriz o de un objeto collection. La instrucción foreach se utiliza para recorrer en iteración una colección de elementos y obtener la información deseada, pero no se debe utilizar para cambiar el contenido de la colección, ya que se pueden producir efectos secundarios imprevisibles.

Comentarios
Las instrucciones del bucle siguen ejecutándose para cada elemento de la matriz o la colección. Cuando ya se han recorrido todos los elementos de la colección, el control se transfiere a la siguiente instrucción fuera del bloque foreach.

En cualquier punto dentro del bloque foreach, puede salir del bucle utilizando la palabra clave break o pasando directamente la iteración siguiente del bucle mediante la palabra clave continue.
También se puede salir de un bucle foreach mediante las instrucciones goto, return o throw.

Ejemplo
En este ejemplo, foreach se utiliza para mostrar el contenido de una matriz de enteros.

//foreach.cs
class ForEachTest
{
static void Main(string[] args)
{
int[] arrayEjemplo = new int[] { 0, 1, 2, 3, 5, 8, 13 };
foreach (int i in arrayEjemplo)
{
System.Console.WriteLine(i);
}
}
}

Resultados
0
1
2
3
5
8
13

for

El bucle for ejecuta una instrucción o un bloque de instrucciones repetidamente hasta que una determinada expresión se evalúa como false. El bucle for es útil para recorrer en iteración matrices y para procesar secuencialmente. En el ejemplo siguiente el valor de int i se escribe en la consola y el valor de i se va incrementando en 1 en el bucle.

Ejemplo
// sentencia_for.cs
// for loop

using System;
class ForLoopTest
{
static void Main()
{
for (int i = 1; i <= 5; i++)
{
Console.WriteLine(i);
}
}
}
Resultados
1
2
3
4
5
Comentarios
La instrucción for ejecuta la instrucción o instrucciones internas repetidamente del siguiente modo:

Primero, se evalúa el valor inicial de la variable i.

A continuación, mientras el valor de i sea menor o igual que 5, la condición se evalúa como true, se ejecuta la instrucción Console.WriteLine y se vuelve a evaluar i.

Cuando i es mayor que 5, la condición se convierte en false y el control se transfiere fuera del bucle.

Puesto que la comprobación de la expresión condicional tiene lugar antes de la ejecución del bucle, las instrucciones internas de un bucle for pueden no llegar a ejecutarse.

Todas las expresiones de la instrucción for son opcionales; por ejemplo, la siguiente instrucción se utiliza para crear un bucle infinito:

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

do

La instrucción do ejecuta una instrucción o un bloque de instrucciones entre { } repetidamente hasta que una expresión especificada se evalúe como false. En el ejemplo siguiente las instrucciones de bucle do-while se ejecutan con la condición de que la variable y sea menor que 5.

Ejemplo

// sentencias_do.cs
using System;
public class TestDoWhile
{
public static void Main ()
{
int x = 0;
do
{
Console.WriteLine(x);
x++;
} while (x < 5);
}
}

Resultados

0
1
2
3
4


Comentarios
A diferencia de la instrucción while, un bucle do-while se ejecuta una vez antes de que se evalúe la expresión condicional.
En cualquier punto dentro del bloque do-while, puede salir del bucle utilizando la instrucción break. Puede pasar directamente a la instrucción de evaluación de expresión while utilizando la instrucción continue; si la expresión se evalúa como true, la ejecución continúa en la primera instrucción del bucle. Si la expresión se evalúa como false, la ejecución continúa en la primera instrucción detrás del bucle do-while.

También se puede salir de un bucle do-while mediante las instrucciones goto, return o throw.

switch

La instrucción switch es una instrucción de control que controla múltiples selecciones y enumeraciones pasando el control a una de las instrucciones case de su cuerpo, como se muestra en el ejemplo siguiente:

int caseSwitch = 1;
switch (caseSwitch)
{
case 1:
Console.WriteLine("Case 1");
break;
case 2:
Console.WriteLine("Case 2");
break;
default:
Console.WriteLine("Default case");
break;
}
Comentarios
El control se transfiere a la instrucción case que coincide con el valor del modificador. La instrucción switch puede incluir cualquier número de instancias case, sin embargo dos instrucciones case nunca pueden tener el mismo valor. La ejecución del cuerpo de la instrucción empieza en la instrucción seleccionada y continúa hasta que la instrucción break transfiere el control fuera del cuerpo case. Es necesario introducir una instrucción de salto como break después de cada bloque case, incluido el último bloque, se trate de una instrucción case o de una instrucción default. Con una excepción, (a diferencia de la instrucción switch de C++), C# no admite el paso implícito de una etiqueta case a otra. Esta excepción se produce si una instrucción case no tiene ningún código.

Si ninguna expresión case coincide con el valor de la instrucción switch, entonces el control se transfiere a las instrucciones que siguen la etiqueta default opcional. Si no existe ninguna etiqueta default, el control se transfiere fuera de la instrucción switch.

Ejemplo
// Sentencia_switch.cs
using System;
class SwitchTest
{
static void Main()
{
Console.WriteLine("Dimenciones del cafe: 1=Small 2=Medium 3=Large");
Console.Write("Entre su seleccion: ");
string s = Console.ReadLine();
int n = int.Parse(s);
int costo = 0;
switch(n)
{
case 1:
costo += 25;
break;
case 2:
costo += 25;
goto case 1;
case 3:
costo += 50;
goto case 1;
default:
Console.WriteLine("Seleccion Invalida. Seleccione 1, 2 o 3.");
break;
}
if (costo != 0)
{
Console.WriteLine("Debe insertar {0} pesos.", costo);
}
Console.WriteLine("Negocio finalizado, Gracias...");
}
}
Entrada
2
Resultados del ejemplo
Dimenciones del cafe: 1=Small 2=Medium 3=Large
Entre su seleccion: 2
Debe insertar 50 pesos.
Negocio finalizado, Gracias.
El siguiente ejemplo muestra que se permite el paso de una etiqueta case a otra para etiquetas case vacías.

// Sentencia_switch2.cs
using System;
class SwitchTest
{
static void Main()
{
int n = 2;
switch(n)
{
case 1:
case 2:
case 3:
Console.WriteLine("Esto es 1, 2 o 3.");
break;
default:
Console.WriteLine("No se que es...");
break;
}
}
}
Resultados
Esto es 1, 2 o 3.
Descripción del código
En el ejemplo anterior, se utilizó una variable de tipo integral, n, para los casos de la instrucción switch. Observe que también se puede utilizar la variable de cadena, s, directamente. En ese caso, la estructura switch puede presentar la siguiente forma:

switch(s)
{
case "1":
// ...
case "2":
// ...
}

martes, 9 de marzo de 2010

if-else

La instrucción if selecciona una instrucción para ejecución en base al valor de una expresión Boolean. En el ejemplo siguiente un indicador Boolean flagCheck se establece en true y, a continuación, se protege en la instrucción if. El resultado es: El indicador se pone en true.

bool flagCheck = true;
if (flagCheck == true)
{
Console.WriteLine("El flag esta true.");
}
else
{
Console.WriteLine("El flag esta false.");
}
Comentarios
Si la expresión en el paréntesis se evalúa como true, a continuación se ejecuta la instrucción Console.WriteLine("El flag esta true."); . Después de ejecutar la instrucción if, el control se transfiere a la siguiente instrucción. Else no se ejecuta en este ejemplo.

Si se desea ejecutar más de una instrucción, es posible ejecutar varias instrucciones en forma condicional al incluirlas en bloques mediante { }, al igual que en el ejemplo anterior.

Las instrucciones que se van a ejecutar como resultado de comprobar la condición pueden ser de cualquier tipo, incluida otra instrucción if anidada dentro de la instrucción if original. En las instrucciones if anidadas, la cláusula else pertenece a la última instrucción if que no tiene una cláusula else correspondiente. Por ejemplo:

if (x > 10)
if (y > 20)
Console.Write("Setencia_1");
else
Console.Write("Sentencia_2");

En este ejemplo, se mostrará Sentencia_2 si la condición (y > 20) se evalúa como false. No obstante, si desea asociar Sentencia_2 a la condición (x >10), utilice llaves:

if (x > 10)
{
if (y > 20)
Console.Write("Sentencia_1");
}
else
Console.Write("Sentencia_2");
En este caso, se mostrará Sentencia_2 si la condición (x > 10) se evalúa como false.

Ejemplo 1
En este ejemplo, se escribe un carácter desde el teclado y el programa comprueba si se trata de un carácter alfabético. En ese caso, comprueba si es minúscula o mayúscula. En cada caso, se muestra el mensaje apropiado.

// Sentencias_if_else.cs
// if-else ejemplo
using System;
class IfTest
{
static void Main()
{
Console.Write("Entre un caracter: ");
char c = (char)Console.Read();
if (Char.IsLetter(c))
{
if (Char.IsLower(c))
{
Console.WriteLine("El caracter esta en minuscula.");
}
else
{
Console.WriteLine("El caracter esta en mayuscula.");
}
}
else
{
Console.WriteLine("No es un caracter del alfabeto.");
}
}
}

Resultado
2
Resultados del ejemplo
Entre un caracter: 2
El caracter no es alfabético.
A continuación se ofrece otro ejemplo:

Ejecución Nº 2:
Entre un caracter: A
El caracter está en mayúscula.

Ejecución Nº 3:
Entre un caracter: h
El carácter esta en minúscula.

También es posible extender la instrucción if de modo que puedan controlarse varias condiciones, mediante la construcción else-if siguiente:

if (Condicion_1)
{
// Sentencia_1;
}
else if (Condicion_2)
{
// Sentencia_2;
}
else if (Condicion_3)
{
// Sentencia_3;
}
else
{
// Sentencia_n;
}

Ejemplo 2
Este ejemplo comprueba si el carácter especificado es una letra minúscula, mayúscula o un número. En cualquier otro caso, se tratará de un carácter no alfanumérico. El programa utiliza la anterior estructura else-if en escalera.

// Sentencias_if_else2.cs
// else-if

using System;
public class
IfTest
{
static void Main()
{
Console.Write("Entre un caracter: ");
char c = (char)Console.Read();

if (Char.IsUpper(c))
{
Console.WriteLine("El caracter está en mayúscula.");
}
else if (Char.IsLower(c))
{
Console.WriteLine("El caracter está en minúscula.");
}
else if (Char.IsDigit(c))
{
Console.WriteLine("El caracter es un numero.");
}
else
{
Console.WriteLine("El caracter no es alfanumerico.");
}
}
}
Resultado
E
Resultados del ejemplo
Entre un caracter: E
El caracter esta en mayúscula.

A continuación se ofrecen otros ejemplos de ejecuciones:

Ejecución Nº 2:
Entre un caracter: e
El caracter está en minúscula.

Ejecución Nº 3:
Entre un caracter: 4
El caracter es un número.

Ejecución Nº 4:

Entre un caracter: $
El caracter no es alfanumerico.

Tipos de instrucciones

C# dispone de las siguientes categorías de instrucciones:

Las acciones que realiza un programa se expresan en instrucciones. Entre las acciones comunes se incluyen declarar variables, asignar valores, llamar a métodos, recorrer colecciones en bucle y crear una bifurcación a uno u otro bloque de código, en función de una condición determinada. El orden en el que se ejecutan las instrucciones en un programa se denomina flujo de control o flujo de ejecución. El flujo de control puede variar cada vez que se ejecuta un programa, en función de cómo reacciona el programa a la entrada que recibe en tiempo de ejecución.

Una instrucción puede constar de una sola línea de código que finaliza en un punto y coma o de una serie de instrucciones de una sola línea en un bloque. Un bloque de instrucciones se incluye entre llaves {} y puede contener bloques anidados. En el código siguiente se muestran dos ejemplos de instrucciones de una sola línea y un bloque de instrucciones de varias líneas:

    static void Main()
    {
        // Declaración.
        int contador;

        // Asignación de lo declarado.
        counter = 1;

        // Error! Esto es una expresión, no una declaración de expresión.
        // counter + 1;

        // Las declaraciones de declaración con inicializadores son funcionalmente
        // equivalente a la declaración de declaración seguida de la declaración de asignación:
        int[] radios = { 15, 32, 108, 74, 9 }; // Declare e inicialice un arreglo.
        const double pi = 3.14159; // Declare and inicialice la constante.

        // por cada bloque de declaración que contenga multiples declaraciones.
        foreach (int radio in radios)
        {
            // Declaración de sentencia con inicializador.
            double circunferencia = pi * (2 * radio);

            // Declaración de expresión (invocación de método). Una sola línea
            // la declaración puede abarcar varias líneas de texto porque los saltos de línea
            // se tratan como espacios en blanco, que el compilador ignora.
            System.Console.WriteLine("El radio del circulo #{0} is {1}. Circunferencia = {2:N2}",
                                    contador, redio, circunferencia);

            // Expression statement (postfix increment).
            contador++;
        } // Fin del bloque de instrucciones foreach
    } // Fin del cuerpo del método principal.
} // Fin de la clase SimpleStatements.
/*
   Salida:
    El radio del circulo #1 = 15. Circunferencia = 94.25
    El radio del circulo #2 = 32. Circunferencia = 201.06
    El radio del circulo #3 = 108. Circunferencia = 678.58
    El radio del circulo #4 = 74. Circunferencia = 464.96
    El radio del circulo #5 = 9. Circunferencia = 56.55
*/

Tipos de instrucciones

En la tabla siguiente se muestran los distintos tipos de instrucciones de C# y sus palabras clave asociadas, con vínculos a temas que incluyen más información:

TIPOS DE INSTRUCCIONES
CategoríaPalabras clave de C# / notas
Instrucciones de declaraciónUna instrucción de declaración introduce una variable o constante nueva. Una declaración de variable puede asignar opcionalmente un valor a la variable. En una declaración de constante, se requiere la asignación.
Instrucciones de expresiónLas instrucciones de expresión que calculan un valor deben almacenar el valor en una variable.
Instrucciones de selecciónLas instrucciones de selección permiten crear bifurcaciones a diferentes secciones de código, en función de una o varias condiciones especificadas. Para obtener más información, vea los temas siguientes:
Instrucciones de iteraciónLas instrucciones de iteración permiten recorrer en bucle colecciones, como matrices, o realizar el mismo conjunto de instrucciones repetidas veces hasta que se cumpla una condición especificada. Para obtener más información, vea los temas siguientes:
Instrucciones de saltoLas instrucciones de salto transfieren el control a otra sección de código. Para obtener más información, vea los temas siguientes:
Instrucciones para el control de excepcionesLas instrucciones para el control de excepciones permiten recuperarse correctamente de condiciones excepcionales producidas en tiempo de ejecución. Para obtener más información, vea los temas siguientes:
Checked y uncheckedLas instrucciones checked y unchecked permiten especificar si las operaciones numéricas pueden producir un desbordamiento cuando el resultado se almacena en una variable que es demasiado pequeña para contener el valor resultante. Para obtener más información, vea checked y unchecked.
Instrucción awaitSi marca un método con el modificador async , puede usar el operador await en el método. Cuando el control alcanza una expresión await en el método asincrónico, el control se devuelve al autor de llamada y el progreso del método se suspende hasta que se completa la tarea esperada. Cuando se completa la tarea, la ejecución puede reanudarse en el método.

Para obtener un ejemplo sencillo, vea la sección "Métodos asincrónicos" de Métodos. Para obtener más información, vea Programación asincrónica con Async y Await.
Instrucción yield returnUn iterador realiza una iteración personalizada en una colección, como una lista o matriz. Un iterador utiliza la instrucción yield return para devolver cada elemento de uno en uno. Cuando se alcanza una instrucción yield return, se recuerda la ubicación actual en el código. La ejecución se reinicia desde esa ubicación la próxima vez que se llama el iterador.

Para obtener más información, consulta Iteradores.
Instrucción fixedLa instrucción fixed impide que el recolector de elementos no utilizados cambie la ubicación de una variable móvil. Para obtener más información, vea fixed.
Instrucción lockLa instrucción lock permite limitar el acceso a bloques de código a un solo subproceso de cada vez. Para obtener más información, vea lock.
Instrucciones con etiquetaPuede asignar una etiqueta a una instrucción y, después, usar la palabra clave goto para saltar a la instrucción con etiqueta. (Vea el ejemplo de la línea siguiente).
Instrucción vacíaLa instrucción vacía consta únicamente de un punto y coma. No hace nada y se puede usar en lugares en los que se requiere una instrucción, pero no es necesario realizar ninguna acción.

Instrucciones de declaración

En el código siguiente se muestran ejemplos de declaraciones de variables con y sin una asignación inicial, y una declaración constante con la inicialización necesaria.


// Declaración de sentencia variable.
double area;
double radio = 2;

// Declaración de sentencia constante.
const double pi = 3.14159;

Instrucciones de expresión

En el código siguiente se muestran ejemplos de instrucciones de expresión, que incluyen la asignación, la creación de objetos con asignación y la invocación de método.

area = 3.14 * (radio * radio);

// Error. No hay sentencia porque no hay asignación:
//circ * 2;

// Expression statement (method invocation).
System.Console.WriteLine();

// Declaración de expresión (creación de un nuevo objeto).
System.Collections.Generic.List<string> strings =
    new System.Collections.Generic.List<string>();

Instrucción vacía

En los ejemplos siguientes se muestran dos usos de una instrucción vacía:


void ProcesarMensajes()
{
    while (ProcesarMensajes())
        ; // Sentencia aquí.
}

void F()
{
    //...
    if (terminado) goto exit;
//...
exit:
    ; // Sentencia aquí.
}

Instrucciones insertadas

Algunas instrucciones, por ejemplo, las instrucciones de iteración, siempre van seguidas de una instrucción insertada. Esta instrucción insertada puede ser una sola instrucción o varias instrucciones incluidas entre llaves {} en un bloque de instrucciones. Las instrucciones insertadas de una sola línea también pueden ir entre llaves {}, como se muestra en el siguiente ejemplo:


// Estilo recomendado. Declaración incorporada en bloque.
foreach (string s in System.IO.Directory.GetDirectories(
                        System.Environment.CurrentDirectory))
{
    System.Console.WriteLine(s);
}

// No recomendado.
foreach (string s in System.IO.Directory.GetDirectories(
                        System.Environment.CurrentDirectory))
    System.Console.WriteLine(s);

Una instrucción insertada que no está incluida entre llaves {} no puede ser una instrucción de declaración o una instrucción con etiqueta. Esto se muestra en el ejemplo siguiente:


if(pointB == true)
    //Error CS1023:
    int radius = 5;

Coloque la instrucción insertada en un bloque para solucionar el error:


if (b == true)
{
    // OK:
    System.DateTime d = System.DateTime.Now;
    System.Console.WriteLine(d.ToLongDateString());
}

Bloques de instrucciones anidadas

Los bloques de instrucciones pueden anidarse, como se muestra en el código siguiente:


foreach (string s in System.IO.Directory.GetDirectories(
    System.Environment.CurrentDirectory))
{
    if (s.StartsWith("CSharp"))
    {
        if (s.EndsWith("FolderTemporal"))
        {
            return s;
        }
    }
}
return "No Encontrado.";

Instrucciones inaccesibles

Si el compilador determina que el flujo de control no puede alcanzar nunca una instrucción determinada bajo ninguna circunstancia, producirá una advertencia CS0162, como se muestra en el ejemplo siguiente:


// Un ejemplo simplificado de código inalcanzable.
const int val = 5;
if (val < 4)
{
    System.Console.WriteLine("Nunca escribiré nada!."); //CS0162
}