Vous êtes sur la page 1sur 75

CAPITULO 1

BREVE INTRODUCCIN A LOS LENGUAJES DE PROGRAMACIN


Comencemos con lo ms elemental, cuando dos o ms personas se comunican, para transmitirse informacin, expresar ideas, noticias, conceptos y hasta contarse algn chisme, utilizan un elemento para hacerlo y a tal elemento lo conocemos como Lenguaje. Sin ahondar en formalidades, un lenguaje es una herramienta para comunicarse por medio de signos, que pueden ser, escritos, sonoros, gestuales, etc. Usualmente, al lenguaje que usamos los humanos (independientemente del idioma) se le llama Lenguaje Natural. De esta manera, por ejemplo, un espaol, un mexicano y un uruguayo se comunicarn entre s usando su lenguaje natural (que en particular es expresado en Espaol con sus variantes regionales), de forma anloga dialogaran un australiano, un irlands y un estadounidense (seguramente comunicndose en Ingls con sus variantes regionales). La importancia en s, de sta herramienta, es el poder de comunicar, solicitar e incluso dar instrucciones para realizar algo concreto. En el mundo de la informtica, debemos ser muy precisos en como damos esas indicaciones y por ello se procura siempre que todo sea claro, sin confusiones, contradicciones ni ambigedades. El Lenguaje Natural humano, es complejo para ser interpretado por mquinas, para ello, a lo largo de la historia, se han creado lenguajes simples y concretos, para poder interactuar con mquinas. La Programacin, es una actividad en la cual tenemos que dar instrucciones precisas a una mquina, para que haga exactamente lo que queremos y para ello, se han creado y perfeccionado lenguajes, conocidos hoy como Lenguajes de Programacin. Los actuales lenguajes de programacin tienen caractersticas que pueden asemejarse en buen grado a los lenguajes naturales como el Espaol, Ingls, o cualquier otro; ya que al igual que en la comunicacin oral o escrita, los lenguajes de programacin tienen un vocabulario definido, adems de reglas ortogrficas, de estructura, de puntuacin, es decir la sintaxis que deben seguir y por supuesto una semntica, esto es el significado que adquieren las conformaciones basadas en las reglas antes mencionadas. Como en los lenguajes humanos corrientes (Lenguajes Naturales), estas reglas deben tomarse en cuenta para que las ideas que tratamos de expresar tengan sentido. Tambin sucede que un lenguaje de programacin cambia con el tiempo, igual que un lenguaje natural. Si t eres un hispano-hablante sabrs que en cada pas hispanoamericano se usan palabras que en otros pases no se utilizan o las mismas palabras tienen un significado distinto entre pases (esto es llamado ambigedad): el idioma Espaol ha venido evolucionando con el tiempo y se ha adaptado a la geografa. En este mismo sentido, el lenguaje de programacin C#.NET es una actualizacin tcnica de otros lenguajes de programacin ms 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 informtica que adems ha desarrollado lenguajes y herramientas como Turbo Pascal, Delphi (de Borland Co.) y Visual J++ (Microsoft). Por lo que C# pretende ser el siguiente eslabn en la evolucin de los lenguajes de programacin ms avanzados, buscando combinar en proporciones adecuadas: Potencia, Sencillez y Actualidad/Tendencia.

FUNDACION CONIN | C Sharp .NET

La evolucin de los ordenadores (computadores) y de los lenguajes de programacin ha sido grandsima. No hace muchos aos existan personas que tenan que hacer agujeros en tarjetas de cartulina para poder dar instrucciones al computador: eran las famosas tarjetas perforadas. Pocos aos despus de esos das existan personas (y hasta ahora existen aquellos) que pueden "hablar con el ordenador", se trata de informticos que en su poca solo disponan de elementos de muy bajo nivel para controlar el computador, eso hasta el da de hoy es la base de las tcnicas de cmputo, independientemente de cuanto hayan aumentado las capacidades de memorias, velocidades de microprocesadores, miniaturizaciones, etc. La forma en que una mquina de cmputo recibe instrucciones es una manera peculiar. No es la idea aqu ahondar sobre este tema, pero es importante brindar una idea al respecto. Supngase que se cuenta con un sistema de riego, en principio asmase algo simple, un jardn con un dispersor de agua, que se activa o desactiva utilizando una simple llave de encendido y apagado, como las de las luces. De esta forma podemos decir que tenemos un sistema que interpreta o entiende 2 instrucciones: Llave para arriba ---> ENCENDIDO Llave hacia abajo ---> APAGADO De esta manera el sistema se enciende o se apaga conforme alguien le da una de estas 2 instrucciones que el mismo interpreta o "entiende". Podemos esquematizar el referido sistema de esta forma: [INSTRUCCIONES] ====> [PROCESAMIENTO] ====> [Acciones / Resultados] Para tratar de simplificar la forma de transmitir o escribir una de esas instrucciones, podemos decir que si al bloque de procesamiento le enviamos la instruccin "1", implica un ENCENDIDO, es decir que le estamos pidiendo poner en marcha el sistema. Por el contrario, si le enviamos un "0", es un APAGADO, le estamos pidiendo detener el sistema. Hemos hecho esto, porque como antes mencionamos, las mquinas deben trabajar con interpretaciones lo ms concreta y simplificadas posibles. Es ms fcil para una mquina elemental, interpretar un "1", un "0" o incluso una serie de stos nmeros [*]. As que ahora tenemos algo como un lenguaje elemental para dar indicaciones, donde tenemos dos instrucciones: Instruccin: ENCENDIDO Instruccin: APAGADO ---> ---> Equivale a: 1 Equivale a: 0

Imaginemos ahora que el sistema de riego, adems de tener encendido y apagado, tiene otra modalidad llamada DIARIO, que simplemente provoca que el mismo se encienda una vez al da, a una hora indicada, por un lapso determinado (ej.: 90 minutos).

FUNDACION CONIN | C Sharp .NET

As que necesitamos otra representacin o equivalencia simple para indicar esta nueva instruccin. Reformulemos el caso anterior, de la siguiente manera: Instruccin: ENCENDIDO Instruccin: APAGADO Instruccin: DIARIO ---> ---> ---> Equivale a: 01 Equivale a: 00 Equivale a: 10

Ya que hemos recalcado las similitudes entre los lenguajes de programacin y los lenguajes naturales tambin hay que tener presente que un lenguaje de programacin es mucho ms estricto que uno natural en el sentido de que no pueden existir ambigedades. Es muy fcil en el idioma Espaol tener frases que impliquen algo que ya conocemos o que signifiquen cosas diferentes. Por el contrario los lenguajes de programacin son claros, especficos y directos, no se admiten ambigedades ni suposiciones. Para poder dominar un lenguaje de programacin (al igual que con los lenguajes naturales) se requiere mucho estudio pero por sobre todo muchsima prctica. Una persona podra leer este manual unas 500 veces pero si no pone en prctica los conceptos ni investiga por su cuenta, jams llegar a dominar este maravilloso lenguaje de programacin. As que: a practicar se ha dicho!

[*] Al sistema numrico compuesto nicamente por los elementos "0" y "1" se le llama Sistema Numrico Binario, o popularmente Sistema Binario. FUNDACION CONIN | C Sharp .NET 3

CAPITULO 2

INTRODUCCIN
El lenguaje C#
Los primeros rumores de que Microsoft estaba desarrollando un nuevo lenguaje de programacin surgieron en 1998, haciendo referencia a un lenguaje que entonces llamaban COOL y que decan era muy similar a Java. En junio de 2000, Microsoft despej todas las dudas liberando la especificacin de un nuevo lenguaje llamado C#. A esto le sigui rpidamente la primera versin de prueba del entorno de desarrollo estndar (SDK) .NET, que inclua un compilador de C#. El nuevo lenguaje estaba diseado 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 tecnologa es el nuevo lenguaje de programacin 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 (orientacin a objetos, gestin automtica de memoria, etc.) a la vez que proporciona un gran rendimiento. 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 estndares (como XML). Es tambin la principal herramienta para programar en la plataforma .NET. Tal vez se estn preguntado Qu es la plataforma .NET? Porqu Microsoft est invirtiendo tanto en esta nueva tecnologa? Qu es lo que es tan novedoso? Cmo es que con .NET se pueden producir aplicaciones multiplataforma? A continuacin hablaremos un poco de la plataforma .NET.

