C sharp NET / Texto Completo

De Wikilibros, la colección de libros de texto de contenido libre.

Esta es la versión para imprimir de C sharp NET.
  • Si imprimes esta página, o eliges la opción de Vista preliminar de impresión de tu navegador, verás que desaparecen este cuadro y los elementos de navegación de arriba y de la izquierda, pues no son útiles en una versión impresa.
  • Pulsando antes en Refrescar esta página te asegurarás de obtener los últimos cambios del libro antes de imprimirlo.
  • Para más información, puedes ver Wikilibros:Versión para imprimir.


Tabla de contenidos


C sharp NET

El lenguaje C#

Los primeros rumores de que Microsoft estaba desarrollando un nuevo lenguaje de programación surgieron en 1998, haciendo referencia a un lenguaje que entonces llamaban COOL y que decían era muy similar a Java. En junio de 2000, Microsoft despejó todas las dudas liberando la especificación de un nuevo lenguaje llamado C#. A esto le siguió rápidamente la primera versión de prueba del entorno de desarrollo estándar (SDK) .NET, que incluía un compilador de C#. El nuevo lenguaje estaba diseñado por Anders Hejlsberg ( creador de Turbo Pascal y arquitecto de Delphi ), Scott Wiltamuth y Peter Golde. Entonces describieron el lenguaje como "...simple, moderno, orientado a objetos, de tipado seguro y con una fuerte herencia de C/C++".

Una muestra de esta nueva tecnología es el nuevo lenguaje de programación C#. Este nuevo lenguaje orientado a objetos con énfasis en internet se basa en las lecciones aprendidas de los lenguajes C, C++, Java y Visual Basic. Por ello se trata de un lenguaje que combina todas las cualidades que se pueden esperar de un lenguaje moderno (orientación a objetos, gestión automática de memoria, etc.) a la vez que proporciona un gran rendimiento.

En este curso intentaremos examinar las cualidades de este lenguaje desde lo más básico a lo más avanzado incluyendo la versión 2.0. Examinaremos paso a paso cómo crear poderosas aplicaciones de escritorio o basadas en web.

Tabla de Contenidos

  1. Capítulo 0: Breve introducción a los lenguajes de programación
  2. Capítulo 1: Introducción
  3. Capítulo 2: Primer programa
  4. Capítulo 3: Fundamentos del lenguaje
  5. Capítulo 4: Estructuras de control
  6. Capítulo 5: Introducción a las clases y objetos
  7. Capítulo 6: Herencia y Polimorfismo
  8. Capítulo 7: Sobrecargando operadores
  9. Capítulo 8: Estructuras
  10. Capítulo 9: Interfaces
  11. Capítulo 10: Estructuras de datos
  12. Capítulo 11: Cadenas y Expresiones regulares
  13. Capítulo 12: Manejo de excepciones
  14. Capítulo 13: Delegación y Eventos
  15. Capítulo 14: Creando Aplicaciones gráficas usando Windows.Forms
  16. Capítulo 15: Creando Aplicaciones gráficas usando Gtk# y Qyoto(Qt4)
  17. Capítulo 16: Accediendo a la información usando ADO.NET
  18. Capítulo 17: Programando Aplicaciones WEB con ASP.NET 2.0
  19. Capítulo 18: Programando Servicios del Web
  20. Capítulo 19: XML
  21. Capítulo 20: Ensamblados y Versiones
  22. Capítulo 21: Atributos y Reflexión
  23. Capítulo 22: Programando en Redes
  24. Capítulo 23: .NET y COM
  25. Capítulo 24: Creando aplicaciones multimedia SDL y DirectX
  26. Capítulo 25: OpenGL y Direct3D
  27. Capítulo 26: Utilizando Bases de Datos
  28. Capítulo 27: Solución a los problemas propuestos
  29. Capítulo 28: Manejo de puertos
  30. Capítulo 29: Sockets
  • Texto Completo
    Versión para imprimir de este libro

Pre-requisitos necesarios para este curso

Lo único que necesitáis para este curso es tener un compilador de C# y un entorno de ejecución de código gestionado. Los más utilizados son el mono, dotgnu y sdk de microsoft.

Autores

Editores principales (si has colaborado añade tu nombre a esta lista):

Fabian Seoane. Tutorial de MonoHispano, migración y editor.

David Cañar - Creación del libro, Capitulo 2 y varias porciones del capítulo 1, 3 y 4

Javier Hernández Sánchez - Creacion del capitulo 9 Interfaces

Sebastian Sasías - Revisión, ampliación y formalización de conceptos (en proceso)

Gustavo Novaro - Varios Para más detalles vea el historial.

Licencia


GNU Heckert Se autoriza la copia, la distribución y la modificación de este documento bajo los términos de la licencia de documentación libre GNU, versión 1.2 o cualquier otra que posteriormente publique la Fundación del Software Libre (Free Software Fundation); sin secciones invariantes (Unvariant Sections), textos de portada (Front-Cover Texts), ni textos de contraportada (Back-Cover Texts).

Se incluye una copia en inglés de esta licencia en el artículo Text of the GNU Free Documentation License.


Referencias

Este Wikilibro tiene extenso material tomado del tutorial de C# del proyecto MonoHispano (http://monohispano.org/tutoriales/csharp/).

Introduccion a los lenguajes

Una Breve Introducción a los Lenguajes de Programación

Los lenguajes modernos de programación tienen carácterísticas que pueden asemejarse en buen grado a los lenguajes hablados como el Español, el Inglés, o cualquier otro; ya que al igual que en la comunicación oral o escrita, los lenguajes de programación tienen un vocabulario definido, además de reglas ortográficas, de estructura, de puntuación, es decir la sintaxis que deben seguir y por supesto una semántica, esto es el significado que adquieren las conformaciones basadas en las reglas antes mencionadas.

Como en los lenguajes humanos corrientes (tambien generalizado como Lenguaje Natural), estas reglas deben tomarse en cuenta para que las ideas que tratamos de expresar tengan sentido. También, un lenguaje de programación al igual que un lenguaje natural cambia con el tiempo. Si tú eres un hispano-hablante sabrás que en cada país hispanoamericano se usan palabras que en otros países no se utilizan o las mismas palabras tienen un significado distinto entre países (esto es llamado ambigüedad): el idioma Español ha venido evolucionando con el tiempo y se ha adaptado a la geografía. En este mismo sentido, el lenguaje de programación C#.NET es una actualización técnica de otros lenguajes de programación más antiguos como lo son el C, C++, Java, Visual Basic, Delphi, etc. El creador de este lenguaje Anders Heljsberg, es un calificado profesional de la informática que además ha desarrollado lenguajes y herramientas como Turbo Pascal, Delphi (de Borland Co.) y Visual J++ (Microsoft). Por lo que C# pretende ser el siguiente eslabón en la evolución de los lenguajes de programación mas avanzados, buscando combinar en proporciones adecuadas: Potencia, Sencillez y Actualidad/Tendencia.


La evolución de los ordenadores (computadores) y de los lenguajes de programación ha sido grandísima. No hace muchos años existían personas que tenían que hacer agujeros en tarjetas de cartulina para poder dar instrucciones al computador: eran las famosas tarjetas perforadas. Pocos años despúes de esos días existían personas (y hasta ahora existen aquellos) que pueden "hablar con el ordenador", se trata de informáticos que en su época solo disponían de elementos de muy bajo nivel para controlar el computador, eso hasta el día de hoy es la base de las técnicas de cómputo, independientemente de cuanto hayan aumentado las capacidades de memorias, velocidades de microprocesadores, miniaturizaciones, etc.

La forma en que un ordenador recibe instrucciones es una manera peculiar. **** Añadir más sobre el lenguaje binario (bajo nivel) y los lenguajes de alto nivel**** (en construcción)

Ya que hemos recalcado las similitudes entre los lenguajes de programación y los lenguajes naturales también hay que tener presente que un lenguaje de programación es mucho más estricto que uno natural en el sentido de que no pueden existir ambigüedades. Es muy fácil en el idioma Español tener frases que impliquen algo que ya conocemos o que signifiquen cosas diferentes. Por el contrario los lenguajes de programación son claros, específicos y directos, no se admiten ambigüedades ni suposiciones.

Para poder dominar un lenguaje de programación (al igual que con los lenguajes naturales) se requiere mucho estudio pero por sobre todo muchísima práctica. Vosotros podréis leer este manual una 500 veces pero si no ponéis en práctica ni investigáis por vosotros mismos, núnca podréis llegar a dominar este maravilloso lenguaje de programación. Así que ¡a practicar se ha dicho!

Introduccion

