jueves, 5 de marzo de 2009

Introducción a C#

Desde el comienzo

Como en todos los lenguajes de programación, las estructuras de comparación y repetición son las que dan vida a los programas, a continuación hablamos un poco de ellas.



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 ()

{


}
else

{


}


El significado de esta instrucción es el siguiente: se evalúa la expresión , que ha de devolver un valor lógico. Si es cierta (devuelve true) se ejecutan las , y si es falsa (false) se ejecutan las 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 como 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 ()
{
case :

case :

...
default:

}
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.
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 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 ;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 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");
}
}
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 ()
{

}
Su significado es el siguiente: Se evalúa la indicada, que ha de producir un valor lógico. Si es cierta (valor lógico true) se ejecutan las y se repite el proceso de evaluación de y ejecución de hasta que deje de serlo. Cuando sea falsa (false) se pasará a ejecutar la instrucción siguiente al while. En realidad 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;
if (args.Length > 0)
while (actual < actual =" actual">del bucle.
Por otro lado, dentro de las 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 y reevaluarse la del bucle, volviéndose a ejecutar las 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 {

} while();

La única diferencia del significado de do...while respecto al de while es que en vez de evaluar primero la condición y ejecutar sólo si es cierta, do...while primero ejecuta las y luego mira la 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 del do...while.
do ... while está especialmente destinado para los casos en los que haya que ejecutar las al menos una vez aún cuando la condición sea falsa desde el principio, como ocurre en el siguiente ejemplo:

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 (; ; ){

}
El significado de esta instrucción es el siguiente: se ejecutan las instrucciones de , que suelen usarse para definir e inicializar variables que luego se usarán en . Luego se evalúa , y si es falsa se continúa ejecutando por la instrucción siguiente al for; mientras que si es cierta se ejecutan las indicadas, luego se ejecutan las instrucciones de -que como su nombre indica suelen usarse para modificar los valores de variables que se usen en - y luego se reevalúa repitiéndose el proceso hasta que ésta última deje de ser cierta.
En 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 , y 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 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.
Como en el resto de instrucciones hasta ahora vistas, en puede ser tanto una única instrucción como un bloque de instrucciones. Además, las variables que se definan en serán visibles sólo dentro de esas .
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 <>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 ( in ) {

}
El significado de esta instrucción es muy sencillo: se ejecutan para cada uno de los elementos de la indicada. es una variable de sólo lectura de tipo que almacenará en cada momento el elemento de la colección que se esté procesando y que podrá ser accedida desde .
Es importante señalar que no puede valer null porque entonces saltaría una excepción de tipo System.NullReferenceException, y que ha de ser un tipo cuyos objetos puedan almacenar los valores de los elementos de
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#]
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;
}
}
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 indicado puede o no almacenar los objetos de la colección.
Por ejemplo, si en el ejemplo anterior sustituimos en el último foreach el 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, 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 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 .
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.

5 comentarios:

  1. Hola profe... leí y "practique" hasta el ejemplo q muestra como se utiliza "switch" y me parece excelente... pro bueno, ya q vamos a trabajar en C#, creo q es muy obvio q todos tengamos el Visual Studio 2005, q es el q utilizamos en el cole! así q aqui se los dejo:

    CD 1 :
    http://rapidshare.com/files/53487045/VSPROD1.part1.rar
    http://rapidshare.com/files/53489755/VSPROD1.part2.rar
    http://rapidshare.com/files/53695921/VSPROD1.part3.rar
    http://rapidshare.com/files/53700679/VSPROD1.part4.rar
    http://rapidshare.com/files/53703645/VSPROD1.part5.rar
    http://rapidshare.com/files/53706250/VSPROD1.part6.rar

    CD 2 :
    http://rapidshare.com/files/53756685/VSPROD2.part1.rar
    http://rapidshare.com/files/53737556/VSPROD2.part2.rar
    http://rapidshare.com/files/53728933/VSPROD2.part3.rar

    ResponderEliminar
  2. Gracias Saul
    Excelente participación de tu parte, gran aporte a ala comunidad.

    Saludos

    ResponderEliminar
  3. prof tengo una consulta que son bucles?

    ResponderEliminar
  4. Jenn:

    Son estructuras de repetición, también se les conoce como bucles, que raro verdad?. como el FOR, el WHILE y el FOR EACH, así como Do while

    Saludos

    ResponderEliminar
  5. muy buenas enseñansas

    sigue asi

    algun todo sera pagado grasias
    por aportar el conocimiento

    ResponderEliminar