La plataforma .NET
Es una plataforma de desarrollo de software con especial nfasis en el desarrollo rpido de aplicaciones, la independencia de lenguaje y la transparencia a travs de redes. La plataforma consta de las siguientes partes: Un conjunto de lenguajes de programacin (C#, J#, JScript, C++ gestionado, Visual Basic.NET, y otros proyectos independientes). Un conjunto de herramientas de desarrollo (entre ellos Mono Develop o Visual Studio.NET de Microsoft ) Una librera de clases amplia y comn para todos los lenguajes. Un sistema de ejecucin de Lenguaje Comn. (CLR). Un conjunto de servidores .NET Un conjunto de servicios .NET Dispositivos electrnicos con soporte .NET (PDA, Celulares, etc.).

FUNDACION CONIN | C Sharp .NET

Los puntos fuertes de la plataforma son: Independencia de lenguaje Todos los lenguajes que conformen con los estndares .NET, sin importar cual, podrn interoperar entre s de forma totalmente transparente, las clases podrn 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 caractersticas de .NET llamado Common Type System (CTS). Librera de clases comn Ms de 4000 clases, objetos y mtodos incluidos en la plataforma .NET estn 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 da 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 disposicin 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 distribucin 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 cdigo de mquina en un proceso que se conoce como JIT (Just In Time [justo a tiempo]) el cual se ejecutar cuando se requiera. Este proceso producir cdigo de mquina bien eficiente que se reutilizar si es que hubiera cdigo 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 tecnologas claves: Servicios Web (Web Services), Web Forms, y Windows Forms. FUNDACION CONIN | C Sharp .NET 5

Estandarizacin Adems de los mritos tcnicos, una de las razones del xito de la plataforma .NET ha sido por el proceso de estandarizacin que Microsoft ha seguido. Este proceso permite la implementacin del lenguaje C# y de la plataforma .NET por terceros, incluso en entornos distintos de Windows.

Resumen introductorio sobre el lenguaje C#


El lenguaje es muy sencillo, sigue el mismo patrn de los lenguajes de programacin modernos. Incluye un amplio soporte de estructuras, componentes, programacin orientada a objetos, manipulacin de errores, recoleccin de basura, etc., que es construido sobre los principios de C++ y Java. Como sabrn, las clases son la base de los lenguajes de programacin 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 mtodos y propiedades, al igual que la sencilla habilidad para implementar encapsulacin, herencia y polimorfismo, que son los tres pilares de la programacin orientada a objetos. C# tiene un nuevo estilo de documentacin XML que se incorpora a lo largo de la aplicacin, lo que simplifica la documentacin en lnea de clases y mtodos. C# soporta tambin 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# tambin provee soporte para estructuras, un concepto el cual ha cambiado significativamente 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 caractersticas de componentes orientados, como propiedades, eventos y construcciones declaradas (tambin llamados atributos). La programacin 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 ms.

C# frente a Java
C# y Java son lenguajes similares, de sintaxis basada en C/C++, orientados a objetos, y ambos incluyen las caractersticas ms importantes de los lenguajes modernos, como son la gestin automtica de memoria y la compilacin a cdigo intermedio. Pero por supuesto, tambin hay diferencias. Una de las diferencias ms importantes es que C# es mucho ms cercano a C++ en cuanto a diseo se refiere. C# toma casi todos sus operadores, palabras reservadas y expresiones directamente de C++. Tambin se han mantenido algunas caractersticas que en Java se han desestimado. Por ejemplo, la posibilidad de trabajar directamente con direcciones de memoria. Si bien tanto Java como .NET proporcionan gestin automtica de memoria, en C# es posible usar lo que se denomina "cdigo no seguro". Cuando se usa cdigo no seguro en C# es posible operar con punteros de forma muy similar a como se hara en C/C++, pero el cdigo que utiliza punteros se queda marcado como no seguro y no se ejecuta en entornos en los que no tiene permisos.

FUNDACION CONIN | C Sharp .NET

C# frente a C++
Puesto que C# se ejecuta en una mquina virtual, sta se hace cargo de la gestin de memoria y por lo tanto el uso de punteros es mucho menos importante en C# que en C++. C# tambin es mucho ms orientado a objetos, hasta el punto de que todos los tipos usados derivan en ltima instancia el tipo 'object'. Adems, muchos tipos se usan de forma distinta. Por ejemplo, en C# se comprueban los lmites 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 mltiple de clases presente en C++. Sin embargo, referido a clases, C# implementa 'propiedades' del tipo de las que existen en Visual Basic, y los mtodos 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, FORTRAN, Java, Python, etc., y con capacidad para aceptar prcticamente cualquier lenguaje. Entonces la pregunta es, porqu se eligi C# en lugar de cualquier otro lenguaje? La razn fundamental es que C# se dise para la plataforma .NET y es capaz de utilizar todo su potencial. Tambin es cierto que es un lenguaje "limpio" en el sentido de que al no tener que proporcionar compatibilidad hacia atrs se ha tenido ms libertad en el diseo 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.

FUNDACION CONIN | C Sharp .NET

CAPITULO 3

PRIMER PROGRAMA
//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 lnea de nuestro programa encontramos lo siguiente: //Programa Hola Mundo. Esta lnea es un ejemplo de comentarios. Un comentario es una parte en nuestro programa que ser ignorado por el compilador. Existen tres tipos de comentarios en C#. El primer tipo es comentario de una sola lnea. El segundo es comentario de varias lneas. El tercer tipo es para crear documentacin. Los comentarios de una sola lnea pueden ser incluidos en lneas independientes, en lneas que ya incluyen cdigo para comentar sobre lo que hace esa lnea o para comentar una lnea de cdigo que no necesitamos. Los comentarios de varias lneas sirven para incluir muchas lneas de texto o cdigo 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 */.
//Este es un ejemplo de comentarios de una lnea /* Este comentario abarca varias lneas */ class HolaMundo { static void Main() { string var = "Mundo"; System.Console.WriteLine("Hola {0}!", var); //Este comentario puede describir que hace esta funcin //System.Console.WriteLine ("y esta lnea no la vamos a desplegar"); } }

FUNDACION CONIN | C Sharp .NET

Clases, Objetos y Tipos


La esencia de la programacin orientada a objetos es la creacin de nuevos tipos. Un tipo es la representacin de un componente (Pensado en un ordenador (un computador) que est compuesto de varios componentes). En programacin un componente es algo que cumple una funcin. Por ejemplo, un componente puede ser un botn en un programa. En una aplicacin 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 "tamao", "posicin", etc. Las propiedades son las mismas pero los valores almacenados en sus atributos pueden ser diferentes. Por ejemplo, un botn puede tener tamao 10 y otro tamao 6. Podemos decir entonces que tenemos varias instancias del mismo componente (o varios botones del mismo tipo) con diferentes valores en sus atributos. La programacin orientada a objetos es esto. Crear componentes que puedan ser reutilizados. 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 programacin orientado a objetos, en C# los tipos o componentes son definidos por una clase (class en ingls). Las diferentes reproducciones o instancias de un componente del mismo tipo se conocen como objetos. Posteriormente en nuestro estudio veremos que en C# hay ms tipos adems 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, 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 despus el nombre de nuestro componente, despus 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) debern estar encerrados entre llaves { }. Las llaves delimitan el inicio y el final de dicho componente.

Mtodos o Funciones
Los mtodos o funciones son trozos de cdigo que realizan una accin, 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 funcin. Por ejemplo, la funcin WriteLine() de la clase Console como debis suponer "Escribe una Lnea en la consola". De forma similar se pueden declarar clases a las que se le aaden un nmero ilimitado de mtodos. En nuestro ejemplo la nica funcin que hemos definido lleva el nombre de Main() la cual es una funcin especial que indica la entrada principal de ejecucin de un programa. Cada programa en C# debe tener una funcin Main().

FUNDACION CONIN | C Sharp .NET

Crear nuevos mtodos o funciones


Para declarar un mtodo o funcin utilizamos el siguiente formato:

[entorno] tipo_a_retornar Nombre_de_la_Funcin ([tipo Argumento1, tipo Argumento2,...]) { //lineas de cdigo } las palabras dentro de corchetes [] son partes opcionales De acuerdo con nuestro ejemplo, la funcin Main() cumple con el formato establecido:
static void Main() { //lineas de cdigo }

En nuestro ejemplo la funcin Main() tiene como entorno la palabra clave static y como tipo_a_retornar la palabra clave void. Cuando la funcin no retorna ningn tipo, utilizamos la palabra void. Ms adelante veremos ms tipos adems de void. La palabra static tambin la veremos ms adelante en nuestro estudio, por el momento debis confiar en el ejemplo y utilizarla an sin saber lo que hace. Podemos aadir a nuestro componente o clase un ilimitado nmero de funciones. Por ejemplo, para aadir ms funciones a nuestro primer ejemplo procederemos a crear una funcin que suma dos valores. Como ya habis aprendido en esta seccin, crearemos nuestra funcin de la forma establecida. Despus del final de la funcin Main crearemos una funcin 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 funcin principal:

FUNDACION CONIN | C Sharp .NET

10

Aadiendo funciones a nuestro programa


//Programa Hola Mundo agregando operaciones matemticas 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); } } }

Al probar nuestro programa, el resultado ser el siguiente:


Hola Mundo! 1 + 3 = 4

sta es una pequea introduccin a funciones, ms adelante estudiaremos ms detalladamente cmo crear y utilizar funciones.

Aplicaciones de consola
Las aplicaciones de consola no poseen una interfaz grfica, no tienen botones o ventanas, poseen una interfaz basada simplemente en texto. El ejemplo que hemos realizado hasta ahora es una aplicacin de consola que despliega texto en la pantalla, para ello hemos utilizado la funcin WriteLine. Como habamos visto en la introduccin, la plataforma .NET posee ms de 4000 componentes cada cual con diferentes funciones internas. En el caso de nuestro programa hemos usado la funcin WriteLineque se encuentra dentro del componente Console. Para poder hacer uso de funciones estticas que se encuentran en otros componentes, en C# como en la mayora de lenguajes de programacin orientados a objetos, debemos especificar el nombre del componente en primer lugar seguido por un punto y a continuacin en el nombre de la funcin.

FUNDACION CONIN | C Sharp .NET

11

Es por esto que utilizamos la frase Console.WriteLine. Dentro del componente Console la plataforma .NET tiene disponibles muchsimas otras funciones que nos ayudan a disear programas de consola. El lenguaje C# est orientado con el paradigma de objetos y hereda muchos elementos de C++.

Namespaces
Quiz algunos de vosotros os habris preguntado qu significa la palabra System que est al inicio de cada programa?. Pes bien, System en este caso representa un Espacio de Nombres (namespace en ingls). Los espacios de nombres (namespaces) se crearon principalmente para dar ms organizacin a los componentes. La plataforma .NET tiene incorporados muchsimos componentes y sera una tarea imposible tratar de memorizar todos los nombres de ellos para no repetirlos. Tarde o temprano querris crear un componente y no sabris si el nombre que queris darle ya existe o no. Para evitarnos este problema y para poder distinguir a dnde 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 institucin educativa que se compone de educacin primaria y educacin secundaria. Cmo podramos crear un componente que se llame Presidente si existen 2 presidentes que tienen funciones distintas uno para la seccin primaria y otro para la seccin secundaria? En este caso podramos aplicar un espacio de nombres para poder crear los componentes Presidente que cumplen distintas funciones. Podramos crear el espacio de nombres Primaria y dentro de ste el componentePresidente. De igual forma el espacio de nombres Secundaria y dentro de ste el componente Presidente cada uno de los componentes podr tener definiciones distintas. Para acceder a las funciones de los componentes Presidente podramos usar:

Primaria.Presidente.nombre_de_la_funcin(); y Secundaria.Presidente.otra_funcin(); Cada una de las dos definiciones de Presidente son independientes, no tienen relacin 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 lnea de cdigo estudiada: System.Console.WriteLine ("Hola {0}!", var); existe una funcin llamada WriteLine dentro del componente Console dentro del nombre de espacioSystem. Cualquier otro componente llamado Console dentro de otro espacio de nombres, es un componente diferente con funciones diferentes que quizs no posea la funcin WriteLine.

FUNDACION CONIN | C Sharp .NET

12

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 organizacin de los componentes. Los espacios de nombres, componentes y mtodos se accedern de la misma forma como lo hemos visto a travs 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 Consolerepetidamente. 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 aadimos la lnea de cdigo using System; al inicio de nuestro programa, podemos llamar al componente Console sin escribir System al inicio:
//Ejemplo Modificado - 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 se ve en el ejemplo que ya no es necesario poner la palabra system.Console.WriteLine, quedando Console.WriteLine. 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 lnea de cdigo using System.Console es invlida y producir errores de compilacin.

FUNDACION CONIN | C Sharp .NET

13

Caracteres sensibles
C# como todos los lenguajes de programacin derivados de C hace diferencia entre caracteres en mayscula y caracteres en minscula. Esto quiere decir que las palabras Using y using son distintas y por lo tanto no cumplen la misma funcin. 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 mtodo que C#

incorpora para desplegar texto en la consola.

FUNDACION CONIN | C Sharp .NET

14

CAPITULO 4 FUNDAMENTOS DEL LENGUAJE


En el captulo anterior introducimos nuestro primer programa en C#, un programa sencillo el cual incorpora muchos temas que hemos cubierto bsicamente y solamente en parte. En esta seccin procuraremos ver ms a fondo las partes bsicas de C#. Nos internaremos ms a fondo en la sintaxis y la estructura de C#, cubriremos lo que son los tipos. Hablaremos de los tipos bsicos o internos y de cmo crear nuevos tipos. Tambin hablaremos en general de la manipulacin de datos. Hablaremos sobre condicionales, operadores matemticos y algunos otros temas relacionados. Empecemos entonces nuestro estudio con lo que son tipos.

Tipos
Los tipos son la base de cualquier programa. Un tipo no es ms que un espacio en el que se almacena una informacin, ya sean nmeros, palabras o tu fecha de nacimiento.

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

Los tipos en C# al igual que C++ y Java se clasifican en dos secciones: Tipos bsicos o internos y tipos creados por el usuario. Los tipos bsicos no son ms que alias para tipos

predefinidos en la librera base de la plataforma .NET. As, el tipo nmero entero (que se representa con la palabra clave int), no es ms que una forma rpida de escribir System.Int32. Dentro de estas dos secciones los tipos del lenguaje C# tambin son divididos en dos grandes categoras: tipos por valor y tipos por referencia. Existe una tercera categora de tipos, disponible solo cuando se usa cdigo no seguro: los punteros, que se discutirn ms 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 direccin donde se encuentran los objetos, es por eso que se las llaman referencias. Ms adelante describiremos como funcionan cada una de estas categoras.

FUNDACION CONIN | C Sharp .NET

15

Tipos bsicos o internos


Los tipos bsicos como hemos dicho son espacios predefinidos y categorizados donde se almacena informacin. En C# tenemos los siguientes tipos internos: Tipos bsicos Nombre para la Con Bytes Tipo C# plataforma .NET signo? utilizados bool byte sbyte short int uint long ulong float System.Boolean System.Byte System.SByte System.Int16 System.Int32 System.Uint32 System.Int64 System.Uint64 System.Single No No Si Si No Si No Si No Si Si Si 1 0 hasta 255 1 -128 hasta 127 2 -32.768 hasta 32.767 2 0 hasta 65535 4 -2.147.483.648 hasta 2.147.483.647 4 0 hasta 4.394.967.395 8 -9.223.372.036.854.775.808 hasta 9.223.372.036.854.775.807 Aproximadamente 1.5E-45 hasta 3.4E38 con 7 cifras significativas Aproximadamente 5.0E-324 hasta 1.7E308 con 7 cifras significativas Aproximadamente 1.0E-28 hasta 7.9E28 con 28 29 cifras significativas

Valores que soporta

1 true o false (verdadero o falso en ingls)

ushort System.Uint16

8 0 hasta 18446744073709551615 4 8 12

double System.Double decimal System.Decimal char System.Char

2 Cualquier carcter Unicode (16 bits)

C# tiene una ventaja y caracterstica especial sobre los dems lenguajes de programacin modernos y es que cada vez que se crea un objeto de un tipo bsico, stos son mapeados internamente a un tipo primitivo de la plataforma .NET el cual es parte del CLS (Especificacin comn 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 deberis decidir qu tipo de variables querris usar. Generalmente esta decisin se basa en el tipo de informacin que vayis a usar y en el tamao de la informacin. Por ejemplo en nuestro ejemplo 2.2 del captulo anterior necesitbamos hacer la suma de dos valores numricos por lo que usamos dos tipos bsicos de nmero entero (usando la palabra clave int) los cuales de acuerdo con nuestra tabla 3.1 son nmeros enteros (no pueden llevar valores decimales) y podrn aceptar valores entre -2,147,483,648 y 2,147,483,647 lo cual es ms que suficiente para nuestro ejemplo de aadir dos nmeros.

FUNDACION CONIN | C Sharp .NET

16

En el caso de que necesitramos hacer uso de nmeros reales (los cuales poseen una parte entera y una parte decimal como el nmero 10.22) podremos hacer uso del tipo float, double y decimal de acuerdo con el tamao del nmero que necesitemos y as cada uno de los tipos tiene su uso y capacidad de acuerdo con la tabla anterior. A continuacin explicaremos brevemente los tipos ms usados en C#:

Enteros
Los tipos que sirven para almacenar nmeros 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 ms utilizado es el int, pes se utiliza para controlar matrices, indexar arreglos (arrays) adems de las operaciones normales con enteros. Adems, se trata de un entero de tamao medio: ms pequeo que long y ulong, pero ms grande que byte, sbyte, short y ushort. El siguiente ejemplo muestra la declaracin y uso de algunos tipos enteros calculando el nmero de segundos en una hora, dia y en un ao. Ejemplo 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 ao: {0}", anio); } }

De nuevo hemos usado el mtodo 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 ms de un argumento, se seguira con {1}, y as sucesivamente. Por ejemplo, las dos lneas que utilizan Console.WriteLine se pueden simplificar as:
Console.WriteLine("En un dia: {0}; en un ao: {1}", dia, anio);

FUNDACION CONIN | C Sharp .NET

17

Tipos de coma flotante


Los tipos de coma flotante sirven para representar a nmeros con parte fraccionaria. La representacin por supuesto puede no ser exacta, bien por errores de la mquina, bien porque el nmero de decimales que se puede alojar es finito. Existen tres clases de tipos de punto flotante: float, double y decimal. De los dos, el ms usado es double, pes es el valor que devuelven la mayora de las funciones matemticas de la librera base. El siguiente ejemplo calcula la raz cuadrada y el logaritmo de dos:
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 raz de dos es {0}", raiz2); } }

Y la salida ser la siguiente:


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

Si intentamos cambiar el tipo de log2 a otro de menos precisin, 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, pus se perdern datos. Lo mismo ocurre con la mayora 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 aritmtica 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 clculos monetarios.

FUNDACION CONIN | C Sharp .NET

18

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 instruccin de condicin solo puede estar gobernada por un valor bool, no como en C/C++, que lo puede estar tambin 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 inclusin del tipo bool en el lenguaje ayuda a la claridad del cdigo y evita algunos errores muy comunes. Ejemplo utilizando tipos de decisin 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 lnea se muestra que el operador "==" tambin devuelve un valor booleano. El resultado debera ser el siguiente:

b es True esto saldr 2 = 2 es True

FUNDACION CONIN | C Sharp .NET

19

El tipo char
El tipo char permite almacenar un carcter 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 adems permite la representacin de otros alfabetos, como el japons, griego, cirlico, etc. Para introducir un carcter se utilizan comillas simples, de forma que declarar un carcter sigue la estructura:
char letra1 = 'a'; char letra2 = '\u0041'; char letra3 = '\n'; //formato simple //formato Unicode que representa la letra A //formato carcter de escape

Para una lista completa de caracteres unicode puede visitar la siguiente pgina: http://unicode.coeurlumiere.com/ La siguiente lista contiene los caracteres de escape comunes y su significado:
\' \" \\ \0 \a \b \f \n \r \t \v apostrofe Comillas Backslash Null (nulo) Alerta Retroceso Form feed Lnea nueva Retorno del carro Tabulacin Horizontal Tabulacin 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 ms usados en C#, lo estudiaremos detalladamente ms adelante.

FUNDACION CONIN | C Sharp .NET

20

Convirtiendo tipos
En nuestros programas muchas veces necesitaremos cambiar de tipo a los objetos que hayamos creado. Esto lo podremos hacer implcitamente o explcitamente. Una conversin de tipos implcita sucede automticamente, es decir el compilador se har cargo de esto. Una conversin explicita en cambio se llevar a cabo nicamente cuando nosotros lo especifiquemos. Hay que tomar en cuenta que no siempre podremos hacer una conversin de un tipo hacia otro. Como regla general las conversiones implcitas 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 conversin implicita de short a int se lleva a cabo en el siguiente ejemplo:
short corto = 3; int entero = corto; //compilar sin ningn problema

Aqu sucede una conversin implcita, 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 ningn problema ya que har una conversin de short a int implcitamente 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, estaramos 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 dndonos un error:
int entero = 300; short corto = entero; //nos dar un error de compilacin

En estos casos es cundo podremos hacer una conversin explcita. Debido a que la informacin almacenada en la variable entero de tipo int est tambin en el rango de capacidad del tipo short y los dos tipos son de la misma clase (enteros) podremos hacer una conversin explicita designando entre parntesis a que tipo queremos convertir de la siguiente manera:
int entero = 300; short corto = (short)entero; //convertir la variable entero al tipo short

FUNDACION CONIN | C Sharp .NET

21

En el ejemplo anterior, el compilador no nos dar ningn problema. Cada uno de los tipos bsicos citados a continuacin soportar una conversin implcita o explcita como se lo expresa en la siguiente tabla: Conversin Implcita (I) Conversin Explcita (E) Desde/hacia byte sbyte short ushort int uint long ulong float double decimal byte sbyte short ushort int uint long ulong float double decimal I E E E E E E E E E E E I E E E E E E E E E I I I E E E E E E E E I E E I E E E E E E E I I I I I E E E E E E I E E I E I E E E E E I I I I I I I E E E E I E E I E I E I E E E I I I I I I I I I E E I I I I I I I I I I E I I I I I I I I E E I

Arreglos
En C# se pueden construir arreglos de prcticamente cualquier tipo de dato. Los arreglos, tambin llamados vectores o arrays, no son ms que una sucesin de datos del mismo tipo. Por ejemplo, el concepto matemtico de vector es una sucesin de nmeros 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]); } }

FUNDACION CONIN | C Sharp .NET

22

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 parmetros 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 parmetro un entero distinto (ntese que se comienza a contar a partir de 0 y el nmero del parmetro se encuentran entre corchetes). Existe una forma ms corta para declarar el arreglo y asignarle los valores:
int[] arr = { 1, 2, 3 }; //es exactamente lo mismo que el ejemplo anterior

Tambin se pueden crear arreglos bidimensionales (y de la misma forma para ms dimensiones). En ese caso la sintaxis para declarar un arreglo bidimensional de enteros ser:
int[,] arr; //declaracin de arreglos bidimensionales en C#

En contraposicin a C/C++, en el que se declarara como:


int[][] arr; //declaracin de arreglos bidimensionales en C/C++

De esta forma, un arreglo bidimensional se declarara y utilizara 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 del arreglo arr[1,1] es {0}", arr[1, 1]); } }

El resultado ser:
El valor del arreglo arr[1,1] es 4

FUNDACION CONIN | C Sharp .NET

23

Igual que el ejemplo anterior, podemos declarar todo el arreglo de la siguiente forma:
int[,] arr = {{1,2},{3,4}};

Identificadores
En una aplicacin siempre se deben crear variables, constantes, mtodos, 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 Despus de que el identificador empiece con una letra o un smbolo _, el identificador puede tener cualquier cantidad de letras, lneas o nmeros. Ejemplo:
EsteIdentificadorEsValido _este_tambin esteEsOtro1 esteEsOtro2

Como ejemplos invlidos tenemos:


Esto es invalido 123_Otro_invlido int

En los ejemplos que no son vlidos, el primero contiene espacios, el segundo empieza con nmeros y el tercero es una palabra clave lo cual no es permitido.

Nota: Es recomendado que las variables siempre empiecen con minsculas y que sigan el patrn 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 minsculas pero la segunda, tercera, etc. palabras estarn unidas a la primera y tendrn su primera letra en maysculas ejemplo: miVariable. Tambin se ha recomendado que el nombre de Mtodos, Clases y dems nombres que necesitamos especificar deban llevar el mismo formato anterior con la excepcin de que la primera letra deber ser mayscula.

FUNDACION CONIN | C Sharp .NET

24

Variables
Una variable es el nombre que se le da al espacio donde se almacena la informacin 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 informacin que deseamos. Para hacerlo utilizamos el smbolo = despus 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 habamos 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 creacin y asignacin de valor de una variable podemos especificar estos dos procesos en una misma lnea.
int var = 10;

La primera vez que una variable recibe un valor se llama inicializacin 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 creacin de una variable se la hace 1 sola vez y la asignacin de diferentes valores se puede hacer cuantas veces queramos.

FUNDACION CONIN | C Sharp .NET

25

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 creacin.

Enumeraciones
Supongamos que estamos diseando un juego y necesitamos crear una variable para saber cul es el estado del tanque de combustible de nuestro automvil. Suponiendo que tenemos 4 niveles en el tanque: lleno, medio, bajo y crtico. Qu tipo de variable podramos usar para especificar estos estados? Una forma de hacerlo podra 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 crtico. Esta alternativa funcionara pero a la larga nos olvidaremos qu nmero 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 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); }

FUNDACION CONIN | C Sharp .NET

26

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 vaco!"); } if (auto == tanque.critico) { Console.WriteLine("Alerta! tu auto se qued sin combustible"); } } } }

Este programa sencillo crea una enumeracin 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 enumeracin. Cuando asignamos a la variable auto1 el valor de tanque.lleno y revisamos el estado del tanque llamando a la funcin RevisarEstadoTanque, podremos comprobar cul es el estado actual del tanque de combustible. sta es una forma muy descriptiva de cmo crear variables que cambien de estado, una solucin 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 enumeracin son valores enteros del tipo int el primer elemento dentro de la enumeracin 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 enumeracin y tampoco asignamos valores a las constantes. En el siguiente ejemplo podemos ver cmo 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:

FUNDACION CONIN | C Sharp .NET

27

Ejemplo de 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 enumeracin. Hay que tener en cuenta que el tipo que va a tener la enumeracin se encuentra despus del nombre de la enumeracin precedido por dos puntos. De esa forma podremos especificar de qu tipo son. Como habamos 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. Tambin se debe tomar en cuenta que los valores de las constantes estn asignados con el signo = y estn separadas por comas. Como habis visto la forma de acceder al valor numrico de las enumeraciones es especificando entre parentesis a qu tipo pertenecen, en este caso (uint). Despus de lo cual especificamos el nombre de la enumeracin seguido por un punto que separa al nombre de la constante. En el caso de que deseemos desplegar slo 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.

FUNDACION CONIN | C Sharp .NET

28

As por ejemplo:
enum nmeros { 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 smbolos con los cuales C# tomar una accin. Por ejemplo existen operadores matemticos para sumar, restar, multiplicar y dividir nmeros. Existen tambin operadores de comparacin que analizar si un valor es igual, mayor o menor que otro y operadores de asignacin los cuales asignarn nuevos valores a los objetos o variables.

Operadores matemticos
Casi todos los lenguajes de programacin soportan operadores matemticos. Estos operadores se utilizan para realizar operaciones matemticas sencillas entre nmeros. Entre estos operadores tenemos los de suma, resta, multiplicacin, divisin y mdulo (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 Console.WriteLine("La Console.WriteLine("La Console.WriteLine("La Console.WriteLine("La } }

los nmeros: {0} y {1}...", a, b); suma es: {0}", c); resta es:{0}", d); multiplicacin es: {0}", e); divisin es: {0} con un residuo de: {1}", f, g);

FUNDACION CONIN | C Sharp .NET

29

Operadores de asignacin
Los operadores de asignacin 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 inicializacin de variables. Como habamos visto, para asignar el valor a una variable simplemente utilizamos el smbolo (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 tomarn el valor de 10.

Adems de estos operadores de asignacin sencillos, existen otros operadores de asignacin que realizan operaciones matemticas antes de asignar el valor a la variable u objeto. Entre ellos tenemos: +=, -=, *=, /=, %=, ++, --.
var += var -= var *= var /= var++; ++var; var--; --var; 10; // realiza la operacin var = var+10; 10; // realiza la operacin var = var-10; 10; // realiza la operacin var = var*10; 10; // realiza la operacin var = var/10; //realiza la operacion var = var+1; despus de procesar esta lnea //realiza la operacin var = var+1; antes de procesar esta lnea //realiza la operacion var = var-1; despus de procesar esta lnea //realiza la operacin var = var-1; antes de procesar esta lnea

Operadores de comparacin
Estos operadores son muy tiles 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 comparacin es de tipo bool es decir verdadero o falso (true o false). Estos operadores se utilizan 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 (falso) //tmese 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 resp = (a >= b); //compara si a es mayor o igual a b y retorna el valor false resp = (a < b); //compara si a es menor a b y retorna el valor true resp = (a > b); //compara si a es mayor a b y retorna el valor false

FUNDACION CONIN | C Sharp .NET

30

Operadores lgicos
Para entender cmo funcionan los operadores lgicos tenemos que aprender un poco lo que son los nmeros binarios. Toda informacin que el ordenador opera internamente es representada por nmeros binarios (por unos y ceros que son conocidos tambin por verdadero y falso), as la letra A el ordenador internamente lo representa en cdigo binario ASCII como 01000001 que en nmeros "normales" o decimales es 65. Para manipular esta informacin en unos y ceros, el ordenador tiene operadores lgicos los cuales permiten cambiar la informacin de una manera que nos convenga. Por medio de estos operadores lgicos el ordenador es capaz de tomar decisiones, procesar cualquier informacin, hacer complicadas operaciones matemticas. Los operadores lgicos ms importantes para nuestro estudio en C# son: AND OR NOT Representado por el smbolo &. Comprueba si todos los nmeros binarios son 1 (o verdadero) entonces la respuesta es 1 (o verdadero). Representado por el smbolo |. Comprueba si cualquiera de los nmeros binarios es 1 (o verdadero) entonces la respuesta es 1 (o verdadero) Representado por el smbolo ~ y !. Invierte la respuesta. En operaciones con tipos bool, el operador ! cambia la variable de verdadero a falso o viceversa, pero en nmeros 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, as por ejemplo si tenemos el nmero 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 expresin tiene como resultado false. Representado por el smbolo ^. En dos nmeros, comprueba si los dos nmeros binarios son iguales, entonces la respuesta es 0 (o falsa). Desplazar a la izquierda. Desplaza todos los bits hacia la izquierda introduciendo ceros al final de la derecha y descartando los ltimos nmeros. As el nmero 01000001 si se lo desplaza a la izquierda una vez 01000001 << 1, se convierte en 10000010 Desplazar a la derecha. Desplaza todos los bits hacia la derecha introduciendo ceros al final de la izquierda y descartando los ltimos nmeros. As el nmero 01000001 si se lo desplaza a la derecha una vez 01000001 >> 1, se convierte en 00100000

XOR <<

>>

FUNDACION CONIN | C Sharp .NET

31

Operadores lgicos de unin


En el caso de que deseemos comparar varios valores para saber si todos son verdaderos o si alguno es verdadero podemos usar los operadores lgicos de unin && y ||.
a && b //esta lnea compara si a y b son verdaderos //retorna el valor true (o verdadero) si los dos lo son a || b //esta lnea compara si a o b son verdaderos //retorna el valor true (o verdadero) si alguno de los dos es !a // esta lnea compara si a es verdadero retorna falso si lo es y viceversa.

a y b pueden representar variables, constantes, nmeros, funciones, expresiones, etc. que den como resultado un valor de decisin (true o false). As por ejemplo, el siguiente ejemplo es vlido:
int a = 0; int b = 10; int c = 20; if ((a <= b) && (c >= b)) { Console.WriteLine("a es menor o igual a b y c es mayor o igual a b"); }

FUNDACION CONIN | C Sharp .NET

32

CAPITULO 5

ESTRUCTURAS DE CONTROL
Hay dos maneras de cambiar el rumbo de ejecucin de un programa, estos pueden ser saltos incondicionales y saltos condicionales. Algunas sentencias son muy similares a las existentes en otros lenguajes, como por ejemplo if, for, while, etc., y otras como foreach, throw o continue son algo ms especficas.

Saltos incondicionales
Las instrucciones de un programa se ejecutan sentencia por sentencia empezando desde el mtodo o funcin 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 mtodos. 2. Con el uso de las palabras claves como goto, break, continue, return y throw las cuales se discutirn ms adelante. Ejemplo de Salto incondicional a otra funcin
using System; namespace Ejemplos { class Salto_Incondicional { 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 mtodo Main()"); } } }

En el ejemplo anterior el programa ejecuta sentencia por sentencia el mtodo principal Main() hasta que encuentra la llamada a otro mtodo. Despus de que el mtodo llamado haya terminado, el mtodo Main() continuar con la ejecucin de las sentencias restantes.

FUNDACION CONIN | C Sharp .NET

33

La sentencia goto
En los inicios de los lenguajes de programacin la sentencia goto fue la ms popular para ir de un lugar a otro dentro del programa. Sin embargo esto creaba una tremenda confusin al momento de disear la aplicacin. Si el programador quera hacer un esquema de cmo funcionaba dicha aplicacin, se vea con un laberinto tipo espagueti de lneas y smbolos conectados entre s. Es por esto que esta sentencia es un poco "problemtica" y fuera de "moda" entre los lenguajes de programacin modernos. C# sin embargo soporta esta sentencia. Se recomienda no utilizarla a menos que sea necesario o si se siente cmodo hacindolo, pero cuando se le cree un laberinto difcil de depurar, no diga que no se le advirti. Hay muchas otras mejores maneras de cumplir con el mismo propsito (la sentencia while por ejemplo es una de ellas), las cuales son ms elegantes y ms sencillas de depurar. La sentencia goto funciona de la siguiente manera: Primero se crea una etiqueta al inicio de cierto bloque de cdigo y despus en otro lugar podemos saltar hacia esa etiqueta usando la palabra clave goto. using System; namespace Ejemplos { class Ejemplo4_2 { static void Main() { int contador=0; REPETIR: Console.WriteLine ("Esta lnea 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 lnea"); } } } 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 cdigo solamente si se cumple con alguna condicin. Entre otros tenemos:

FUNDACION CONIN | C Sharp .NET

34

Instruccin if

Esta sentencia sirve para ejecutar unas instrucciones en caso de que se cumpla determinada condicin. La forma completa de la instruccin if es if( condicin ) { instrucciones; ... } else { instrucciones; ... } donde la clusula else es opcional. Si la condicin es verdadera, se ejecutarn las instrucciones dentro del bloque if, mientras que si es falsa, se ejecutar el bloque else. El valor que controla la sentencia if debe ser de tipo bool. El siguiente ejemplo //programa que determina si un valor es positivo o negativo using System; class InstruccionIf{ public static void Main() { double d; Console.WriteLine("Introduce un numero"); d = Double.Parse( Console.ReadLine() ); if( d>0 ) { Console.WriteLine("El numero {0} es positivo", d); } else { Console.WriteLine("El numero {0} es negativo", d); }

} }

te pide que introduzcas un nmero y dependiendo de si se cumple que dicho nmero es mayor que cero (condicin), se ejecuta un bloque u otro. La sentencia d = Double.Parse( Console.ReadLine() ); tal vez requiera algo de explicacin adicional. En realidad, con Console.ReadLine() estamos leyendo lo que el usuario introduce por pantalla, que es una cadena de caractres, y con Double.Parse lo que hacemos es interpretar esa cadena de caractres y convertirla en un tipo numrico double, de forma que tendr el valor del nmero que introduzcamos por la consola.

FUNDACION CONIN | C Sharp .NET

35

Las intrucciones if se pueden anidar, y existe tambin una extensin de la sentencia if, la sentencia if-else-if. Su formato es el siguiente: if( condicion1 ) { instrucciones; } else if( condicion2 ) { instrucciones; } ... else { instrucciones; } Las instrucciones condicionales se evalan de arriba a abajo. Tan pronto como se encuentra una condicin true, se ejecuta la instruccin asociada con ella, y el resto de la escalera se omite. Si ninguna de las condiciones es true, se ejecutar la ltima instruccin else. La ltima instruccin else acta como condicin predeterminada, es decir, si no funciona ninguna de las otras pruebas condicionales, se realiza esta ltima instruccin. Si no existe esta instruccin else final y el resto de de las condiciones son falsas, entonces no se realizar ninguna accin. El siguiente ejemplo using System; class IfElseIf{ public static void Main() { string opcion; Console.WriteLine("Elija una opcin (si/no)"); opcion = Console.ReadLine(); if( opcion=="si" ) { Console.WriteLine( "Muy bien, ha elegido si" ); } else if( opcion=="no" ) { Console.WriteLine( "Ha elegido no" ); } else{ Console.WriteLine("No entiendo lo que ha escrito"); }

FUNDACION CONIN | C Sharp .NET

36

} le pide al usuario que elija una opcin si/no y la procesa usando una estructura if-else-if. Si la opcin no es ni "si" ni "no", entonces se ejecuta la sentencia else por defecto, que imprime por pantalla el mensaje "No entiendo lo que ha escrito" Nota: Hay que tener mucho cuidado que el simbolo = no es igual a ==, el primero sirve para asignar un valor a una variable y el segundo sirve para comparar si dos trminos son iguales.

Instruccin switch

La instruccin switch es muy parecida a la estructura if-else-if, slo que permite seleccionar entre varias alternativas de una manera ms cmoda. Funciona de la siguiente manera: el valor de una expresin se prueba sucesivamente con una lista de constantes. Cuando se encuentra una coincidencia, se ejecuta la secuencia de instrucciones asociada con esa coincidencia. La forma general de la instruccin switch es la siguiente: switch( expresin ){ case constante1: instrucciones; break; case constante2: instrucciones; break; ... default: instrucciones; break; } La sentencia default se ejecutar slo si ninguna constante de las que siguen a case coincide con expresin. Es algo similar al else final de la instruccin if-else-if. Sin ms, vamos a por un ejemplo using System; class InstruccionSwitch{ public static void Main() { string s; Console.WriteLine( Console.WriteLine( Console.WriteLine( Console.WriteLine( Console.WriteLine( "Elige hacer algo con los nmeros 2 y 3"); " + para sumarlos" ); " - para restarlos" ); " * para multiplicarlos" ); " / para dividirlos (division entera)" );

FUNDACION CONIN | C Sharp .NET

37

s = Console.ReadLine(); switch(s){ case "+": Console.WriteLine("El resultado es {0}", break; case "-": Console.WriteLine("El resultado es {0}", break; case "*": Console.WriteLine("El resultado es {0}", break; case "/": Console.WriteLine("El resultado es {0}", break; default: Console.WriteLine("No te entiendo"); break; }

2+3); 2-3); 2*3); 2/3);

El cual solicita al usuario que inserte uno de los smbolos +-*/ , y con un switch compara los resultados para hacer diferentes acciones dependiendo del valor de s, que es la cadena de caracteres que almacena la eleccin del usuario. El resultado debera ser algo parecido a esto: Elige hacer algo con los nmeros 2 y 3 + para sumarlos - para restarlos * para multiplicarlos / para dividirlos (division entera) * El resultado es 6 Como habr notado, al final de todo case siempre hay una sentencia break. Esto no es obligatorio, puede haber en su lugar otra sentencia de salto como un goto inclusive en el caso default. Siempre se deber tener un break o un goto en cada caso a menos que la sentencia est vaca. En esta situacin se ejecutar el siguiente caso que viene en la lista. Si no se toma en cuenta sto se obtiene un error en tiempo de compilacin. Otros lenguajes, como C/C++ o Java no tienen esta restriccin. La razn de adoptarla en C# es doble: por un lado, elimina muchos errores comunes y en segundo lugar permite al compilador reorganizar las sentencias de los case, y as permitir su optimizacin. Ejemplo: using System; class InstruccionSwitch{ FUNDACION CONIN | C Sharp .NET 38

public static void Main() { int voto; Console.WriteLine( "Qu tipo de musica te gusta ms"); Console.WriteLine( "1 - Rock" ); Console.WriteLine( "2 - Clsica (clasica cuenta como instrumental)" ); Console.WriteLine( "3 - Instrumental" ); Console.WriteLine( "4 - Alternativa (alternativo cuenta como Rock)" ); voto = Int32.Parse(Console.ReadLine()); switch(voto){ case 1: Console.WriteLine("Has votado por Rock o Alternativo"); break; case 2: //Debido a que no tiene ni un goto ni break y est vaca va al siguiente caso case 3: Console.WriteLine("Has votado por Clsica o Instrumental"); break; case 4: goto case 1; default: Console.WriteLine("No te entiendo"); break; }

Como bien se puede notar en el ejemplo, en el case 4, se utiliza la instruccin goto, indicando que se vaya al case 1, ya que segn la lgica del ejemplo, es igual elegir 1 o 4. Ntese que no es necesario usarbreak; en el case 4 ya que se utiliz goto.

Bucle for

El bucle for de C# es idntico al encontrado en los lenguajes C/C++ y Java. El formato general es for( inicializacin; condicin; iteracin ) { instrucciones; } Las sentencias de inicializacin se ejecutan una vez al principio y sirven principalmente para asignar valores a las variables que servirn de contador. Las sentencias de condicin, por su parte, se ejecutan cada vez que el bucle vuelve al principio y sirven para controlar el bucle: ste seguir realizndose siempre y cuando estas condiciones sean true. Las sentencias de iteracin se ejecutan tambin cada vez que se realiza una nuevo ciclo en el bucle, y sirven para cambiar el estado de las variables que gobiernan las sentencias de condicin. Pero todo esto se entiende mejor con un ejemplo FUNDACION CONIN | C Sharp .NET 39

using System; class BucleFor{ public static void Main() { int i; //el contador for( i = 0; i < 10; i++) { Console.WriteLine( i ); }

} }

Este ejemplo imprime por pantalla los 10 primero enteros positivos. Es un caso muy simple del bucle for. Por cierto, el operador ++ lo que hace es que aade una unidad a la variable a la que acompaa, de forma que, por ejemplo, 9++ es 10. De esta forma, la variable i se incrementa a cada vuelta. En el ejemplo anterior, las sentencias de inicializacin y de iteracin eran nicas, pero esto no tiene por qu ser as, de hecho se pueden utilizar varias sentencias separadas por comas. Por ejemplo, se pueden usar dos variables para controlar el bucle using System; class BucleFor2{ public static void Main() { int i; int j; for( i=0, j=10; i<j; i++, j--) { Console.WriteLine("( {0} , {1} )", i, j); }

Por su parte, la expresin condicional del bucle for puede ser cualquier expresin que genere un valor booleano. En este caso se ha usado "i<j", pero tambin hubiera sido vlida "i==5", "true" (el bucle se realizar indefinidamente) o "false" (el bucle no se realizar).

Bucle while

El bucle while es un bucle que se realiza mientras se cumpla determinada condicin. Tiene la forma while( condicin ) { instrucciones; FUNDACION CONIN | C Sharp .NET 40

} Donde la condicin tiene que ser un valor booleano. Tiene una estructura muy sencilla, as que vamos a ver directamente un ejemplo. using System; class BucleWhile{ public static void Main() { int i = 0; while( i<10) { Console.WriteLine( i ); i = i+1; } } } En el que se realiza lo mismo que en el ejemplo anterior, slo que ahora con un bucle while.

Bucle do-while

Se trata de una ligera variante del bucle anterior, con la diferencia de que ahora primero se ejecutan las instrucciones y luego se evala la condicin, de forma que tiene tiene una estructura: do{ instrucciones; } while( condicin ); El siguiente ejemplo using System; class BucleDoWhile{ public static void Main() { string s = ""; do {

} while( s != "si" );

Console.WriteLine( "Introduce si para salir del bucle" ); s = Console.ReadLine();

FUNDACION CONIN | C Sharp .NET

41

} muestra un programa que ejecuta un bucle hasta que el usuario introduce "si". Por cierto, != es lo contrario de ==, es decir, != devuelve true cuando los valores comparados son distintos.

Bucle foreach

El bucle foreach se utiliza para hacer iteraciones sobre elementos de una coleccin, como pueden ser los enteros dentro de un arreglo de enteros. La sintaxis sigue la siguiente estructura: foreach( tipo in coleccion ) { instrucciones; } Como hemos comentado, el uso ms inmediato es iterar sobre un arreglo de nmeros: using System; class BucleForeach{ public static void Main() { int[,] arr = {{1,2},{2,3}}; foreach( int elem in arr ) { Console.WriteLine( elem ); }

Este ejemplo slo imprime los valores de una matriz, pero como se puede comprobar mejora mucho la claridad del cdigo comparndolo con una implementacin con bucles for como esta using System; class BucleForeach{ public static void Main() { int i, j; //seran los indexadores de la matriz int[,] arr = {{1,2},{2,3}}; for(i = 0; i<2; i++ ) { for( j = 0; j<2; j++ ) { Console.WriteLine( arr[i,j] ); FUNDACION CONIN | C Sharp .NET 42

Adems, es posible utilizar el bucle foreach con cualquier tipo que sea una coleccin, no solo con arreglos, como veremos ms adelante.

Usando continue y break

continue y break son dos palabras clave que nos permiten saltar incondicionalmente al inicio de
un bucle (continue) o fuera de un bucle (break) cuando se necesite. Por ejemplo: using System; class continueBreak { public static void Main() { for(int i = 0; i<10; i++ ) { if (i==5) continue; if (i==9) break; Console.Write("{0},",i); } } } Este pequeo programa entrar en un bucle for que har que la variable i tome los valores del 1 al 10, pero al llegar al nmero 5 el bucle saltar incondicionalmente al inicio del bucle sin ejecutar las lneas que siguen ms adelante por lo que no ejecutar la lnea que imprime en la pantalla el nmero 5. Cosa similar sucede cuando llega al nmero 9: el bucle ser detenido por el salto incondicional break que romper el bucle cuando encuentre esta palabra. El resultado ser el siguiente: 0,1,2,3,4,6,7,8, El bucle salt la lnea que imprime 5 y termin cuando lleg a 9 gracias a las palabras clave continue y break.

FUNDACION CONIN | C Sharp .NET

43

CAPITULO 6

CLASES Y OBJETOS
Como hemos dicho, C# es un lenguaje orientado a objetos. A diferencia de lenguajes como C++ o Python en los que la orientacin a objetos es opcional, en C# y al igual que en Java, la orientacin a objetos es ineludible, de hecho cualquier mtodo o variable est contenida dentro de un objeto. Y el concepto fundamental en torno a la orientacin a objetos es la clase. Una clase es como una plantilla que describe cmo deben ser las instancias de dicha clase, de forma que cuando creamos una instancia, sta tendr exactamente los mismos mtodos y variables que los que tiene la clase. Los datos y mtodos contenidos en una clase se llaman miembros de la clase y se accede a ellos siempre mediante el operador "." . En el siguiente ejemplo, se definir una clase, Clase1 y en el mtodo Main se crear una instancia de Clase1 llamada MiClase. Una buena idea es jugar un poco con el cdigo para ver que la instancia de la clase efectivamente tiene los mismos miembros que la clase Clase1 (que sera la plantilla de la que hablbamos antes) using System; //definimos nuestra clase class Clase1{ public int a = 1; private double b = 3; public char c = 'a';

//usamos la clase que hemos creado class UsoClase{ public static void Main() { Clase1 MiClase = new Clase1(); // asi creamos una instancia de Clase1 Console.WriteLine( MiClase.c ); //podemos llamar a los tipos que hay dentro de Clase1 } } los identificadores public delante de los tipos que hay dentro de Clase1 son necesarios para luego poder ser llamados desde otra clase, como en este caso, que estamos llamando a los miembros de una instancia de Clase1 desde UsoClase. Pero en las clases no solo hay variables, tambin podemos incluir mtodos. using System; //definimos nuestra clase class Clase1{ public int a = 1; public double b = 3; public char c = 'a'; FUNDACION CONIN | C Sharp .NET 44

public void Descripcion() { Console.WriteLine("Hola, soy una clase"); }

//usamos la clase que hemos creado class UsoClase{ public static void Main() { Clase1 MiClase = new Clase1(); // asi creamos una instancia de Clase1 Console.WriteLine( MiClase.c ); //podemos usar todos los tipos que hay dentro de Clase1 MiClase.Descripcion(); } } Podemos hacer ms cosas con las clases, como heredar otras clases o implementar interfaces, pero en este captulo nos centraremos en el uso de mtodos y variables.

Mtodos

Los mtodos, tambin llamados funciones, son trozos de cdigo que reciben unos datos, hacen algo con esos datos, y a veces devuelven algn valor. En C#, todos los mtodos se encuentran contenidos dentro de un objeto. La estructura mnima de un mtodo tiene las siguientes partes: * * * * Tipo devuelto Nombre del mtodo Parmetros (puede ser vaco) Cuerpo del mtodo

de forma que el siguiente mtodo: double Divide( double a, double b ) { return a/b; } devuelve un tipo double, tiene por nombre Divide, los parmetos son a y b, ambos del tipo double, y el cuerpo del mtodo es simplemente "return a/b;". Cuando queramos llamar a un mtodo, debemos simplemente poner el nombre del mtodo y sus argumentos dentro de un parntesis separados por comas. Para llamar al mtodo Divide declarado antes, simplemente debemos escribir Divide(8, 2); Segn lo que hemos visto, el ejemplo del mtodo Divide() completo necesita tener una clase donde definirse y un mtodo Main() donde ejecutarse.

FUNDACION CONIN | C Sharp .NET

45

using System; class Metodo{ public double Divide( double a, double b ) { return a/b; } } class Principal{ public static void Main() { Metodo m = new Metodo(); Console.WriteLine( m.Divide(8, 2) ); } }

Pasando valores a los mtodos


Parmetros
La declaracin formal de parmetros tambin define variables. Hay cuatro tipos de parmetros: parmetros por valor, por referencia, parmetros de salida, y arreglos de parmetros.

Paso por valor

El paso de parmetros por valor es usado por defecto para pasar parmetros a mtodos. Cuando se pasa un parmetro por valor a una funcin realmente se est pasando una copia de dicho parmetro, por lo que las modificaciones que le hagamos al parmetro dentro del mtodo no afectarn al parmetro original. El ejemplo using System; class Test { static void F(int p) { p++; Console.WriteLine("p = {0}", p); } static void Main() { int a = 1; Console.WriteLine("pre: a = {0}", a); F(a); Console.WriteLine("post: a = {0}", a); } } muestra un mtodo F que tiene un parmetro por valor llamado p. El ejemplo produce la salida: pre: a = 1 p=2 post: a = 1 FUNDACION CONIN | C Sharp .NET 46

aunque el valor del parmetro p haya sido modificado dentro del mtodo, ste parmetro solamente tena una copia del valor del parmetro a que pasamos al mtodo; por lo que cuando imprimimos el parmetro avemos que ste parmetro ha mantenido su valor original.

Paso por referencia

El paso de parmetros por referencia es la contraposicin lgica al paso por valor. En el paso por referencia no se realiza ninguna copia del objeto, sino que lo que se le pasa a la funcin es una referencia del objeto, de forma que el parmetro pasa directamente a la funcin y cualquier modificacin sobre el parmetro dentro de la funcin afectar al parmetro original using System; class Test { static void Swap(ref int a, ref int b) { // intercambia los dos valores int t = a; a = b; b = t; } static void Main() { int x = 1; int y = 2; Console.WriteLine("pre: x = {0}, y = {1}", x, y); Swap(ref x, ref y); Console.WriteLine("post: x = {0}, y = {1}", x, y);

muestra un mtodo swap que tiene dos parmetros por referencia. La salida producida es: pre: x = 1, y = 2 post: x = 2, y = 1 La palabra clave ref debe de ser usada tanto en la declaracin formal de la funcin como en los usos que se hace de sta.

Parmetro de salida

El parmetro de salida es similar al parmetro por referencia, salvo que el valor inicial de dicho argumento carece de importancia. Un argumento de salida se declara con el modificador out. El ejemplo using System; class Test { static void Divide(int num1, int num2, out int result, out int resid) { result = num1 / num2; FUNDACION CONIN | C Sharp .NET 47

} static void Main() { int valor1 = 10; int valor2 = 3; int respuesta, residuo; Divide(valor1, valor2, out respuesta, out residuo); Console.WriteLine("La divisin de {0} para {1} = {2} con un residuo de {3}", valor1, valor2, respuesta, residuo); } } muestra un mtodo Divide que incluye dos parmetros de salida. Uno para el resultado (variable result) de la divisin y otro para el resto (variable resid). Vemos que estos resultados son asignados a las variablesrespuesta y residuo respectivamente.

resid = num1 % num2;

Arreglo de parmetros

Habr ocasiones que necesitemos pasar varios parmetros a un mtodo (o funcin) pero no sabremos con anticipacin cuantos parmetros tendremos que pasar; para esto podremos usar un arreglo de parmetros. Un arreglo de parmetros permite guardar una relacin de varios a uno: varios argumentos pueden ser representados por un nico arreglo de parmetros. En otras palabras, los arreglos de parmetros permiten listas de argumentos de tamao variable. Un arreglo de parmetros se declara con el modificador params. Slo puede haber un arreglo de parmetros en cada mtodo, y siempre debe ser el ltimo parmetro especificado. El tipo del arreglo de parmetros debe ser siempre un tipo arreglo unidimensional. Al llamar a la funcin se puede pasar uno o varios argumentos del tipo del arreglo. El ejemplo using System; class Test { static void F(params int[] args) { Console.WriteLine("n de argumentos: {0}", args.Length); for (int i = 0; i < args.Length; i++) Console.WriteLine("args[{0}] = {1}", i, args[i]); } static void Main() { F(); F(1); F(1, 2); F(1, 2, 3); F(new int[] {1, 2, 3, 4}); } } muestra un mtodo F que toma un nmero variable de argumentos int, y varias llamadas a este mtodo. La salida es: FUNDACION CONIN | C Sharp .NET 48

n de argumentos: n de argumentos: args[0] = 1 n de argumentos: args[0] = 1 args[1] = 2 n de argumentos: args[0] = 1 args[1] = 2 args[2] = 3 n de argumentos: args[0] = 1 args[1] = 2 args[2] = 3 args[3] = 4

0 1 2 3

La mayora de los ejemplos presentes en este captulo utilizan el mtodo WriteLine de la clase Console. El comportamiento para las sustituciones, como muestra el ejemplo int a = 1, b = 2; Console.WriteLine("a = {0}, b = {1}", a, b); se consigue usando un arreglo de parmetros. El mtodo WriteLine proporciona varios mtodos sobrecargados para el caso comn en el que se pasa un pequeo nmero de argumentos, y un mtodo que usa un arreglo de parmetros. using System; namespace System { public class Console { public static void WriteLine(string public static void WriteLine(string public static void WriteLine(string ... public static void WriteLine(string } }

s) {...} s, object a) {...} s, object a, object b) {...} s, params object[] args) {...}

Modificadores public y static

El modificador public lo hemos utilizado anteriormente. Se puede utilizar en la declaracin de cualquier mtodo o variable, y como es de esperar, produce el efecto de que el campo afectado se vuelve pblico, esto es, se puede utilizar desde otras clases

FUNDACION CONIN | C Sharp .NET

49

using System; class Metodo{ public double Divide( double a, double b ) { return a/b; } } class Principal{ public static void Main() { Metodo m = new Metodo(); Console.WriteLine( m.Divide(8, 2) ); } } Si por ejemplo intentamos declarar el mtodo Divide sin el modificador public, obtendremos un error en tiempo de compilacin. El modificador complementario de public es private, que provoca que el mtodo o dato solo sea accesible desde la clase en la que est declarado. Si no se especifica nada, se toma por defecto el modificador private De esta forma podramos separar las clases Metodo y Principal en dos archivos separados, llamados por ejemplo metodo.cs y principal.cs . Para compilar esto, bastar compilar ambos archivos al mismo tiempo, de forma similar a esto: mcs principal.cs metodo.cs Adems, tampoco es necesario crear una instancia de la clase slo para acceder a un mtodo declarado en ella. Para eso debemos anteponer a la declaracin del mtodo el modificador static. Los mtodos estticos se caracterizan por no necesitar una instancia de la clase para cumplir su funcin, pero como contrapartida, no pueden acceder a datos propios de la clase. using System; class Metodo{ public static double Divide( double a, double b ) { return a/b; } } class Principal{ public static void Main() { Console.WriteLine( Metodo.Divide(8, 2) ); } }

FUNDACION CONIN | C Sharp .NET

50

Los mtodos estticos se utilizan en multitud de situaciones. Por ejemplo, el mtodo Console.WriteLine() o las funciones de la librera matemtica estndar no son ms que mtodos estticos de sus respectivas clases.

Constructores e instancias de una clase

Como hemos visto, las instancias de una clase se crean con la sintaxis nombreclase objeto = new nombreclase( argumentos ); donde nombreclase es el nombre que le hemos dado a la definicin de la clase, argumentos es una lista de argumentos posiblemente vaca y objeto es el nombre que queremos darle a la instancia de la clase. Una vez creada una clase, sus miembros se inicializan a sus valores predeterminados ( cero para valores numricos, cadena vaca para el tipo string, etc. ). La siguiente clase representa un punto sobre el plano, de forma que tiene dos valores pblicos X e Y, y un mtodo que calcula la distancia al origen del punto (mdulo) using System; class Punto{ public double X; public double Y; public double Modulo() { double d; d = Math.Sqrt(X*X + Y*Y); //Sqrt = raiz cuadrada return d; }

class Principal{ public static void Main() { Punto A = new Punto(); A.X = 1; A.Y = 1; Console.WriteLine("El modulo del punto (1,1) es: {0}", A.Modulo() ); } }

Ahora bien, la forma en la que se crea la instancia, es decir, inicializando los datos a cero (ejercicio: comprobar esto), se puede personalizar, de forma que podemos construir nuestro FUNDACION CONIN | C Sharp .NET 51

propio constructor que le diga a la clase los valores por defecto que debe tomar. Esto se realiza simplemente escribiendo dentro de la clase un mtodo que tenga el mismo nombre que la clase y en el que no se especifica el valor devuelto. La clase Punto con un constructor sera as: using System; class Punto{ public double X; public double Y; public Punto() //constructor { X = 1; Y = 1; } public double Modulo() { double d; d = Math.Sqrt(X*X + Y*Y); //Sqrt = raiz cuadrada return d; }

de forma que ahora al crear una instancia de la clase se crea el punto (1,1) en lugar del (0,0), que era el que se creaba por defecto. De esta forma, al crear la instancia, par ya contendr los valores (1,1) . En la prctica se utilizan mucho constructores con parmetos, de forma que al crear la instancia se le asignan valores segn los parmetros. La siguiente implementacin de Par contiene un constructor que acepta un par de valores, que servirn para inicializar los valores A y B class Punto{ public Punto( double val1, double val2) { X = val1; Y = val2; } ... } Tambin tenemos la posibilidad de declarar una clase con varios constructores (cada uno con diferentes parmetros) Lo que har el compilador de C# es buscar el constructor que se adece a los parmetros que le llegan, y ejecutarlo como si fuera un mtodo ms. Dependiendo de la llamada que se haga en el "new", usaremos un constructor u otro.

Sobrecarga de mtodos

En C#, al igual que en C++ y en Java es posible definir varios mtodos con el mismo nombre pero con distintos parmetros, de forma que el compilador decide a cul se llama dependiendo de los parmetros que le lleguen. FUNDACION CONIN | C Sharp .NET 52

Esto es muy prctico, pues no tienes que renombrar cada funcin segn el tipo de valor que acepta. El siguiente ejemplo implementa un par de mtodos que elevan al cuadrado el valor que reciben, y se implementan para tipos double y para int. En C, que es un lenguaje que no soporta sobrecarga de mtodos, se tendra que haber llamado distinto a ambos mtodos, por ejemplo alcuadrado_double y alcuadrado_int using System; class Eleva{ public static double AlCuadrado( int a ) { return a*a; } public static double AlCuadrado( double a ) { return a*a; }

class Principal{ public static void Main() { Console.WriteLine("4 al cuadrado es {0}", Eleva.AlCuadrado(4) ); Console.WriteLine("3.2 al cuadrado es {0}", Eleva.AlCuadrado(3.2) ); } }

La palabra reservada this

La palabra reservada this sirve para hacer referencia a miembros de la clase en caso de que se quiera especificar, ya sea por motivos de colisin de nombres o por la claridad del cdigo. Su sintaxis es this.campo donde campo es la variable de la clase a la que queremos hacer referencia. En el siguiente ejemplo, declaramos un constructor para la clase Punto, que toma dos argumentos X e Y. Entonces es obligado el uso de this para distinguir entre el X de la clase y el X tomado como parmetro class Complejo { double X; double Y; Complejo(double X, double Y) FUNDACION CONIN | C Sharp .NET 53

{ }

this.X = X; this.Y = Y;

Propiedades e indizadores
Propiedades
Las propiedades son una caracterstica de C# que permiten aparentemente el acceso a un miembro de la clase mientras mantiene el control asociado al acceso mediante mtodos. Para los programadores de Java hay que decir que esto no es ms que la formalizacin del patrn de asignacin (setter) y mtodo de lectura (getter) Las propiedades son como mtodos que se declaran dentro de un bloque asociado a una variable mediante las palabras reservadas get (se encarga de devolver algo cuando se llama al tipo que lo contiene ) y set (que hace algo cuando se le asigna un valor a la variable que lo contiene. Este valor viene especificado en la variable value ) using System; class TestProperties { private static string clave; public string Clave { get { Console.WriteLine ("Acceso a la propiedad clave"); return clave; } set { Console.WriteLine ("Cambio del valor de clave"); clave = value; } } } class Test { public static void Main () { TestProperties tp = new TestProperties(); string c = "ClaveClave"; tp.Clave = c; Console.WriteLine (tp.Clave); } } En realidad, lo que se hace es declarar una variable privada de forma que no se puede acceder de forma directa, y se crean dos mtodos ( o uno si solo se requiere acceso de lectura) que FUNDACION CONIN | C Sharp .NET 54

permiten acceder al contenido de la variable y tal vez modificarla. Si no queremos que se pueda modificar la variable, no inclumos el mtodo "set" y ya tendramos propiedades de slo lectura.

Indexadores

Hemos visto, en el apartado en el que tratamos las propiedades, que podemos acceder a una variable privada de una clase a travs de eventos que nos permiten controlar la forma en la que accedemos a dicha variable. Los indexadores nos van a permitir hacer algo parecido. Nos van a permitir acceder a una clase como si se tratara de un arreglo. Lo vemos de forma ms sencilla con un ejemplo: using System; class PruebaIndexadores { private int[] tabla = {1, 2, 3, 4}; public int this [int indice] { get { Console.WriteLine ("La posicion {0} de la tabla tiene el valor {1}", indice, tabla[indice]); return tabla[indice]; } set { Console.WriteLine ("Escrito el valor {0} en la posicin {1} de la tabla", value, indice); tabla[indice] = value; } }

Tenemos una clase PruebaIndexadores en la que hay un array llamado "tabla", declarado como privado, por lo que no podremos acceder a l desde fuera de nuestra clase. Pero hemos declarado tambin un indexador (public int this [int indice]), que nos permitir acceder a l de forma ms controlada. Para probar esta clase, creamos otra clase con un punto de entrada (public static void Main ()), que ser donde hagamos las pruebas. Primero creamos un objeto de la clase PruebaIndexadores: PruebaIndexadores obj = new PruebaIndexadores (); Luego accedemos a una posicin del indexador: int a = obj[3];

FUNDACION CONIN | C Sharp .NET

55

Esta lnea lo que hace es llamar al indexador, pasndole como parmetro el ndice, en este caso 3. Al ser una consulta de lectura, se ejecuta el cdigo que haya en la parte "get" del indexador. Una vez ejecutado, lo que nos aparece por pantalla es esto: La posicion 3 de la tabla tiene el valor 4 Vamos ahora a hacer un cambio en la tabla: obj[3] = 6; Lo que se ejecuta ahora es la parte "set" del indexador. Lo que aparecer en pantalla una vez ejecutado esto ser: Escrito el valor 6 en la posicin 3 de la tabla Ntese que tenemos que hacer explcitamente el acceso al array (tabla[indice]=value) en el set, ya que el indexador no tiene forma de saber qu variable se supone que tiene que manejar. Si no pusiramos esa lnea, en realidad el indexador no cambiara el valor del array. Para comprobar que realmente se ha hecho el cambio, volvemos a acceder al indexador: a = obj[3]; Y esta vez nos aparecer esto: La posicion 3 de la tabla tiene el valor 6.

FUNDACION CONIN | C Sharp .NET

56

CAPITULO 7

HERENCIA Y POLIMORFISMO Herencia


La herencia es un concepto fundamental de la programacin orientada a objetos. Cuando se dice que una cierta clase A hereda otra clase B significa que la clase A contiene todos los miembros de la clase B ms algunos que opcionalmente puede implementar ella misma Las clases en C# soportan herencia simple, de forma que una clase puede derivar de otra, pero no de varias (como si era posible en C++). De hecho, en C# todas las clases derivan implcitamente de la clase object. La sintaxis que se utiliza es la siguiente: class MiClaseDerivada : MiClaseBase { //miembros } En el siguiente ejemplo definimos una clase A con un mtodo F(). Posteriormente definimos una clase B que hereda A y adems define un mtodo G(). Finalmente creamos una clase con un mtodo Main() que llamar a los dos mtodos de B, al implementado por B y al heredado using System; class A{ public void F() { Console.WriteLine("Soy F() de A"); } } class B : A{ public void G() { Console.WriteLine("Soy G() de B"); } } class Principal{ public static void Main() { B clase_heredada = new B(); clase_heredada.F(); clase_heredada.G(); FUNDACION CONIN | C Sharp .NET 57

[editar]La palabra reservada base La palabra reservada base sirve para acceder a miembros de la clase heredada de la misma forma que this sirve para acceder a miembros de la propia clase. Su sintaxis es idntica a la de this, esto es: base.nombre_del_miembro En el siguiente ejemplo declaramos una clase B que hereda A y que utiliza el mtodo F() de A. class B : A{ public void H() { base.F(); Console.WriteLine("soy H() de B"); } } [editar]Clases Abstractas Las clases abstractas son clases que contienen algn mtodo incompleto, esto es, que est definido pero no implementado. Por lo tanto, no se pueden instanciar y su nico propsito es servir de clase base de las que se derivarn otras clases. Las clases que heredan una clase abstracta deben implementar los mtodos incompletos. Las clases abstractas se declaran con la palabra reservada abstract using System; abstract class A{ public void F(); //metodo no implementado } class B : A{ //error en tiempo de compilacin, B tiene que definir un mtodo F() } [editar]Miembros virtual Mtodos, propiedades e indexadores pueden ser virtual, lo que significa que su implementacin puede ser sobreescrita en clases derivadas. El ejemplo using System; class A { public virtual void F() { Console.WriteLine("A.F"); } FUNDACION CONIN | C Sharp .NET 58

} class B: A { public override void F() { base.F(); Console.WriteLine("B.F"); } } class Test { public static void Main() { B b = new B(); b.F(); A a = b; a.F(); } } muestra una clase A con un mtodo virtual F, y una clase B que sobreescribe F. El mtodo sobreescrito en B contiene una llamada, base.F(), el cual llama al mtodo sobreescrito en A. [editar]Problemas

Por escribir. Puedes colaborar escribiendo estos problemas.


<<- Anterior (Captulo 5) | (Captulo 7) Siguiente->>

propuestos

Versin para imprimir esta pagina Este cdigo me pareci interesante de compartir, una modesta recreacin del efecto matrix, escrita en C#. using System; namespace m7tr1x { class Program { static void Main(string[] args) { Console.Title = "tH3 M7tr1x 3ff3<t"; Console.ForegroundColor = ConsoleColor.DarkGreen; Console.WindowLeft = Console.WindowTop = 0; Console.WindowHeight = Console.BufferHeight = Console.LargestWindowHeight; Console.WindowWidth = Console.BufferWidth = Console.LargestWindowWidth; Console.WriteLine("H1T 7NY K3Y T0 C0NT1NU3 =/"); Console.ReadKey(); Console.CursorVisible = false; int width, height; int[] y; FUNDACION CONIN | C Sharp .NET 59

} static bool thistime = false; private static void MatrixStep(int width, int height, int[] y, int[] l) { int x; thistime = !thistime; for (x = 0; x <width; ++x) { if (x % 11 == 10) { if (!thistime) continue; Console.ForegroundColor = ConsoleColor.White; } else { Console.ForegroundColor = ConsoleColor.DarkGreen; Console.SetCursorPosition(x, inBoxY(y[x] - 2 - (l[x] / 40 * 2), height)); Console.Write(R); Console.ForegroundColor = ConsoleColor.Green; } Console.SetCursorPosition(x, y[x]); Console.Write(R); y[x] = inBoxY(y[x] + 1, height); Console.SetCursorPosition(x, inBoxY(y[x] - l[x], height)); Console.Write(' '); } } private static void Initialize(out int width, out int height, out int[] y, out int[] l) { int h1; int h2 = (h1 = (height = Console.WindowHeight) / 2) / 2; width = Console.WindowWidth - 1; FUNDACION CONIN | C Sharp .NET 60

int[] l; Initialize(out width, out height, out y, out l); int ms; while (true) { DateTime t1 = DateTime.Now; MatrixStep(width, height, y, l); ms = 10 - (int)((TimeSpan)(DateTime.Now - t1)).TotalMilliseconds; if (ms> 0) System.Threading.Thread.Sleep(ms); if (Console.KeyAvailable) if (Console.ReadKey().Key == ConsoleKey.F5) Initialize(out width, out height, out y, out l); }

} static Random r = new Random(); static char R { get { int t = r.Next(10); if (t <= 2) return (char)('0' + r.Next(10)); else if (t <= 4) return (char)('a' + r.Next(27)); else if (t <= 6) return (char)('A' + r.Next(27)); else return (char)(r.Next(32, 255)); } } public static int inBoxY(int n, int height) { n = n % height; if (n <0) return n + height; else return n; }

y = new int[width]; l = new int[width]; int x; Console.Clear(); for (x = 0; x <width; ++x) { y[x] = r.Next(height); l[x] = r.Next(h2 * ((x % 11 != 10) ? 2 : 1), h1 * ((x % 11 != 10) ? 2 : 1)); }

FUNDACION CONIN | C Sharp .NET

61

CAPITULO 8

SOBRECARGA DE OPERADORES Qu es la sobrecarga de operadores?


La sobrecarga de operadores es la capacidad para transformar los operadores de un lenguaje como por ejemplo el +, -, etc, cuando se dice transformar se refiere a que los operandos que entran en juego no tienen que ser los que admite el lenguaje por defecto. Mediante esta tcnica podemos sumar dos objetos creados por nosotros o un objeto y un entero, en vez de limitarnos a sumar nmeros enteros o reales, por ejemplo. La sobrecarga de operadores ya era posible en c++ y en otros lenguajes, pero sorprendentemente java no lo incorpora, as que podemos decir que esta caracterstica es una ventaja de c# respecto a java, aunque mucha gente, esta posibilidad, no lo considera una ventaja porque complica el cdigo. A la hora de hablar de operadores vamos a distinguir entre dos tipos, los unarios y los binarios. Los unarios son aquellos que solo requieren un operando, por ejemplo a++, en este caso el operando es 'a' y el operador '++'. Los operadores binarios son aquellos que necesitan dos operadores, por ejemplo a+c , ahora el operador es '+' y los operandos 'a' y 'c'. Es importante esta distincin ya que la programacin se har de forma diferente. Los operadores que podemos sobrecargar son los unarios, +, -, !, ~, ++, --; y los binarios +, -, *, /, %, &, |, ^, <<, >>. Es importante decir que los operadores de comparacin, ==, !=, <, >, <=, >=, se pueden sobrecargar pero con la condicin que siempre se sobrecargue el complementario, es decir, si sobrecargamos el == debemos sobrecargar el !=.

Sobrecargando operadores en la prctica


Para mostrar la sobrecarga vamos a usar el repetido ejemplo de los numeros complejos, ( aunque tambin valdra el de las coordenadas cartesianas ). Como se sabe, los nmeros complejos tienen dos partes, la real y la imaginaria, cuando se suma dos numeros complejos su resultado es la suma de las dos partes, para ello se va a crear una clase llamada ComplexNum que contendr ambas partes. Sin esta tcnica no se podra sumar dos objetos de este tipo con este prctico mtodo, ya que esta clase no es vlida como operando de los operadores de c#. Empecemos con el cdigo de la clase de nmeros complejos. public class ComplexNum { private float img; private float real; // constructor de la clase public ComplexNum(float real, float img) { this.real = real; this.img = img; } // propiedad Real public float Real{ get{ FUNDACION CONIN | C Sharp .NET 62

} set{ real = value; }

return real;

// propiedad Img public float Img{ get{ return img; } set{ img = value; } } // Sobrescribimos el miembro ToString heredado de Object override public string ToString() { if ( img >= 0 ) return real + "+" + img +"i"; else return real + "" + img + "i"; } public static ComplexNum operator+(ComplexNum a, ComplexNum b) { return new ComplexNum(a.real + b.real, a.img + b.img); } } En el ejemplo hemos puesto la clase, con un constructor , dos propiedades para obtener los datos privados de la clase y un mtodo que nos transfoma el nmero complejo a una cadena de caracteres para que se pueda visualizar fcilmente. Finalmente hemos sobrecargado el operador '+', de forma que podremos sumar dos nmeros complejos como si se tratara de nmeros usuales.

Operadores binarios
Para empezar vamos a sobrecargar el operador suma('+') para que al sumar dos objetos de la clase ComplexNum, es decir dos nmeros complejos obtengamos un nmero complejo que ser la suma de ambas partes. Cabe destacar que los prototipos para sobrecargar operadores sern: public static Operando operator+(Operando a, Operando b)

FUNDACION CONIN | C Sharp .NET

63

Este es el prototipo para el operador +, el resto de operadores binarios van a seguir el mismo patrn. Por tanto el cdigo del mtodo de sobrecarga ser el siguiente: public static ComplexNum operator+(ComplexNum a, ComplexNum b) { return new ComplexNum(a.Real + b.Real, a.Img + b.Img); } Este mtodo sobrecarga el operador suma para que podamos sumar dos nmeros complejos. Un dato a tener en cuenta es que los mtodos que sobrecargan operadores deben ser static. Como se ve en el cdigo los operandos son 'a' y 'b', que se reciben como parmetro y el resultado de la operacin es otro nmero complejo que es el que retorna el mtodo. Por tanto se limita a crear un nuevo nmero complejo con ambas partes operadas. De la misma forma podemos crear la sobrecarga del operador resta('-') para que lleve a cabo la misma funcin: public static ComplexNum operator-(ComplexNum a, ComplexNum b) { return new ComplexNum(a.Real - b.Real, a.Img - b.Img); } Como vemos el mtodo es idntico solo que sustituyendo los + por -. En este caso el trabajo que hacemos dentro del mtodo es trivial pero podra ser tan complejo como se quisiera.

Operadores Unarios
En esta seccin se ver cmo sobrecargar los operadores unarios, es decir aquellos que toman un solo operando, como por ejemplo a++. El prototipo de los mtodos que van a sobrecargar operadores unarios ser: public static Operando operator++(Operando a) Como antes sustituyendo el ++ por cualquier operador unario. El ejemplo dentro de nuestra clase de nmeros complejos sera: public static ComplexNum operator++(ComplexNum a) { float auximg = a.Img; float auxreal = a.Real; } return new ComplexNum(++auxreal, ++auximg);

FUNDACION CONIN | C Sharp .NET

64

A primera vista puede quedar la duda si estamos sobrecargando la operacion ++a o a++. Este aspecto se encarga el compilador de resolverlo, es decir, se sobrecarga la operacin ++ y el compilador se encarga de "sumar y asignar" o "asignar y sumar". Este problema no ocurra en C++, cosa que tenamos que manejar nosotros. Como hemos dicho antes, la operacin que hagamos dentro del mtodo que sobrecarga el operador es totalmente libre, se puede poner el ejemplo de multiplicar dos matrices lo que es mas complejo que sumar dos nmeros complejos.

FUNDACION CONIN | C Sharp .NET

65

CAPITULO 9

ESTRUCTURAS
La lista de similitudes entre clases y estructuras es larga: las estructuras pueden implementar interfaces, y pueden tener el mismo tipo de miembros que las clases. Sin embargo, las estructuras difieren de las clases en algunos puntos importantes: las estructuras son tipos por valor en lugar de tipos por referencia, y no permiten la herencia. Los valores de las estructuras quedan almacenados "en la pila" o "alineados". Los programadores cuidadosos pueden a veces mejorar el rendimiento mediante un uso meditado de las estructuras. Por ejemplo, el uso de una estructura ms bien que una clase para un Punto puede producir una gran diferencia en el nmero de asignaciones producidas en memoria en tiempo de ejecucin. El siguiente programa crea e inicializa un arreglo de 100 puntos. Con Punto implementado como clase, 101 objetos separados son inicializados ( uno para el vector y uno para cada uno de los 100 elementos ) class Punto { public int x, y; public Punto(int x, int y) { this.x = x; this.y = y; } } class Test { static void Main() { Punto[] Puntos = new Punto[100]; for (int i = 0; i < 100; i++) { Puntos[i] = new Punto(i, i*i); } } } Si Punto fuera implementado como una estructura, como en struct Punto { public int x, y; public Punto(int x, int y) { this.x = x; this.y = y; } } nicamente un objeto es inicializado: el elemento del arreglo. Las instancias de Punto se almacenan de forma alineada en el arreglo. Esta optimizacin puede ser mal usada. Usar FUNDACION CONIN | C Sharp .NET 66

estructuras en lugar de clases tambin puede hacer que una aplicacin funcione ms lento o utilice ms memoria, pues pasar una instancia de estructura por valor provoca que una copia de esa estructura sea creada. [editar]Rendimiento Como hemos dicho, la principal ventaja por la que se usan en determinadas circunstancias estructuras y no clases es que en circunstancias particulares stas demuestran mucho mejor rendimiento.

FUNDACION CONIN | C Sharp .NET

67

CAPITULO 10

INTERFACES
Una Interfaz es una coleccin de miembros abstractos relacionados semnticamente. Una interfaz representa un comportamiento que una clase dada puede soportar. El nmero de miembros de una interfaz dependen del comportamiento que queramos soportar, por ejemplo todos los objetos que sean mviles podran querer soportar los mtodos acelerar y frenar. Segn la interfaz de C# una interfaz sera: public interface IMovil { bool Acelerar(int n); bool Frenar(int n); } Tambin podramos declarar dentro de la interfaz una propiedad que nos permita leer y/o escribir la velocidad que queremos que tome nuestro objeto. public interface IMovil { bool Velocidad{get; set;} } Dado que una interfaz es una coleccin de miembros abstractos cualquier clase o estructura que quiera implementar una interfaz est obligada a implementar cada uno de los mtodos que se declaran en la interfaz. De esta forma se consigue un cierto tipo de polimorfismo ya que si varias clases implementan la misma estructura tenemos la posibilidad de tratar con todas ellas de la misma forma. Seguramente alguien se preguntara por que usar interfaces pudiendo usar una clase base abstracta definiendo los mtodos anteriores como abstractos, la primera razn es simplicidad, una clase base abstracta suele hacer ms que definir una coleccin de mtodos, es capaz de definir mtodos pblicos, privados, protegidos y tambin metodos concretos (estticos) a los que pueden acceder todas las clases que deriven de ella mientras que una interfaz se limita a definir una coleccin de mtodos sin ninguna implementacin. La segunda razn es que C# solamente soporta herencia simple, pero sin embargo podemos hacer que una clase implemente mltiples interfaces. He aqu como haramos para heredar de una clase base e implementar una interfaz, teniendo en cuenta que VehiculoDeMotor sera nuestra clase base e IMovil nuestra interfaz. public class CocheDeportivo : VehiculoDeMotor, IMovil { //Implementacin de los mtodos abstractos de vehculo bool Acelerar(int n) { //implementacin de Acelerar } FUNDACION CONIN | C Sharp .NET 68

bool Frenar(int n) { //implementacin de Frenar }

Hay que tener en cuenta que siempre hay que poner la clase base antes de las interfaces. Ahora nuestra clase CocheDeportivo as como cualquier otra clase que implemente IMovil podra acelerar y frenar, hay que tener en cuenta que si implementamos IMovil tendremos que implementar absolutamente todos sus mtodos. [editar]Obteniendo

Referencias a la Interfaz

Si hemos creado la clase CocheDeportivo podemos querer saber si ste soporta el comportamiento de IMovil de modo que podemos hacer un cast explcito: CocheDeportivo coche1 = new CocheDeportivo(); IMovil movil = (IMovil) coche1; movil.Acelerar(30); En caso de que nuestro objeto implemente la interfaz podramos operar sobre l con todos los mtodos de la misma, pero en caso de que no la soporte tendramos un error en tiempo de ejecucin, con lo cual la forma correcta de hacerlo es: CocheDeportivo coche1 = new CocheDeportivo(); try{ IMovil movil = (IMovil) coche1; movil.Acelerar(30); } catch(InvalidCastException e){ //gestin del error } Otra forma de hacerlo sin tener que recurrir a la gestin de excepciones sera utilizando la palabra reservada as de C#: CocheDeportivo coche1 = new CocheDeportivo(); IMovil movil; movil = coche1 as IMovil; if (movil != null) movil.Frenar(10); else //otro tratamiento La palabra reservada as pone la variable de tipo interfaz a null si la interfaz dada no est soportada por el objeto. Por ltimo tambin podemos usar la palabra reservada is de C# para descubrir si un objeto implementa o no una interfaz: FUNDACION CONIN | C Sharp .NET 69

CocheDeportivo coche1 = new CocheDeportivo(); if (coche1 is IMovil) coche1.Acelerar(10); else //otra gestin [editar]Pasar

interfaces como parmetros

Las interfaces son tipos de datos fuertemente tipados (valga la redundancia) de modo que se pueden pasar como parmetros a mtodos y se pueden usar tambin como valores de retorno. Hemos creado la interfaz IGiro de la siguiente manera: public interface IGiro { void GirarDerecha(int grados); void GirarIzquierda(int grados); } Y queremos que nuestro coche deportivo pueda girar a izquierda y derecha: public class CocheDeportivo : VehiculoDeMotor, IMovil, IGiro { //Implementacin de los mtodos abstractos de vehculo bool Acelerar(int n) { //Implementacin de Acelerar } bool Frenar(int n) { //Implementacin de frenar } void GirarDerecha(int grados) { //Implementacin de GirarDerecha } void GirarIzquierda(int grados) { //Implementacin de GirarIzquierda }

Como hemos visto para soportar otra interfaz simplemente la aadimos al final despus de una ",". Ahora supongamos que queremos hacer un mtodo que nos provea de utilidades para el giro por ejemplo hacer trompos, le podramos pasar una interfaz IGiro de la siguiente forma public class UtilsGiro FUNDACION CONIN | C Sharp .NET 70

public static void Trompo(IGiro giro) { giro.GirarIzquierda(360); }

[editar]Implementacin

Explcita de una Interfaz

Siguiendo con nuestro ejemplo de los coches definimos una nuevas interfaces: public interface IAltaVelocidad { void Turbo(bool activar); //resto de metodods } Como se puede ver nuestra interfaz implementa un mtodo Turbo. Qu pasara si una clase heredase a su vez de la clase Formula Uno que tambin implemente el metodo void Turbo (bool)? Bueno vamos a verlo: public class Campeon : Formula1, IAltaVelocidad { public override void Turbo(bool activar) { //gestion del turbo } } Esto en un principio sera correcto pero qu pasa si hacemos lo siguiente: Campeon miCampeon = new Campeon(); miCampeon.Turbo(true); IAltaVelocidad iav = (IAltaVelocidad) miCampeon; iav.Turbo(true); Ambas veces se llamara al mismo mtodo, el definido en la clase Formula1, pero como haramos si quisiramos tener dos Turbos diferentes? la respuesta es hacer que los mtodos definidos en la interfaz sean slo accesibles desde una referencia a la interfaz, esto es lo que se llama implementacin explcita de una interface. public class Campeon : Formula1, IAltaVelocidad { public override void Turbo(bool activar) { //gestin del turbo } FUNDACION CONIN | C Sharp .NET 71

void IAltaVelocidad.Turbo(bool activar) { //gestin del turbo }

El segundo mtodo slo podr ser llamado si usamos una referencia de tipo IAltaVelocidad mientras que el primero podr ser llamado usando una referencia a Campeon o a Formula1 (su clase base). Existen algunas reglas extra al hacer esto, por ejemplo no podemos usar modificadores de accesibilidad (public, private, protected) ya que si intentamos que slo se pueda acceder al mtodo desde una referencia a la interfaz hacerlo sera contraproducente. Tambin hay que tener en cuenta que pueden haber colisiones de nombres entre clases base e interfaces y entre interfaces entre si, tcnicamente no existe ninguna diferencia y todas pueden ser tratadas como hemos explicado arriba. [editar]Jerarquas

de interfaces

Las interfaces pueden servir de base para otras interfaces al igual que las clases, e igual que en stas la idea es que vayamos de lo general a lo particular. Por ejemplo: interface IVehiculo { void Acelerar(); void Frenar(); } interface IVehiculoGasolina : IVehiculo { void CambiarVelocidadInyeccion(int velocidad); } interface IVehiculo4x4: IVehiculoGasolina { void Activar4x4(bool activar); } Al implementar una de estas interfaces en nuestra clase tenemos que implementar todos los mtodos de esta interfaz y de sus ancestros. public class CocheDeJuguete : IVehiculo { void IVehiculo.Acelerar(int n) { //Gestin del acelerado } void IVehiculo.Frenar(int n) { //Gestin del frenado FUNDACION CONIN | C Sharp .NET 72

} public class CocheNormal:IVehiculoGasolina { void IVehiculo.Acelerar(int n) { //Gestin del acelerado } void IVehiculo.Frenar(int n) { //Gestin del frenado } void IVehiculoGasolina.CambiarVelocidadInyeccion(int velocidad) { //Gestin de la inyeccion } } public class TodoTerreno:IVehiculo4x4 { void IVehiculo.Acelerar(int n) { //Gestin del acelerado } void IVehiculo.Frenar(int n) { //Gestin del frenado } void IVehiculoGasolina.CambiarVelocidadInyeccion(int velocidad) { //Gestin de la inyeccion } void IVehiculo4x4.Activar4x4(bool activar) { //Gestin de 4x4 }

Y lgicamente las llamadas a los mtodos seran: TodoTerreno miTodoTerreno = new TodoTerreno(); ((IVehiculo4x4)miTodoTerreno).Acelerar(20); ((IVehiculo4x4)miTodoTerreno).Frenar(20); ((IVehiculo4x4)miTodoTerreno).CambiarVelocidadInyeccion(1000); ((IVehiculo4x4)miTodoTerreno).Activar4x4(true);

FUNDACION CONIN | C Sharp .NET

73

FUNDACION CONIN | C Sharp .NET

74

CAPITULO 11

ESTRUCTURAS DE DATOS
CAPITULO 12

EXPRESIONES REGULARES
CAPITULO 13

EXCEPCIONES
CAPITULO 14

DELEGACION Y EVENTOS
CAPITULO 15

APLICACIONES GRAFICAS USANDO WINDOWS.FORM


CAPITULO 16

APLICACIONES WEB CON ASP .NET


CAPITULO 17

SERVICIOS WEB
CAPITULO 18

ACCESO A DATOS CON ADO .NET


CAPITULO 19

XML

FUNDACION CONIN | C Sharp .NET

75

Vous aimerez peut-être aussi