<- Anterior (MENU PRINCIPAL) | Siguiente (Capítulo 2) ->

Volver al MENU PRINCIPAL

Capítulo 1

Como hemos dicho C# (C Sharp) es parte de la plataforma .NET. C# es un lenguaje orientado a objetos simple, seguro, moderno, de alto rendimiento y con especial énfasis en internet y sus estándares (como XML). Es también la principal herramienta para programar en la plataforma .NET.

Tal vez os habréis preguntado ¿Qué es la plataforma .NET? ¿Porqué Microsoft está invirtiendo tanto en esta nueva tecnología? ¿Qué es lo que es tan novedoso? ¿Como es que con .NET se pueden producir aplicaciones multi-plataforma? A continuación hablaremos un poco de la plataforma .NET

La plataforma .NET

Marco de trabajo .NET
Marco de trabajo .NET

La plataforma .NET es una plataforma de desarrollo de software con especial énfasis en el desarrollo rápido de aplicaciones, la independencia de lenguaje y la transparencia a través de redes.

La plataforma consta de las siguientes partes:

  • Un conjunto de lenguajes de programación (C#, J#, JScript, C++ gestionado, Visual Básic.NET, y otros proyectos independientes).
  • Un conjunto de herramientas de desarrollo (entre ellos Monodevelop o Visual Studio.NET de Microsoft )
  • Una libreria de clases amplia y común para todos los lenguajes.
  • Un sistema de ejecucion de Lenguaje Común. (CLR).
  • Un conjunto de servidores .NET
  • Un conjunto de servicios .NET
  • Dispositivos electrónicos con soporte .NET (?)

Los puntos fuertes de la plataforma son:

Independencia de lenguaje

Todos los lenguajes que conformen con los estándares .NET, sin importar cual, podrán interoperar entre sí de forma totalmente transparente, las clases podrán ser heredadas entre unos lenguajes y otros, y se podrá disfrutar de polimorfismo entre lenguajes. Por ejemplo, si yo tengo una clase en C#, esta clase podrá ser heredada y utilizada en Visual Basic o JScript o cualquier lenguaje .NET. Todo esto es posible por medio de una de las características de .NET llamado Common Type System (CTS). También tiene la cualidad de que se pueden incluir más lenguajes a la plataforma. En la actualidad existen proyectos independientes de incluir PHP, Python, Ada y otros lenguajes en la plataforma.

Librería de clases común

Más de 4000 clases, objetos y métodos incluidos en la plataforma .NET están disponibles para todos los lenguajes.

Multiplataforma

Cuando un programa es compilado, no es compilado en un archivo ejecutable sino en un lenguaje intermedio llamado “Lenguaje Intermedio” (IL) el cual podrá ser ejecutado por el CLR (Common Language Runtime) en la plataforma en que el CLR esté disponible (hasta el día de hoy Microsoft solamente tiene un CLR para los sistemas operativos Windows, pero el proyecto Mono (www.mono-project.com) y dotGNU (www.dotGNU.org) han puesto a disposición un CLR para GNU/Linux, MacOS y muchas otras plataformas). Los sistemas operativos Windows XP o superiores incluyen el CLR nativamente y SuSE Linux 9.3 o superior planea incorporar el CLR (Mono) en su distribución lo que quiere decir que un programa .NET podrá ser compilado y ejecutado en cualquiera de estas plataformas, o en cualquier plataforma que incluya un CLR.

El CLR compilará estos archivos IL nuevamente en código de máquina en un proceso que se conoce como JIT (justo a tiempo) el cual se ejecutará cuando se requiera. Este proceso producirá código de máquina bien eficiente que se reutilizará si es que hubiera código que se repitiera, haciendo que los programas sean ejecutados muy eficientemente.

Windows Forms, Web Forms, Web Services

La plataforma .NET incluye un conjunto de clases especial para datos y XML que son la base de 3 tecnologías claves: Servicios Web (Web Services), Web Forms, y Windows Forms los cuales son poderosas herramientas para la creación de aplicaciones tanto para la plataforma como para el Web.

Estandarización

Además de los méritos técnicos, una de las razones del éxito de la plataforma .NET ha sido por el proceso de estandarización que Microsoft ha seguido (y que ha sorprendido a más de uno). Microsoft, en lugar de reservarse todos los derechos sobre el lenguaje y la plataforma, ha publicado las especificaciones del lenguaje y de la plataforma, que han sido posteriormente revisadas y ratificadas por la Asociación Europea de Fabricantes de Computadoras (ECMA). Esta especificación (que se puede descargar libremente de Internet) permite la implementación del lenguaje C# y de la plataforma .NET por terceros, incluso en entornos distintos de Windows. Mono Hispano mantiene una traducción del estándar que describe el lenguaje C# en http://monohispano.org/ecma/ (Enlace roto)

Un resúmen introductorio sobre el lenguaje C#

El lenguaje es muy sencillo, sigue el mismo patrón de los lenguajes de programación modernos. Incluye un amplio soporte de estructuras, componentes, programación orientada a objetos, manipulación de errores, recolección de basura, etc, que es construido sobre los principios de C++ y Java. Como sabréis, las clases son la base de los lenguajes de programación orientados a objetos, lo cual permite extender el lenguaje a un mejor modelo para solucionar problemas. C# contiene las herramientas para definir nuevas clases, sus métodos y propiedades, al igual que la sencilla habilidad para implementar encapsulación, herencia y polimorfismo, que son los tres pilares de la programación orientada a objetos. C# tiene un nuevo estilo de documentación XML que se incorpora a lo largo de la aplicación, lo que simplifica la documentación en línea de clases y métodos. C# soporta también interfaces, una forma de estipular los servicios requeridos de una clase. Las clases en C# pueden heredar de un padre pero puede implementar varias interfaces. C# también provee soporte para estructuras, un concepto el cual ha cambiado signifivamente desde C++. Una estructura es un tipo restringido que no exige tanto del sistema operativo como una clase. Una estructura no puede heredar ni dar herencias de clases pero puede implementar una interfaz. C# provee características de componentes orientados, como propiedades, eventos y construcciones declaradas (también llamados atributos). La programación orientada a componentes es soportada por el CLR. C# provee soporte para acceder directamente a la memoria usando el estilo de punteros de C++ y mucho más.

C# frente a Java

C# y Java son lenguajes similares, de sintaxis basada en C/C++, orientados a objetos, y ambos incluyen las características más importantes de los lenguajes modernos, como son la gestión automática de memoria y la compilación a código intermedio. Pero por supuesto, también hay diferencias.

Una de las diferencias más importantes es que C# es mucho más cercano a C++ en cuanto a diseño se refiere. C# toma casi todos sus operadores, palabras reservadas y expresiones directamente de C++. También se han mantenido algunas características que en Java se han desestimado. Por ejemplo, la posibilidad de trabajar directamente con direcciones de memoria. Si bien tanto Java como .NET proporcionan gestión automática de memoria, en C# es posible usar lo que se denomina "código no seguro". Cuando se usa código no seguro en C# es posible operar con punteros de forma muy similar a como se haría en C/C++, pero el código que utiliza punteros se queda marcado como no seguro y no se ejecuta en entornos en los que no tiene permisos.

C# frente a C++

Puesto que C# se ejecuta en una máquina virtual, ésta se hace cargo de la gestión de memoria y por lo tanto el uso de punteros es mucho menos importante en C# que en C++. C# también es mucho más orientado a objetos, hasta el punto de que todos los tipos usados derivan en última instancia el tipo 'object'. Además, muchos tipos se usan de forma distinta. Por ejemplo, en C# se comprueban los límites de los arrays antes de usarlos, evitando así que se pueda escribir pasado el final del vector.

Al igual que Java, C# renuncia a la idea de herencia múltiple de clases presente en C++. Sin embargo, referido a clases, C# implementa 'propiedades' del tipo de las que existen en Visual Basic, y los métodos de las clases son accedidos mediante '.' en lugar de '::'.

¿Por qué C#?

La plataforma .NET acepta varios lenguajes. Por ahora, C#, Visual Basic, C++ gestionado, Nemerle, FORTRAN, Java, Python, etc. , y con capacidad para aceptar prácticamente cualquier lenguaje. Entonces la pregunta es, ¿porqué se eligió C# en lugar de cualquier otro lenguaje?.

La razón fundamental es que C# se diseñó para la plataforma .NET y es capaz de utilizar todo su potencial. También es cierto que es un lenguaje "limpio" en el sentido de que al no tener que proporcionar compatibilidad hacia atrás se ha tenido más libertad en el diseño y se ha puesto especial hincapié en la simplicidad. Por ejemplo, en C# hay un tipo de clase y siempre se le aplica el recolector de basura mientras que en C++ gestionado hay dos tipos de clases, una a la que se aplica el recolector y otra a la que no.

Instalando lo necesario para empezar

Para poder empezar con nuestro curso debéis tener instalado en vuestro ordenador los archivos básicos para poder compilar y ejecutar vuestros programas. El conjunto de utilidades "Microsoft .NET Framework" y el ".NET Framework SDK" para Windows y el proyecto MONO o dotGNU para Linux, MacOS, BeOS proporcionan estas herramientas. Podréis encontrarlas en las siguientes direcciónes:

Para Windows:

http://msdn.microsoft.com/netframework/downloads/updates/default.aspx

Para Linux u otras plataformas:

Proyecto Mono

http://mono-project.com/Downloads (manual que describe distintos métodos de instalación)

Proyecto dotGNU

http://dotgnu.org/pnet-packages.html


Otras utilidades

Además de los archivos básicos para poder compilar y ejecutar vuestros programas, os recomendamos que instaléis un entorno de programación (IDE) que os ayudará a programar. Los siguientes programas son recomendados:

Para Windows:

Para Linux:

Estos programas son opcionales, os ayudarán con vuestra tarea de programación pero no son indispesables. En este curso no daremos intrucciones especiales de como utilizar ninguno de ellos por lo que correrá por vuestra cuenta el aprender a utilizarlos. En este curso daremos instrucciones de como compilar y ejecutar vuestros programas sin la ayuda de estos entornos.

<- Anterior (MENU PRINCIPAL) | Siguiente (Capítulo 2) ->

Primer Programa ¡Hola Mundo!

<- Anterior (Capítulo 1) | Siguiente (Capítulo 3) ->

CAPÍTULO 2

Primer programa ¡Hola Mundo!

En un alarde de originalidad, empezaremos con un simple programa que desplegará la frase “¡Hola Mundo!”. Con este programa introduciremos las bases de nuestro estudio. Debido a que la plataforma .NET es independiente del sistema operativo en este libro procuraremos mantenernos imparciales en cuanto este asunto, eso si, cuando llegue el tiempo de compilar y ejecutar daremos ejemplos de como hacerlo tanto en Windows como en Linux (en otras plataformas como MacOS será lo mismo que en Linux).

Si estáis utilizando un entorno de desarrollo integrado debéis abrir un nuevo proyecto de consola en C#, escribir o copiar lo que se muestra en el ejemplo 2.1 y compilad el proyecto para ver su resultado. Si preferís programar con un editor de textos, abrid vuestro editor de texto favorito y grabad en un directorio conocido lo que se encuentra en el ejemplo 2.1 como Programa.cs, abrid una ventana de terminal (en linux) o una ventana de comandos (Ejecutar(Run) -> cmd) en Windows y compilad vuestro proyecto con el siguiente comando:

en linux con MONO(en el directorio donde habéis grabado vuestro programa):

mcs Programa.cs

en linux con dotGNU(en el directorio donde habéis grabado vuestro programa):

cscc -o Programa.exe Programa.cs

en Windows (en el directorio donde habéis grabado vuestro programa):

csc Programa.cs

de esta forma obtendréis vuestro primer programa. Para ejecutarlo simplemente escribid:

con MONO:

mono Programa.exe

con dotGNU:

ilsrun Programa.exe

o en Windows:

Programa


Ejemplo 2.1 Programa Hola Mundo

//Ejemplo 2.1 - Programa Hola Mundo
 
 
  class HolaMundo
  {
      static void Main()
      {
          string var="Mundo";
          System.Console.WriteLine ("Hola {0}!", var);
      }
  }


Analicemos paso a paso nuestro programa de ejemplo:

Comentarios

En la primera línea de nuestro programa encontramos lo siguiente: //Ejemplo 2.1 .... Esta línea es un ejemplo de comentarios. Un comentario es una parte en vuestro programa que será ignorado por el compilador.

Existen tres tipos de comentarios en C#. El primer tipo es comentario de un sola línea. El segundo es comentario de varias líneas. El tercer tipo es para crear documentación. Este último tipo de comentario lo estudiaremos en el capítulo 13 de este libro.

Los comentarios de una sola línea pueden ser incluidos en líneas independientes, en líneas que ya incluyen código para comentar sobre lo que hace esa línea o para comentar una línea de código que no necesitamos.

Los comentarios de varias líneas sirven para incluir muchas líneas de texto o código como un comentario. Tienen una marca de inicio que dice cuando empieza el comentario y una marca que indica el final de dicho comentario. La marca de inicio es /* y la marca para finalizar es */ Así por ejemplo tenemos:

//Este es un ejemplo de comentarios de una línea
 
 /* 
    este comentario 
    abarca varias lineas
 */
 
class HolaMundo
{
     static void Main()
     {
       string var="Mundo";
       System.Console.WriteLine ("Hola {0}!", var); //Este comentario puede describir lo que esta función hace
       //System.Console.WriteLine ("y esta linea no la vamos a desplegar"); 
     }
}

Clases, Objetos y tipos

La esencia de la programación orientada a objetos es la creación de nuevos tipos. Un tipo es la representación de un componente (Pensado en un ordenador (un computador) que está compuesto de varios componentes). En programación un componente es algo que cumple una función. Por ejemplo, un componente puede ser un botón en un programa. En una aplicación podemos tener varios botones del mismo tipo como por ejemplo botones de Aceptar, Cancelar, etc. Porque son del mismo tipo estos botones tienen propiedades y comportamientos similares. Pueden tener propiedades como cambiar de "tamaño", "posición", etc. Las propiedades son las mismas pero los valores almacenados en sus atributos pueden ser diferentes. Por ejemplo, un botón puede tener tamaño 10 y otro tamaño 6. Podemos decir entonces que tenemos varias instancias del mismo componente (o varios botones del mismo tipo) con diferentes valores en sus atributos.

La programación orientada a objetos es esto. Crear componentes que puedan ser reusados. Así no tenemos que programar varios componentes que cumplan funciones similares sino solo uno que podrá llevar diferentes atributos y que podrá ser reproducido (o instanciado) tantas veces como lo necesitemos.

Como en varios lenguajes de programación orientado a objetos, en C# los tipos o componentes son definidos por una clase (class en inglés). Las diferentes reproducciones o instancias de un componente del mismo tipo se conoce como objetos. Posteriormente en nuestro estudio veremos que en C# hay más tipos además de las clases. Aprenderemos sobre enums, structs y delegates. Pero por el momento nos dedicaremos a las clases.

Como hemos visto en nuestro primer programa (Ejemplo 2.1), empezamos nuestro programa declarando el tipo de componente que vamos a utilizar (un componente de tipo class) y su nombre HolaMundo. Para declarar nuestro componente como una clase, primero introducimos la palabra clave class, y después el nombre de nuestro componente, después de lo cual declaramos las funciones que va a cumplir su comportamiento y sus propiedades. Todas las funciones, comportamiento y propiedades de nuestro componente (en este caso nuestra clase) deberán estar encerrados entre corchetes { }. Los corchetes delimitan el inicio y el final de dicho componente.

Métodos o Funciones

Los métodos o funciones son trozos de código que realizan una acción, esto es, toman unos argumentos y devuelven un valor. En C#, las funciones deben ser declaradas dentro de un objeto, normalmente dentro de una clase.

Las funciones normalmente llevan nombre que definen su función. Por ejemplo, la función WriteLine() de la clase Console como debéis suponer "Escribe una Linea en la consola". De forma similar se pueden declarar clases a las que se le añaden un número ilimitado de métodos. En nuestro ejemplo 2.1 la única función que hemos definido lleva el nombre de Main() la cual es una función especial que indica la entrada principal de ejecución de un programa. Cada programa en C# debe tener una función Main().

Crear nuevos métodos o funciones

Para declarar un método o función utilizamos el siguiente formato:

[entorno] tipo_a_retornar Nombre_de_la_Función ([tipo Argumento1, tipo Argumento2,...])
{
 //lineas de código
}
las palabras dentro de corchetes [] son partes opcionales

de acuerdo con nuestro ejemplo 2.1, la función Main() cumple con el formato establecido:

static void Main()
{
 //lineas de código
}
  • entorno: static
  • tipo_a_retornar: void
  • Nombre_de_la_Función: Main
  • Argumentos: ninguno

En nuestro ejemplo la función Main() tiene como entorno la palabra clave static y como tipo_a_retornar la palabra clave void. Cuando la función no retorna ningún tipo, utilizamos la palabra void. Más adelante veremos más tipos además de void. La palabra static también la veremos más adelante en nuestro estudio, por el momento debéis confiar en el ejemplo y utilizarla aún sin saber lo que hace.

Podemos añadir a nuestro componente o clase un ilimitado número de funciones. Por ejemplo, para añadir más funciones a nuestro primer ejemplo procederemos a crear una función que suma dos valores. Como ya habéis aprendido en esta sección, crearemos nuestra función de la forma establecida. Después del final de la función Main crearemos una función con entorno static que retorne el tipo int, que se llame Suma y que acepte dos argumentos de tipo int. Para hacerla funcionar vamos a llamarla desde nuestra función principal:

Ejemplo 2.2 - Añadiendo funciones a nuestro programa

//Ejemplo 2.2 - Programa Hola Mundo con C# más adición
 
 namespace Programa1
 { 
   class HolaMundo
   {
     static void Main()
     {
       string var="Mundo";
       System.Console.WriteLine ("Hola {0}!", var);
       int num1 = 1;
       int num2 = 3;
       int resultado = Suma (num1, num2);
       System.Console.WriteLine ("{0}+{1} = {2}", num1, num2, resultado); 
     }
 
     static int Suma(int valor1, int valor2)
     {
       return (valor1+valor2);
     }
   }
 }

probad vuestro programa, compiladlo y ejecutadlo. El resultado será el siguiente:

Hola Mundo!
1 + 3 = 4

Ésta es una pequeña introducción a funciones, más adelante estudiaremos más detalladamente como crear y utilizar funciones.

Aplicaciones de consola

Las aplicaciones de consola no poseen una interfaz gráfica, no tienen botones o ventanas, poseen una interfaz basada simplemente en texto. El ejemplo que hemos realizado hasta ahora es una aplicación de consola que despliega texto en la pantalla, para ello hemos utilizado la función WriteLine.

Como habíamos visto en la introducción, la plataforma .NET posee más de 4000 componentes cada cual con diferentes funciones internas. En el caso de nuestro programa hemos usado la función WriteLine que se encuentra dentro del componente Console. Para poder hacer uso de funciones estáticas que se encuentran en otros componentes, en C# como en la mayoría de lenguajes de programación orientados a objetos, debemos especificar el nombre del componente en primer lugar seguido por un punto y a continuación en el nombre de la función. Es por esto que utilizamos la frase Console.WriteLine. Dentro del componente Console la plataforma .NET tiene disponibles muchísimas otras funciones que nos ayudan a diseñar programas de consola. El lenguaje C# esta orientado con el paradigma de objetos y hereda muchos elementos de C++.

Namespaces

Quizá algunos de vosotros os habréis preguntado ¿que significa la palabra System que está al inicio de cada programa?. Púes bien, System en este caso representa un Espacio de nombres (namespace en inglés).

Los espacios de nombres (namespaces) se crearon principalmente para dar más organización a los componentes. La plataforma .NET tiene incorporados muchísimos componentes y sería una tarea imposible tratar de memorizar todos los nombres de ellos para no repetirlos. Tarde o temprano querréis crear un componente y no sabréis si el nombre que queréis darle ya existe o no. Para evitarnos este problema y para poder distinguir a dónde pertenecen ciertos componentes se han creado los espacios de nombres.

Pongamos un ejemplo para comprender este concepto. Supongamos que deseamos crear varios componentes para una institución educativa que se compone de educación primaria y educación secundaria. ¿Cómo podríamos crear un componente que se llame Presidente si existen 2 presidentes que tienen funciones distintas uno para la sección primaria y otro para la sección secundaria? En este caso podríamos aplicar un espacio de nombres para poder crear los componentes Presidente que cumplen distintas funciones. Podríamos crear el espacio de nombres Primaria y dentro de éste el componente Presidente. De igual forma el espacio de nombres Secundaria y dentro de éste el componente Presidente cada uno componentes podrá tener definiciones distintas. Para acceder a las funciones de los componentes Presidente podríamos usar:

Primaria.Presidente.nombre_de_la_función();
y
Secundaria.Presidente.otra_función();

Cada una de las dos definiciones de Presidente son independientes, no tienen relación entre sí ya que pertenecen a dos espacios de nombre distintos.

De ésta forma podremos crear componentes y funciones con el nombre que deseemos siempre y cuando especifiquemos a qué espacio de nombres pertenecen.

De acuerdo con la línea de código estudiada: System.Console.WriteLine ("Hola {0}!", var); existe una función llamada WriteLine dentro del componente Console dentro del nombre de espacio System. Cualquier otro componente llamado Console dentro de otro espacio de nombres, es un componente diferente con funciones diferentes que quizás no posea la función WriteLine.

Algo importante que debemos notar es que los espacios de nombres pueden tener sub-espacios de nombres y estos a su vez sub-espacios de nombres. El objetivo de esto, como lo hemos dicho, es mantener una organización de los componentes. Los espacios de nombres, componentes y métodos se accederán de la misma forma como lo hemos visto a través de un punto.

La palabra clave using

En ciertos proyectos tendremos que usar cierto espacio de nombres muchas veces. Supongamos que estamos implementando un programa de consola y tenemos que usar el componente Console repetidamente. Una forma de ahorrarnos escribir System varias veces es especificar el espacio de nombres que vamos a usar al inicio de nuestro programa con la palabra clave using. Por ejemplo en nuestro ejemplo 2.2 si añadimos la línea de código using System; al inicio de nuestro programa, podemos llamar al componente Console sin escribir System al inicio:

Ejemplo 2.2 Modificado - La palabra clave using

//Ejemplo 2.2 Modificado - La palabra clave ''using''
 
 using System;
 
 namespace Programa1
 { 
   class HolaMundo
   {
     static void Main()
     {
       string var="Mundo";
       Console.WriteLine ("Hola {0}!", var);
       int num1 = 1;
       int num2 = 3;
       int resultado = Suma (num1, num2);
       Console.WriteLine ("{0}+{1} = {2}", num1, num2, resultado); 
     }
     static int Suma(int valor1, int valor2)
     {
       return valor1+valor2;
     }
   }
 }

Comparando con nuestro ejemplo 2.2 original las líneas en negrita muestran esta ventaja.

Algo importante para tener en cuenta es que la palabra clave using no puede ser utilizada para ahorrarse el escribir el nombre de la clase. Por ejemplo la línea de código using System.Console es inválida y producirá errores de compilación.

Caracteres sensibles

C# como todos los lenguajes de programación derivados de C hace diferencia entre caracteres en mayúscula y caracteres en minúscula. Esto quiere decir que las palabras Using y using son distintas y por lo tanto no cumplen la misma función. Debido a esto debemos tener mucho cuidado cuando escribimos nuestros programas.

system.console.writeLine es diferente a system.Console.WriteLine y es diferente a System.Console.WriteLine que es el nombre de espacio, componente y método que C# incorpora para desplegar texto en la consola.

Finalizada esta pequeña introducción a nuestro primer programa en C#, pasamos al capítulo 3 en donde examinaremos mas profundamente los fundamentos de C#.

<- Anterior (Capítulo 1) | Siguiente (Capítulo 3) ->

Fundamentos del lenguaje

<- Anterior (Capítulo 2) | Siguiente (Capítulo 4) ->

CAPÍTULO 3

En el capítulo 2 hemos introducido nuestro primer programa en C#, un programa sencillo el cual incorpora muchos temas que hemos cubierto básicamente y solamente en parte. En esta sección del libro procuraremos ver más a fondo las partes básicas de C#. Nos internaremos más a fondo en la sintaxis y la estructura de C#.

En este capítulo cubriremos lo que son los tipos. Hablaremos de tipos básicos o internos y de cómo crear nuevos tipos. También hablaremos en general de la manipulación de datos. Hablaremos sobre condicionales, operadores matemáticos y varios otros temas relacionados. Empecemos entonces nuestro estudio con lo que son tipos.

Tipos

Importancia de los tipos de datos

Los tipos son la base de cualquier programa. Un tipo no es más que un espacio en el que se almacena una información, ya sean números, palabras o tu fecha de nacimiento.

Tipos en C#

C# es un lenguaje de tipeado seguro (o fuertemente tipado) lo cual quiere decir que el programador debe definir a que tipo pertenece cada pedazo de información o cada objeto que se crea. De esta forma podemos crear objetos de tipo número entero, de tipo cadenas de texto, de tipo ventana, de tipo botones, entre otros. Haciendo esto, C# nos ayudará a mantener nuestro código seguro en donde cada tipo cumple con su función. En todas las operaciones el compilador comprueba los tipos para ver su compatibilidad. Las operaciones no válidas no se compilan. De esta forma se evitan muchos errores y se consigue una mayor fiabilidad. Esto también permite a C# anticipar de antemano la cantidad de recursos del sistema que nuestro programa utilizará haciendo nuestro código seguro y eficiente.

Los tipos en C# al igual que C++ y Java se clasifican en dos secciones: Tipos básicos o internos y tipos creados por el usuario.

Los tipos básicos no son más que alias para tipos predefinidos en la librería base de la plataforma .NET. Así, el tipo número entero (que se representa con la palabra clave int), no es más que una forma rápida de escribir System.Int32.

Dentro de estas dos secciones los tipos del lenguaje C# también son divididos en dos grandes categorías: tipos por valor y tipos por referencia. Existe una tercera categoría de tipos, disponible solo cuando se usa código no seguro: los punteros, que se discutirán más adelante cuando hablemos de los objetos COM.

Los tipos por valor difieren de los tipos por referencia en que las variables de los tipos por valor contienen directamente su valor, mientras que las variables de los tipos por referencia almacenan la dirección donde se encuentran los objetos, es por eso que se las llaman referencias. Más adelante describiremos como funcionan cada una de estas categorías.

Tipos básicos o internos

Los tipos básicos como hemos dicho son espacios predefinidos y categorizados donde se almacena información. En C# tenemos los siguientes tipos internos:

Tabla 3.1 - Tipos básicos

Tipo C# Nombre para la plataforma .NET Con signo? Bytes utilizados Valores que soporta
bool System.Boolean No 1 true o false (verdadero o falso en inglés)
byte System.Byte No 1 0 hasta 255
sbyte System.SByte Si 1 -128 hasta 127
short System.Int16 Si 2 -32.768 hasta 32.767
ushort System.Uint16 No 2 0 hasta 65535
int System.Int32 Si 4 -2.147.483.648 hasta 2.147.483.647
uint System.Uint32 No 4 0 hasta 4.394.967.395
long System.Int64 Si 8 -9.223.372.036.854.775.808 hasta 9.223.372.036.854.775.807
ulong System.Uint64 No 8 0 hasta 18446744073709551615
float System.Single Si 4 Approximadamente ±1.5E-45 hasta ±3.4E38 con 7 cifras significativas
double System.Double Si 8 Approximadamente ±5.0E-324 hasta ±1.7E308 con 7 cifras significativas
decimal System.Decimal Si 12 Approximadamente ±1.0E-28 hasta ±7.9E28 con 28 ó 29 cifras significativas
char System.Char   2 Cualquier carácter Unicode (16 bits)

C# tiene una ventaja y característica especial sobre los demás lenguajes de programación modernos y es que cada vez que se crea un objeto de un tipo básico, éstos son mapeados internamente a un tipo primitivo de la plataforma .NET el cual es parte del CLS (Especificación común del lenguaje) lo cual nos permite acceder y hacer uso de estos desde cualquier lenguaje de la plataforma .NET. Es decir si es que creamos un objeto de tipo int (entero) en C#, ese objeto podrá ser usado como tal dentro de J#, JScript, Visual Basic .NET y cualquier otro lenguaje que conforme los requisitos de .NET.

Escogiendo qué tipo usar

A la hora de programar deberéis decidir qué tipo de variables querréis usar. Generalmente esta decisión se basa en el tipo de información que vayáis a usar y en el tamaño de la información. Por ejemplo en nuestro ejemplo 2.2 del capítulo anterior necesitábamos hacer la suma de dos valores numéricos por lo que usamos dos tipos básicos de número entero (usando la palabra clave int) los cuales de acuerdo con nuestra tabla 3.1 son números enteros (no pueden llevar valores decimales) y podrán aceptar valores entre -2,147,483,648 y 2,147,483,647 lo cual es más que suficiente para nuestro ejemplo de añadir dos números. En el caso de que necesitáramos hacer uso de números reales (los cuales poseen una parte entera y una parte decimal como el número 10.22) podremos hacer uso del tipo float, double y decimal de acuerdo con el tamaño del número que necesitemos y así cada uno de los tipos tiene su uso y capacidad de acuerdo con la tabla 3.1.

A continuación explicaremos brevemente los tipos más usados en C#:

Enteros

Los tipos que sirven para almacenar números enteros son: byte, sbyte. short, ushort, int, uint, long y ulong. Como se aprecia en la tabla, C# define versiones con y sin signo para tipos con los mismos bytes utilizados. Cada tipo se distingue por la capacidad de almacenaje.

Probablemente el tipo más utilizado es el int, púes se utiliza para controlar matrices, indizar arreglos (arrays) además de las operaciones normales con enteros. Además, se trata de un entero de tamaño medio: más pequeño que long y ulong, pero más grande que byte, sbyte, short y ushort.

El siguiente ejemplo muestra la declaración y uso de algunos tipos enteros calculando el número de segundos en una hora, dia y en un año.

Ejemplo 3.1 - utilizando tipos enteros (int)

// Ejemplo 3.1 - utilizando tipos enteros (int)
using System;
class Enteros{
   public static void Main()
   {
       int minuto = 60;    //segundos por minuto
       int hora = minuto*60;
       int dia = hora*24;
       long anio = dia*365;
       Console.WriteLine("Segundos en un dia: {0}", dia);
       Console.WriteLine("Segundos en un año: {0}", anio);
   }
}        
       

De nuevo hemos usado el método Console.WriteLine para imprimir los resultados por la consola. El identificador {0} dentro de la cadena de texto indica que se sustituye {0} por el primer argumento. si hubiera más de un argumento, se seguiría con {1}, y así sucesivamente. Por ejemplo, las dos líneas que utilizan Console.WriteLine se pueden simplificar así:

   Console.WriteLine("En un dia: {0}; en un año: {1}", dia, anio );

Tipos de coma flotante

Los tipos de coma flotante sirven para representar a números con parte fraccionaria. La representación por supuesto puede no ser exacta, bien por errores de la máquina, bien porque el número de decimales que se puede alojar es finito.

Existen tres clases de tipos de punto flotante : float, double y decimal. De los dos, el más usado es double, púes es el valor que devuelven la mayoría de las funciones matemáticas de la librería base.

El siguiente ejemplo calcula la raíz cuadrada y el logaritmo de dos:

Ejemplo 3.2 - utilizando tipos flotantes

 // Ejemplo 3.2 - utilizando tipos flotantes
 using System;

 class Flotante{
    public static void Main()
    {
        int a = 2;
        double log2 = Math.Log(a);
        double raiz2 = Math.Sqrt(a);
        Console.WriteLine("El logaritmo de dos es {0}", log2 );
        Console.WriteLine("La raiz de dos es {0}", raiz2 );
    }
 }

y la salida será la siguiente:

El logaritmo de dos es 0.693147180559945
La raiz de dos es 1.4142135623731            
       

si intentamos cambiar el tipo de log2 a otro de menos precisión, como float o int, el compilador protestará. Esto se debe, como hemos dicho a que el valor devuelto por Math.Log() es de tipo double y si se quiere convertir a float, pués se perderán datos. Lo mismo ocurre con la mayoría de los miembros de la clase Math, como Math.Sin(), Math.Tan(), etc.

El tipo decimal

El tipo decimal es un tipo "nuevo" en el sentido de que no tiene equivalente en C/C++. Es muy parecido a los tipo de coma flotante float y double.

En la aritmética de los tipos de coma flotante ordinarios, se pueden producir leves errores de redondeo. El tipo decimal elimina estos errores y puede representar correctamente hasta 28 lugares decimales. Esta capacidad para representar valores decimales sin errores de redondeo lo hace especialmente eficaz para cálculos monetarios.

El tipo bool

El tipo bool sirve para expresar los valores verdadero/falso, que en C# se muestran con las palabras reservadas true y false.

En C#, por ejemplo, una instrucción de condición solo puede estar gobernada por un valor bool, no como en C/C++, que lo puede estar también por un entero. De esta forma se ayuda a eliminar el error tan frecuente en programadores de C/C++ cuando usa "=" en lugar de "==". En definitiva, la inclusión del tipo bool en el lenguaje ayuda a la claridad del código y evita algunos errores muy comunes.

El siguiente ejemplo, muestra algunos usos del tipo bool:

Ejemplo 3.3 - utilizando tipos de decisión bool

// Ejemplo 3.1 - utilizando tipos de decisión bool
using System;
class Booleano{
   public static void Main()
   {
       bool b;
       b = true;
       Console.WriteLine("b es {0}", b);
       if(b)
       {   
          Console.WriteLine("esto saldrá");
       }
       b = false;
       if(b)
       {
           Console.WriteLine("esto no saldrá");
       }
       Console.WriteLine("2==2 es {0}", 2==2);
   }
}
       

En la última línea se muestra que el operador "==" también devuelve un valor booleano. El resultado debería ser el siguiente:

b es True
esto saldrá
2==2 es True

El tipo char

El tipo char permite almacenar un carácter en formato simple, unicode de 16 bits o caracteres de escape. Usando el formato unicode nos garantiza que los acentos se ven de forma adecuada y además permite la representación de otros alfabetos, como el japonés, griego, cirílico, etc. Para introducir un carácter se utilizan comillas simples, de forma que declarar un carácter sigue la estructura

char letra1 = 'a'; //formato simple
char letra2 = '\u0041'; //formato Unicode que representa la letra A
char letra3 = '\n'; formato carácter de escape

Para una lista completa de caracteres unicode podréis visitar la siguiente página: http://unicode.coeurlumiere.com/

La siguiente lista contiene los caracteres de escape comunes y su significado:

\' apostrofe
\" Comillas
\\ Backslash
\0 Null (nulo)
\a Alerta
\b Retroceso
\f Form feed
\n Línea nueva
\r Retorno del carro
\t Tabulación Horizontal
\v Tabulación Vertical

Tipo Cadenas

Los tipos cadena (palabra clave string) son tipos que almacenan un grupo de caracteres. En C# los tipos cadena se crean con la palabra clave string seguido por el nombre de la variable que deseamos instanciar. Para asignar un valor a este tipo debemos hacerlo entre comillas de la siguiente forma:

string miCadena = "Esta es una cadena de caracteres";

Debido a que el tipo cadena (string) es uno de los tipos más usados en C#, lo estudiaremos detalladamente más adelante.

Convirtiendo tipos

En nuestros programas muchas veces necesitaremos cambiar de tipo a los objetos que hayamos creado. Esto lo podremos hacer implícitamente o explícitamente. Una conversión de tipos implícita sucede automáticamente, es decir el compilador se hará cargo de esto. Una conversión explicita en cambio se llevará a cabo únicamente cuando nosotros lo especifiquemos. Hay que tomar en cuenta que no siempre podremos hacer una conversión de un tipo hacia otro.

Como regla general las conversiones implícitas se llevan a cabo cuando se desea cambiar un tipo de menor capacidad hacia un tipo de mayor capacidad de la misma especie. Por ejemplo si deseamos crear 2 tipos enteros (misma clase) el uno que lleve el tipo short (menor capacidad) y el otro que lleve el tipo int (mayor capacidad) una conversión implicita de short a int se lleva a cabo en el siguiente ejemplo:

short corto = 3;
int entero = corto; //compilará sin ningún problema

aquí sucede una conversión implícita, el valor de la variable corto (en este caso 3) que es de tipo short es asignado a la variable de tipo int sin que el compilador nos de ningún problema ya que hará una conversión de short a int implícitamente por nosotros debido a la regla anteriormente citada.

En el caso que queramos hacer de forma inversa, es decir asignar un valor int a una variable short, estaríamos violando la regla de asignar un tipo de menor capacidad a una variable de tipo de mayor capacidad aunque sean de la misma clase (enteros). Asi el siguiente ejemplo no compilará dándonos un error:

int entero = 300;
short corto = entero; //nos dará un error de compilación

En estos casos es cuando podremos hacer una conversión explícita. Debido a que la información almacenada en la variable entero de tipo int está también en el rango de capacidad del tipo short y los dos tipos son de la misma clase (enteros) podremos hacer una conversión explicita designando entre paréntesis a que tipo queremos convertir de la siguiente manera:

int entero = 300;
short corto = (short) entero; //convertirá la variable entero para que sea del tipo short

En el ejemplo anterior, el compilador no nos dará ningún problema. Cada uno de los tipos básicos citados a continuación soportará una conversión implícita o explícita como se lo expresa en la siguiente tabla:

Conversión Implicita (I) Conversión Explícita (E)
Desde/hacia byte sbyte short ushort int uint long ulong float double decimal
byte I E I I I I I I I I I
sbyte E I I E I E I E I I I
short E E I E I E I E I I I
ushort E E E I I I I I I I I
int E E E E I E I E I I I
uint E E E E E I I I I I I
long E E E E E E I E I I I
ulong E E E E E E E I I I I
float E E E E E E E E I I E
double E E E E E E E E E I E
decimal E E E E E E E E E E I

Arreglos

En C# se pueden construir arreglos de prácticamente cualquier tipo de dato. Los arreglos, también llamados vectores o arrays, no son más que una sucesión de datos del mismo tipo. Por ejemplo, el concepto matemático de vector es una sucesión de números y por lo tanto es un arreglo unidimensional. Así, podemos construir arreglos de objetos, de cadenas de texto, y, por supuesto, arreglos de enteros:

using System;

class Arreglo{
   public static void Main()
   {
       int[] arr = new int[3];
       arr[0] = 1;
       arr[1] = 2;
       arr[2] = 3;
       Console.WriteLine( arr[1] );
   }
}

Para crear un arreglo debemos especificar de qué tipo deseamos crear el arreglo seguido por corchetes [ ] que es el distintivo del arreglo (en nuestro ejemplo usamos int[]), seguido por la palabra clave new y el tipo y la cantidad de parámetros que tendrá nuestro arreglo. En el ejemplo anterior, por ejemplo, se creó un arreglo arr unidimensional con capacidad para 3 enteros (especificado por new int[3]), y luego se le asignó a cada parámetro un entero distinto (nótese que se comienza a contar a partir de 0 y el número del parametro se encuentran entre corchetes).

Existe una forma más corta para declarar el arreglo y asignarle los valores:

int[] arr = {1,2,3}; //es exactamente lo mismo que el ejemplo anterior
       

También se pueden crear arreglos bidimensionales (y de la misma forma para más dimensiones). En ese caso la sintaxis para declarar un arreglo bidimensional de enteros será

int[,] arr; //declaración de arreglos bidimensionales en C#

en contraposición a C/C++, en el que se declararía como

int[][] arr; //declaración de arreglos bidimensionales en C/C++

De esta forma, un arreglo bidimensional se declararía y utilizaría de la siguiente forma:

using System;
class Arreglo2{
  public static void Main()
  {
      int[,] arr = new int[2,2];
      arr[0,0] = 1;
      arr[1,0] = 2;
      arr[0,1] = 3;
      arr[1,1] = 4;
      Console.WriteLine("El valor que posee la variable arr[1,1] es {0}", arr[1,1] );
  }
}

el resultado será:

El valor que posee la variable arr[1,1] es 4
   

igual que el ejemplo anterior, podemos declarar todo el arreglo de la siguiente forma:

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

Hablaremos más sobre arreglos más adelante

Identificadores, Variables, Constantes y Enumeraciones

Identificadores

En una aplicación siempre se deben crear variables, constantes, métodos, objetos, etc. Para poder crearlos debemos asignar nombres o identificadores. Estos identificadores deben seguir ciertas reglas:

  1. Un identificador DEBE empezar con una letra o un signo _
  2. Un identificador NO puede tener espacios en blanco
  3. Un identificador NO puede llevar el mismo nombre que una palabra clave

Después de que el identificador empiece con una letra o un simbolo _, el identificador puede tener cualquier cantidad de letras, líneas o números.

Ejemplo:

EsteIdentificadorEsValido
_este_tambien
esteEsOtro1
esteEsOtro2

como ejemplos inválidos tenemos:

Esto es invalido
123_Otro_inválido 
int 

en los ejemplos que no son válidos, el primero contiene espacios, el segundo empieza con numeros y el tercero es una palabra clave lo cual no es permitido.


Nota: Es recomendado que las variables siempre empiecen con minusculas y que sigan el patrón llamado Camello es decir que el nombre de la variable que tenga varias palabras debe ser formado de la siguiente manera: la primera palabra empezará con minúsculas pero la segunda, tercera, etc palabras estarán unidas a la primera y tendrán su primera letra en mayúsculas ejemplo: miVariable. También se ha recomendado que el nombre de Métodos, Clases y demás nombres que necesitamos especificar deberán llevar el mismo formato anterior con la excepción de que la Primera letra deberá ser mayúscula.


Variables

Una variable es el nombre que se le da al espacio donde se almacena la información de los tipos. Las variables pueden llevar cualquier nombre que deseemos, eso sí no se podrá hacer uso de palabras claves de C#. En los ejemplos anteriores hemos usado varias variables con diferentes tipos y diferentes valores.

Para crear una variable debemos especificar a qué tipo pertenece antes del nombre que le vamos a dar. Por ejemplo si deseamos crear una variable que se llame var y que sea del tipo entero (int) procederemos de la siguiente manera:

int var;

Una vez creada la variable podemos almacenar la información que deseamos. Para hacerlo utilizamos el símbolo = después del nombre de la variable.

var = 10;

Hay que tener presente que la variable como su nombre lo indica podrá tomar otros valores. Por ejemplo si deseamos que nuestra variable cambie de valor a 5 hacemos lo que habíamos hecho en el ejemplo anterior pero con el nuevo valor:

var = 5;

De ahora en adelante la variable var pasa a tener el valor de 5.

Para simplificar el proceso de creación y asignación de valor de una variable podemos especificar estos dos procesos en una misma línea.

int var = 10;

La primera vez que una variable recibe un valor se llama inicialización de la variable. En C# todas las variables que van a ser utilizadas deben ser inicializadas para que vuestro programa pueda funcionar.

En caso anterior hemos creado la variable var e inicializado la variable con el valor 10. Hay que tener cuidado que la creación de una variable se la hace 1 sola vez y la asignación de diferentes valores se puede hacer cuantas veces queramos.

Constantes

Las constantes como su nombre lo indica son variables cuyo valor no puede ser alterado. Éstas se utilizan para definir valores que no cambian con el tiempo. Por ejemplo podemos definir una constante para especificar cuantos segundos hay en una hora de la siguiente forma:

const int segPorHora = 3600;

Esta constante no podrá ser cambiada a lo largo de nuestro programa. En el caso de que queramos asignarle otro valor, el compilador nos dará un error.

Las constantes deben ser inicializadas en el momento de su creación.

Enumeraciones

Supongamos que estamos diseñando un juego y necesitamos crear una variable para saber cuál es el estado del tanque de combustible de nuestro automóvil. Suponiendo que tenemos 4 niveles en el tanque: lleno, medio, bajo y crítico. ¿Qué tipo de variable podríamos usar para especificar estos estados? Una forma de hacerlo podría ser si especificamos una variable de tipo int (entero) que tome los valores de 1 para lleno, 2 para medio, 3 para bajo y 4 para crítico. Esta alternativa funcionaría pero a la larga nos olvidaremos qué número representaba qué. Una forma muy elegante de solucionar este problema es utilizando el tipo enum o enumeraciones. Veamos el siguiente ejemplo para comprender este concepto:

Ejemplo 3.1 - Control del estado de combustible

 using System;
 namespace Autos 
 {
 class Control
 {
   enum tanque
   {
     lleno,
     medio,
     bajo,
     critico,
   }

   static void Main()
   {
     tanque auto1 = tanque.lleno;
     RevisarEstadoTanque(auto1);   
     
     auto1 = tanque.critico;
     RevisarEstadoTanque(auto1);  
   }
 
   static void RevisarEstadoTanque(tanque auto)
   {
     if (auto==tanque.lleno)
        Console.WriteLine ("¡El tanque está lleno!");
     if (auto==tanque.medio)
        Console.WriteLine ("El tanque está por la mitad");
     if (auto==tanque.bajo)
        Console.WriteLine ("¡El tanque está casi vacío!");
     if (auto==tanque.critico)
        Console.WriteLine ("¡Alerta! tu auto se quedó sin combustible");
   }

 }

 }

Este programa sencillo crea una enumeración llamada tanque y dentro de ella crea 4 constantes: lleno, medio, bajo, y critico. Dentro de nuestro programa creamos la variable de tipo tanque llamada auto1 la cual podrá tomar los valores especificados dentro de la enumeración. Cuando asignamos a la variable auto1 el valor de tanque.lleno y revisamos el estado del tanque llamando a la función RevisarEstadoTanque, podremos comprobar cuál es el estado actual del tanque de combustible. Ésta es una forma muy descriptiva de cómo crear variables que cambien de estado, una solución elegante y sencilla a nuestro problema.

En realidad las constantes dentro de las enumeraciones tienen valores enteros asignados. Estos valores pueden ser inicializados con distintos valores que nosotros deseemos e incluso podemos especificar qué tipo de entero queremos usar. En nuestro ejemplo anterior los valores de la enumeración son valores enteros del tipo int el primer elemento dentro de la enumeración tiene asignado el valor de 0, el siguiente el valor 1 y así sucesivamente. Esto sucede cuando no especificamos a qué tipo queremos inicializar nuestra enumeración y tampoco asignamos valores a las constantes. En el siguiente ejemplo podemos ver cómo especificar otro tipo de constantes y otros valores.

Supongamos que queremos especificar cuantos segundos hay en un minuto, cuantos segundos hay en una hora y cuantos segundos hay en 24 horas. Con enumeraciones lo podemos hacer de la siguiente manera:

Ejemplo 3.2 - Enumeraciones

 using System;
 namespace Ejemplos
 {
 class Enumeraciones
 {
   enum segundos :uint
   {
     minuto = 60,
     hora = 3600,
     dia = 86400,
   }
   static void Main()
   {
     Console.WriteLine("Existen {0} segundos en 1 minuto, {1} segundos en 1 hora y {2} segundos en 24 horas",(uint)segundos.minuto, (uint)segundos.hora, (uint)segundos.dia);
   }
 }
 }

El resultado es el siguiente:

Existen 60 segundos en 1 minuto, 3600 segundos en 1 hora y 86400 segundos en 24 horas

El ejemplo anterior nos muestra otra forma de usar una enumeración. Hay que tener en cuenta que el tipo que va a tener la enumeración se encuentra después del nombre de la enumeración precedido por dos puntos. De esa forma podremos especificar de qué tipo son. Como habíamos dicho anteriormente se podrá utilizar cualquier tipo de la clase enteros como byte, sbyte, short, ushort, int, uint, long o ulong. En el caso de que no se especifique a qué tipo pertenece el compilador le dará el tipo int. También se debe tomar en cuenta que los valores de las constantes están asignados con el signo = y están separadas por comas.

Como habéis visto la forma de acceder al valor numérico de las enumeraciones es especificando entre parentesis a qué tipo pertenecen, en este caso (uint). Después de lo cual especificamos el nombre de la enumeración seguido por un punto que separa al nombre de la constante. En el caso de que deseemos desplegar sólo el nombre de la constante y no su valor, se debe omitir el nombre del tipo como: segundos.hora sin (uint) al inicio.

En el caso de que solamente especifiquemos algunos valores de las constantes, el compilador asignará el siguiente valor a la siguiente constante. Así por ejemplo:

   enum numeros 
   {
     uno, //toma el valor de 0
     dos, //toma el valor de 1
     diez = 10, //toma el valor de 10
     once, //toma el valor de 11
   }

Operadores

Los operadores son símbolos con los cuales C# tomará una acción. Por ejemplo existen operadores matemáticos para sumar, restar, multiplicar y dividir números. Existen tambien operadores de comparación que analizará si un valor es igual, mayor o menor que otro y operadores de asignación los cuales asignarán nuevos valores a los objetos o variables. A continuación explicaremos un poco más detalladamente los operadores en C#:

Operadores matemáticos

Casi todos los lenguajes de programación soportan operadores matemáticos. Estos operadores se utilizan para realizar operaciones matemáticas sencillas entre números. Entre estos operadores tenemos los de suma, resta, multiplicación, división y módulo (o residuo): +,-,*,/,%, y se los usa de la siguiente manera:

 using System;
 
 class operadoresMatematicos
 {
        public static void Main()
        {
                int a = 7;
                int b = 4;
                int c = a + b;
                int d = a - b;
                int e = a * b;
                int f = a / b;
                int g = a % b;
                Console.WriteLine ("De los números: {0} y {1} la suma es: {2}, la resta es:{3}, la multiplicación es: {4}, la división es: {5} con un residuo de: {6}",a,b,c,d,e,f,g);
        }
 }

Operadores de asignación

Los operadores de asignación son aquellos que sirven para asignar el valor del objeto o variable de la derecha al objeto o variable de la izquierda. Un ejemplo sencillo de este tipo de operadores es la inicialización de variables. Como habíamos visto, para asignar el valor a una variable simplemente utilizamos el símbolo (u operador) igual =

int a = 15; //la variable a tomará el valor de 15.
int b = a = 10; //la variable a y la variable b tomarán el valor de 10.

Además de estos operadores de asignación sencillos, existen otros operadores de asignación que realizan operaciones matemáticas antes de asignar el valor a la variable u objeto. Entre ellos tenemos: +=, -=, *=, /=, %=, ++, --. Ejemplos:

var += 10; // realiza la operación var = var+10;
var -= 10; // realiza la operación var = var-10;
var *= 10; // realiza la operación var = var*10;
var /= 10; // realiza la operación var = var/10;
var++; //realiza la operacion var = var+1; despues de procesar esta linea 
++var; //realiza la operación var = var+1; antes de procesar esta linea
var--; //realiza la operacion var = var-1; despues de procesar esta linea
--var; //realiza la operación var = var-1; antes de procesar esta linea

Operadores de comparación

Estos operadores son múy utiles cuando tenemos que cambiar el flujo de nuestro programa. Con ellos podemos comparar si un objeto o variable es igual (==), no es igual (!=), es mayor o igual (>=), es menor o igual (<=), es mayor (>) o es menor (<) que otro objeto. El resultado de esta comparación es de tipo bool es decir verdadero o falso (true o false). Estos operadores se los usa de la siguiente forma:

int a = 10;
int b = 20;
bool resp;

resp = (a == b); // compara si a es igual a b y retorna el valor bool false (o falso), tómese en cuenta que a==b es MUY diferente a a=b
resp = (a != b); // compara si a es diferente a b y retorna el valor bool true (o verdadero)
resp = (a <= b); // compara si a es menor o igual a b y retorna el valor bool true (o verdadero)
resp = (a >= b); // compara si a es mayor o igual a b y retorna el valor bool false (o falso)
resp = (a < b); // compara si a es menor a b y retorna el valor bool true (o verdadero)
resp = (a > b); // compara si a es mayor a b y retorna el valor bool false (o falso)

Operadores lógicos

Para entender como funcionan los operadores lógicos tenemos que aprender un poco lo que son los números binarios. En esta parte del libro no cubriremos en detalle este extenso tema de los números binarios ni del Algebra que gobierna estos números ni mucho menos de como se comportan las puertas lógicas dentro de un ordenador porque nos tomaría uno o dos libros completos, pero nos gustaría dar un poco de bases de como es que los números binarios forman parte de los operadores lógicos. Toda información que el ordenador opera internamente es representada por números binarios (por unos y ceros que son conocidos tambien por verdadero y falso), así la letra A el ordenador internamente lo representa en código binaro ASCII como 01000001 que en números "normales" o decimales es 65. Para manipular esta información en unos y ceros, el ordernador tiene operadores lógicos los cuales permiten cambiar la información de una manera que nos convenga. Por medio de estos operadores lógicos el ordenador es capáz de tomar decisiones, procesar cualquier información, hacer complicadas operaciones matemáticas, o en otras palabras, por medio de estos operadores lógicos, el ordenador hace todo lo que vosotros le habéis visto hacer.

Los operadores lógicos más importantes para nuestro estudio en C# son:

AND

Representado por el simbolo &. Comprueba si todos los números binarios son 1 (o verdadero) entonces la respuesta es 1 (o verdadero)

OR

Representado por el simbolo | (barra vertical de la tecla del 1). Comprueba si cualquiera de los números binarios es 1 (o verdadero) entonces la respuesta es 1 (o verdadero)

NOT

Representado por el simbolo ~ y !. Invierte la respuesta. En operaciones con tipos bool, el operador ! cambia la variable de verdadero a falso o viceversa, pero en números binarios, el operador ~ cambia cada uno de los unos y ceros por su opuesto, cuando encuentra un uno lo cambia por un cero y viceversa, asi por ejemplo si tenemos el numero binario 01000001 y aplicamos el operador NOT ~ obtendremos 10111110, pero si tenemos una expresion que se evalua como true (o verdadera) y si se aplica el operador !, se obtiene una respuesta false (o falsa). Por ejemplo (!(10==10)) esta expresión tiene como resultado false

XOR

Representado por el simbolo ^. En dos números, comprueba si los dos números binarios son iguales, entonces la respuesta es 0 (o falso).

<<

Desplazar a la izquierda desplaza todos los bits hacia la izquierda introduciendo ceros al final de la derecha y descartando los ultimos números. Asi el número 01000001 si se lo desplaza a la izquierda una vez 01000001 << 1, se convierte en 10000010

>>

Al igual que el operador anterior, desplazar a la derecha desplaza todos los bits hacia la derecha introduciendo ceros al final de la izquierda y descartando los ultimos números. Asi el número 01000001 si se lo desplaza a la derecha una vez 01000001 >> 1, se convierte en 00100000

Operadores lógicos de unión

En el caso de que deseamos comparar varios valores para saber si todos son verdaderos o si alguno es verdadero podemos usar los operadores lógicos de unión && y ||

a && b // esta línea compara si a y b son verdaderos retorna el valor true (o verdadero) si los dos lo son
a || b // esta línea compara si a o b son verdaderos retorna el valor true (o verdadero) si alguno de los dos es
!a     // esta línea compara si a es verdadero retorna falso si lo es y viceversa.

a y b pueden representar variables, constantes, números, funciones, expresiones, etc. que den como resultado un valor de decisión (true o false). Asi por ejemplo, el siguiente ejemplo es válido:

int a = 0;
int b = 10;
int c = 20;

if ((a <= b) && (c >= b))
  System.Console.WriteLine ("a es menor o igual a b y c es mayor o igual a b");


<- Anterior (Capítulo 2) | Siguiente (Capítulo 4) ->

Estructuras de control

<- Anterior (Capítulo 3) | Siguiente (Capítulo 5) ->

Estructuras de control

Hay dos maneras de cambiar el rumbo de ejecución de un programa, estos pueden ser saltos incondicionales y saltos condicionales. En este capítulo se describen algunas de estas sentencias. Algunas son muy similares a las existentes en otros lenguajes, como las sentencias if, for, while, etc. y otras, como foreach, throw o continue, son algo más específicas.

Saltos incondicionales

Las instrucciones de un programa se ejecutan sentencia por sentencia empezando desde el método o función principal llamado Main() hasta terminar con el programa. El programa sin embargo, tomará otros rumbos incondicionalmente en dos oportunidades: 1. Cuando encuentre la llamada a otros métodos (Ejemplo 4.1) y 2. Con el uso de las palabras claves como goto, break, continue, return y throw las cuales se discutirán más adelante.

Ejemplo 4.1 - Salto incondicional a otra función

 using System; 
 namespace Ejemplos{
   class Ejemplo4_1{
     static void Main(){
       Console.WriteLine ("Esta parte se ejecuta primero");
       LlamadaOtraFuncion();
       Console.WriteLine ("Esta parte se ejecuta al final");
     }
     
     static void LlamadaOtraFuncion(){
       Console.WriteLine ("Ha salido del método Main()");
     }
   }
 }

En el ejemplo anterior el programa ejecuta sentencia por sentencia el método principal Main() hasta que encuentra la llamada a otro método. Después de que el método llamado haya terminado el método Main continuará con la ejecución de las sentencias restantes.

La sentencia goto

En los inicios de los lenguajes de programación la sentencia goto fue la más popular para ir de un lugar a otro dentro del programa. Sin embargo esto creaba una tremenda confusión al momento de diseñar la aplicación. Si el programador quería hacer un esquema de como funcionaba dicha aplicación, se veía con un laberinto tipo espagueti de líneas y símbolos conectados entre si. Es por esto que esta sentencia es un poco "problemática" y fuera de "moda" entre los lenguajes de programación modernos. C# sin embargo soporta esta sentencia. Os recomendamos no utilizarla a menos que se necesario o si os sentís cómodos haciéndolo, pero cuando os cree un laberinto difícil de depurar, no digáis que no os advertimos de no utilizarla. Hay muchas otras mejores maneras de cumplir con el mismo propósito (la sentencia while por ejemplo es una de ellas), las cuales son más elegantes y más sencillas de depurar.

La sentencia goto funciona de la siguiente manera:

Primero se crea una etiqueta al inicio de cierto bloque de código y después en otro lugar podemos saltar hacia esa etiqueta usando la palabra clave goto. El siguiente ejemplo ilustra la sentencia goto:

 using System; 
 namespace Ejemplos
 {
    class Ejemplo4_2
    {
       static void Main()
       {
   int contador=0;
   REPETIR:
   Console.WriteLine ("Esta línea se repetirá 100 veces, esta es la linea numero: {0}", contador);
   if (contador++ < 100)
      goto REPETIR;
          Console.WriteLine ("Despues de que el contador sea igual o mayor que 100 se imprimirá esta línea");
       }   
    }
 }

Esta sentencia es un ejemplo de salto incondicional ya que por si solo saltará a la etiqueta seleccionada incondicionalmente.

Saltos condicionales

Los saltos condicionales sirven para ejecutar cierto códi