Está en la página 1de 632
Teac CD-ROM | PROGRAMACION Microsoft® ys y FRANCISCO CHARTE OJEDA JANAYA\ LOM | Agradecimientos Por costumbre, y también algo de logica, estas paginas, que estan al princi- pio del libro y que no tienen el mas minimo interés para la mayoria de los lec- tores, se redactan siempre al final, practicamente cuando todo el trabajo, no solo el del autor, ha llegado a su fin. Su redaccidn es como una marca divisoria: se termina, por fin, el duro trabajo de muchas semanas y personas y se avista, por suerte, el producto que finalmente llegara a manos del lector. El autor puede tomarse un respiro y dejar descansar el teclado del ordena- dor, y dedicar unos minutos a recorrer todo el proceso que ha seguido hasta llegar aqui. Primero la idea de elaborar este libro, surgida de mis editores, Vie- tor Manuel y Susana, y el que suscribe. Les agradezco, y por extensién a toda la editorial, la confianza que depositan reiteradamente en mi. De verdad, espe- ro seguir mereciéndola y no fallaros. Para que las ideas puedan ser convertidas en algo tangible hacen falta herra- mientas, sin las que seria imposible desarrollar nuestro trabajo. Esas herramien- tas no las habriamos tenido en nuestras manos sin la inestimable colaboracion y ayuda de Microsoft Ibérica, personificada en mi caso en las personas de Ja- vier Izquierdo, José Antonio Alvarez e Ibrahim Pérez. Gracias por esa ayuda y por poner a nuestro alcance estos impresionantes productos. Qué seria de la vida sin los amigos? Estos, habitualmente, no suelen inter- venir en nuestro trabajo pero, por suerte, hay algunas excepciones: los amigos- compaiieros-consejeros. Por una parte quiero agradecer el apoyo y la ayuda, siempre dirigida a mejorar la calidad del libro, de Tomas Eisman que, ademas, es la persona que se ocupa de convertir un monton de documentos y archivos de imagenes en un libro de verdad, tal y como llega a las manos del lector. Tam- bién doy las gracias a José Manuel Alarcon, Jorge Serrano, José Luis Freire y todos los demas amigos que, de forma personal unas veces y electrénica en otras, estan siempre ahi para escucharme y contar conmigo. Gracias a todos. Por ultimo, y, como suele decirse, no por ello menos importante, el agrade- cimiento mas profundo a mi familia, las personas que me animan minuto a minuto y que sufren esta aficién-dedicacién que no entiende de horas ni fines de semana. Os quiero. Indice de contenidos Agradecimientos Introduccién .... {Otro nuevo lenguaje? Raices del lenguaje C# Orientacion a objetos .. Orientacion a componentes .. Programaci6n con atributos Objetos y valores Un lenguaje mas Mirando al futuro .. Sin abandonar el pasado Integracion en la plataforma .NET Integracion en Visual Studio.NET. Estandarizacion de C# Objetivo de este libro. 1. Primera toma de contacto... Puesta en marcha de Visual C# .NET.. La pagina de inicio ..... Elementos fundamentales ..... Inicio de un nuevo proyecto Anilisis del cédigo BE indice de contenidos —$—$ SS Ejecucién Un vistazo al ensamblado .. Opciones del proyecto... Puntos clave Resumen. 2, El entorno de desarrollo . Disposicién general Soluciones y proyectos .. Objetos existentes en un médulo Examinando clases y otros elementos Acceso a los asistente: Disenadores y editores .. Disefio de formularios Edicién de propiedades.. Componentes y controles.. Disefiadores adicionales El editor de cédigo Otras herramientas .... El Explorador de servidores Tareas pendientes ..... La ventana de comandos .. La ayuda de Visual C# NET Adaptacién del entorno .. Opciones del entorno .. Configuracién de botones y mens Seleccién de paletas visibles Afiadir y eliminar botones ... Ajiadir y eliminar menus de opciones Creacién de nuevas paletas y mentis Opciones diversas . Configuracién de herramientas externas Automatizacién de tareas Registro de una nueva macro Fjecucién de una macro .... Cédigo de la macro Puntos clave Resumen... 3. La plataforma Microsoft .NET .... Nuevas necesidades.... .NET, gla solucién definitiva’ Esquema de desarrollo y ejecucion Composicién de una aplicacién .NET . Ensamblados y manifiestos .... Ensamblados y dominios de aplicacién Programacién con Visual C# .NET Se Ensamblados privados y compartidos .. 91 Proceso de compilacién y ejecucién....... Cédigo intermedio El sistema comun de tipos Ejecucion supervisada ... Compilacién JIT... Informacién de tipo Servicios .NET para las aplicaciones Puntos clave Resumen... 4, Tipos de datos .............sses00 El sistema comtn de tipos Un sistema de tipos unificado Empaquetado y desempaquetado de datos Tipos intrinsecos ... Tipos no ajustados a la CLS Declaraci6n de variable: Ambitos y visibilidad Vida de una variable Especificacién de tipo Asignacién de un valor inicial .... Tipos definidos por el usuario .. Enumeraciones... Comprobacién estricta de tipos Estructuras Asignacién e igualdad. Miembros publicos y privados Metodos, constructores y propiedades Arreglos Beets Declaracién de un arreglo Arreglos con varias dimensiones . Rangos dindmicos Informacién sobre un arreglo Asignacién y copia Otras operaciones con arreglos Trabajo con caracteres ... Cadenas de caracteres .... Manipulacién intensiva de cadenas Constantes ... Puntos clave Resumen... 5. Operadores y expresiones Asignacién de valores Operadores aritméticos Indice de contenidos Operaciones con variables Object... Operadores relacionales Operadores légicos... Operaciones entre bit Expresiones con referencias Puntos clave Resumen... 6. Estructuras de control .. Estructuras condicionales La salida falsa ... Condiciones anidadas . Condicionales multiples Estructuras de repeticion Bucles por contador... Bucles condicionales Bucles que recorren un arreglo Control estructurado de excepciones .. Funciones y métodos Declaracién de un mies, Recepeién de parametros Devolucion de valores Devolucién de arreglos . Parametros por valor y por referencia Listas variables de parametros. Salida de un metodo ......... Métodos recursivos Puntos clave . Resumen. 7, Programacién orientada a objetos.. Ambitos con nombre... Definicién de ambitos con nombre Referencias a un ambito con nombre Conflictos entre Ambitos con nombre . Clases de objetos.. Definicion de una clase... Visibilidad de una clase y sus miembros Clases derivadas y herencia Constructores y destructores Clases anidadas Objetos de una clase. Miembros de una clase. Miembros compartidos . Miembros sobrecargados . Miembros redefinidos y ocultos .. Programacién con Visual C# .NET Acceso a los miembros de la clase base . Uso polimérfico de los objetos Métodos virtuales .... Interfaces Definicién de una interfaz . Implementacién de una interfaz Puntos clave Resumen 8. Programacién orientada a componentes ... Propiedades Definicién de una propiedad . Propiedades de sélo lectura y solo escetare. Indexadore: Delegados y eventos Asociacién entre eventos y controladores Otros usos de los delegados..... Componentes .NET ... Clases y componentes Uso no visual...... Uso visual del componente .. Puntos clave .. Resumen... 9. Programacién concurrente .......... Aplicaciones de la concurrencia Aplicaciones, hilos y prioridades La clase Thread. Puesta en marcha del nuevo hilo Enumeraciones concurrentes Prioridad de ejecucién. Elementos de sincronizacién .. Esperas entre hilos Accesos exclusives Interbloqueos y sefales Puntos clave Resumen... 10. Formularios Windows .... Qué son los formularios Windows? Una aplicacién Windows sencilla Disefio del formulario ... Implementacién de funcionalidad Analisis del cédigo generado Resumiendo e de contenidos Informacién sobre la aplicacion Inicio de la aplicacién . Datos del entorno de la aplicacién . Otros miembros de interés Aplicaciones de documento multiple... Preparacion de la ventana principal .. Creacién de un ment de opcione: Disenio de la ventana hija MDI Unién de las piezas... Trabajo con componentes Miembros comunes ... Posicién y dimensiones Orden de acceso y foco de entrada scsi 264 Anclaje y adosado de controles . Eventos de teclado y ratén Arreglos de controles La coleccién de contreles . Uso compartido de gestores de eventos.. Creacion de controles en ejecucién. Herencia visual...... Puntos clave . Resumen...... 11. Formularios Web .. De ASP a ASP.NET . Naturaleza de un documento ASP . Ocultacién del codigo en ASP.NET Libertad de eleccién de lenguaje . Adiés a los guiones interpretados ... Enlace entre el documento y el codigo El disefador de formularios Web . La clase Page .. Distribucion del contenido. Eventos y gestores Componentes HTML . Componentes de servidor ..... Uso de componentes de servidor Examen del cédigo HTML en el servidor Examen del cédigo en el cliente. Componentes de validacién Solicitudes y respuestas ... Identificacién del cliente ......... Parametros de la solicitud Parametros de formularios . Uso de cookies Programacién con Visual Ct .NET Modulos de configuracién .... Edicién del archivo web.config ... Almacenamiento de datos de aplicacién Recuperando informacion de configuracién Puntos clave . 307 7 Resumen 12. Servicios de entrada y salida ............. Primera aproximacién El paradigma de los flujos de datos - Preparados para otras plataformas .. Recuperando informacion del sistema de archivos Unidades existentes en el sistema .... Enumeracidn de carpetas y archivos Informacién sobre un objeto Unidades, caminos y nombres Manipulacién de carpetas y archivo Acceso al contenido de los archivos... Metodologia general Apertura de archivos Datos con tipo.. Un visor de archivos de texto. Flujos binarios.. Flujos en memoria Puntos clave .. Resumen... 13. Elaboracién de graficos .. Ambitos relacionados con GDI-......... Elementos de propésito general ., Graficos vectoriales y 2D... Manipulacién de imagenes Impresion Tipografias Primera aproximacion Preparacion de un pincel Dibujo de entidades simples Relleno de areas... : Afiadimos un texto Elementos basicos Colores... Puntos y coordenadas Brochas Lapices | indice de contenidos Tipos de letra... Manipulacién de mapas de bit: Recuperacién de una imagen Informacién y manipulacién Visualizacion de las imagenes Caminos y regiones ... - Creacién de un camino ... Transformaciones. Creacién de una regién . El componente PictureBox .. Graficos en ASP.NET Puntos clave Resumen .. 14. Impresién de datos .... Fas s del proceso de impresiOn as: seoeseeeiee S77 Documento a imprimir Superficie de impresién Composicién de un documento Configuracién de parametros.. Seleccién del dispositivo de destino Configuracién de pagina ... Visualizacién preliminar. Puntos clave Resumen. 389 392 15. Desarrollo de componentes .. Conceptos basicos zCuando un objeto es un componente? Un sencillo ejemplo Instalacién del componente Uso visual del componente Mejoras para la fase de diseitio Atributos para componentes .. Actualizacion automatica de la ventana Propiedades . Valores por defecto y persistencia.... Validez de los valores asignados Eventos y atributos........ Editores y convertidores a medida . Puntos clave .... Resumen. 16. Controles Windows Tipos de controles Windows La clase Control ... Programacion con Visual C# NET 417 417 419 423 Derivar de Control .. Dibujo del control . Propiedades protegidas Ocultacién de propiedades Eventos de cambios en propiedades. Nuevas propiedades y eventos . Interceptar los eventos de teclado y raton Controles compuestos .. Propiedades de componentes contenidos Otras bases para nuestros controle: Puntos clave ............ Resumen... 17. Controles Web .. La clase Control y sus derivadas Desarrollo de un‘control simp Posicién, dimensiones y estilo ... Adicién de nuevos miembros La clase HtmlTextWriter Controles compuesto Pagelets ..csaceu Creacién de un pagelet Uso de un pagelet Puntos clave Resumen... 18. Creacién de servicios Windows.. Esquema general ... La clase ServiceBase Creacién del objeto que acttia como servicio Eventos operacionales .. Instalacion del servicio. Asistentes disponibles para desarrollar servicios . Un servicio horario para red .. Definicion de la clase de servicio. Preparacién del instalador . Instalacion del servicio Comprobacién del servicio. Control de los servicios... La clase ServiceController Un controlador genérico Un controlador para ServicioHorario.. Puntos clave ... Resumen... J Indice de contenidos 19. Desarrollo de servicios Web................ {Qué es un servicio Web?... Servicios y aplicaciones... Universalidad de un servicio Protocolos y lenguajes . Introduccion a XML. ZQué es XML? .. Trabajo con etiquetas .. Visualizacion de los documentos Estructura de un documento XML Estructura de los datos ......... Conjuntos de caracteres en XML. Documentos XML bien formados Documentos XML validos Analizadores de XML... Validacion de documentos {Qué es una DTD? Analisis de la estructura del documento Elaboracion de la DTD... Cémo aplicar una DTD a un documento XMI Validacién del documento Atributos 0 propiedades Introduccion a XSL Transformacién de documentos... XSL basico.......... Cémo aplicar plantillas . Seleccion de datos... Las posibilidades de XSL. Introduccion a XSD .. El editor de esquemas XML de Visual Studio NET cea 517 Codificacién manual del esquema. Introduccion a XSLT y XPath . Introduccion a SOAP Estructura de un mensaje SOAP SOAP y Visual Studio .NET . Introduccion a WSDL y UDDI Creacion de un servicio Web .. Anatomia de un servicio Web El servicio horario El médulo asmx Médulo de descripcisn del servicio. Consumo de un servicio Web Referencias externas .. ¢Donde esta el proxy? Uso del servicio Web desde el consumidor . Programacién con Visual Ct NET Puntos Clave ooo... cece een siinienntineennenun are BOS Resumen... 20. Fundamentos de tratamiento de datos {Qué es una base de datos? {Qué es un RDBMS? ... Estructura fisica de una base de datos. Nombres de archivo «0.0... Estructura ldgica de una base de datos Procedimientos almacenadbs.... Otros elementos Idgicos ... Introduccién a SQL E] Analizador de consultas SQL . Componentes y derivados de SQL DDL. DML Transact-SQL... Definicién de datos... Creacién de una base de datos . Creacién de tablas ... Modificacién de una tabla Otras operaciones . Manipulacién de datos .. Insercién de nuevas filas Seleccién de datos ... Modificacién de datos Eliminacion de datos Relaciones entre tablas Puntos clave .. Resumen. 21. Acceso a datos con ADO.NET.... Modelo de objetos de ADO.NET .. Estructura de un objeto DataSet .. Creacién de un DataSet a partir de una tabla .. Recuperacion de la estructura de un DataSet .. Control de la conexion Acceso a los datos... Actualizacion de los dato: Enlace de datos e interfaz. Enlace en aplicaciones Web .. Enlace en aplicaciones Windows de contenid scan La coleccién DataBindings ... Asistentes y disefiadores de Visual C# .NET Creacién automatica de objetos . El asistente para formularios de datos Puntos clave . Resumen... 22. efio de informes con Crystal Reports .NET .. El disenador de informes Creacion del informe .. Modificacion del diseno ..... Formulas y campos especiales Formato de los elementos ...... Explotacién del informe Visualizacion en un formulario Winds Visualizacion en un formulario Web Impresion y exportacién del informe Puntos clave Resumen... 23. Recuperacién de informacién de tipos en ejecucién . Servicios de reflexién Ensamblados y médulos.. . Informacion sobre el ensamblado oc... sagicenemacneases OOO. Modulos que componen el ensamblado. Tipos definidos en un ensamblado La clase Type... Pardmetros de un metodo... Jerarquia de tipos de un ensamblado Uso dindmico de objetos.. La clase Activator .. Invocacion dinamica ... Puntos clave . Resumen... 24, Interactuacién con COM y el API de Windows .. Uso de componentes COM.... Importacién de controles Active Importacién de librerias de tipos Uso dinamico de componentes COM .. Exposicién de componentes .NET a COM Desarrollo y opciones del componente Uso del componente desde un cliente COM Acceso al API de Windows. 624 626 628 630 weve 631 1 632 634 Programacién con Visual C# NET 634 635 Declaracién de la funci6n..... Uso de las funciones Puntos clave Resumen... A. Contenido del CD-ROM Uso de los ejemplos Atencién al lector... seseerecereseeess O41 indice alfabético.... Introduccion Tras muchos meses de trabajo de un importante grupo de personas, entre las que se encuentra el prestigioso Anders Hejlsberg, Microsoft esta en condi- ciones de ofrecer a los programadores un lenguaje que, manteniendo la potencia y flexibilidad de C++, cuenta con la simplicidad y capacidades RAD de Visual Basic. Un lenguaje que puede utilizarse igualmente como lenguaje de script en paginas ASP.NET, en la creacién de interfaces de usuario, componentes y servi- cios Web. Tras analizar las caracteristicas mas importantes de este nuevo lenguaje, re- cién Iegado a este complejo campo del desarrollo de software, podemos afir- mar que encontramos en él una solucién global, de propésito general, y accesible para cualquier programador, independientemente de las nociones previas con que cuente. Su integracién con Visual Studio .NET, ademas, hace mas facil que nunca la construccién de todo tipo de proyectos. Si, como programador, usa habitualmente el lenguaje C++ para desarrollar sobre Windows, indudablemente le interesara conocer C# y sus nuevas posibili- dades. Por decirlo coloquialmente, con C# se sentira como en casa gracias a que la sintaxis es muy cercana a C++ pero, al tiempo, tendra la seguridad de que muchos problemas de este lenguaje no los encontrara en C#. Practicamente lo mismo podria decirse si usa para sus desarrollos el lenguaje Java. En cuanto a los programadores que hasta ahora han usado Visual Basic, ob- viamente la opcién mas rapida y accesible para llegar al mundo .NET es Visual Basic NET. El aprendizaje de C#, no obstante, no le resultara complejo una vez. se haya familiarizado con los conceptos de orientacién a objetos introducides en Visual Basic .NET. J tutroduceisn eOtro nuevo lenguaje? La mayoria de los programadores, al oir hablar de C#, responden en prime- ra instancia con esta interrogacién 0, incluso, utilizando un tono exclamativo sobre la misma frase. ;Necesitamos realmente otro nuevo lenguaje? {No es su- ficiente con los que ya existen? ¢No sirven para los proyectos que tenemos que desarrollar actualmente? Estas, y otras muchas, son cuestiones que Microsoft se planteo en su momento y, tras las cuales, decidié embarearse en un proyecto tan ambicioso. Se imagina realizar cualquier tarea actual, no necesariamente relacionada con la informatica, efectuada con las herramientas que se utilizaban hace tres o cuatro décadas? Publicar un periédico con maquinas de escribir, sin ordenado- res ni software de maquetacién; fabricar coches sin las modernas cadenas de montaje robotizadas, practicamente a mano, 0 cocinar sin disponer de los elec- trodomésticos que tanto nos facilitan la vida: vitroceramica, lavavajillas, bati- dora, etc. Son todas tareas que, obviamente, podriamos seguir realizando, aunque empleando bastante mas tiempo y trabajo. EI panorama actual en el campo del desarrollo de software es, guardando las distancias, bastante similar. Seguimos usando lenguajes como C y C++, creados hace casi treinta anos con el objetivo de desarrollar sistemas de la época, para construir aplicaciones modernas con interfaz de usuario grafica, aplicaciones Web y componentes. Esos lenguajes, y otros muchos, han ido actualizandose lentamente a lo largo de los anos pero, en la mayoria de los casos, no ofrecen soluciones integrales para las necesidades actuales, sino tan s6lo parches para ir resolviéndolas de manera puntual. Es en este contexto en el que debemos situar la aparicién de C#, un nuevo lenguaje propuesto por Microsoft precisamente para satisfacer las necesidades actuales y de un futuro cercano. C# es, por tanto, una herramienta, como todos los lenguajes de programacién, pero adaptada al trabajo actual y sin compro misos de compatibilidad ascendente. Preguntarnos, por tanto, si era necesario otro lenguaje seria como pregun- tar si es necesario otro nuevo sistema de motorizacién para los vehicules o un nuevo método de cultivo de cereales. Son eventos que ocurren periddicamente y que, en su mayor parte, estan destinados a facilitarnos la vida Raices del lenguaje C# Tras la exposicién que acaba de leer seguramente pensara que no tendra mas remedio que aprender un nuevo lenguaje, pero lo que seguramente no sepa es que dicho aprendizaje puede llevarle menos tiempo del previsto, C# es un lenguaje nuevo, pero esta basado en otro muy utilizado del que, en parte, toma su nombre. Ese lenguaje es C++. No es algo que ocurra por primera vez, ya en el pasado otros desarrolladores tomaron C++ como base para crear nue- vos lenguaj s. Fs el caso, por ejemplo, de Java Programacién con Visual C#.NET [ER Si conoce C++, Java o, incluso, C, empezar a programar en C# le resultara realmente facil, necesitando algo ms de aprendizaje si procede de otros len- guajes. C+ es el lenguaje orientado a objetos mas usado en la actualidad, de ahi que parezca la opcién mas légica como punto de partida para la evolucién hacia otros lenguajes mas avanzados. El objetivo de Microsoft ha sido la creacién del primer lenguaje orientado a componentes, al estilo de Visual Basic, pero con la flexibilidad y potencia de C++ y sin muchas de sus complejidades. C, C++ 0 Visual Basic estan pensados para el desarrollo de aplicaciones en sistemas operativos que ofrecen sus s cios a través de cientos 0 miles de funciones independientes que, en conjunto, forman lo que se conoce coloquialmente como API (Application Programming Interface). En contraposicién, C# ha sido disefiado para una plataforma, la pla- taforma Microsoft .NET, en la que los servicios son ofrecidos en forma de com- ponentes. Aunque C# es un primo muy cercano de C++, tambien tiene influencias de Visual Basic, Modula 2, Smalltalk y Java. El resultado es un lenguaje orientado al trabajo con componentes que mantiene, en su mayor parte, los operadores y estructuras propias del lenguaje C++. rvi- Orientaci6n a objetos Como hijo directo de C++, C# cuenta con la mayoria de las caracteristicas de orientacidn a objetos de aquél. La entidad de primer nivel es, como en todos los lenguajes de esta categoria, la clase, definicién a partir de la cual se crearian objetos y derivarian nuevas clases. La encapsulacién, la herencia y el poli- morfismo son, por tanto, los tres pilares basicos de la orientacién a objetos en C# como en C++. A diferencia de lo que ocurre en otros lenguajes, en C# no existen los con- ceptos de definicién e implementacién como elementos separados de una clase No existen los archivos de cabecera, como en C++, ni los médulos IDL (Interfa- ce Definition Language) 0 elementos similares. La clase se define e implementa en un solo paso, en el mismo modulo, de tal manera que resulta como una en- tidad auto-contenida. Esto simplifica tanto la codificacion como el posterior mantenimiento haciendo posible, ademas, la utilizacion de C# como lenguaje de guiones para ASP.NET, algo que seria dificil conseguir en un lenguaje como cH Las clases, como entidades de primer nivel, pueden agruparse en Ambitos con nombre o namespaces. El concepto y la sintaxis son bastantes cercanos a los existentes en C++. Estos ambitos pueden anidarse unos dentro de otros, de la misma forma que las clases, dando lugar a jerarquias 0 arboles. A diferencia de lo que ocurre en Java, el nombre jerarquico de un ambito no se encuentra obli- gadamente asociado con la localizacion y nombre fisicos de los modulos en el sistema de archivos. Aligual que en C++ y otros lenguajes orientados a objetos, los miembros de una clase C# cuentan con modificadores que establecen su visibilidad, asi como J ntroduccion con elementos sintacticos que determinan si una clase puede o no actuar como base de otra o debe utilizarse necesariamente para derivar otras clases. Orientaci6n a componentes Ademés de un lenguaje orientado a objetos, C# es el primer lenguaje de la familia C/C++ que también esta orientado al trabajo con componentes. Esto significa que cuenta con construcciones sintacticas nativas para la definicién, implementacién y consumo de propiedades, métodos y eventos, lo cual le di- ferencia claramente de C++ 0 Java. Para definir una propiedad en el interior de una clase C? se utiliza una sin- taxis especifica, no necesitando la simulacién mediante métodos que se ajustan a un cierto patron de nomenclatura. Igualmente, pueden usarse eventos sin ne- cesidad de tratar con punteros a funciones 0 métodos. La existencia de pala- bras clave, como property, event y delegate, simplifica la construccién de estos elementos que, como sabemos, son fundamentales a la hora de trabajar con componentes, no sélo con objetos. En este aspecto, por tanto, C# asimila, e incluso supera, las tradicionales fa- cilidades que da Visual Basic a la hora de usar y disefiar componentes sin, por ello, perder un pice de potencia y flexibilidad. Para construir un componente con C# no es necesario hacer nada especial aparte de crear una nueva clase. Dicho de otro modo, cualquier clase de objeto C# es un componente, sin necesidad de crear GUID (Globally Unique Identifier) para interfaces y clases de componentes, efectuar operaciones de registro, im- plementar interfaces como IUnknown, etc., operaciones todas ellas habituales cuando se utiliza C++. La documentacion de las clases, especialmente interesante cuando se crean componentes para ser utilizados por otros miembros de un equipo o incluso por terceros, es generada automaticamente a partir de los comentarios inclui- dos en el cédigo. Estos siguen una notacién XML, siendo C# el primer lenguaje en utilizar este sistema con este fin concreto. Programacion con atributos Ademas de miembros de datos, variables simples dentro de una clase, mé- todos, propiedades y eventos, un componente cuenta con otras cualidades que, hasta ahora, no se expresaban mediante elementos sintdcticos del lenguaje. Un componente COM, por ejemplo, puede utilizar o no transacciones durante su funcionamiento. Este es un atributo que, en el caso de Windows 2000, se esta- blece mediante los servicios de COM+. En Cf este tipo de cualidades se definen en el mismo cédigo del componente, usando para ello un nuevo elemento: el atributo. Los atributos pueden asociarse tanto a clases como a miembros de clases, por ejemplo métodos 0 propiedades. Programacion con Visual C# NET La utilizacion de atributos hace innecesarios los archivos IDL y las operaciones de configuracién a posteriori, durante el proceso de instalacion de los compo- nentes Los atributos se introducen como parte del cédigo fuente, delimitados por los caracteres [ y ], y es el compilador el encargado de procesarlos generando la informacion de configuracién apropiada. Para indicar, por ejemplo, que un método de una clase debe exponerse como parte de un servicio Web, basta con disponer delante de ese método el atributo [WebMethod]. De forma similar se indicaria el uso de transacciones, la persistencia de la clase 0 se asociarian co- mentarios e identificadores. Mediante los atributos lo que se hace es incluir en el cddigo informacién declarativa, que no programatica. El sistema de atributos es totalmente extensible, de tal forma que el progra- mador puede definir sus propios atributos a fin de asociar a los componentes la informacién que precise. Dicha informacién puede recuperarse posterior- mente, durante la ejecucion de la aplicacién, utilizando un mecanismo de re- flexién. Objetes y valores Los programadores més puristas siempre han criticado que lenguajes como C++ y Java no son realmente orientados a objetos, sino lenguajes con algunas caracteristicas de orientacién a objetos ya que en ellos existen elementos migi- cos que no pueden ser tratados como objetos. Esos elementos son los tipos de datos basicos: enteros, cadenas de caracteres y, en general, variables que con- tienen valores en lugar de referencias a objetos. En aquellos lenguajes orientados a objetos puros, cuyo mayor exponente es Smalltalk, todos los elementos son objetos y pueden ser tratados de manera homogénea, sin distinguir entre valores nativos y objetos generados a partir de una clase. Como todo, este esquema de funcionamiento tiene ventajas y des- ventajas. Entre las segundas la mas importante es la velocidad, ya que los ob- jetos tienen unas necesidades de asignacién de memoria y acceso a sus miembros que no existen en los valores. Por eso resulta mucho mas rapido trabajar, por ejemplo en C++, con un entero nativo que con un objeto que representa ese en- tero. Aparentemente, al disefiar un nuevo lenguaje, habria que optar por una de las dos alternativas posibles: existen tipos que no son objetos, con el fin de me- jorar el rendimiento, 0 todos los valores son objetos. C4, sin embargo, retine lo mejor de ambos mundos. En C# todos los valores pueden ser tratados como objetos, a pesar de que existen tipos que almacenan valores y otros que traba- jan con referencias. Esto es posible gracias a una técnica denominada boxing/ unboxing. Cualquier valor puede ser convertido en un objeto mediante esta téenica siempre que sea necesario. En ocasiones, la conversién es totalmente transpa- rente para nosotros y es que, en definitiva, todos los tipos, ya sean primitivos 0 clases de objetos, derivan en C¥ de una base comun. Esto nos permite trabajar § Introduccién con un sistema de tipos de datos unificado, en el que no hay que pensar si la variable sobre la que va a operarse, por ejemplo invocando a un método, con- tiene un valor o una referencia. Para crear nuevos tipos de datos por referencia, lo que conocemos habitual- mente como objetos, en C# se definen clases, mientras que la creacion de nue- vos tipos de datos por valor se efectia mediante las estructuras. Esta es una diferencia primordial entre C# y C++, ya que en el primero una estructura, a pesar de poder contar con métodos y elementos caracteristicos de una clase, no se crea con una asignacién dinamica de memoria como un objeto, sino que se aloja en la pila como cualquier variable de tipo intrinseco. Un lenguaje mas seguro Tradicionalmente los programadores que usan la mayoria de lenguajes ac- tuales, y especialmente C++, han tenido que ocuparse no sdlo de programar la tarea concreta que tenian encomendada sino que, ademas, han debido sortear los peligros de este lenguaje. El uso incorrecto de los punteros, la conversion inadvertida de valores integrales en evaluacién de expresiones booleanas o la ocultacién de métodos heredados de una clase, por mencionar alguno, son errores que se comenten a menudo en C++ y originan no pocos quebraderos de cabeza, Comparativamente hablando, C# resulta un lenguaje mucho mas seguro. Para empezar es un lenguaje con una estricta comprobacién de tipos, en el que no se efecttian automaticamente conversiones potencialmente peligrosas, y que da un valor inicial por defecto a todas las variables, independientemente de su dmbito. No es posible, por ejemplo, utilizar un entero como tinico ope- rando de un condicional, evitando de esta manera que una asignacién equivo- cada, por utilizar el operador = en lugar ==, genere un error légico dificil de encontrar. La destruccién de objetos, y liberacién de la memoria asociada, se produce de manera automatica gracias a la existencia de un recolector de basura. El programador, consecuentemente, no tiene que ocuparse de manera explicita de la destruccién que, en ocasiones, resulta en islas de memoria olvidadas o acceso a objetos inexistentes cuando se ha operado con multiples referencias al mismo objeto. En C# tan slo existe un operador para acceder a los miembros de una clase, independientemente de su naturaleza. Esto evita errores habituales en C++ por la confusion que plantea el uso de los operadores « y -> de acceso a miem- bros y el operador :: de resolucién de ambito. Que al definir una clase, derivada de otra, un nuevo metodo oculte acciden- talmente a uno de los heredados, por coincidir en nombre y lista de parametros, es algo que no puede darse en Ci. Es necesario indicar, de manera explicita, que quiere ocultarse dicho método. Esto, ademas, no sera posible si en la clase original no se especificé que el método podia ser ocultado en las clases deriva- das. Programacion con Visual C# NET [RQ Mirando al futuro Como se apunta en el propio titulo de este articulo, C# es un lenguaje dise nado con el futuro en mente aunque, como se indica en el punto siguiente, sin romper en absoluto con el presente y pasado. La perfecta integracin con la plataforma Microsoft .NET, en parte escrita con el propio lenguaje C#, nos per- mite utilizarlo para construir practicamente cualquier tipo de proyecto, de ex- tremo a extremo. Podemos usar C# para fabricar los componentes que encapsulan la logica de negocio y acceden a bases de datos, las interfaces de usuario que actuan como clientes de dichos componentes y el cédigo de servidor que actuia detras de las interfaces Web. Fl desarrollo de aplicaciones distribuidas es mas simple que nunca y se abren las puertas a nuevas técnicas, como el ofrecimiento de productos a través de servicios Web. Si antes, con el fin de crear una aplicacién distribuida con componentes ejecutindose en un servidor de aplicaciones e interfaces Windows y Web, era preciso usar Visual C++, Visual Basic y Visual InterDevy como herramientas, aparte de COM, MFC, ASP, HTML, ADO y otros elementos que actuan como contenidos 0 intermediarios. Ahora solo precisamos C#, ASP.NET y ADO.NET para conseguir el mismo resultado, sin necesidad de conocer multiples lengua- jes de programacién, modelos de componentes y mecanismos de comunicacion y acceso a datos. Fl compilador de C# de Microsoft no genera codigo ejecutable en ningun caso, sino que produce codigo MSIL (Microsoft Intermediate Language). No es un concepto nuevo en absoluto, hace décadas que existen compiladores de Pascal y COBOL que generan cédigo intermedio durante la compilacién y usan un intérprete para la ejecucién de dicho cédigo. Es el mismo concepto usado por Visual Basic desde su aparicion, hace algo mas de diez afios, y mas recientemen- te por Java y su byte-code. Gracias a la generacién de cédigo MSIL, el programador que utiliza C# no tiene por qué preocuparse del sistema operative o procesador en el que va a ejecutarse la aplicacién. En principio la plataforma Microsoft NET se encon- trara disponible para Windows 98, Me, NT, 2000 y XP, estando en preparacién una Compact .NET Framework para dispositivos méviles tipo Pocket PC. En el futuro, sin embargo, este entorno de ejecucion de codigo MSIL estara disponi- ble para procesadores de 64 bits y posiblemente otros sistemas operativos no Windows. El compilador JIT de cada sistema en particular se encargara de traducir el MSIL en cédigo nativo aprovechando las caracteristicas del pro- cesador y sistema operative concreto en el que vaya a producirse la ejecuc sin necesidad de mantener varias ediciones diferentes del mismo proyecto. Otra ventaja del uso de MSIL, es que la cooperacién entre C# y otros lengua- jes NET ajustados a la CLS (Common Language Specification) es total, de tal for- ma que podemos derivar una nueva clase C# tomando como base otra escrita en Visual Basic.NET, por poner un ejemplo. Cada programador puede usar el lenguaje de su preferencia sin limitar las opciones de los demas. B introduce Sin abandonar el pasado Sin duda alguna, los servicios e interfaces Web y la comunicacién de datos mediante XML sen el futuro del desarrollo de soluciones software a corto y me- dio plazo. No hay que olvidar, sin embargo, que actualmente son millones de usuarios les que ulilizan distintas versiones de Windows con aplicaciones ba- sadas en los servicios que podriamos denominar clasicos en este sistema ope- rativo: el API de Windows y el modelo de componentes COM. El lenguaje C# esta preparado no sélo para el futuro, sino también para pre- servar las inversiones actuales gracias a su perfecta integracién con COM y los servicios de Windows en general Cualquier componente .NET escrito con C# puede ser expuesto a aplicacio- nes antiguas como un componente COM sin, por ello, tener que codificar nin- guna funcionalidad adicional, No tenemos que preocuparnos de interfaces como IUnknown, librerias de tipos, registro ni nada similar. Partiendo de la informa- cion de tipos almacenada en los ensamblados, utilizando el mecanismo de re- flexion anteriormente citado, una herramienta se encarga de realizar todo el trabajo por nosotros. De manera andloga, desde una aplicacién C# podemes usar componentes COM como si fuesen componentes .NET, sin ningun trabajo extraordinario por nuestra parte. También el acceso a las funciones del API de Windows, o cuales. quiera otras alojadas en bibliotecas de enlace dinamico, resulta una tarea sen- cilla, no precisando mas que una declaracién o prototipo de la funcién indicando mediante atributos la DLL en que se encuentra Aunque no es una técnica demasiado recomendable ni necesaria, con C# po- demos utilizar punteros clasicos, al estilo de C++, y algunos otros elementos que podriamos denominar no seguros. De hecho, para usarlos es preciso delimi- tar claramente el bloque de codigo en el que se utilizan indicando que se trata de codigo no seguro pero que, en ocasiones, puede facilitar la integracién con componentes heredados de proyectos previos. Integracion en la plataforma .NET En principio, C# es un lenguaje disefiado por Microsoft para generar codigo ajustado a la CLS que se ejecute bajo la supervisién del entorno comun de eje- cucién de la plataforma NET, lo que se conoce como CLR (Common Language Runtime). Esta integracion entre la plataforma y el lenguaje permite utilizar desde éste todos los servicios que ofrece aquella. Esto significa que podemos usar C# para construir aplicaciones Windows sirviéndonos de las clases contenidas en System, Windows . Forms, uno de los dmbitos existentes en Ja plataforma. Igualmente, puede utilizarse su equiva- lente Web para, mediante controles de servidor, generar automaticamente y de manera dinamica codigo HTML para interfaces Web. Programacion con Visual C# NET A fin de generar graficos, manipular imagenes y publicar informacion es po- sible usar los servicios de GDI+. Para el acceso a datos se utilizan los objetos de ADO.NET, y lo mismo es aplicable para las operaciones de entrada y salida, gestion de multiples hilos de ejecucién 0 extraccién de informacién a partir de los atributos. En definitiva, todos los servicios disponibles en la plataforma .NET apare- cen para C# como clases nativas, por lo que pueden utilizarse directamente sin necesidad de ningun tipo de importacién previa de librerias de tipos o defini- cién de prototipos. Integracion en Visual Studio.NET Como queda patente tras leer los puntos anteriores, C# es un lenguaje po- tente, flexible y moderno, orientado al trabajo con componentes, seguro y mas simple que otros de la familia C++. Disponiendo tan sélo del compilador de C#, incluido en la plataforma .NET, y un editor simple podria desarrollar cual- quiera de los tipos de proyecto mencionados previamente: componentes, in- terfaces de usuario Windows y Web, servicios Web, ete. Fl mayor sentido practico de este lenguaje, sin embargo, lo encontramos en Visual Studio NET gracias a la estrecha integracién entre dicho entorno y C#, mucho mayor que la que tiene Visual C++ .NET y equivalente 0 incluso supe- rior a la de Visual Basic, NET. Gracias a esta integracién, los disefiadores de Visual Studio .NET son capa- ces de generar cédigo C? al crear interfaces de usuario basadas en formularios Windows y formularios Web, producir adaptadores de datos, guiones embebi- dos en documentos ASP.NET, etc. El lenguaje C# esta pensado con el objetivo de ofrecer capacidades RAD a los desarrolladores de C++ sin sacrificar la potencia y flexibilidad. Esas cuali- dades RAD, para desarrollo rapido de aplicaciones, son las que encontramos en cl entorno de Visual Studio .NET, mientras que el propio lenguaje pone el resto. Estandarizacion de C# Si hay una acusacién que practicamente todos los desarrolladores, en un momento u otre, hemos hecho a Microsoft, esa ha sido, sin duda alguna, su falta de compromiso con los estandares establecidos, ya fuesen oficiales o de hecho. En los ultimos tiempos, sin embargo, Microsoft esta convenciéndonos de lo contrario. No hay mas que ver su apoyo incondicional a XML (Extensible Markup Language) en practicamente toda su gama de productos, asi como su contribucién a la creacién de nuevos estandares, como SOAP (Simple Object Access Protocol) 0 WSDL (Web Services Description Language) conjuntamente con otras empresas. BM istroduccion El lenguaje C# no ha sido creado tan s6lo por y para Microsoft y su platafor- ma .NET. Conjuntamente con Intel y HP, a finales del aho 2000 Microsoft re- mitié al ECMA (European Computer Manufacturers Association), una institucion independiente dedicada al proceso de creacién de estandares, tanto el borra- dor del lenguaje C# como el de CLI (Common Language Infraestructura), parte fundamental de .NET. A los grupos de trabajo 1C39/TG2 y TC39/TG3 del ECMA, dedicados a es- tudiar este proceso, se unieron varias empresas mas: Fujitsu Software, IBM, Netscape, Open Wave e ISE, entre otras. Desde entonces, en reuniones men- suales habitualmente, esta entidad trabaja en la definicion de una especifica- cidn del lenguaje. Es un proceso que previamente intento efectuar Sun con Java pero al que finalmente renuni Que el lenguaje C# sea un estandar, igual que lo son C++ 0 C, significa que potencialmente cualquiera puede crear un compilador de C# para cualquier sistema operativo, recurriendo para ello al estandar detinido en el ECMA. No dependeran de Microsoft, empresa que tampoco controlara de manera unilate- ral la evolucion del lenguaje, algo que si ocurre con la mayoria de lenguajes usados actualmente si exceptuamos C++: Object Pascal, Java, Perl, etc. Objetivo de este libro Al redactar este libro el objetivo que tenemos en mente es facilitar al lector un material didactico que, por si solo, le permita aprender a programar con Vi- sual C# NET y utilizar este lenguaje para desarrollar los tipos de proyecto mas habituales. El libro, por tanto, no estudia a fondo el entorno de Visual Studio -NET, el funcionamiento de la plataforma .NET 0 sus servicios, centrandose en las novedades de Visual C# .NET como lenguaje y el trabajo diario con él. Comenzando desde el primer capitulo, el que tiene a la vuelta de esta pa- gina, podra seguir procedimientos practicos para familiarizarse basicamente con el entorno de trabajo y los fundamentos del funcionamiento de la platafor- ma, centrandonos a partir de entonces en el estudio del lenguaje, el desarrollo de aplicaciones Windows y Web, componentes y servicios. En los distintos capitulos aprendera a utilizar, desde Visual C7, ADO.NET para trabajar con datos procedentes de bases de datos como SQL Server, GDI+ con el fin de crear graficos, manipular imagenes o imprimir informacion, ASP.NET para disefar interfaces de usuario y servicios Web, Crystal Reports.NET con el fin de crear informes, etc. También aprendera a crear aplicaciones, sin importar su tipo, usando multi- ples hilos de ejecucién concurrentes, reutilizando componentes COM heredados de proyectos previos 0 accediendo a los servicios nativos del API de Windows. Disponiendo de alguna de las ediciones de Visual Studio .NET, 0 bien de Visual C# .NET Standard como producto separado, lo Unico que necesitara para comenzar a desarrollar sus propias aplicaciones es el libro que tiene en sus manos. Pase la pagina y péngase cémodo. No pierda el ordenador de vista y prepdrese para comenzar. 1 Primera toma de contacto En este capitulo, asumiendo que ya tiene instalado en su sistema Visual C# .NET o alguna de las ediciones de Visual Studio .NET, vamos a experimentar nuestra primera toma de contacto con el entorno y, de paso, aprenderemos al- gunos conceptos basicos con el fin de crear nuestra primera aplicacién .NET con Visual C# NET. 1 objetivo principal es ayudarle a perder el miedo duran- te esos primeros minutos en los que ha de enfrentarse a una nueva herramienta, con un entorno que desconoce, y que suelen ser los mas dificiles. Recuerde que este libro esta redactado usando la edicién Enterprise Architect de Visual Studio .NET en castellano por lo que, en su caso, utilizando posible- mente una edicién distinta del mismo producto o bien Visual C# NET Stan- dard, puede encontrar diferencias puntuales en algunas imagenes, opciones disponibles y elementos similares. Observe que en este capitulo el contenido tedrico es minimo. Para iniciar Visual C# NET y crear un programa simple no lo necesitamos. En los capitulos siguientes tendremos tiempo de ocuparnos tedricamente sobre aspectos del lenguaje, el entorno y la plataforma .NET. Dado que el entorno de Visual C#, la edicién Standard, es el mismo que el de Visual Studio .NET, en el resto del libro se utilizar una denominacién u otra para hacer referencia al entorno, mientras que se utilizara el término "C#" para hacer referencia especificamente a dicho lenguaje. sam. Primera toma de contacto Puesta en marcha de Visual C# .NET Recurriendo, como es habitual, al menu Inicio de Windows, encontrara en la lista de programas una entrada correspondiente a Visual C# .NET 0 Visual Studio .NET, segun el producto que tenga instalado. Seleccionandola pondra en marcha el entorno de desarrollo. En la ventana de presentacién, la tipica splash que tan sélo permanece unos segundos en pantalla, podra ver los ele- mentos relacionados con Visual Studio NET que tiene instalados en su siste- ma. En la figura 1.1, por ejemplo, puede ver que el entorno usado es la Visual Studio .NET Enterprise Architect, que cuenta con Visual Basic NET, Visual Ct -NET, Visual C++ .NET, Crystal Reports y Application Center Test. Se autora eluso de este producto a Francisco Chatte Ojeda [Eze programa et prctugo por lye yaad reacts come se debe an cua de diego Aces don dr de apr (2 17-081 Mey Cerperton, Reread bs daachoe Productos rstaados de a farila Visual Stud a a e woldticter wlll ter weer Somtrerote aylsin Cee - = Figura 1.1. En la ventana de inicio podemos ver los productos que tenemos instalados Si afadimos al entorno otros productos, como Visual |# .NET, COBOL .NET © Perl .NET, por poner algunos ejemplos, estos apareceran también en forma de iconos en esa misma ventana de inicio. En cualquier caso, a nosotros nos basta con que exista Visual C# NET que, en definitiva, es la herramienta en la que vamos a centrar nuestra atencién La pagina de inicio Tras una instalacién nueva de Visual C# .NET, asumiendo que es la primera vez que iniciamos el entorno, lo primero que veremos aparecer sera la Pagina de inicio, concretamente la seccion Ilamada Mi perfil. En ella existen varios apar- tados que nos permiten configurar el comportamiento del entorno para que se adapte lo mejor posible a nuestros conocimientos (véase figura 1.2) al Ct NET Programacion con Cemrpranbe us I signees confouracn et personals de acer @ ss recede revit Ceomnacin ovo: (Carasin reaene] Z “ [Predctormden be Wrosloads__—_ edo ay fale ae Figura 1.2. Ajustamos nuestro perfil utilizando la pagina de inicio Desplegando la lista titulada Perfil, la que aparece en la parte superior de la pagina, podremos indicar la herramienta que estamos acostumbrados a usar: Visual Basic, Visual C++, Visual InterDev, etc. Dependiendo de la opcién elegi- da, automaticamente se establecerd la configuracién de*teclado y distribucion de ventanas de Visual C# .NET. Estos elementos, no obstante, también pueden establecerse de manera individual. En la figura 1.2, por ejemplo, se ha optado por la configuracién predeterminada para programadores de Visual C#, pero podriamos alterar, por ejemplo, la distribucion de teclado para establecer la habitual en Visual Basic 6 si es que conociamos dicho entorno. Otros aspectos que puede configurar en esta seccion es el filtro para acceder a la ayuda y si ésta se mostrara en una ventana interna, dentro del mismo en- torno, o bien como una ventana independiente. Por tltimo, en la parte inferior, puede indicar aquello que desea que ocurra cada vez que inicie de nuevo Vi- sual C# NET. Puede dejar que aparezca siempre la Pagina de inicio, concreta- mente la seccién Introducci6n, o bien indicar que se abra el tiltimo proyecto con el que se trabajé, que se muestre un cuadro de didlogo para seleccionar el pro- yecto, etc. Si en algdin momento pierde la Pagina de inicio de vista, porque la haya cerrado inadvertidamente, puede recuperaria pulsando el bot6ngijjo selec- cione la opcién Ver>Explorador Web>Inicio. 1. Primera toma de contacto En caso de que mantenga en la opcion Al iniciar el valor ofrecido por defec- to, cada vez que inicie Visual C# NET se encontrara con una ventana como la dela ura 1.3. Realmente es otra seccién de la misma Pagina de inicio, en este caso ofreciendo una lista de los tiltimos proyectos con los que se ha trabajado, para abrirlos con un simple clic, asi como los botones necesarios para abrir otros proyectos 0 iniciar uno nuevo. "marie nn An TT tab sual: Bose ae “70 2180188 | saree slat aia. Figura 1.3. Aspecto de la Pagina de inicio ofreciendo las opciones para abrir @ iniciar proyectos Usando el resto de las secciones de la Pagina de inicio podra acceder a la co- munidad en linea, a través de Internet, noticias sobre Visual C# NET, actuali zaciones, servicios Web de ejemplo, etc. Tan sélo tiene que pulsar cada una de las opciones y experimentar para ver el resultado. Elementos fundamentales Ademis de la Pagina de inicio, en el entorno de Visual C# NET encontrara algunos elementos mas, algunos de ellos fundamentales para poder desarrollar nuestro trabajo. En realidad, los elementos visibles dependeran de la distribu- cion de ventanas que previamente, en la seccion Mi perfil, hayamos selecciona- do. Asumiendo que hemos mantenido la disposicion por defecto, en la parte derecha podemos ver dos ventanas adosadas. La primera, en la parte superior, cuenta con dos paginas: Explorador de soluciones y Vista de clases. Fn la infe rior aparece la ventana Ayuda dinamica Programacién con Visual Ct NET El entorno de desarrollo en el que trabaja Visual C# .NET es capaz de ocul- tar automaticamente las ventanas que no estan utilizandose, mostrandolas de manera inmediata en cuanto el puntero del ratén se sittia en el lugar adecuado. En la parte superior izquierda del entorno, segtin la ventana mostrada en la fi- gura 1.3, puede ver que hay una pestafia con un icono y un texto en vertical: Explorador de soluciones. Debajo hay un botén con otro icono. Si situa el pun- tero del ratén sobre él vera aparecer el Cuadro de herramientas. La parte superior de la ventana principal esté ocupada por un menit de op- ciones y unas paletas de herramientas, Con ellos podra iniciar un nuevo proyec- to, abrir y guardar archivos, acceder a la Pagina de inicio, navegar por la ayuda, etc. Conocerd algunos detalles mas sobre el entorno en un capitulo posterior. Por ahora simplemente tenemos una nocién general de lo que hay alrededor. Inicio de un nuevo proyecto Con el fin de cumplir con el habitual ritual que practicamente exige que el primer programa que se escribe con un nuevo lenguaje o herramienta sea el ti- pico Hola mundo, vamos a ver cuales serian los pasos que dariamos en Visual C# .NET para conseguir dicho objetivo. De paso veremos cémo crear una apli- cacién de consola con Visual C#, Asumiendo que acaba de iniciar Visual Ca .NET y que, por tanto, tiene la Pagina de inicio delante, para iniciar un nuevo proyecto tiene las alternativas indicadas en la figura 1.4. Podemos pulsar el boton Nuevo proyecto, ya sea el que aparece en la parte inferior de la mencionada Pagina de inicio 0 el que hay en la barra de botones, en la parte superior. La otra alternativa es desplegar cl menu: Archivo y seleccionar la opcién Nuevo>Proyecto En cualquier caso, independientemente del método usado, veremos apare- cer el cuadro de didlogo Nuevo proyecto. En él encontrara dos listas, segtin se aprecia en la figura 1.5. La de la izquierda contiene varias carpetas agrupando los distintos tipos de proyecto disponibles, mientras que en la de la derecha aparecen los elementos de la carpeta seleccionada a la izquierda. En nuestro caso hemos elegido a la izquierda la carpeta Proyectos de Visual C# y a la de- recha el elemento Aplicacién de consola. Los tipos de proyecto disponibles en la herramienta dependeran del pro- ducto que tengamos instalado. La figura 1.5 corresponde a Visual Studio .NET, de ahi que existan carpetas de proyecto Visual Basic y Visual C++. Si tenemos instalado Visual C# .NET como producto separado, l6gicamen- te esas carpetas no existiran. Ademaés de indicar el tipo de proyecto que deseamos iniciar, en este caso una aplicacién de consola, en los apartados Nombre y Ubicacién deberemos 1. Primera toma de contacto a introducir el camino en el que se creara el proyecto y su nombre. Este determi- nara el nombre de la carpeta en la que se almacenaran todos los archives con que cuente el proyecto. Menu Archivo Botén Nuevo proyecto verte Pred BG) > Boton Nuevo proyecto Figura 1.4. Elementos de interfaz para iniciar un nuevo proyecto “a rovectos te Wael Ck (i Proyectos de ashe (Gh rroyecton de talc» plementacén 2 Ga Otres proyectos Gi sclcones de Vint tudo Figura 1.5. Cuadro de didlogo Nuevo proyecto Analisis del codigo Introducidos todos los parametros en el cuadro de dialogo anterior, al pul sar Intre o el botén equivalente se creara el nuevo proyecto. Sus elementos Programacién con Visual Ce NET [ERD podremos verlos en la ventana del Explorador de soluciones, mientras que el co- digo correspondiente al unico médulo existente en el proyecto aparecera abier- to en el correspondiente editor (véase figura 1.6). Sélo tenemos que introducir las sentencias a ejecutar cuando este proyecto se ejecute. eines Class: 117 panto de extrade peizcipel de ta apiicacton. (staTmc0ac frearae void Masn(steing(} aces) c a 17 Tenor wocagae serat chaige pare Antciar Ia ” Figura 1.6. El cédigo del nuevo proyecto aparece en el editor de Visual C# NET El codigo define una clase, lamada Class1, que contiene un método Hama- do Main().Ensu interior introducimos la sentencia System. Console.Write- Line("Hola mundo" ), de tal forma que el programa completo seria el siguiente: using System; namespace HolaMundo { //) (/] Descripcién breve de Classl. 1) class Class1 t 1/4 i// Punto de entrada principal de 1a aplicacion. Jd) [STAThread] static void main(string[] arg: { t Primera toma de contacto iW /1 TODO: agregar aqui cOdigo para iniciar la aplicacior yh system.Console.Writeline("Hola mundo”); y » y Lo que hacemos en esa sentencia es invocar al método WriteLine() de la clase Console, una clase definida en el ambito System Podemos llamar di- rectamente al método, sin crear previamente un objeto de la clase Console, porque es un método compartido o estatico. Conocera todos estos detalles en capitulos posteriores, por ahora es suficiente con que tenga una idea global de lo que esta haciendo. El mencionado método WriteLine() puede tomar distintos parametros, entre ellos una cadena de caracteres. Cuando introduzca el codigo en el editor, al abrir el paréntesis para la lista de parametros, vera aparecer una pequena ventana emergente de ayuda indicandole los parametros necesarios. Observe que dicha ventana cuenta con unos pequefios botones, en forma de flecha, que nos permiten elegir entre varias versiones diferentes del métodoWriteLine( ), ya que éste se encuentra sobrecargado. Ejecuci6én Para desarrollar este sencillo programa no hemos utilizado ningiin disentador, ni editado propiedades ni trabajado visualmente con componentes. Tan solo nos hemos servido de un asistente, el que ha generado la mayor parte del codi- g0, y usado el editor para introducir una sentencia. El resultado, no obstante, es una aplicacion de consola completa Basta la pulsacién de la combinacién de teclas Control-F5 para compilar el proyecto, obteniendo el correspondiente ejecutable, ¢ iniciarlo. El resultado sera similar al mostrado en la figura 1.7. Simplemente aparece en una ventana de consola la cadena de texto entregada como parametro a WriteLine(). La combinacién de teclas Control-F5 equivale a la opcién Depurar>Iniciar sin depurar. Lo habitual es usar Depurar>iniciar, o pulsar F5, pero en ese caso la ventana de consola se cerraria de inmediato al finalizar la ejecucion del programa, impidiéndonos observar el resultado. Antes de ejecutarse, el cédigo ha sido compilado generando cédigo en MSII (Microsoft Intermediate Language). Dicho codigo se almacena en un ensaniblado que, en apariencia, es como un ejecutable cualquiera. Encontrara dicho ensam- blado, en este caso HolaMundo.exe, en la subcarpeta bin de la carpeta co- rrespondiente al proyecto. Programacién con Visual C# NET Figura 1.7. Resultado de la ejecucién del programa Los proyectos generados con Visual C# .NET tan sdlo pueden ser ejecutados en sistemas donde esté instalada la plataforma Microsoft .NET. Es decir, no puede tomar el archivo HolaMundo.exe, copiarlo a otro ordenador y esperar a que funcione directamente. La plataforma Microsoft NET se encuentra inclui- da en Windows .NET y sera distribuida como un afiadido para las demas ver- siones de Windows. Un vistazo al ensamblado En este caso, a partir del ejemplo anterior, hemos obtenido un ensamblado compuesto de tan sdlo un archivo: el propio ejecutable. Como se ha dicho, el ensamblado no contiene codigo directamente ejecutable sino MSIL, un cdigo intermedio, no es cédigo fuente ni tampoco ejecutable, que es compilado a pos- teriori en un proceso que conocera con mayor detalle en un proximo capitulo. Podemos echar un vistazo al contenido del ensamblado gracias a la existen- cia de la herramienta externa ildasm. Recurra a la linea de comandos usando la opcién Simbolo del sistema de Visual Studio .NET que aparece en el grupo de programas de Visual Studio NET. A continuacién cambie a la carpeta en la que se encuentra el proyecto de ejemplo anterior e introduzca el comando ildasm seguido del nombre del ejecutable, HolaMundo. exe en este caso. Vera apare- cer una ventana similar a la de la figura 1.8, en la que se ha desplegado la rama HolaMundo y el nodo Class1 El ensamblado, HolaMundo . exe, contiene un manitiesto, representado como MANIFEST en la ventana citada antes, y un ambito llamado HolaMundo. En el interior de ese ambito encontramos la clase Class1 que, a su vez, cuenta con un constructor y un método compartido o estatico llamado Main() Haga doble clic sobre el método Main( ). Vera aparecer una nueva ventana con el cédigo MSIL de ese método, un cédigo que, como se ve en la figura 1.9, se asemeja bastante al lenguaje ensamblador. No vamos a entrar en detalles sobre el codigo MSIL ya que no nos interesa en este momento, pero puede ver que es 1. Primera toma de contacto El en- un cédigo bastante compacto que, en total, no llega a ocupar 16 byte: samblado completo, que contiene este cédigo e infermacién adicional, tan sélo ocupa 5 kbytes. MANIFEST HolaMunde Chass} lass vate auto ansibelrtikiit Figura 1.8. Contenido de nuestro primer ensamblado construido con Visual C# NET ¢ void [RscorLiv]systen.STAThreadattribute::.ctor() = ¢ Gt 00 14. (Oxb) “Wo1a mundo” void (mscorLib}systen.Console::WriteLine(string) fy //end OF method C1551: :Hain Figura 1.9. Cédigo MSIL del método Main() Opciones del proyecto Al explorar el contenido del ensamblado hemos visto que hay una clase Ia- mada Class 1. Esta clase esta contenida en un Ambito 0 espacio con nombre de- nominado HolaMunde. Esta claro que el nombre de ese ambito se ha obtenido a partir del nombre de proyecto, nombre que establecimos en el asistente en el Programacién con Visual C# .NET momento de la creacién, traduciéndose en la sentencia namespace HolaMundo que podemos ver al inicio del programa. Por defecto, todos los elementos que se ariadan al proyecto seran anadidos a ese Ambito. Desde la ventana de propiedades del proyecto es posible modificar éstos y muchos otros pardmetros. Para abrir esa ventana pulse con el botén secunda- rio del ratén sobre el proyecto, en la ventana Explorador de soluciones, y se- leccione (véase Ia figura 1.10) la opcién Propiedades. Aparecera una ventana como la de la figura 1.11, estando abierta por defecto la pagina General. En ella se indica el nombre que tendra el ensamblado, el tipo de aplicacién resultante y el nombre del espacio de nombres 0 ambito al que se afiadiran por defecto los nuevos elementos. Figura 1.10. El ment emergente del proyecto nos da acceso a la ventana de propiedades Al ocuparnos del lenguaje Visual C# .NET propiamente dicho profundiza- remos sobre la utilidad y uso de los ambitos con nombre. Puntos clave * Al iniciar Visual C# NET se encontrar con el entorno de desarrollo de Visual Studio .NET, un entorno que estard compartido con otros lengua- jes y herramientas en caso de que no esté usando Visual C# NET, como producto independiente, sino algunas de las ediciones de Visual Studio -NET. * Elentorno de desarrollo puede adecuarse a nuestros conocimientos. Uti- lizando la seccién Mi perfil de la Pagina de inicio podemos establecer la distribucién de teclado, disposicion de la ventana y otros parametros re- lacionados. Hi. Primera toma de contacto © Cada vez que iniciemos Visual C# .NET nos encontraremos con la Pagina de inicio, desde la que podemos abrir un proyecto existente o crear uno nuevo. En el entorno de desarrollo encontramos algunos elementos fundamenta- les, como el Explorador de soluciones, la ventana de Ayuda dindmica o el Cuadro de herramientas. Desde el Explorador de soluciones podemos acceder a los distintos elemen- tos que forman parte de nuestro proyecto, utilizando el ment emergente asociado para manipular esos elementos En la ventana Nuevo proyecto se encuentran los asistentes que usaremos para iniciar los distintos tipos de proyecto que pueden desarrollarse con Visual C# .NET. El resultado de un proyecto Visual C# NET es un ensamblado. Este pue- de componerse de uno o mas médulos, en cuyo interior se aloja el codigo MSIL. Los ejecutables obtenidos con Visual C# .NET no pueden utilizarse direc- tamente en cualquier equipo, es necesario instalar previamente la plata- forma Microsoft .NET. Utilizando la ventana de propiedades del proyecto podemos configurar multitud de opciones, entre ellas el nombre del ensamblado y el del am- bito en el que se van a incluir por defecto todos los elementos que per- tenecen al proyecto. [archivo de pect Carpata de Figura 1.11. La ventana de propiedades del proyecto cuenta con multiples paginas de opciones Programacién con Visual C# NET Resumen Este capitulo nos ha servido para acercarnos por primera vez a Visual C# NET, principalmente el entorno de desarrollo, siguiendo los pasos necesarios para desarrollar una sencilla aplicacién de consola. De manera analoga podria- mos haber creado una aplicacién Windows con un formulario, una aplicacion Web o un componente. El proceso no habria side mucho mas complejo, aunque si los recursos utilizados por el proyecto. Lo importante es que, basicamente, ya sabe qué pasos debe dar para iniciar Visual C# .NET, crear un proyecto, compilarlo y ejecutarlo desde el propio en- torno. Ha usado un método de una clase ya existente y usado una herramienta para examinar el contenido de un ensamblado. En conjunto, todo ello tiene como objetivo hacerle perder un poco el miedo inicial al comenzar a usar una nueva herramienta. En la practica, tiene una base inicial para comenzar a tra- bajar en los proximos capitulos. z EI entorno de desarrollo Los programadores somos usuarios de aplicaciones, en nuestro caso herra- mientas de desarrollo, que, basicamente, cuentan con los mismos elementos que podemos encontrar en cualquier otra aplicacién: ventanas con menus de opciones, barras de botones, ments emergentes, paletas de herramientas, etc. En este sentido, el entorno de desarrollo de Visual C# NET no se diferencia en exceso del que podriamos encontrar en un programa de retoque fotografico, una hoja de calculo o una aplicacién de disefo. La diferencia, obvia, es que nosotros tratamos con elementos relativamente abstractos: disefiamos venta- nas y componentes y codificamos una ldgica de implementacién que queda oculta Para poder hacer nuestro trabajo necesitamos, légicamente, conocer el en- torno en el que vamos a desenvolvernos. En nuestro caso esto significa conocer los elementos del entorno de desarrollo de Visual C# .NET. Ese es el objetivo de este capitulo: indicarle qué elementos son los que puede encontrar y su utili- dad. No se trata de establecer un material de referencia, para eso ya esta la propia ayuda del entorno, sino de descubrir rapidamente los elementos mas importantes y la manera de utilizarlos. Disposicién general El entorno de desarrollo de Visual C# .NET utiliza por defecto un esquema de ventanas adosadas o ancladas unas a otras. Existe un elemento central: la ME 2 Flentorno de desarrollo ventana en la que aparece la Pagina de inicio, los distintos editores de codigo y disenadores visuales. Esa parte ocupa, como acaba de decirse, el espacio cen- tral. Los distintos elementos abiertos aparecen como paginas apiladas unas sobre otras, con una pestana en la parte superior que facilita su seleccion. Aparte de ventanas adosadas unas a otras y ventanas apiladas en forma de paginas, también podemos encontrar ventanas que se ocultan automaticamente, cuando no son necesarias, y aparecen al situar el puntero del ratén sobre la pestafia que contiene su titulo. Las ventanas también pueden quedar como flo- tantes, sin ningtin enlace visual con el entorno. En cualquier caso, todos estos estados pucden alterarse con una simple operacién de arrastrar y soltar 0 un sencillo clic de raton. En la figura 2.1 se indica el estado de algunas ventanas. La parte central esta ocupada por un disefiador de esquemas XML, en la parte superior, y el editor de cédigo, en la inferior. A la derecha aparecen la ventana Explorador de solu- ciones y la ventana Propiedades, adosadas una sobre la otra. En el margen iz- quierdo del entorno, verticalmente, podemos ver dos pestanias que corresponden al Explorador de servidores y el Cuadro de herramientas. Ventanas apiladas Control eculiacion aulomatica \ cael Sea] 744 Bescxspsion brave de cinss:. Ventanas que se autoocultan Ventanas adosadas Figura 2.1. Estado de las ventanas que hay en el entorno Programacién con Visual C# NET Para controlar la ocultacién automatica de las ventanas se usa el boton que aparece en el extremo derecho de la barra de titulo, junto al boton de cierre. Dicho boton simula una chincheta que podemes pinchar, para que la ventana quede fija en su posicién, o bien soltar, para que se oculte automaticamente cuando no esté siendo necesaria. E] botén de ocultacion autematica solo apare- ce en las ventanas que estan adosadas a algtin margen de! entorno, no en las ventanas flotantes. Una ventana que no se oculta automaticamente permanece siempre adosada aun margen de la ventana principal de Visual C# NET, no siendo posible mo- dificar este estado hasta en tanto no desactivemos la propiedad de ocultacion automatica, En ese momento, podemos tomar la ventana, con el boton princi- pal del raton, y arrastrarla por el entorno hasta una nueva localizacisn. Si to- mamos la ventana pulsando sobre su barra de titulo desplazaremos todo el conjunto, en caso de que haya multiples ventanas apiladas en paginas. Si tan solo quiere operar sobre una de ellas, en lugar de la barra de titulo pulse sobre la pestaa que representa a esa ventana A medida que vaya arrastrando la ventana sobre el entorno, un borde dina- mico le iré mostrando cémo quedaria si la soltase en ese momento. Pruebe a acercar el puntero del ratén a los margenes de la ventana principal, les de otras ventanas ya adosadas o flotantes o la barra de titulo de esas ventanas. La ven- tana arrastrada quedara adosada al margen o apilada como una nueva pagina, segtn los casos. Si libera la ventana lejos de cualquier margen conseguira que quede como flotante. Las paginas que ocupan el area central del entorno, en la que aparecen di- sefiadores, editores y el navegador Web, aunque pueden adosarse unas a otras, en lugar de aparecer todas apiladas en forma de paginas, no pueden quedar flotantes. Recurra a las opciones del ment emergente, pulsando el botén se- cundario del raton sobre cualquiera de las pestanas, para conseguir un efecto idéntico sin necesidad de arrastrar y soltar Usando la ventana de opciones del entorno, que conocer posteriormente, es posible cambiar el mecanismo de funcionamiento de las ventanas de Visual C# .NET de tal manera que en lugar de aparecer ancladas unas a otras, que es la opcién por defecto, se ajusten al funcionamiento tipico de una aplicacién MDI (Multiple Document Interface), con una ventana prin- cipal conteniendo las ventanas hija de editores y disefiadores, Soluciones y proyectos Los distintos elementos que se ulilizan en Visual C# .NET para desarrollar aplicaciones: formularios, recursos, codigo, etc., se agrupan de manera jerar- quica en varios niveles. La raiz, 0 el nodo principal, es la selucion, que puede Bo > Ef entorno de desarrotto contener uno 0 mas proyectos. En cada proyecto existiran formularios, contro- les, definiciones de clases, referencias externas, etc. Mediante el Explorador de soluciones podemos gestionar todos esos elementos. El Explorador de soluciones aparece inicialmente, asumiendo que estamos utilizando la configuracién por defecto de Visual C# .NE'T, en la parte superior derecha del entorno. Si no lo ve, puede hacerlo aparecer mediante la combina- cién Control-Alt-L. También puede usar la opcién Explorador de soluciones del menti Ver consiguiendo el mismo resultado. En la figura 2.2 puede ver esta ven- tana con los elementos de una aplicacién Windows simple. Los menus emer- gentes son los que corresponden al proyecto. [Mebane SF wesc eee Figura 2.2. Ventana del Explorador de soluciones Como puede ver, la solucién aparece como primer elemento de la ventana, eneste caso contando con tan sélo un nodo: el proyecto WindowsApplicationl. I'ste dispone de una carpeta de referencias y dos médulos. Fl llamado Form1.cs corresponde al formulario existente en el proyecto. Haciendo doble clic sobre cualquiera de estos elementos lo abriremos en su respective editor o disefador También puede usar los dos primeras botones que hay en la parte superior de la ventana, contando de izquierda a derecha, para acceder al cédigo o al di- senador del elemento seleccionado en ese momento. Usando el menu emergente asociado a cada elemento es posible realizar di- versas tareas. Si pulsa el boton secundario del ratén sobre un proyecto, por ejemplo, podra generarlo, eliminarlo, cambiar el nombre, anadirle nuevos ele- mentos 0 nuevas referencias Cada uno de los elementos que aparece en el Explorador de soluciones se al- macena en un archivo con una determinada extension y formato. La solucion, Programacion con Visual C# NET que relaciona a los demas elementos, se aloja en un archivo de texto con ex- tension s1n. Los proyectos, dependiendo del lenguaje, se almacenan en archi- vos con extensiones diversas, En cl caso de Visual C# la extension es csproj, siendo su contenido XML. Algo similar ocurre con los médulos de codigo y correspondientes a formularios, cada uno de los cuales se escribe en un archi- vo con extensién que identifica el lenguaje. Eche un vistazo a la carpeta del proyecto creado en el capitulo previo para ver los distintos archivos generados, También puede seleccionar un ele- mento cualquiera en el Explorador de soluciones y ver el camino y nombre del archivo correspondiente en la ventana Propiedades. istentes en un médulo s soluciones, los proyectos y las carpetas actuan como contenedores que permiten clasificar los médulos de tiltimo nivel. Estos contienen definiciones de clases, por ejemplo asociadas a un formulario, un componente o un servi- cio. Este cédigo siempre podemos verlo en el editor de texto. En algunas oca- siones también es posible utilizar un disefiador con la finalidad de modificar indirectamente ese cédigo, por ejemplo cuando el médulo corresponde a un formulario. En un médulo pueden existir ambitos con nombre, definiciones de clases, propiedades, métodos y eventos, entre otros elementos. Mediante la ventana Vista de clases podemos obtener un esquema jerarquico de todos esos elemen- tos, lo cual simplifica su localizacién y manipulacién. Esta ventana, que puede ver en la figura 2.3, se hace aparecer con la combinacién de teclas Control- Mayus-C 0 la opcion Ver>Vista de clases. Bg cloves TO tacac winter ces 2g Ob a0 nist Figura 2.3. Ventana Vista de clases | 2. El entorno de desarrollo Los elementos que aparecen en la figura 2.3 son los que existen en el proyec- to HolaMundo desarrollado en el capitulo previo. Existe un ambito con nom- bre, llamado precisamente HolaMundo, en cuyo interior esta la clase Class1. Esta, a su vez, cuenta con un método: Main(). Si el proyecto fuese mas com- plejo, por ejemplo una aplicacion Windows con formularios, podriamos acce- der con esta ventana a sus propiedades y métodos asociados a eventos. Utilizando las opciones del ment emergente asociado a cada uno de estos elementos, que haremos aparecer con el botén secundario del ratén, podremos anadir nuevas clases al proyecto, nuevos miembros a las clases, acceder a la definicion del elemento, mostrarla en el Examinador de objetos, etc. Son opcio- nes que, en su mayoria, se encuentran en el menti principal del entorno, pero que resulta mucho mas comodo usar desde el ment emergente. En la esquina superior izquierda de la ventana Vista de clases hay un botén que, al ser pulsado, despliega un menu de opciones. Con ellas puede alte- rar el orden en que aparecen los elementos en la lista jerarquica. Examinando clases y otros elementos Una de las ventanas que no estan visibles inicialmente en el entorno es el Examinador de objetos, que puede ser muy util para obtener informacion diver- sa sobre los elementos que forman parte de la aplicacién y también los que te- nemos a nuestra disposicion por ser servicios de la plataforma Microsoft .NET. La combinacion de teclas a usar en este caso es Control-Alt-J. Tambien pue- de utilizar la opcién Ver>Otras ventanas>Examinador de objetos para mostrar la ventana que se ve en la figura 2.4 ocupando practicamente todo el espacio disponible en el entorno. Como se aprecia, la ventana cuenta con dos paneles claramente diferenciados. A la izquierda tenemos la lista de objetos, mientras que a la derecha esté la lista de miembros. Aparte de poder ver los elementos que forman parte de Ja aplicacion y sus miembros, como en la ventana Vista de clases, en el Examinador de objetos podemos acceder también a otros ambitos y clases. En la figura 2.4, por ejem- plo, se esta examinando la lista de miembros de la clase Application, defini- da en el ambito System.Windows.Forms. El miembro seleccionado, en la lista de la derecha, es ProductName y, segun se indica en la parte inferior, es una propiedad de tipo String que puede sélo leerse Acceso a los asistentes El Explorador de soluciones y la ventana Vista de clases nos permiten cono- cer y manipular los elementos que existan actualmente abiertos en el entorno: Programacién con Visual Ct .NET proyectos, formularios, clases, métodos, etc. Esos elementos son creados, por regla general, mediante el uso de diversos asistentes. Al pulsar el botén Nuevo proyecto, o seleccionar ciertas opciones de los menus emergentes de las cita- das ventanas, estamos abriendo esos asistentes. Figura 2.4. El Examinador de objetos aparece como una pagina mas, al mismo nivel que disefiadores y editores La mayoria de las opciones que hay en la ventana Nuevo proyecto son asis- tentes que generan un nuevo proyecto, ya sea afiadiéndolo a la solucion actual © bien creando una nueva solucién. Estos asistentes, por regla general, no necesitan ninguna informacién adicional aparte del nombre del proyecto, por- que son lo suficientemente especificos como para saber qué elementos tienen que aftadir al proyecto. En algunos casos, no obstante, si puede ser necesaria esa intervencién. Es lo que ocurre al crear un nuevo proyecto de base de datos © de instalacién. En el primer caso podremos elegir una referencia a una base de datos, 0 bien crearla en ese momento, en la ventana de la figura 2.5. En el segundo, al crear un proyecto de instalacion, aparece un asistente de varios pa- sos (vease figura 2.6) que nos guia en el proceso que finalmente anadira los elementos que se ajusten a nuestras preferencias. En los ments emergentes de muchas ventanas, como Vista de clases o Ex- plorador de soluciones, existen opciones que dan paso a asistentes para ahadir nuevos elementos generando automaticamente el cédigo, o un esqueleto, ba- sndose en los datos que introduzcamos. 2. El entorne de desarrollo Etija.un ipa de proyecto de Brpect detamine dénde y cro 20 ean los archives en 2 ‘etn. Figura 2.6. Asistente para crear un proyecto de instalacion Desde el Explorador de soluciones, teniendo seleccionado un proyecto, pue- de usar las opciones del meni emergente para afiadir un nuevo formulario, una nueva clase, un nuevo componente, etc. En todos los casos se crea un nuevo médulo de cédigo correspondiente al elemento afadido. Son opciones que también puede encontrar en el ment Proyecto de la barra principal de menus. Tanto en el menu emergente como en el citado ment Proyecto existe una opcion, llamada Agregar nuevo elemento, que da paso a la ventana mos- trada en la figura 2.7. En ella aparecen, clasificados por tipos, todos los ele- mentos que es posible afiadir al proyecto. Algunas opciones simplemente afiaden un archive al proyecto mientras que otras, como el Asistente para formularios de datos, realizan tareas considerablemente mas complejas, conectando con una base de datos, definiendo el conjunto de columnas y filas sobre las que va a operarse y disenando una interfaz de usuario para ello. Ademias de asistentes, en el menu de opciones de Visual Studio .NET encon- traremos multiples herramientas mediante las que se pueden anadir referencias Programacién con Visual C# NET al proyecto actual, generar paginas HTML con informacién sobre dicho proyec- to, etc. Figura 2.7. Opciones de la ventana Agregar nuevo elemento Disenadores y editores Las clases, los formularios, las paginas HTML, los archivos XML y, en ge- neral, todos los elementos que se generan a partir de asistentes y opciones de Visual C# .NET deben ser personalizados, anadiendo los objetos precisos para que la aplicacién final desarrolle la funcién que se espera de ella. Con este fin utilizaremos disefiadores y editores diversos, asi como los elementos que apa- recen en el Cuadro de herramientas. Desde el Explorador de soluciones es posible acceder al disefiador y/o edi- tor del elemento que se tenga seleccionado en ese momento. Con este fin se uti- lizan los botones resenados en la figura 2.8. El segundo, que se usa para abrir el disehador que corresponda, sélo aparece en caso de que el elemento seleccio- nado tenga asociado un disefiador. Figura 2.8. Acceso al editor 0 disefiador asociado a un elemento del proyecto J 2. El entorno de desarrollo El editor utilizado es siempre el mismo, si bien su funcionalidad se adapta al tipo de archivo sobre el que se esté trabajando. Los disefiadores, por el con- trario, son especificos y facilitan tareas tan diversas como el disefio de una in- terfaz de usuario Windows o Web, el disefio de un esquema XML, ete Diseno de formulario: Hasta ahora no ha utilizado ningtin disefiador de Visual C# NET y, como supondra, uno de los mas utilizados es el que nos permite disefiar formularios para aplicaciones Windows. Su funcionamiento es similar al usado para crear interfaces Web ya que, fundamentalmente, su finalidad y comportamiento son practicamente idénticos. En el diseriador de formularios Windows el contene- dor es una ventana, mientras que en el de formularios Web dicho contenedor es una pagina HTML. Inicie un nuevo proyecto seleccionando el elemento Aplicacién para Windows de la ventana Nuevo proyecto. Tras un momento se encontrara con un formula- rio, con el titulo Form1 en la parte superior, y una importante lista de controles en el Cuadro de herramientas. Puede seleccionar algunos controles, pulsando sobre ellos con el boton principal del ratén, e insertarlos en el formulario efec- tuando la misma operacién en la posicién donde desee colocarlos. Lagicamen- te tiene que hacerlo uno a uno, es decir, no puede seleccionar simultaneamente varios controles. Ademas de componentes visuales, como las etiquetas de texto, las cajas de texto o los botones, existen otros, por el contrario, que son componentes no vi- suales. Si inserta en un formulario un componente ToolTip o un ImageList, por poner dos ejemplos, vera que el disenador los muestra aparte, en la parte inferior (véase la figura 2.9), pero no en el interior del formulario. A medida que vamos insertando componentes en el contenedor, indepen- dientemente de donde aparezcan, el disefiador se encargara de actualizar ade- cuadamente el cddigo. Al insertar un botén, por poner un ejemplo, el diseriador generara el codigo C# 0 HTML para completar la definicién de la clase o pagi- na, segtin el caso, con la declaracion de ese botén. De manera analoga, al modi- ficar sus dimensiones 0 posicién, es el disefiador quien actualiza ese cédigo Mediante el disenador de formularios podemos mover los componentes, cambiar su tamaiio y acceder a las opciones de su menu emergente. Por si solo, no obstante, nos seria de poca utilidad. Para completar su trabajo son funda- mentales las ventanas Propiedades y Cuadro de herramientas. Edicion de propiedades Como acaba de decirse, uno de los elementos indispensables al trabajar con un disenador es la ventana Propiedades. En realidad esta ventana tiene mas funciones, ya que puede utilizarse también para acceder a las propiedades de cualquier elemento que haya seleccionado en el Explorador de soluciones, a pesar de que no haya abierto un disefiador ee 57 | ovo “| Figura 2.9. El disefiador muestra los componentes dentro o fuera del formulario seguin su tipo La ventana Propiedades es muy parecida a la que encontramos en Visual Basic 6.0. En la figura 2.10 puede ver indicados algunos de los elementos de la mencionada ventana, particularmente la finalidad de cada uno de los botones que aparecen en su parte superior. La lista de propiedades puede aparecer ordenada por categorias, es la op- cién por defecto, o bien alfabéticamente. Se altera este orden con los dos pri- meros botones. El siguiente botén se utiliza para mostrar la lista de propiedades, que es el estado por defecto. En la parte inferior aparece una pequeiia descrip- cién de la propiedad seleccionada en ese momento, correspondiente al compo- nente que se muestra en la lista desplegable que hay justo debajo del titulo de la ventana. Cada entrada de la lista que ocupa la parte central de la ventana se compo- ne de dos elementos: el nombre de la propiedad y su valor actual. El valor de una propiedad depende de su tipo, puede ser una cadena de caracteres, un nit- mero, un valor de una enumeracién, un color o incluso un objeto. Las propiedades y los métodos son miembros de un objeto, concretamente del componente seleccionado. En un capitulo posterior aprender a definir este tipo de miembros. Cada miembro, propiedad o evento, tiene un nombre estati- co, el cual no podemos alterar, y un valor que suele ser dinamico y podemos B22. El entorno de desarrollo modificar de distintas formas, dependiendo del tipo de la propiedad. Propieda- des como Text o Name, por ejemplo, almacenan una cadena de caracteres, un valor que, en la ventana Propiedades, se modifica utilizando el teclado, como hariamos en un editor cualquiera. Nombre del componente Clase de! componente ra Acceso ala pagina de eventos. Propiedades Orden por categorias Orden altabético ~ Nombre de la propiedad — Valor de la propiedad Descripeion de la propiedad Figura 2.10. Elementos de la ventana Propiedades Otras propiedades, por el contrario, muestran directamente una lista de los valores que pueden contener 0, incluso, un editor especifico. Vea la figura 2.11, en la cual aparece, en la parte superior, la lista de valores que puede tomar la propiedad DialogResult. En este caso no hay que introducir el valor usando el teclado, basta con desplegar la lista y seleccionar uno de los disponibles. Mas abajo puede ver el editor de la propiedad Dock. Dicha propiedad deter- mina si un componente se adosara en una cierta posicién de su contenedor y, en lugar de seleccionar un valor, el editor muestra graficamente las posibilida- des disponibles. Cada evento de un componente puede tener asociado el nombre de un mé- todo que, como ya sabe, sera ejecutado cuando el suceso representado por el evento tenga lugar. La lista de eventos de un cierto objeto aparece como una segunda pagina de la ventana Propiedades. En la figura 2.12 puede ver la lista de eventos del boton que hay en el formulario. Haciendo doble clic sobre cual- quiera de ellos se generara el cédigo correspondiente para poder gestionarlo. Para ello se completara la definicion de la clase con un nuevo metodo, situan- dose el cursor en el punto adecuado para introducir la implementacion Programacién con Visual Ce .NET [ER A | sae serie Coan de be ‘Static vod mainly i Application. Ran new Forma () | private void button Click|objeer sender, System.bvent Figura 2.12. Edicion de los eventos de un componente BH 2 Elentorno de desarrollo Componentes y controles Tanto la ventana Propiedades como el propio disefiador de formularios se usan para modificar objetos 0 componentes, elementos que podemos encon- trar, en su mayor parte, en la ventana Cuadro de herramientas. El Cuadro de herramientas dispone de multiples paginas, cada una de las cuales contiene un grupo de componentes. Existen componentes genéricos, que pueden utilizarse indistintamente del tipo de proyecto que esté desarrollandose, y otros mucho mas especificos. Los componentes de acceso a datos, por ejemplo, son del pri- mer tipo y cuentan con su propia pagina, mientras que los usados en formula- rios Windows 0 Web son especificos del tipo de aplicacién. Mediante el menu emergente asociado al Cuadro de herramientas podemos, como se aprecia en la figura 2.13, modificar el orden en que aparecen los ele- mentos, cambiar el modo de visualizacion entre Lista, el modo por defecto, y una vista simple de iconos, sin nombres de componentes. Tambien es posible modificar los nombres de los componentes, aunque no es algo habitual en los componentes originales, y afiadir mas fichas 0 paginas a esta ventana. En la parte inferior puede ver una ficha llamada Mis trozos de codigo, afiadida con el fin de alojar en ella porciones de codigo a usar en multiples proyectos Figura 2.13. El Cuadro de herramientas y su ment emergente Para cambiar de una pagina a otra tan solo hay que pulsar en los titulos que, a modo de botones, pueden verse en la parte superior e inferior, encima y de- bajo, respectivamente, de la lista de componentes que ocupa la parte central. Si ésta contiene mas elementos de los que es posible mostrar de una sola vez, tam- bién vera aparecer en el extremo derecho, arriba y abajo, sendos botones en for- ma de flecha que facilitan el desplazamiento. Programacion con Visual C# .NET Aparte de tomar componentes y controles del Cuadro de herramientas para colocarlos en el interior de un contenedor, este elemento también puede utili- zarse en sentido inverso. Teniendo marcado en el editor cualquier porcién de cédigo, mediante la técnica de arrastrar y soltar podemos alojarlo en la pagina que nos interese del Cuadro de herramientas y darle un nombre. Posteriormen- te, cuando lo necesitemos, podemos recuperar esa porcién de cédigo de igual forma. Podriamos decir que el Cuadro de herramientas puede utilizarse como un portapapeles persistente, que no pierde su contenido al desconectar y vol- ver a iniciar, y clasificable. Disenadores adicionales Aparte del disefador de formularios Windows y formularios Web, Visual C# NET dispone de otros muchos que facilitan la creacién de esquemas XML, pa- ginas HTML, la estructura de conjuntos de datos, imagenes de mapas de bits, iconos y cursores, etc. Cada uno de ellos tiene sus particularidades, si bien hay similitudes, por ejemplo, entre el disenador que se utiliza para los esquemas XML y el usado para la estructura de conjuntos de datos, o entre el diseniador de mapas bits y el de iconos. En la figura 2.14 puede ver el disefiador de esquemas XML mostrando un esquema recién creado. Todas las opciones necesarias para afadir elementos, atributos, claves y relaciones se encuentran en el menti emergente asociado a cada objeto de los que aparece en el disefiador. Usando el botén que hay en la parte inferior del disenador podemos acceder al cédigo XML, ya en el editor que revisaremos en el punto siguiente. El editor de paginas HTML es similar al de formularios Web, si bien los com- ponentes que podemos incluir, alojados en una pagina distinta del Cuadro de herramientas, no son componentes ASP.NET sino componentes HTML puros. Mediante el editor que aparece en la figura 2.15 se facilita la edicién de cual- quier tipo de imagen que pudiéramos necesitar en el proyecto, ya sea un gra- fico para el fondo de la ventana, un icono o un cursor. En la parte superior del diseniador aparecen las distintas herramientas que es posible utilizar para, por ejemplo, dibujar lineas, borrar, insertar texto, etc. En lugar de usar el disenador de imagenes de Visual C# .NET, puede uti- lizar cualquier aplicacién externa, mas especializada, y a continuacion im- portar el archivo en la solucién mediante las opciones del menu emergente. El editor de codigo Los formularios Windows, los formularios Web, las paginas HTML, los es- quemas XSL, los documentos XML y, en general, si exceptuamos el caso de las 2. El entorne de desarrollo ——$<—$—$————————————— SS imagenes, todos los elementos manipulados visualmente mediante disenadores. son la representacién de un eddigo. Ese codigo puede, en el caso de los formu- larios Windows, estar escrito en distintos lenguajes, mientras que en los docu- mentos XML, XSL o HTML el lenguaje sera, l6gicamente, XML y HTML. “s mee Pons dena | anna deco | Fart. [oto AAS sd | Figura 2.14. El disefiador de esquemas XML El editor de cédigo es siempre el mismo, si bien su comportamiento se adap- ta al tipo de documento sobre el que esta trabajandose. Los distintos elementos sintacticos del documento se diferencian utilizando colores y estilos. Las listas desplegables y ventanas flotantes ofrecen informacion sobre los miembros y pardmetros de cada elemento a medida que va escribiéndose. En la figura 2.16, por ejemplo, puede ver cémo al editar un documento XML, basado en el es- quema de la figura 2.15, el editor, al introducir el simbolo de apertura de mar- ca, automaticamente nos muestra las que podemos utilizar en ese mbito. Aparte de los elementos indicados, dependiendo del tipo de documento tam- bién notara diferencia en los botones que aparecen justo encima del editor. Al trabajar con un documento XML tenemos botones para verificar la validez del documento o mostrarlo en el explorador. Esta barra de botones es diferente cuando, por ejemplo, esta editandose el eddigo C# de un formulario Windows El editor de cédigo de Visual C# .NET se usa como cualquier editor de texto, utilizando las mismas teclas y combinaciones de teclas para desplazarse carac- ter a caracter, palabra a palabra, linea a linea, pagina a pagina, etc. Utilizaremos las mismas combinaciones para copiar, pegar, eliminar, etc. También puede Programacion con Visual C# .NET utilizar el ratén y sus botones para seleccionar porciones de texto y, mediante operaciones de arrastrar y soltar, efectuar cambios. Figura 2.15. Aspecto del disefiador de imagenes de mapas de bits Ademas de esta funcionalidad basica, el editor de Visual C# .NET también dispone de comandos que simplifican la aplicacién de formato al cédigo, por ejemplo sangrandolo adecuadamente u ocultando estructuras como los méto- dos o las clases para facilitar una vista esquematica del contenido. Al efectuar operaciones con el portapapeles podemos utilizar las habituales combinacio- nes de tecla, pero también recurrir al anillo del portapapeles que aparece en el Cuadro de herramientas. Si bien la funcién principal del editor de cédigo es, como su propio nombre indica, permitir la edicién de archivos de codigo, mediante las opciones exis- tentes en el mend contextual puede utilizarse este mismo editor para controlar algunos aspectos de la depuracién del proyecto. Otras herramientas Los editores y disefiadores, conjuntamente con la ventana Propiedades y el Cuadro de herramientas, son los elementos que podriamos considerar basicos del entorno, puesto que resultan indispensables para realizar nuestro trabajo: 2. El entorno de desarrollo desarrollar aplicaciones. No son, sin embargo, los unicos elementos, hay otros muchos y, légicamente, todos ellos son utiles. Figura 2.16. Edicién de un documento XML. Algunas de las ventanas que van a mencionarse a continuacién no estan vi- sibles en principio. Tendra que utilizar la correspondiente opcién del menu Ver o del submenti Ver>Otras ventanas para hacerlas aparecer. El Explorador de servidores Al desarrollar una aplicacién podemos necesitar componentes adicionales, no disponibles en el Cuadro de herramientas, como puedan ser conexiones con bases de datos, colas de mensajes y otros servicios que haya instalados en el sistema. En lugar de utilizar una herramienta externa, o escribir el codigo ne- cesario para acceder a esos servicios, podemos servirnos del Explorador de ser- vidores. Esta ventana aparece, inicialmente, en el margen izquierdo del entorno de Visual C# NET, pero ya sabe que puede recurrir al ment de opciones para hacerla aparecer. En la ventana Explorador de servidores encontraremos, en principio, dos ele- mentos: Conexiones de datos y Servidores. El primero de ellos actua como raiz de todas las conexiones de datos que podamos tener definidas, mientras que el segundo es la raiz de los servidores, ordenadores, a los que tengamos acceso. Programacién con Visual C# NET La lista de conexiones de datos en principio estara vacia, mientras que en la de servidores aparecera el ordenador local. Usando las opciones del menti emergente de cada nodo podremos definir nuevas conexiones de datos, asi como registrar otros servidores que pueda ha- ber en nuestra red para asi acceder a sus servicios. También puede utilizar con este fin dos de los botones que hay en la parte superior de la ventana, concreta- mente los que tienen un signo + junto al icono de una base de datos y un orde- nador. Desplegando una conexién de datos podra acceder a los distintos elemen- tos que haya en la base de datos: tablas, vistas, procedimientos almacenados, etc. Andlogamente, abriendo la rama de un servidor tendremos acceso a sus servicios: colas de mensajes, servidores de datos y servicios de informes entre otros. En la figura 2.17 puede ver abiertas las dos ramas mostrando una co- nexi6n de datos y los servicios del sistema local. Usando la técnica de arrastrar y soltar puede insertar en el disefiador cualquiera de los elementos mostrados en el Explorador de servidores, creando adaptadores de datos, informes 0 con- troladores de servicios. Figura 2.17. Ventana del Explorador de servidores Tareas pendientes Otro de los elementos nuevos del entorno de Visual Studio .NET, inexisten- te en versiones previas, es la lista de tareas. En dicha lista aparece informacién recogida del cédigo de los diferentes médulos que componen el proyecto. Cada vez que se encuentra un comentario que comienza por las palabras TODO, HACK 0 UNDONE el comentario es tratado como una entrada de la lista de tareas, ex- trayéndose su localizacién, estado, persona responsable, prioridad, etc. Tam- bién aparecen en dicha lista otros elementos, por ejemplo mensajes de error por fallos en el cédigo. Los elementos que aparecen en la Lista de tareas, cuyo aspecto por defecto puede ver en la figura 2.18, y su orden, dependen de las opciones que se hayan 2. El entorno de desarrollo seleccionado en el meni Ver>Mostrar tareas. También es posible usar el menti emergente, como se aprecia en la citada figura, para seleccionar la lista de ta- reas a mostrar. Igualmente, podemos modificar el orden con tan solo pulsar en el encabezado de una de las columnas Hig ce aripars agregar uns eva ares ‘TODO; Actulew ls rleneriacin lesgquens activo no ednte ol lento Figura 2.18. Aspecto de la Lista de tareas Partiendo de la lista de tareas, basta un doble clic sobre cualquiera de los ele- mentos para acceder al punto exacto del codigo en el que se espera la accion. De esta forma es mucho més facil Hevar un control de los trabajos pendientes que hay en el proyecto. La ventana de comandos Visual Studio .NET cuenta con un entorno totalmente configurable, en el que cada uno de los objetos que ve puede ser utilizado programaticamente, desde cédigo, de la misma manera que hariamos con cualquier otro objeto de una aplicacion. Mediante la Ventana de comandos (véase la figura 2.19) es posible utilizar esos objetos para, de manera interactiva, efectuar cualquier operacion que deseemos. Es posible, por ejemplo, iniciar un nuevo proyecto o abrir un archivo sin necesidad de recurrir a las opciones del ment de Visual Studio NET. La Ventana de comandos resulta interesante si vamos a programar macros © crear proyectos de aiiadidos para el entorno de Visual Studio NET, ya que nos permiten comprobar el funcionamiento de los distintos objetos que forman parte de ese entorno de manera directa. También sera util durante la depura- cian de una aplicacion para, por ejemplo, comprobar 0 modificar el valor de una variable o ejecutar en modo intérprete cualquier sentencia que pudiera interesarnos. Programacion con Visual Ct .NET Figura 2.19. Introducimos una orden en la Ventana de comandos La ayuda de Visual C# .NET Visual Studio .NET es un entorno de cierta complejidad en el que podemos utilizar multiples lenguajes, entre ellos Visual C# .NET, infinidad de compo- hentes y, por supuesto, todos los servicios disponibles en la plataforma Microsoft .NET. Cada uno de estos elementos cuenta con su respectiva ayuda, recurso indispensable para poder aprovechar todas sus posibilidades. Todas las opciones relativas a la ayuda las encontraré en el menu del mismo nombre. Desde él podra acceder a la tabla de contenidos, buscar una cierta pa- labra clave, establecer filtros, etc. La ayuda se muestra, por defecto, como una pagina mas en el area de contenido del entorno, igual que lo haria un disefiador 0 el editor de cédigo. Una novedad, relativa a la ayuda, es la existencia de la ventana Ayuda dina- mica, que puede ver en la parte inferior derecha de la figura 2.20. Si mantiene abierta esta ventana vera que, a medida que introduce cédigo, selecciona com- ponentes © abre ventanas, aparece una lista de temas de ayuda relacionados con el contexto en el que se encuentre. Légicamente, puede seguir utilizando la tecla Fl para acceder a una ayuda sensible al contexto, pero la ventana Ayuda dinamica siempre aporta mas informacion. Con las opciones del menu Ayuda también puede acceder al servicio técnico de Microsoft, asi como obtener informacion relativa a la version concreta de Visual C# NET 0 Visual Studio .NET que esté usando, los lenguajes y herramien- tas instalados, etc. En la figura 2.21, por ejemplo, puede ver que el entorno de desarrollo es la versién 7.0.9500 y que, aparte de Visual C# .NET, también es- tan disponibles Visual Basic NET, Visual C++ .NET, Crystal Reports para Vi- sual Studio .NET y Application Center Test. Adaptacion del entorno El entorno de Visual C# .NET es personalizable y automatizable, de tal ma- nera que podemos adaptarlo a nuestras preferencias haciendo mas faci pido nuestro trabajo habitual. Al principio del capitulo se indieé cémo modificar la disposicién y comportamiento de las ventanas, con las cuales tenemos que BH > Elentorno de desarrollo trabajar continuamente, y poco mas. En este punto nos ocuparemos con mayor ion de este entorno. detalle de la personaliza smesrere Supane une U8 cesrestencnee alo, moderna, preporcina Segutied de apes y ests aientade ‘hjetoe El tig creas medina Ce se comple tore codigo 15M cota a datos . icin do de Common 2 Programa concn 5) Retoonca fengus + Leroi Yous ‘or compatibilidad entre versiones. 4e prover 0, un modele do abjetos 9 ea. desarrollo. La biblioteca pare prot Vlual G# es NET Framework En esta seccién Ler SE acido y vetajaé de uso ge Ce. incure el Mapa dela documentacién y une Comparacién entre Cit y Cf, te ST opines de corspilador de CB yl errors de ‘senetar dese la linea fgeneracion. incuye informacion acerca de cémmo Oregar archives, dases, métodos, propiedades y otros tlementos a los proyectos. aoe reine et del lengusie Figura 2.20. La ayuda de Visual Studio NET Recuerde que mediante el apartado Mi perfil de la Pagina de inicio puede se- leccionar una configuracién por defecto para la disposicién de las ventanas y las combinaciones de teclado. Partiendo de esa configuracién por defecto, sin embargo, podemos efectuar los cambios que consideremos oportunos. Recuerde que puede hacer aparecer la Pagina de inicio mediante la op- cién Ver>Explorador Web>Inicio del mend principal. Opciones del entorno El entorno de Visual Cf .NET no sélo se compone de ventanas que, como aca- bamos de ver, podemos situar donde mas nos convenga y cuyo comportamiento podemos personalizar, también hay otros elementos y muchas opciones para configurarlos. Todas esas opciones aparecen en la ventana que se muestra en la figura 2.22, ala que puede acceder mediante la opcion Herramientas>Opciones. Programacién con Visual C# NET [J ik hoe oer Oe Figura 2.21. Informacion sobre el entorno de desarrollo y herramientas instaladas Figura 2.22. Ventana con opciones generales del entorno La lista que hay a la izquierda muestra multiples carpetas con elementos, cada uno de los cuales corresponde a un conjunto de opciones que aparecen en el espacio que hay a la derecha. Como puede ver, la lista es bastante extensa y, de acorde con ello, el numero de opciones muy importante. Con ellas puede practicamente personalizar cualquier elemento: los estilos y colores que se uti- lizan para realzar la sintaxis en el editor de codigo, las combinaciones de teclas asociadas a opciones y acciones, las palabras clave que reconoceré la lista de tareas, etc. Tal y como se aprecia en la parte inferior de la figura 2.22, siempre El entorno de desarrollo tenemos a nuestra disposicién el boton Ayuda con la finalidad de poder apren- der mas sobre el significado 0 la utilidad de las opciones que aparecen en la ventana. En la parte superior de la pagina General de la carpeta Entorno, que es la que aparece abierta por defecto, encontramos unos botones que nos permiten alter- nar entre los dos mecanismos posibles de distribucién de las ventanas del en- torno: utilizando ventanas adosadas 0 ancladas, que es el modo por defecto, 0 bien usando un entorno clasico MDI. Puede seleccionar la opcién Entorno MDI y reiniciar el entorno para ver la diferencia. Configuraci6n de botones y ments En la parte superior del entorno de Visual C# NET aparecen varias paletas de botones que facilitan el acceso rapido a las opciones més habituales, asi como un menti donde se encuentran practicamente todas las opciones disponi- bles. Las paletas de botones cuentan con un asa, en el extremo izquierdo, de la cual podemos tomarlas para Ilevarlas a cualquier otro punto, disponiéndolas horizontal o verticalmente en los margenes del entorno o bien dejandolas como ventanas flotantes La configuracién de las paletas de botones no es estatica, podemos tanto ocultar como mostrar paletas de botones, asi como modificar los botones con- tenidos en ellas. [gual ocurre con los mentis de Visual C# NET. Seleccién de paletas visibles Inicialmente, en el entorno de Visual C# .NET tan solo aparecen dos de las paletas de botones que hay disponibles. La primera de ellas, conocida como Estandar, aloja los botones que nos permiten guardar y abrir archivos y proyec- tos, efectuar las habituales tareas de edicién y acceder a ventanas de uso in- tensivo como el Cuadro de herramientas o la ventana Propiedades. La segunda paleta, conocida como Web, cuenta con los botones tipicos de exploracion que, por ejemplo, a la hora de acceder a la ayuda nos permiten ir hacia atras y ade- lante, modificar el tamafio de letra, ete. Aparte de estas dos, Visual C# .NET cuenta con al menos veinticinco pale- tas mas. Puede acceder a ellas pulsando sobre las paletas de botones visibles con el botén secundario del ratén. Se desplegara un menu como el que vemos en la figura 2.23, en el que puede marcar y desmarcar las paletas que desea hacer visibles. Como puede ver en esa figura, hay paletas de botones especifi- cas para el trabajo con archivos HTML 0 XML, edicién de imagenes, diseiio de datos, etc. Lo normal es que activemos tan solo las barras de botones que necesitemos en cada momento ya que, de lo contrario, no tendriamos espacio suficiente en pantalla a menos que contemos con un monitor con mucho espacio de visuali- zacion y trabajando con una resolucién relativamente alta. En la figura 2.24 puede ver como queda el entorno de Visual Studio .NET tras activar todas las paletas de botones disponibles en principio. Programacién con Visual Ct NET Ty were Centre ideo hante crt gs et crt ag -rry | ser aay Scr Beate Oia de cos tet d cto de gn | kore mires ferdetra fore, smema mt Figura 2.23. Menu para mostrar/ocultar paletas de botones Una alternativa, a la hora de mostrar y ocultar barras de botones, consiste en utilizar la opcién Personalizar que aparece al final de la figura 2.23, abrien- do la ventana de personalizacién de opciones de menti y botones. Esta ventana dispone de tres paginas diferentes, abriéndose por defecto la llamada Barras de herramientas. En ella, como se aprecia en la figura 2.25, existe una lista en la que aparecen todas las paletas de botones y podemos marcar y desmarear para mostrarlas u ocultarlas, respectivamente. Anadir y eliminar botones Como acaba de decirse, en las paletas de botones tan sélo aparecen represen- tadas las operaciones que se utilizan de manera mas o menos frecuente. Esta configuracién, sin embargo, puede depender en parte del usuario de la herra- mienta, ya que no todos seguimos los mismos pasos para efectuar un cierto trabajo. Por ello, es posible tanto quitar botones existentes en una paleta como aiadir otros nuevos. La segunda pagina de la ventana Personalizar, Ilamada Comandos, cuenta con dos listas: la de la izquierda contiene varios grupos de comandos, mientras que la de la derecha muestra los comandos existentes en el grupo seleccionado a la izquierda. Mientras tengamos abierta esta ventana, que puede ver en la PME 2. Elentorno de desarrollo figura 2.26, podemos utilizar la técnica de arrastrar y soltar tanto para eliminar botones de las paletas de herramientas que hay visibles como para aiadirlos, tomandolos de la lista Comandos y situandolds en la posicién que deseemos de la paleta. Figura 2.25. Otra forma de mostrar y ocultar barras de botones Programacién con Visual C# NET Figura 2.26. Lista de los comandos disponibles para alojar en paletas de botones Para eliminar un comando existente en una paleta pulse sobre él con el botén principal del raton y arrdstrelo hasta situarlo fuera de la paleta, en cualquier punto de la pantalla. Anadir y eliminar ments de opciones Usando la misma técnica que acaba de describirse en el punto previo, arras- trando comandos a las paletas de botones y fuera de ellas, también podemos adaptar la configuracién de los mentis de Visual C#. Los comandos pueden situarse en la barra de mentis como nuevas opciones principales o bien como opciones simples de un mend ya existente, En la figura 2.27, por ejemplo, pue- de comprobar como anadimos al menu Proyecto, ya existente, el comando Guar- dar todo, de tal manera que podamos ejecutar esa accion también desde este ment. Fl ment: emergente que aparece sobre la opcién recién afiadida lo hemos hecho aparecer con el botén secundario del ratén, como es habitual. Con sus opciones podemos modificar el titulo de la opcién, asignarle un icono distinto, iniciar un grupo de opciones, ete. Creacion de nuevas paletas y menus demas de afiadir nuevos elementos a las paletas de botones y mentis de opciones ya existentes, también tenemos la posibilidad tanto de crear nuevas paletas como de aniadir nuevos mentis al entorno. Comencemos viendo aque- llos pasos que es necesario dar para crear una nueva paleta de botones 0 co- mandos. 2. Fl entorno de di Figura 2.27. Anadimos opciones a un menu existente En la pagina Barras de herramientas de la ventana Personalizar, segiin ha po- dido verse en una figura previa, existe, a la derecha, un boton llamado Nueva Al pulsarlo aparecera una nueva paleta de botones, vacia y flotante. Podemos disponerla en cualquier punto del entorno, donde nos interese, y después usar la misma técnica descrita antes para aniadir los comandos que deseemos tener en esa nueva paleta. La figura 2.28 muestra una paleta de herramientas, a la que hemos llamado muy originalmente MiPaleta, que dispone de cinco botones con tareas que, se supone, realizamos habitualmente sats Figura 2.28. Una nueva paleta de botones Si lo que deseamos es crear un nuevo menti, tendremos que seleccionar el ultimo elemento de la lista Categorias en la pagina Comandos de la misma ven- tana. A la derecha vera aparecer un tinico comando: Nuevo menu. Arrastrelo hasta situarlo en la barra de ments, como se ha hecho en la figura 2.29, 0, si lo prefiere, en el interior de una barra de botones, creando de este modo un menu Programacién con Visual Ct .NET desplegable. Una vez creado el ment, pulse el botén secundario de! ratén so- bre él para establecer el nombre y modificar cualquier otra propiedad. Reetstlece agen dl ben tyres nagar det bot Canby de td Sto tao (sangre) ‘tht er mers) Figura 2.29, Afiadimos un nuevo ment al entorno Ajadido el ment, el proceso para insertar en él opciones u otros ments es idéntico al descrito en el punto previo. En la figura 2.30 puede ver el ment tras haber aiiadido cinco opciones. Figura 2.30. Nuevo menu de opciones Opciones diversas La ventana Personalizar cuenta, como se decia antes, con tres paginas dis- tintas. En la tercera, titulada Opciones, encontrara distintas opciones que afec- tan a las barras de botones y ments de opciones estableciendo, por ejemplo, el 2. El entorne de desarrollo tamano de los iconos, los efectos de animacién al desplegar un menti, la apari- cion de las combinaciones de tecla cuando se sittia el puntero del raton sobre un boton, etc. Probablemente lo mas interesante de esta ventana sea el boton Teclade que aparece en la parte inferior. Al pulsarlo vera aparecer una ventana como la de la figura 2.31. En realidad es la ventana de opciones del entorno que aparece con el elemento Entorno>Teclado ya seleccionado. En la lista que ocupa la parte central aparecen todos los comandos disponibles en el entorno, mientras que justo debajo se indican las combinaciones de tecla para ejecutarlos sin neces dad de recurrir a botones ni opciones. Logicamente, podemos tanto modificar las asignaciones existentes como afadir atajos de teclado a opciones que no contasen con ellos. Figura 2.31. Configuracién de los atajos de teclado Configuracion de herramientas externas Aunque Visual C# NET cuenta, como ha podido ver y verd en los distintos capitulos de este libro, con un entorno que tiene infinidad de posibilidades, esta claro que no puede integrar absolutamente todos los recursos que un pro- gramador pudiera necesitar para efectuar su trabajo, desde el primero hasta el ultimo. Es por eso que desde Visual C# .NET resulta posible acceder a herra- mientas externas, para lo cual tan sdlo hay que definir la configuracion apro- piada para ejecutarlas. Si abre el menti Herramientas encontraré en él opciones para ejecutar algu- nas herramientas externas, como el comprobador de controles ActiveX, el ge- nerador de GUID o el Visor de objetos OLE y COM. Estas son herramientas externas ya preconfiguradas. Para anadir cualquier herramienta adicional utilice la opcion Herramientas externas de ese mismo ment, abriendo la ventana mostrada en la figura 2.32. Programacién con Visual C# .NET a En ella aparece una lista con todas las aplicaciones configuradas en este mo- mento. Al seleccionar cualquiera de ellas, en la parte inferior aparecen el titu- lo, comando de ejecucién y argumentos, entre otros datos. Los botones que aparecen a la derecha permiten afiadir y eliminar opciones del menu, asi como establecer el orden. [eter roronvnrn wl : ; = Figura 2.32. Ventana Herramientas externas Pulsando el botén Afiadir aparecerd un nuevo elemento en la lista. Usando los controles que hay en la parte inferior configuramos el titulo y los parametros. Estos pueden seleccionarse de una lista desplegable, como se aprecia en la fi- gura 2.33. En ese caso se esta configurando una opcién, llamada Bloc de notas, que al ejecutarse abrira en dicha aplicacion el médulo de cédigo fuente sobre el que estemos trabajando. De manera andloga podriamos configurar cualquier otra herramienta. Automatizaci6n de tareas En el trabajo diario es corriente que existan tareas mas o menos repetitivas, no complejas pero en las que se emplea un cierto tiempo precisamente por la frecuencia con la que hay que realizarlas, Visual C# .NET cuenta con diversos mecanismos para aulomatizar esas tareas, desde la programacién de nuevos asistentes hasta el registro y reproduccién de macros. Este ultimo es, segura- mente, el método mas simple, aunque no por ello el que tiene menos posibili- dades. Las macros pueden crearse de dos maneras distintas: registrando las accio- nes efectuadas con el teclado y el raton o bien codificandolas manualmente. Una vez existen, pueden ejecutarse desde una opcion de ment, con una combi- nacion de teclado o pulsando un botén. 2. El entorno de desarrollo Figura 2.33. Afiadimos una nueva herramienta externa Registro de una nueva macro Comencemos por el principio, registrando la que seria nuestra primera macro en Visual C# .NET. Con este fin seleccionariamos la opcién Herramientas>Ma- cros>Grabar TemporaryMacro. También podemos pulsar la combinacién de te- clas Mayis-Control-R para conseguir exactamente la misma accién. Al iniciar el registro de una nueva macro veremos aparecer como ventana flotante la paleta de botones mostrada en la figura 2.34. Con el primer boton detendremos momentaneamente el registro, con el segundo lo finalizaremos y con el tercero cancelaremos la grabacién. Figura 2.34. Paleta de botones para controlar el registro de una macro Durante el registro de la macro podemos usar las opciones del menu, los bo- tones disponibles en las paletas, podemos realizar las tareas habituales de di- seno en los formularios 0 en el codigo fuente. Cualquier accién se registrara y traducira a érdenes que, finalmente, seran las que compongan la macro. Puede, por ejemplo, introducir un texto en el editor de cédigo y copiarlo varias veces. Programacion con Visual C# NET NW $$ Ejecucion de una macro Al finalizar el registro de la macro, pulsando el segundo de los botones exis- tentes en la paleta, ésta desaparecera y la macro quedara almacenada en un espacio temporal. Para ejecutarla tan sélo tenemos que pulsar la combinacion Mayus-Control-P, 0 bien usar la opcion Herramientas>Macros>Ejecutar Tempo- raryMacro. Al hacerlo, vera como se reproduce la insercion del texto que intro- dujo durante el registro. En este momento la macro esta, como se ha dicho, almacenada de forma temporal. Esto significa que el registro de una nueva macro eliminaria a ésta que tenemos. Si hemos creado una macro util, que puede servirnos en otras ocasiones e incluso otros proyectos, lo normal es que la guardemos. Para ello usaremos la opcién Herramientas>Macros>Guardar TemporaryMacro. Apare- cera el Explorador de macros (véase la figura 2.35) invitandonos a asignar un nombre a esa macro temporal. De esta forma podemos guardar tantas macros como necesitemos. Figura 2.35. Asignamos un nombre a la macro recién registrada Teniendo el Explorador de macros abierto, podemos ejecutar cualquier macro simplemente haciendo doble clic sobre su nombre, sin necesidad de acceder a opcién de mend alguna. Codigo de la macro Usando las opciones del mend emergente asociado a cada elemento del Ex- plorador de macros podemos acceder al codigo fuente de cada una de ellas. Por ejemplo, pulsando el botén secundario del ratén sobre la macro que acabamos de registrar y seleccionando la opcién Editar, nos encontraremos con una venta- na como la de la figura 2.36. Es el editor de macros de Visual C# .NET, un pun- to desde el cual podemos tanto explorar el codigo de las macros existentes como J 2. El entorno de desarrollo modificarlo 0, incluso, crear nuevas macros directamente, introduciendo el c6- digo Visual C# apropiado. Gpeion Steice oe Option Fxplicit ort pores EBvOTE Imports system. Diaguoscics Public Rodule Recordingitodule Suh Dacraazusce|) DTE. deeivebocument Selection, StartoeLine( _ ‘vaStartOfLinsOpt ions, vaSteart@fLineOpt ioneP rer Text) DYE. Activepoctment Select ion. NevLine() DYE. Aceivebocument .Select son, Seartorisme( _ ‘YeBtartOfLineOpt ions. veStartOsLAnedpeionsl sreeText) DTE.Acesvapocument Selection. Text = "1234567850" DPE. sctivevocument Select ion, StartorLine( _ ‘ya2taccofLineopt ions -vetartOfbineoptiousFirscText, True) DIE. Activedocument Select ion, DIE. ActiveDocument Select DTE. Actsvebocument Select ion, TE. accavevocument seiect ion, DIE, Actavebocument ZeLect sor DYE. detsveocument Select son DTE. Actsvedocument Select ion, Paste () rnd Sub Figura 2.36. Editor de macros de Visual Studio .NET Para codificar una macro se utiliza el modelo de objetos de Visual Studio NET, un modelo en el que cada elemento del entorno esta representado por un objeto, un modelo en el que cada accién que realizamos mediante el teclado 0 ratén tiene una correspondencia con un método de un objeto. En la figura 2.36 puede ver cémo se usa el objeto Act iveDocument para acceder a la seleccién de texto del documento actual, usando métodos como Copy() y Paste() para copiarlo y pegarlo. Légicamente, para sacar el mejor provecho de las macros es indispensable conocer a fondo este modelo de objetos, un tema que, por su extension y com- plejidad, queda fuera del ambito de este libro. Puntos clave * Los proyectos Visual C# .NET se agrupan en soluciones. Un proyecto pue- de contener formularios, médulos de codigo, archivos de recursos y otros elementos adicionales. Programacién con Visual C# NET * Los médulos correspondientes a elementos visuales, como formularios 0 imagenes, se editan usando los disenadores existentes en el entorno, con la ayuda de ventanas como Propiedades y Cuadro de herramientas. * El codigo asociado a esos elementos, asi como cualquier otro cédigo del proyecto, se manipula en un editor de texto con realce sintactico y tecnologia Iniellisense de ayuda a la edicion. * La base del desarrollo con Visual C# .NET sigue siendo el uso de compo- nentes y controles. Estos se insertan en contenedores, como pueden ser los formularios, y se personalizan mediante propiedades y eventos. ¢ Elentorno de desarrollo cuenta con un modelo de objetos que facilita su control mediante comandos. Ese mismo modelo puede utilizarse para automatizar tareas o crear nuevos asistentes. + Las ventanas existentes en el entorno pueden anclarse unas a otras, apilarse en multiples paginas o quedar como flotantes, todo ello median- te operaciones de arrastrar y soltar. * Otros elementos del entorno, como las paletas de botones y los mentis de opciones, pueden adaptarse a nuestras preferencias. Recuerde utilizar el botdn secundario del raton sobre cualquier elemento para acceder a sus opciones. * La automatizacion de tareas resulta posible y sencilla gracias a la nueva P y 8 posibilidad de registrar y reproducir macros. Resumen Como ha podido ver en este capitulo, el entorno de Visual C# .NET cuenta con multitud de elementos algunos de los cuales, sobre todo los fundamenta- les, ha conocido con algo mas de detalle. También se ha tratado la personali- zacion de ese entorno, asi como la automatizacién de tareas mediante el uso de macros. Los elementos descritos con mas profundidad, como los disenadores o el edi tor, son seguramente los mas utilizados, pero hay otros muchos que ni siquiera se han mencionado, como las ventanas de depuracién, el esquema de docu- mento, etc. Algunos de ellos tendra ocasién de conocerlos en posteriores capi- tulos. En el campo de la automatizacion tan solo se ha abordado el registro y re- produccién de una macro simple, una macro que hemos almacenado con un hombre para poder usarla siempre que nos interese. Conociendo el modelo de objetos de Visual Studio .NET tenemos también otras posibilidades, como la creacion de asistentes 0 afiadidos al entorno. En la ventana de creacion de nue- vos proyectos encontrara opciones que generan un esqueleto para este tipo de elementos. wt & \ El desarrollo de aplicaciones en general, y en particular en el entorno del sistema operativo Windows, ha cambiado mucho en la ultima década, desde la aparicion de la primera version de Visual Basic, y, especialmente, desde la di- fusidn a escala global de Internet y la mayor presencia de dispositivos moviles. Hace diez aftos las aplicaciones se creaban usando un mismo lenguaje para to- das las tareas y para un sistema operativo concreto, escenario que ha ido ha- ciéndose mas y mas complejo en los tiltimos anos. Las primeras aplicaciones para Windows se desarrollaban usando el len- guaje C y Hamadas directas a las funciones del API de Windows. Esta forma de exponer los servicios propios del sistema, a través de cientos o miles de funcio- nes independientes, era general a todos los sistemas operativos. El trabajo era realmente complejo, siendo necesario el trabajo intensivo con punteros y mane- jadores (handles), para facilitar parametros de la aplicacién al sistema y vicever- sa, con el consiguiente peligro de incurrir en fallos mas 0 menos tipicos: la no liberacion de bloques de memoria que quedan perdidos, reutilizacién de un puntero con direcciones de datos ya liberados, uso del manejador invalido al llamar a una funci6n, etc. Para simplificar este esquema, y ayudar a los programadores haciendo mas facil su trabajo, se buscaron soluciones siguiendo caminos paralelos, e incluso a veces divergentes, dentro de la propia Microsoft. Asi, por una parte nacié Vi- sual Basic para facilitar el desarrollo de aplicaciones simples con interfaz de usuario, ocultando todos los detalles de comunicacién con el sistema. Solo habia que usar unos controles, conocidos como VBX, para disefiar las ventanas y usar un mecanismo de propiedades y eventos para controlar el flujo de la aplicacion. M3. La plataforma Microsoft .NET ee En contraposicién, a los programadores que utilizaban C se les ofrecié como solucién el lenguaje C++, orientado a objetos pero con la misma complejidad y debilidad que C, y una biblioteca de clases, llamada MFC (Microsoft Foundation Classes), que hasta cierto punto encapsulaba en objetos la funcionalidad usada mas habitualmente del API de Windows. Paralelamente a Visual Basic y las MFC surgié COM (Component Object Model), un modelo de objetos que tenia por objetivo hacer posible la reutilizacién de componentes binarios sin importar las diferencias entre lenguajes. COM, no obstante, siempre ha sido muy complejo y su éxito se debe, en parte, al éxito de Visual Basic 5 y 6, con los que resultaba muy facil crear este tipo de componen- tes, y el ofrecimiento de una biblioteca de plantillas, la ATL (Active Template Library), que, conjuntamente con una serie de asistentes, allanaba su desarrollo en CH Nuevas necesidades Todo el escenario que acaba de exponerse se cifie al desarrollo de aplicacio- nes para un sistema operativo: Windows. Este escenario adquiere mayor com- plejidad debido a dos factores fundamentales: la necesidad de aprovechar las posibilidades que ofrece la red Internet y la cada vez mayor presencia, gnecesi- dad?, de llegar con la informacion a todos lados mediante el uso de dispositivos méviles tales como teléfonos celulares, asistentes digitales personales y dispo- sitivos parecidos. Para cubrir estas necesidades, relativamente recientes, también se han se- guido varios caminos paralelos. Con el fin de crear aplicaciones para Internet puede utilizar ASP (Active Server Page), conjuntamente con un lenguaje de guio- nes como JScript o VBScript, o bien ISAPI (Internet Information Server API), uti- lizando C++ para crear médulos que solo funcionan con IIS. Con Visual Basic 6, gracias a la integracién de COM tanto en IIS como en el lenguaje, se facilitaba el desarrollo de este tipo de proyectos. En cuanto a las aplicaciones méviles, practicamente se ha contado con los mismos entornos de desarrollo existentes para Windows, como Visual C++ y Visual Basic, pero modificados para ajustarse a las limitaciones de un sistema operative embebido como es el usado en los Pocket PC Con el fin de agrupar bajo un mismo nombre todos los servicios necesarios para este tipo de aplicaciones, servicios como ASP, ADO o los servicios de componentes COM+, nace la denominacién Windows DNA (Distributed Internet Architecture). En resumen, podriamos decir que a medida que han ido surgiendo las ne- cesidades se han hecho también anadidos tanto al sistema operativo como a las herramientas de desarrollo, ahadidos heterogéneos que en algunas ocasiones vienen en forma de mas funciones tipo API, en otras como componentes COM que se integran en el sistema y en otras como asistentes para los entornos de desarrollo, Programacién con Visual C# NET .NET, dla solucion definitiva? El resultado de esta década de evolucién en el desarrollo de aplicaciones, en general y particularmente en el entorno de Windows, ha tenido como resul- tado la existencia actualmente de multit'd de servicios duplicados, especificos para un determinado lenguaje o herramienta, y pocas posibilidades reales de reutilizacién del cédigo, al tiempo que el propio sistema ha ido ganando en com- plejidad de manera vertiginosa La solucién, quiza definitiva, que propone Microsoft para solventar esta situacion es la plataforma .NET. Esta consta de un conjunto de servicios uni- versales, idénticos para todos los lenguajes, al tiempo que mantiene la integra- cidn con los desarrollos existentes y hace posible una interoperabilidad entre lenguajes desconocida hasta el momento. Aunque actualmente la plataforma .NET solo esta disponible para Windows 98, Me, NT, 2000 y XP pronto apare- cera una version compacta para dispositivos méviles, al tiempo que no se des- carta la aparicion en otros sistemas operativos, como Linux. Para desarrollar aplicaciones NET puede utilizarse practicamente cual- quier lenguaje de programacién, desde C+ y Visual Basic hasta el nuevo Vi- sual C#, pasando por COBOL, Perl, Pascal, Java o Python. No tenemos, por tanto, que usar obligatoriamente un determinado lenguaje. Los servicios de la plataforma, tanto la biblioteca de componentes como los servicios basicos, son expuestos de manera idéntica a todos los lenguajes, de tal manera que todos ellos tienen las mismas posibilidades. Podemos, por tanto, crear un componen- te de servidor con multiples hilos de ejecucién utilizando Visual C# NET 0 una interfaz Web sirviéndonos de Visual C++ .NET. La plataforma .NET no sélo hace posible el desarrollo de componentes y aplicaciones para Windows, que sigue siendo uno de los primeros objetivos de la mayoria de los programadores, sino también la creacion de aplicaciones y servicios Web, aplicaciones de consola, bibliotecas de clases genéricas, aplica- ciones para dispositivos moviles, etc. Es, por tanto, un recurso adaptado a las necesidades actuales, frente a las soluciones antiguas y reiteradamente actuali- zadas 0 parcheadas a lo largo de los aiios. Desde las aplicaciones .NET puede seguir utilizindose el API de Windows y los componentes COM. De manera andloga, los componentes .NET pueden ser usados por aplicaciones clasicas también a través de COM. No se rompe, por tanto, con los proyectos ya existentes forzando una actualizacién global. Usando los servicios de interoperabilidad cualquier empresa puede ir desarro- lando sus nuevas aplicaciones en .NET integrandolas con las que ya tiene. Junto con la propia plataforma NET, la novedad mas importante es el ofre- cimiento de un nuevo lenguaje, C#, preparado para el escenario actual en el que el desarrollo de aplicaciones hace un uso intensive de componentes prefa- bricados. Para terminar este punto, destacar que el desarrollo general de aplicacio- nes, sin importar su naturaleza, resulta mucho mas sencillo en la plataforma .NET de lo que era anteriormente usando el API de Windows, MFC o Visual f 3. La plataforma Microsoft NET a Basic. Esto es asi porque todos los servicios se exponen en forma de componen- tes, dado que .NET es una plataforma disenada con una orientacion a compo- nentes en mente. Podemos olvidarnos de los manejadores, los punteros y la gestion de bloques de memoria, centrandonos directamente en la funcionalidad de nuestra aplicacién. Esquema de desarrollo y ejecuci6n Vamos a comenzar trazando un esquema general del desarrollo y ejecucién de las aplicaciones en la plataforma Microsoft NET para a continuacién, en los puntos siguientes, ir profundizando en los detalles de algunos puntos mas con- cretos. Las herramientas de desarrollo para la plataforma .NET, en nuestro caso Visual C# NET, generan a partir de los diferentes médulos que conforman un proyecto los respectivos médulos de cédigo objeto. Este se aloja, como es tra- dicional, en archivos con extensiones EXE y DLL aunque, en realidad, la estruc- tura interna de dichos archivos no es la clasica y el codigo que contienen no es directamente ejecutable, de ahi que no puedan usarse sobre Windows si no se tiene instalada la plataforma Microsoft .NET. Cada uno de los médulos objeto contiene cédigo independiente del tipo de procesador y sistema operativo. Este codigo, lamado cédigo en MSIL (Microsoft Intermediate Language), no puede ejecutarse sin mas, sino que tiene que ser pre- viamente compilado para el sistema y procesador concretos donde va a uti zarse la aplicacion. Al compilador que efectuia esa compilacidn al vuelo, cuando es necesario, se le conoce como compilador JIT (Just in-time) En la plataforma NET la unidad minima que puede alojarse en memoria no es la biblioteca de enlace dinamico ni el ejecutable, sino el assembly, un termi- no que podemos traducir por montaje o ensamblado. Un assembly puede ser un solo archivo bien estar compuesto de multiples archivos con dependencias entre ellos. Una misma aplicacion puede constar de miltiples ensamblados, de la mis- ma manera que un programa Windows clasico puede componerse de diversas bibliotecas de enlace dindmico. Todos los ensamblados de una aplicacién se ejecutan en el contexto de un mismo application domain 0 dominio de aplica cién. El concepto de dominio de aplicacién es una evolucién del concepto de proceso tal y como se conoce actualmente en Windows, es un contexto en el que se comparten determinados recursos: espacio de direccionamiento, mode- lo de hilos, etc Para generar el codigo MSIL, los compiladores hacen uso del CTS (Common Type System), un sistema en el que se definen los tipos de datos y operaciones posibles recogiendo la sintaxis de muchos lenguajes. Si se desea que el codigo pueda cooperar con otros desarrollos, sin importar el lenguaje en que se escri- ban, entonces habra que ajustarse a la CLS (Conmion Language Specification), una especificacion en la que se define un subconjunto del CTS que es comuin a todos los lenguajes. Programacion con Visual Cf .NET a El cédigo MSIL contenido en los ensamblados es alojado en memoria, a de- manda del usuario 0 bien de otras aplicaciones, por el CLR (Common Language Runtime). El CLR, 0 entorno comin de ejecucién, es una de las piedras angula- res de la plataforma .NET. Se encarga no solo de abrir los ensamblados, prepa- rar el dominio de aplicacion necesario y alojar el cédigo en memoria, sino que, ademas, es el responsable de supervisar ese codigo encargandose, por ejem- plo, de recolectar los objetos en desuso liberando la correspondiente memoria, un proceso que se conoce habitualmente como GC (Garbage Collection) 0 reco- leccion de basura. Para convertir el cédigo MSIL en cédigo ejecutable, el CLR utiliza un com- pilador JIT. Este optimizara el codigo para el sistema operative y procesador en que va a ejecutarse, de tal manera que la aplicacion siempre aprovechara de la mejor forma los recursos del entorno donde vaya a ejecutarse. Antes de com- pilar, sin embargo, el CLR verifica el codigo para comprobar que es seguro y puede ser apropiadamente supervisado en ejecucidn. La figura 3.1 resume esquematicamente algunos de los pasos que se han mencionado. Estos se han separado en dos grandes bloques: desarrollo y ejecu- cion. Para el desarrollo dispondremos de Visual C# .NET, usando sus disena- dores y editores para generar el cédigo fuente que, finalmente, compilaremos obteniendo los correspondientes ensamblados. Cuando éstos sean requeridos, para ¢jecutar la aplicacion, el cédigo MSIL que contienen sera verificado y compilado a cédigo nativo, ejecutandose en la plataforma .NET bajo supervi- sién del CLR Figura 3.1. Esquema general de trabajo de una aplicacién NET Resta decir que las aplicaciones .NET haran uso de los servicios de la plata- forma Microsoft NET, lo que se conoce también como Microsoft! .NET Framework. Estos servicios proveen de todo lo necesario para aplicaciones clasicas, aplica- ciones Web, servicios web, acceso a datos, etc. | 3. La plataforma Microsoft .NET Composicion de una aplicaci6n .NET Una aplicacion .NET consta de uno 0 mas ensamblados, cada uno de los cua- les estara formado de uno 0 mas archivos conteniendo recursos y codigo MSIL. La aplicacién, por tanto, puede ser tan sencilla como para estar compuesta de un simple archivo EXE 0 DLL, o tan compleja como para constar de multiples archivos con cédigo y otros elementos. Las aplicaciones .NET se ejecutan en el contexto de un dominio de aplica- cién, un ambito virtual mediante el que se aisla a esa aplicacién de otras que pu- dieran estar ejecutandose en el sistema. Un mismo proceso de Windows puede contener multiples dominios de aplicacién sin que, por ello, existan conflictos entre ellos. Ensamblados y manifiestos Siun ensamblado puede estar compuesto de miiltiples médulos, cabe pregun- tarse cémo sabra el sistema, a la hora de utilizar dicho ensamblado, qué modu- los son los que forman parte de él. La respuesta la encontramos en una porcién de informacién, conocida como manifiesto, que relaciona a todos los elemen- tos del ensamblado y, ademas, sefiala las dependencias existentes respecto a otros ensamblados, por ejemplo con servicios del sistema Aunque es posible generar el manifiesto almacenandolo en un archivo indepen- diente, lo habitual es que se incorpore a uno de los archivos que forman parte del ensamblado. En los dos ejemplos desarrollados en capitulos previos, por ejemplo, el manifiesto se encuentra en el interior del ejecutable obtenido como nico resultado. Busque el archivoEXE resultante de los proyectos de los dos capitulos pre- vios en la subcarpeta \bin de la carpeta donde esté almacenado el ejem- plo. Uno era una aplicacién consola y el otro una aplicacién Windows sin ninguna funcionalidad. Podemos ver el contenido de cualquier ensamblado, concretamente el ma- nifiesto que lo describe, utilizando para ello la herramienta ildasmmencionada en el primer capitulo. La encontrara normalmente en la carpeta \Archivos de programa\Microsoft .NET\FrameworkSDK\Bin de la unidad donde haya instalado la plataforma Microsoft .NET. Invoque esta utilidad pasando como pardmetro el camino y nombre del ejecutable AppWindowsForm. exe creado como ejemplo en el segundo capitulo. Vera aparecer una ventana como la de la figura 3.2. En ella se enumeran los elementos que existen: un manifiesto y un 4mbito con nombre que contiene una clase. Programacién con Visual C# NET P MANIFEST = WAgpiindount orn Eien! ‘late pe ado snubbed ‘eters [Sten vino: Forney Wied Fare Fen boar povae ols [Syter Windows Foe tere Widens Finns Bion ongenerts vate cas: ye yer ConyponeraModel Condon lobe pate cae [Syst widows Fema Sste Wedoee Foes Lab eeBorTprrvteclac System Widow Forms olan Vind Ferme Ton Figura 3.2. Contenido de un ensamblado Haciendo doble clic sobre el elemento MANIFEST se abrira una nueva venta- na mostrando el manifiesto del ensamblado. Su contenido, como puede verse en la figura 3.3, seguramente no le diré mucho. En las primeras lineas se hace referencia a varios ensamblados externos, concretamente los necesarios para usar formularios Windows y mscor Lib, que contiene los servicios basicos del entorno comin. Si abre este mismo proyecto en el entorno de Visual Studio .NET y a conti- nuacién abre el Explorador de soluciones, vera en la lista de archivos uno Ila- mado Assembly Info. vb. Este médulo contiene la informacion del ensamblado que se utiliza para crear el manifiesto. Ensamblados y dominios de aplicacion Un ensamblado, como ya se ha dicho, contiene el codigo y los recursos de una aplicacién, ya sea en un solo archivo o en varios. Hasta cierto punto, podria- mos establecer una analogia con cualquier aplicacién Windows tradicional, compuesta de un ejecutable principal y, opcionalmente, codigo adicional dis- tribuido en méodulos DLL. Cuando una aplicacion Windows tradicional se pone en marcha, el sistema crea un nuevo proceso y un primer hilo de ejecucion para ejecutarla. El proceso define el ambito de los recursos disponibles para la aplicacion, por ejemplo el espacio de direcciones privado, evitando conflictos con otras aplicaciones que, a su vez, contarian con otro proceso. Al iniciar una aplicacion .NET el CLR, 0 entorno comtin de ejecucion, crea un nuevo dominio de aplicacion 0 AppDomain. Cada aplicacién alojara en su 3. La plataforma Micros AppDomain los ensamblados que necesite. A diferencia de lo que ocurre con las aplicaciones tradicionales, el aislamiento de las aplicaciones no precisa el uso de un proceso independiente. De hecho, es posible que el entorno de ejecucion utilice un mismo proceso para varios AppDomain. No por ello, sin embargo, ha- bra conflictos ya que cada AppDomain mantiene totalmente aislada a su apli- cacion de las dem issenbiy extern systen-Windows-FOrns wubLickeytoken = (H7 7a SC 56 19 94 EB sssenbly extern system.Drawing jubLickeytoken = (80 2F SF 7F 11 D5 on 30) scuston instance void (nscorlib]systen.Reflection.AssenblyCopyrightattribute::.ctor(string) = ¢ ‘euston instance void [nscorlib jsysten Reflection AesenblyoyNanenttribute:: .ctor(string) ~ ( ‘euston instance void [mscorlib ]systen.Reflection-AssenblydepFiteattripute:: ctor(string) = ( [nscor lib ]systen.ReFlection-AssenbiydelaySignittribute::.ctor(bocl) - ( [nscor ip /systen.Refiection-Assenbiprradenarkattribute:: ctar(etring) ~ ¢ ion Assenblyconfigurationattribute::.ctor(string)) ‘automatically, Anstance void [nscor1ib jsysten.ReFLection.Accenblycs insti I vetor(string) = ( riptionnttribuce::.ctor(string) -| jeFLection-Assenbipritienttribute::.ctor(string) = (81 Figura 3.3. Contenido del manifiesto La figura 4.4 es una representacién esquematica de lo que podrian ser dos aplicaciones NET. Ambas se ejecutan en el mismo proceso, pero cada una en su propio dominio. La primera aplicacién, arriba a la izquierda, es nuestro ejem- plo AppWindowsForm que, como ya sabemos esti compuesta de un solo en- samblado que, a su vez, consta de tan s6lo un modulo ejecutable. La segunda aplicacion, hipotéeticamente consta de dos ensamblados. E| primero esta com- puesto de un ejecutable y algun modulo DLL, mientras que el segundo es una DLL adicional. Un mismo ensamblado puede, en la practica, ser utilizado por diferentes aplicaciones, de tal forma que se alojaria en el dominio de cada una de ellas. El Programacion con Visual Ct .NET entorno de ejecucién se encargara de compartir el cédigo del ensamblado entre los dominios, asegurando que en cada uno de ellos el ensamblado aparezca como privado. Figura 3.4. Representacién de dos dominios de aplicacién y sus ensamblados Ensamblados privados y compartidos En el punto anterior se indica la posibilidad de que un mismo ensamblado sea usado por mas de una aplicacién. En la practica, esto sélo seria posible si ese ensamblado fuese de tipo shared 0 compartido. Por defecto, los ensambla- dos que se generan al compilar un proyecto son privados, ensamblados que sdlo seran usados por la aplicacién que esta desarrollandose. A diferencia de lo que ocurre con los componentes y servicios ofrecidos a través de COM, cuyos médulos deben contar con distintas entradas en el re- gistro para que puedan ser encontradas por las aplicaciones, los ensamblados privados no precisan configuracién alguna. Basta con distribuirlos conjunta- mente, todos los ensamblados de la aplicacion, copiandolos en el sistema de destino para que funcionen correctamente. La instalacion, por tanto, es tan simple como arrastrar y soltar los archivos desde un soporte, por ejemplo un CD-ROM, al disco de destino. La desinstalacién, consecuentemente, es igual- mente simple, bastando con eliminar los archivos. No hay entradas huérfanas en el registro de Windows ni nada parecido. Gracias a este comportamiento, no tendremos nunca mas problemas con las versiones de las DLL instaladas en el sistema. Cada aplicacion se distribuye con los ensamblados en la versién apropiada, sin entrar en conflicto con otras versiones que pudiesen estar utilizando otras aplicaciones. Adiés al conocido como DLL hell. Si todos los ensamblados fuesen privados, no obstante, nos encontrariamos en una situacién compleja al tener que distribuir también, junto a nuestra apli- cacién, todos los que contienen los servicios del sistema y el Microsoft .NET Framework, Para evitarlo existen los ensamblados compartidos, ensamblados que pueden ser utilizados por miiltiples aplicaciones. J 3. La plataforma Microsoft NET Los ensamblados compartidos no se distribuyen con las aplicaciones, sino que se instalan en un lugar comin del sistema para que todas ellas puedan en- contrarlos. Este lugar comin se conoce come GAC (Global Assembly Cache) siendo como un depésito global de ensamblados. La localizacién de este depo- sito dependera del sistema operativo donde esté instalada la plataforma. En Windows XP, por ejemplo, la carpeta Windows \assembly es la que contiene el GAC (véase figura 3.5) © G movetver SO meet | sbspterctonayment | sistem nanoyenert ress Biseentecary Figura 3.5. Carpeta en la que se encuentra el depésito de ensamblados compartidos Al disponer de un depésito global para los ensamblados compartides po- dria pensarse en los mismos problemas que se tienen habitualmente en Windows con las versiones de las DLL. Afortunadamente, ese problema, el de las distin- tas versiones del mismo componente, no existe en la plataforma .NET. Para que un ensamblado pueda ser compartido es obligatorio que su nombre sea tinico, fin para el cual se le asocia una clave publica de tipo RSA y también se distin- gue entre versiones del mismo elemento. En la figura 3.5 puede ver que una de las columnas existentes es, precisamente, Version. Podriamos tener ensambla- dos con el mismo nombre pero de distinta versién sin ningtin problema, cada aplicacion utilizaria la versién en la que esté interesada. Programacién con Visual C# Disponemos de diversas herramientas mediante las cuales generar esas cla- ves ptblicas e instalar los ensamblados compartidos en el GAC. Desde Visual C# .NET, lo habitual es anadir el atributo AssemblyKeyFileAttribute a la informacion del ensamblado, haciendo referencia a un archivo, previamente generado con la herramienta sn. En la figura 3.6 puede ver como se genera una clave almacenandola en el archivo AppWindowsForm. snk. Figura 3.6. Generacion de una nueva clave desde la linea de comandos Proceso de compilacion y ejecucion Ahora que ya sabemos, basicamente, cual es la estructura de una aplicacion NET al nivel de médulos, ensamblados y contextos de ejecucion, vamos a en- trar con algo mas de detalle en el proceso de ejecucién del cédigo que contienen esos médulos. Nos interesard conocer, especialmente, los pasos de verifica- n, compilacion y ejecucion en el entorno comin de manera supervisada Las indicaciones dadas a continuacion se aplican a todos los lenguajes .NET, ya que todos ellos generan sélo codigo MSIL y no cédigo nativo. La excepeién es Visual C++ NET que, como posiblemente ya sabe, si es capaz de generar co- digo native Windows. A ese tipo de cédigo no se aplicarian las normas que van a describirse Codigo intermedio Actualmente la mayoria de las herramientas existentes para el desarrollo de aplicaciones generan cédigo nativo, directamente ejecutable, para un determi- nado procesador y sistema operativo. Siempre se ha asumido que es la manera de obtener el mejor rendimiento, aunque esto dependeria mucho del compilador utilizado. Algunos compiladores no se actualizan a medida que surgen nuevos procesadores, por lo que no aprovechan los nuevos conjuntos de instrucciones y posibilidades. M3. La platajorma Microsoft NET Una aplicacion nativa no puede utilizarse directamente en otros sistemas operatives, en ocasiones ni en distintas versiones del mismo sistema, y tampo- co se ejecutarian en otros procesadores. F's necesario, por lo tanto, actualizar y recompilar, contando con multiples versiones de la misma aplicacién: una para cada combinacion de procesador y sistema operativo. Mediante los lenguajes que forman parte de Visual Studio .NET, y sus res pectivos compiladores, lo que obtenemos es siempre codigo MSIL 0 codigo in- termedio. Es un cédigo independiente de sistemas operativos y procesadores por lo que, en principio, nunca tendremos que recompilar un proyecto a causa de un cambio de procesador o sistema. Es posible generar codigo MSIL. con C# y Visual Basic NET, pero también con multitud de lenguajes de terceros fabri- cantes, desde Perl hasta COBOL y Fortran, pasando por un ensamblador espe- cifico. Logicamente, el codigo MSIL no puede ser ejecutado directamente. Esta ca- racteristica puede ser considerada como un inconveniente 0 como una ventaja, dependiendo de como se mire. La misma aplicacién .NET podria ejecutarse en Windows 2000, Windows CE o la préxima version de Windows 64 bits, apro- vechando en todos los casos los recursos del procesador y sistema sin, por ello, tener que compilar ni modificar nada. Puede ver el codigo MSIL de un médulo con la misma herramienta ildasm utilizada previamente. Es algo que ya hizo en el primer capitulo, obteniendo la definicion del método Main() en ensamblador MSIL El sistema comun de lipos Para generar cédigo MSIL valido, que pueda ser ejecutado en el CLR, los compiladores deben hacer uso de los tipos y operaciones definidos en el CTS (Common Type System), un sistema comin en el que se recogen todos los tipos de datos y todas las operaciones que es posible efectuar, recogiendo la funcio nalidad de un gran abanico de lenguaj Podriamos decir que en el CTS se recogen las instrucciones basicas y los ti- pos de datos elementales que pueden utilizarse en el entorno comun de ejecu- cion. No todos los lenguajes NET haran uso de todas las posibilidades del CTS, usando tan solo los elementos que requieran. No importa que el lenguaje de alto nivel utilizado sea BASIC, COBOL, C# 0 Pascal, el codigo para, por ejem- plo, codificar un bucle sera sintacticamente distinto en cada lenguaje, pero el codigo MSIL resultante sera idéntico. Partiendo de la base de que el codigo MSIL es indistinto del lenguaje de alto nivel usado para generarlo, es facil comprender que un lenguaje puede utilizar codigo escrito en otro, por ejemplo en forma de componente, sin ningtin pro- blema. En realidad, esto sera cierto siempre que ninguno de los lenguajes use elementos del CTS que el otro no comprende. Hay que tener en cuenta que el CTS recoge caracteristicas y operaciones que pueden no estar contempladas en todos los lenguajes de alto nivel. La sobrecarga de operadores en clases propias, por ejemplo, es una posibilidad contemplada en el CIS y posible en C# 0 C++, pero no en Visual Basic .NET. Programacion con Visual C# .NET EE — — Existe, no obstante, un minimo comtin denominador, un subconjunto del CTS que si existe en todos los lenguajes .NET. Ese subconjunto esta recogido en la CLS (Conon Language Specification), una especiticacién que define las operacio- nes y tipos que deben usarse si se quiere obtener un codigo que pueda coope- rar sin limitaciones con otros lenguajes. Los ensamblados que contienen codigo ajustado a la CLS pueden ser usados desde otros proyectos aunque el lenguaje sea distinto. Es posible, por ejemplo, definir una clase en Visual Basic NET y, posteriormente, derivar una nueva con C#. Esto no seria posible si no respeta- se la CLS. Que un determinado ensamblado se ajuste a la CLS 0 no es un aspecto que se configura mediante un atributo. Este, habitualmente, toma por defecto el valor true, que es lo que, por regla general, nos interesara. Podemos, no obstante, abrir el modulo AssemblyInfo y modificar dicho atributo como se muestra en la figura 3.7. De esta forma podriamos usar construcciones recogidas en el CTS pero no en la especificacién comtin para hacer posible la interoperabilidad entre lenguajes. Un proyecto puede utilizar internamente construcciones no ajustadas a la CLS pero no exponiéndolas al exterior, no haciéndolas publicas, obtenien- do como resultado una aplicacion ajustada a la CLS. Dicho de otra manera: para que una aplicaci6n esté ajustada a la CLS basta con que los tipos ex- puestos ptiblicamente cumplan con dicha especificaci6n. Ejecucién supervisada El codigo MSIL, una vez compilado a cédigo nativo mediante el compilador JIT, sera ejecutado bajo la supervision del CLR. En realidad, el cédigo es ve- rificado antes de compilarse como parte del proceso de iniciacién de la aplica- cién. En esa verificacion el CLR comprueba que el codigo MSIL no almacena construcciones peligrosas que no puedan ser supervisadas, como el uso de pun- teros. Las diferentes tareas del CLR persiguen comprobar que el cédigo puede ser ejecutado segun los permisos establecidos, facilitar los servicios basicos de ges- tion de memoria 0 control de excepciones, facilitar la cooperacién entre len- guajes o la ejecucién distribuida o bien asegurar la ausencia de conflictos entre diferentes dominios de aplicacién. El codigo que se ejecuta bajo supervision del CLR se denomina managed code © codigo gestionado. Esta supervisién hace posible, por ejemplo, que en los pro- gramas no tengamos que preocuparnos de la liberacién de la memoria ocupa- da por los objetos, ya que es el propio CLR, concretamente el recolector de basura, quien controla la vida de esos objetos y los destruye cuando no son ne- cesarios. 3. La plataforma Microsoft .NET La informacion general de un sneanb lado se controle mediante el 23g Conpunto de atribucos. Cambie estos atributos para moditicar 1a int AssenbiyTic1e("")] AsgenblyDeseription("™)) Assenbiycontiguration("*)] AsvenbiyProduct [essenbiy: Assenbiycopyright (ascenbiy! AsoenbiyTeadenark (*™)] (assenbiy: Assenblycuteure (™")] (aasenbiyt CLSComp Liane (FEve)} uy 1) te amtormacion de vereién de un eneenblado consta de los siguientes u 7 Vereen pranctpar 1] Versién secundaria 1 Veraién de compitecién Wo Reviesen a Figura 3.7. Modificamos el atributo CLSCompliant del ensamblado Gracias a la ejecucién supervisada de las aplicaciones, el CLR garantiza una estabilidad superior a la existente tradicionalmente en las aplicaciones Windows. Una aplicacion .NET dificilmente puede ejecutarse conteniendo un error que provoque un fallo incontrolade, y mucho menos que afecte a otros dominios de aplicacién 0 el propio sistema. Compilacion JIT Durante la fase de desarrollo utilizamos un compilador dependiente del len- guaje, un compilador que toma cédigo fuente, escrito en Visual Basic, C#, COBOL © cualquier otro lenguaje NET, y genera cédigo MSIL. Ese cédigo, como ya sabe, no es directamente ejecutable. Aqui es donde entran en escena los compiladores JIT 0 just in-time, conocidos asi por efectuar una compilacién al vuclo a medida que es necesario. También se les conoce como jitters. Observe que hablamos de compiladores, en plural, ya que existiran miilti- ples compiladores JIT segun el sistema operativo y el procesador. De esta ma- nera, un mismo cédigo MSIL puede dar lugar a un cédigo nativo distinto para, por ejemplo, un Windows 64 bits sobre Itanium y un Windows CE sobre Pocket PC. En unos casos, cuando el sistema es rapido y con recursos, el com- pilador JIT optimiza el codigo todo lo posible, aunque para ello se emplee mas Programacién con Visual C# .. memoria y mas ciclos del procesador. Cuando el entorno es mas limitado, por ejemplo sobre dispositivos méviles, el jitter practicamente se limita a traducir las sentencias MSIL a érdenes nativas, sin optimizaciones y consumiendo la menor cantidad de recursos posible. Los compiladores JIT no son invocados de una manera explicita, sino que es el entorno de ejecucién el que los utiliza segtuin va siendo necesario. Por regla general no se compila todo el cédigo de los ensamblados a medida que éstos se alojan en memoria, sino que van compilandose individualmente los métodos a medida que son invocados. Esto reduce el tiempo de iniciacién de la aplica- cién. Por otra parte, cada método es compilado una sola vez. Al invocar por pri- mera vez a un método se llama al jitter y a continuacion se ejecuta. Las veces siguientes es ejecutado directamente. De esta manera se obtiene un buen ba- lance entre velocidad de puesta en marcha y velocidad de ejecucién Cuando el cédigo de un determinado ensamblado va a utilizarse siempre sobre la misma versién de la plataforma .NET y el mismo sistema operativo y procesador, no hay necesidad de efectuar la compilacién dindmicamente, du- rante la ejecucién, siendo posible compilar a codigo nativo. Para ello existe lo que se ha venido a Hamar un pre-jilter, una herramienta que podemos utilizar desde la linea de comandos para compilar cualquier ensamblado. Esto es espe- cialmente apropiado, por ejemplo, en el caso de los propios servicios de la pla- taforma .NET. Estos se encuentran precompilados, por lo que no es necesario volver a compilar su cédigo con cada aplicacién. Informaci6n de tipos Aparte de cédigo y recursos, los ensamblados también contienen informa- cidn sobre los elementos 0 tipos con que cuentan. A esta informacién se le Ha- ma habitualmente metadata o meta-informacién. Gracias a la informacién de tipos, el CLR puede efectuar todo el trabajo que se ha descrito en un punto pre- vio. El compilador JIT convierte el codigo MSIL en codigo native, pero deja la informacion de tipos en manos del CLR. Para establecer una analogia, y comprender mejor en qué consiste esta meta- informacién, pensemos un momento en el contenido de un servidor COM que aloja un control ActiveX. En el interior de la biblioteca no sdlo se encuentra el cédigo del control, también existe una libreria de tipos que permite que ese control pueda ser manipulado visualmente, por ejemplo en el entorno de Vi- sual Basic. Visual Basic no podria mostrar las propiedades de los controles si no existiese esa libreria de tipos. E] caso de la informacion de tipos incluida en los ensamblados es identico. La informacién de tipos en los ensamblados no sélo hara posible la manipu- lacién visual de los componentes, sino que también sera util, por ejemplo, para trabajar con objetos mediante enlace en ejecucion. Usando determinados servi- cios de la plataforma incluso podemos recuperar esa informacion desde apli- caciones propias. Hl 3. La plataforma Microsoft .NET Servicios .NET para las aplicaciones Las aplicaciones .NET se escriben en un determinado lenguaje, que podemos elegir libremente, y para hacer su trabajo se apoyara en los servicios que ofrece la propia plataforma .NET. Estos servicios se alojan en ensamblados precom- pilados, ensamblados compartidos que podemos encontrar en el depdsito glo- bal del que hablabamos anteriormente. En los capitulos siguientes conoceremos algunos de los servicios .NET, par- te de los cuales se han representado en la figura 3.8. Por una parte tenemos los servicios que pedriamos denominar comunes, accesibles independientemente de] tipo de aplicacion que estemos desarrollando, Con ellos podemos trabajar con bases de datos, manipular documentos 0 XML o acceder a elementos remo- tos. Sobre éstos se encuentran los servicios para la Web y para Windows. Figura 3.8. Esquema de parte de los servicios de /a plataforma Microsoft .NET Desde nuestras aplicaciones, usaremos estos servicios creando objetos de clases definidas en determinados ambitos 0 espacios con nombre. Al crear, en el segundo capitulo, un formulario Windows, por ejemplo, estabamos usando una clase, llamada Form, definida en el ambito System. Windows.Forms. Puntos clave * Las necesidades de desarrollo actuales son muy distintas a las de hace unos anos y, consecuentemente, las herramientas de desarrollo usadas hasta ahora comienzan a no ser suficientes. * La plataforma Microsoft .NET facilita un entorno de ejecucién comin para multiples lenguajes, un sistema de tipos también comin y una bi- blioteca de clases con servicios fundamentales. Programacion con Visual ce NET [EER El ensamblado constituye la unidad basica de distribucién y seguridad de una aplicacion .NET. Un ensamblado consta de un manifiesto, codigo IL y recursos * Un ensamblado puede constar de un solo médulo o estar formado por varios. El manifiesto, alojado en uno de los médulos, establece la relacién logica entre ellos que da lugar al ensamblado. * La mayoria de los ensamblados son privados, pudiendo usarse tan solo internamente en el proyecto del que forman parte. Existen ensamblados compartidos, como los que albergan los servicios de la plataforma .NET, que se alojan en un lugar bien conocido. * Al iniciar una aplicacién .NET, los ensamblados que la componen se alo- jan en el contexto de un dominio de aplicacién * Alcompilar un proyecto Visual C# NET el ensamblado obtenido no aloja cédigo ejecutable, sino cédigo intermedio. Este, conocido como MSIL, es independiente de procesadores y plataformas. * Fl cédigo IL se compila a cédigo nativo, por parte de un jilter, justo en el momento en que es preciso ejecutarlo. También es posible precompilar a cédigo nativo si se desea * Las aplicaciones NET se ejecutan en un entorno comun, conocido como CLR, que consta de servicios basicos como los encargados de gestionar la memoria y recolectar basura. * EICLR reconoce un conjunto comin de tipos Hamado CTS. EL CLS, un sub- conjunto de CTS, asegura la interoperabilidad entre lenguajes * Ademas de cédigo, los ensamblados también alojan en su interior infor- macion de tipos. Esta resulta fundamental, por ejemplo, a la hora de mani- pular los componentes en entornos visuales. * La plataforma .NET consta de una serie de servicios, en forma de biblio- teca de clases de componentes, que facilitan el desarrollo de todo tipo de aplicaciones: Windows, Web, servicios, acceso a datos, ete. Resumen Al finalizar este capitulo ya disponemos de una nocién general sobre la es- tructura de las aplicaciones .NET, asi como del proceso que se sigue hasta que se llega a su ejecucién. Partiendo de nuestro proyecto se generan uno 0 mas en- samblados, cada uno de los cuales aloja codigo MSIL e informacion de tipos. Cada ensamblado puede componerse de multiples archivos, utilizandose un manifiesto para definir tanto los elementos que forman parte del ensamblado como las dependencias que tiene respecto a otros. Los ensamblados se alojan en memoria, en el momento de la ejecucién, tras r verificados por el CLR. Este es el encargado de crear el dominio o AppDomain 3. La plataforma Microsoft NET para la nueva aplicacién, incluir en él los ensamblados y crear el primer hilo de ejecucion. A medida que es necesario, el cédigo MSIL va compilandose a cédi- go nativo, trabajo que efectta el compilador JIT 0 jitter. El CLR, aparte de ofre- cer servicios basicos, supervisa la ejecucién encargandose de tareas como la recoleccién de basura o gestion de excepciones. Se han introducido muchos términos y conceptos que, a partir del capitulo siguiente, necesitaremos conocer para ir avanzando en el conocimiento del len- guaje C# y los servicios .NET. 4 Tipos de datos Un programa es una secuencia de sentencias u érdenes cuyo fin principal, generalmente, es manipular informacion. Esa informacion se almacena en va- riables, se introduce en el cédigo en forma de constantes o es recuperada de di- versas fuentes. En cualquier caso es fundamental que conozcamos los tipos de datos que existen en Visual C# .NET, asi como la forma de aprovecharlos en nuestros propios programas. El objetivo de este capitulo no es slo darle a conocer los tipos de datos dis- ponibles en el lenguaje, sino también mostrarle como declarar y utilizar varia- bles, crear sus propias estructuras de datos 0 bien como trabajar con arreglos, caracteres y constantes. El sistema comun de tipo En el capitulo anterior se citaba la existencia de CTS, un sistema comtin de tipos compartido por todos los lenguajes disponibles para la plataforma Mi- crosoft .NET. Estos pueden clasificarse segtin el esquema de la figura 4.1. Como puede ver existen dos grandes ramas: los tipos que almacenan valores y los que alojan referencias. Es una diferencia fundamental Los tipos de datos que almacenan directamente un valor ocupan un espacio de memoria en la pila, generalmente asignado de manera estatica, de modo que su manipulacion resulta muy eficiente. Por el contrario, los representados en la rama derecha son tipos de datos que podriamos denominar como complejos. 4. Tipos de datos El espacio de memoria necesario para almacenar la informacién es asignado dinamicamente, tomandolo de un area conocido habitualmente como heap. Lo que se obtiene es una referencia al lugar en el que se encuentra el valor, no el valor en si. Cada vez que quiere recuperarse al valor, o manipularse, es necesa- rio tomar la referencia y acceder al espacio de memoria previamente asignado El tiempo empleado, por tanto, es algo mayor: Referencias Figura 4.1. Clasificacion de los tipos de datos NET En este capitulo vamos a centrarnos basicamente en los tipos de datos de la rama izquierda: intrinsecos, enumeraciones y estructuras. Posteriormente abor- daremos el tratamiento de los distintos tipos de clases y las interfaces. Si tra- taremos a continuacién el uso de arreglos. Un sistema de tipo unificado La mayoria de lenguajes actuales, excepcién hecha de Smalltalk y pocos més, diferencian claramente entre objetos y datos que no son objetos. En C++, por poner un ejemplo bien conocido, los tipos de datos intrinsecos, como enteros y caracteres, no pueden ser tratados como objetos de una clase. Podriamos, no obstante, definir clases que encapsulan esos tipos de datos, eso si, a costa de una bajada importante del rendimiento, que es lo que ocurre en Smalltalk. Visual C# NET cuenta con un sistema de tipos unificado y combina lo mejor de ambos mundos, de los lenguajes en los que todo es un objeto y de aque- Ilos en los que existen tipos de datos que no son objetos. Para conseguir esto todos los tipos de datos de Visual C# .NET parten de una raiz comtn, llamada Object, de la que derivan, por una parte, los tipos que almacenan directa- mente el valor y, por otra, los que mantienen referencias. En la figura 4.2 se ha representado esquematicamente, y de manera simplifi- cada, este sistema de tipos unificado. La raiz, como acaba de decirse, es Object Programacién con Visual Ct .NET Uno de sus tipos derivados es ValueType que, como puede ver, actiia como base de todos los tipos de datos intrinsecos, como Byte, Char o Integer, asi como de las enumeraciones y estructuras definidas por el usuario. ValueType Figura 4.2. Sistema de tipos unificado de Visual C# .NET La rama de la derecha representa cualquier clase, ya sea existente en la pla- taforma .NET, como Array y Queue, o definida por el usuario. Todas ellas de- rivan también de Object. Contamos, por tanto, con un ascendiente comun para todos los tipos, independientemente de que almacenen un valor 0 una re- ferencia. Esto tiene muchas ventajas ya que, en la practica, cualquier tipo pue- de ser tratado como si fuera un objeto, al estilo de Smalltalk. Los tipos que almacenan valor, sin embargo, tienen un rendimiento muy eficiente, equipara- ble a los tipos intrinsecos de C++ y muchos otros lenguajes. Empaquetado y desempaquetado de datos El almacenamiento en memoria de un tipo de dato por valor y otro por re- ferencia, representado en la figura 4.3, afecta al rendimiento y, légicamente, determina en cierta manera la forma de usar el dato en si. La variable entera que aparece en esa figura contiene directamente un valor, de tal forma que el acceso al dato es directo y prima el rendimiento. La representada debajo, una variable que tiene como tipo una clase, almacena una referencia. El acceso al dato requiere un paso adicional, pero a través de esa referencia puede accederse no solo al valor, sino a todos los miembros de que disponga de la clase: mé- todos, propiedades, ete. La existencia de una raiz comin, segtin se ha visto en el punto previo, fa~ cilita la conversién de cualquier tipo de dato que almacena un valor en un objeto que lo contiene, y viceversa. Es lo que se conoce como boxing (empaque- tado) y unboxing (desempaquetado). El entero que aparece en la figura 4.3, por ejemplo, puede ser empaquetado para tratarlo como un objeto en una colec- cién de objetos heterogéneos, algo que no podriamos hacer si fuese un valor simple 4. Tipos de datos ‘Clase Verable = New Clese() Figura 4.3. Representacién de dos variables, una conteniendo un valor y otra una referencia Dado que tanto los tipos que almacenan valores como los que contienen re- ferencias son derivados de Object, la conversion de uno a otro, empaquetado o desempaquetado, se produce automaticamente, de manera implicita, aunque también podemos especificar de manera explicita el tipo deseado. El codigo siguiente muestra algunas situaciones en los que se empaqueta y desempaqueta un valor entero. /{ un entero con un valor inicial int Numero = 5; fy un objeto Object RNumero; RNumero = Numero; // empaquetado J? Aqui RWumero tiene el valor 5 Console. WriteLine(RNumero) ; // al asiqnar un nuevo valor se J/ produce un nuevo empaquetado RNumero = 10; J( desempaquetamos Numero = (int )RNumero; // y mostramos los valores Console.WriteLine(Numero)}; Console. Writeline(RNumero); // Aqui se produce un nuevo empaquetado Console.WriteLine(10.GetType())? Observe en este cédigo, en la declaraci6n de variables, que es posible asig- nar un valor inicial en el mismo momento de la declaraci6n, Esto contribuye a simplificar el trabajo, al no ser necesaria una asignacién separada tras cada declaracién. Al ejecutar esta aplicacién de consola obtenemos el resultado que puede ver- se en la figura 4.4. En principio RNumero toma el valor que tenia inicialmente isual C# NET aly Programacién con Numero en el momento de proceder al empaquetamiento. Observe, ya al final del codigo, come podemos incluso usar una constante para invocar a métodos de Object, en este caso concreto en el método Get Type(). En ese caso tam- bien se produce un empaquetado del yalor para obtener un objeto, tras lo cual se llama a Get Type() Figura 4.4. Valores empaquetados y desempaquetados Recurriendo una vez mas a la herramienta ildasm, que hemos usado en capitulos previos, podemos acceder al codigo MSIL generado a partir del pro- grama anterior y ver, como en la figura 4.5, el momento en que se realiza el empaquetado y desempaquetado de datos. En dicha figura, por ejemplo, se ha destacado la linea en la cual se empaqueta el valor 10, que aparece en la po- sicion anterior, justo antes de llamar al método Get Type ( ) Tipos intrinsecos Conocemos con esta denominacién a los tipos de datos que podriamos con siderar como fundamentales para el lenguaje: numeros enteros y con parte de cimal de distintos tamafios, caracteres, cadenas, légicos, etc. Si ha programado previamente con C, C++ 0 Java, posiblemente le resulten familiares tipos como int, Long 0 bool, pero seguramente no sabra que algunos de esos tipos, aun- que coinciden en nombre, pueden almacenar rangos de valores distintos La tabla 4.1 resume los tipos de datos de Visual C# .NET. Todos estos tipos existen en la plataforma .NET y en C#, forman parte del CTS pero algunos de ellos no de la especificacion CLS, por lo que no existen como tales tipos natives en ciertos lenguajes, como Visual Basic NET Tabla 4.1. Tipos de datos intrinsecos de VisualC# .NET . byte Numero entero de 8 bits sin signo sbyte Numero entero de 8 bits con signo short ushort int uint long ulong float double decimal bool char string object Numero entero de 16 bits sin signo Numero entero de 16 bits con signo Numero entero de 32 bits sin signo Numero entero de 32 bits con signo Numero entero de 64 bits sin signo Numero entero de 64 bits con signo Numero con parte decimal de precision simple Numero con parte decimal de precisién doble Numero con parte decimal fija para calculos financieros true 0 false Un caracter de! conjunto Unicode Cadena de caracteres Referencia a cualquier objeto Private Midebysig static void Wain(string(] args) cil wanaged sentrypeint Ceustom instance void [nscorlib]systen_statnreadattribs 71 Cowe size smaxstack 1 Thocals init (0) 61 (0x34) Ainta2 Numero, [1] object RMunero) Tae 19.5 stioc-0 Adloc-0 box stloc-1 agioc-1 [nscorlib]systen.1nt32 void [rscorlib]system.Console: :WriteLine(object) void [mscorlib]systen.Console: :Writeline(int92) void [mscorlin]system.console: :Writeline(object) 10 ‘instance class [mscorlib]systen.Type [mscorlib]systen void [mscorlib]System.Console: :Uriteline(object) Figura 4.5. En el cédigo MSIL es facil encontrar el punto en el que se empaquetan los datos Programacién con Visual Ct NET Observe el tamaiio de los tipos enteros, ya que difiere de los habituales en la mayoria de compiladores de C/C++. int es un numero de 32 bits, no de 16, y long es un entero de 64 bits Cada uno de los tipos de Visual C# tiene una correspondencia con un tipo del CTS de la plataforma .NET. En realidad, los tipos de la tabla 4.1 son el nom- bre que se les ha dado en Visual C# .NET a los tipos del CTS. En la tabla 4.2 puede ver la correspondencia entre tipos de Visual C# .NET y su denomina- cién en el ambito System de la plataforma .NET. Tabla 4.2. Equivalencia de tipos entre Visual C# .NET y el CTS System.Byte byte system.sByte sbyte System. Int16 short System. UInt1l6 ushort system. Int32 int System.UInt32 uint System.Int64 long system.uInt64 ulong System.Single float System.Double double system.Decimal decimal System.Boolean bool System.Char char system.String string System.Object object System. IntPtr No existe system.UIntPtr No existe Tipos no ajustados a la CLS Algunos de los tipos de datos que aparecen en tabla 4.2 forman parte del sistema comun de tipos de la plataforma .NET, por lo que cualquiera que de- sarrolle un nuevo lenguaje puede, opcionalmente, implementar su uso. No son tipos de datos, sin embargo, que aparezcan en la especificacién CLS. Esto significa que su presencia en un lenguaje no es indispensable y en ciertos len- guajes, por ejemplo Visual Basic .NET, no existen como tipos nativos. Que esos tipos no aparezcan como natives en el lenguaje no significa que no puedan ser utilizados. Al ser parte de la plataforma .NET, es posible declarar BW 4. Tipos de datos variables de esos como si fuesen estructuras creadas por nosotros mismos. En el siguiente programa, por ejemplo, se muestra como utilizar el tipo IntPtr para trabajar con un puntero, Se utilizan los servicios de interoperabilidad de la plataforma .NEY para asignar un bloque de memoria, escribir un dato en él, posteriormente recuperarlo y, finalmente, liberar esa memoria. using System; / Ambito en el que esta contenido la // clase Marshal using System.Runtime.InteropServices; namespace Punteros { class Classl ‘ [STAThread] static void Main(string|] arcs) { / Declaramos una variable de un t ente en C# po // no existente nativa System.IntPtr Puntero; (/ Asignamos un bloque de memoria Puntero = Marshal.AllochGlabal (255); (/ y escribimos en el primer byte un valor Marshal.WriteByte(Puntero, 16); // Mostranos la direccion y el valor gue contiene Console.WriteLine("{0} = {1)", Puntero.ToString(}, Marshal.ReadByte(Puntero) }; // hiberanos la memoria Marshal.FreeHGlobal (Puntero) ; La sintaxis {0} y {1} en el primer parametro del método WriteLine( ) se utiliza para introducir los valores de los parametros que se facilitan en segundo y tercer lugar. La ejecucién del programa genera la salida de una cadena de caracteres (véase la figura 4.6) en la que se muestra la direccién del blogue de memoria asignado, recuperada directamente a partir de la variable IntPtr mediante el método ToString(), y el valor recuperado de esa direccion. De manera analoga podriamos utilizar los demas lipos de datos, incluso los que aparecen come natives en C#. Es equivalente usar System.Integer a utilizar int. Programacion con Visual C# NET [RO Figura 4.6. Direccién del bloque de memoria y valor que contiene Declaracién de variables Los tipos de datos no son utiles por si mismos, de una manera aislada. Su fi- nalidad es facilitar la manipulacion de informacién, por ejemplo estableciendo la estructura de una variable en memoria y el formato de los datos que puede contener, Las variables pueden ser declaradas en diferentes ambitos: interior de una funcién, interior de una clase, etc. Ademas, existen una serie de pala- bras clave que nos permiten indicar la visibilidad de la variable fuera de ese ambito. ‘Ademas del ambito, en la declaracién también se establece el tipo de las va- riables que, como ya sabe, determina los valores que podran contener. De manera opcional, es posible dar un valor inicial en el mismo momento de la declaracién. De no especificarse lo contrario, las nuevas variables tendran asignado un valor por defecto Ambitos y visibilidad Utilizando sintaxis de declaracién por defecto, que es lo mas habitual, la va- riable tendrd el Ambito por defecto. Este determina que una variable declarada en el interior de una funcién, por ejemplo, sélo sea visible en su interior y, ademas, su vida se limite al tiempo durante el que esa funcidn esta ejecutando- se. Es lo que se conoce habitualmente como variable local. Un ambito aun més reducido tienen aquellas variables declaradas en un bloque de cédigo, como puede ser un bucle o un condicional. ‘Tan slo puede accederse a ellas desde instrucciones existentes en ese bloque. En contraposi- cién, una variable declarada fuera de cualquier funcién, al de clase, sera com- partida por todo el cédigo de esa entidad. $i ademas usamos el modificador public, la variable sera visible en todo el namespace, el Ambito con nombre en el que se introducen las clases que formaran la aplicacién. de date: Es mds facil comprender esto mediante algo de cédigo. Iniciamos una nue- va aplicacién de consola e introducimos el codigo siguiente: using System; namespace Ambitos class Class] { // Variable visible en todo el namespace public int Enterol = 5; // Variable visible s6lo en e1 médulo private int Entero2 - 10; [STAThread] static void Main(string[] args) { Class1 Miobjeto = new Classi(); // Variable visible sélo en Main() int Entero3 = 15; Miobjeto.Auxiliar(); // invocamos a otro método // Creamos un objeto de la clase Simple Simple MiSimple = new Simple(}; MiSimple.Enumera(}; // y llamamos a Enumera() // &n este punto son visibles todas las variables a // excepcion de la existente en la clase Simple Console.WriteLine("Main()"); Console.WriteLine("{0}, {1} y {2}", MiObjeto.Enterol, Miobjeto.Entero2, Entero3); } // Método auxiliar en el mismo médulo y ambito public void Auxiliar() « Console.WriteLine("Auxiliar"); (/ No tiene acceso a Entero3 porque es una variable visible // sélo en el interior de Main() Console.WriteLine("{0}, (1) y (2)", Enterol, Entero2, Entero3); (J Una clase que esta en el mismo namespace pero /) tuera de la anterior class Simple { // esta variable es privada de la clase private int Entero4 ~ 20; public void Enumera(} { Console.WriteLine("Simple.Enumera()"); Programacién con Visual C#.NET [RE // Aqui no tenemos acceso a la variable de Main) // nia la del médulo (Entero2), pero si a la visible // en todo el namespace Console.Writebine("(0}, {1} y (2}", Enterol, Entero4, Entero2 */); } Como puede ver, tenemos cuatro variables enteras llamadas Enterol, En- tero2, Entero3 y Entero4, cada una de ellas con un ambito distinto. La primera esta declarada en el interior de Class1 pero usando el modificador public, lo que da como resultado que la variable sea visible en todo el Ambito con nombre, 0 namespace, establecido como principal en la ventana de opciones del proyecto. La segunda, a pesar de declararse en el mismo punto, sdlo es vi- sible en class1 ya que se ha usado el modificador private Entero3 es una variable local al método Main( ), de ahi que no sea accesi- ble desde ningtin punto externo, ni desde la funcién Auxiliar(), que esta en la misma clase, ni desde una clase externa pero dentro del mismo namespace. Por ultimo tenemos Entero4, una variable con visibilidad limitada a la clase Simple. Esto significa que cualquier método de esa clase puede acceder a la variable, pero ningun cédigo externo tiene esa posibilidad. El cédigo, tal y como aparece mas arriba, genera errores de compilacién. Para obtener un ejecutable valido sustituya los parametros no accesibles por el va- lor 0. Ahora podré ejecutar, obteniendo un resultado similar al de la figura 4.7 Figura 4.7. Valores de las variables en distintos puntos No se preocupe en este momento por la sintaxis utilizada para definir una clase, crear un objeto a partir de ella y usar sus métodos. Es un aspecto del que nos ocuparemos con detalle en un capitulo posterior. B 4. Tipos de datos Vida de una variable Al trabajar con variables es necesario distinguir entre lo que es la visibili- dad, los puntos desde los que puede accederse a ella, y la vida de la variable, que es el tiempo transcurrido desde el momento en el que empieza a existir hasta que se destruye. En el programa anterior, por ejemplo, la variable Ente~ ro3 comienza a existir cuando se inicia la ejecucion del método Main ( ), destru- yéndose cuando éste finaliza. Lo mismo ocurriria, por ejemplo, si hubiésemos declarado una variable en el método Auxiliar(). El tiempo de vida, por lo tanto, esta limitado al espacio de tiempo durante el que se ejecuta el método en cuestion. Distinto es el caso de la variable Entero4, declarada como miembro de una clase. Cada vez que se crea un objeto de esta clase se inicia la vida de la varia- ble, permaneciendo accesible para todos los métodos de la clase hasta que el ob- jeto sea destruido Por Ultimo tenemos las variables Enterol y Entero2, pertenecientes a la clase Class]. Mediante ciertos modificadores es posible alterar el tiempo de vida de una variable sin, por ello, alterar su visibilidad. Por ejemplo, en el caso de la varia~ ble Entero4, local a la clase Simple, seria suficiente con anadir delante stat ic para tener una variable que existe desde que se inicia el programa hasta que termina, una variable compartida por todos los objetos de esa clase. La visibi- lidad, sin embargo, seguiria siendo la misma. Una variable estatica, nombre con el que se conoce a las declaradas usando la palabra static, tiene utilidad en caso de que deseemos mantener su valor mas alla del tiempo de vida del blo- que en que se encuentra Seguramente comprendera el concepto de variable estatica, y su funciona- miento, mucho mejor con un ejemplo. Nuevamente partimos de una aplicacién de consola. En este caso ademas del método Main() contaremos con otro, lla- mado MuestraVariables(). La clase cuenta con dos variables del mismo tipo. Estas dos variables, como puede ver en el codigo siguiente, tienen un tiem- po de vida distinto. La primera se ha declarado sin mod ificador alguno, dando lugar a una variable automdtica. Asi se conoce a las variables que son creadas cada vez que se entra en su ambito y destruidas al salir de él, en este caso cada vez que se crea un objeto de la clase CLass1 y cada vez que dicho objeto se destruye o libera. La segunda, por el contrario, es estatica, de tal forma que existe durante toda la ejecucion del programa. using System; namespace Variablesrstaticas £ class Class! 4 /{ una variable normal byte valorl; /{ y otra estatica static byte Valor2; Progranacion con Visual C# NET sat) [STAThread] static void Main(string[] args) { byte Contador; fer(Contador = 1; Contador <= 10; Contador++) MuestraVariables(); > Método con dos variab static void MuestraVariables() { Class] MiObjeto = new Classl(); Miobjeto.valori++; Class1.Valor2+ y mostranos su contenids Congole.WriteLine{"Valor1={0), Valor2=(1}", MiObjeto.Valorl, Classl.Valor2); } } Alejecutar el programa obtendra un resultado como el de la figura 4.8, en el que se ve claramente que en cada llamada al metodo Muestravariables() la variable Valor] tiene de partida el valor 0, mientras que Valor2 conserva el contenido de la invocacién anterior y, por ello, su valor va incrementandose en cada llamada Figura 4.8, Valores obtenidos por las variables locales Las variables declaradas en el interior de una clase pueden tener un tiempo de vida asociado a los objetos creados a partir de ella, segtin se ha descrito 4, Tipos de datos anteriormente, o bien una vida global asociada a la propia clase. Observe que para acceder a Valor 1 es necesario contar con un objeto de la clase, ya que dicha variable no existe de forma aislada. Valor 2, por el contrario, existe desde el principio, sin necesidad de crear objeto alguno, y por ello se puede hacer referencia a ella utilizando el nombre de la propia clase. Especificacion de tipo Ademas del ambito, el tiempo de vida y el identificador de la propia varia- ble, una declaracién debe completarse especificando su tipo. Lo ha visto en los ejemplos previos, donde hemos usado variables de tipo int y byte. Basta con poner delante del identificador de la variable el nombre del tipo que deseamos. Cuando multiples variables vayan a compartir el mismo tipo, no hay que in- dicarlo repetidamente, siendo suficiente la separacion de identificadores con comas y la indicacién del tipo al inicio, como vemos en el siguiente ejemplo int Varl, Var2, Var3; byte Vard, vars; En este caso Var 1, Var2 y Var3 son de tipo int, mientras que Var4 y Var5 son de tipo byte Asignacion de un valor inicial Otra posibilidad, en la declaracion de una variable, es asignar un valor ini- cial a las variables en el momento de la declaracién, ahorrando asi una asigna- cién posterior. Lo ha podido ver también en alguno de los ejemplos usados en este capitulo. Basta con poner el simbolo = al final, seguido del valor inicial que, logicamente, debera estar en consonancia con el tipo que se ha indicado. En caso de que estemos declarando mas de una variable del mismo tipo, los valores de cada una de ellas irian detras del identificador. En la linea siguiente tiene un ejemplo de este caso concreto. int varl = 5, var2 = 10, Var3 = 15; Ademas de valores constantes, en la asignacién del valor inicial también podemos usar otras variables e, incluso, expresiones que den como resultado un valor del tipo que espera la variable. Tipos definidos por el usuario Ademas de los tipos de datos que podriamos denominar intrinsecos, pre- definidos en el lenguaje, Visual C# NET nos permite usar cualesquiera otros Programacién con Visual C# .NET 117 que hayamos podido definir. Siempre ciféndonos a los tipos que almacenan valores, no referencias, es posible crear basicamente dos tipos de datos: enu- meraciones y estructuras. En un capitulo posterior veremos que también es posible definir tipos de referencia, concretamente clases de objetos. Tanto las enumeraciones como las estructuras son entidades derivadas de System. ValueType. Una enumeracion puede definirse practicamente en cual- quier lugar, como las declaraciones de variables, mientras que las estructuras sélo pueden aparecer en clases, siendo tipos mds complejos que las enumera- ciones. Légicamente, en Visual C# .NET existen enumeraciones y estructuras pre- definidas, muchas de las cuales conocera al estudiar servicios como GDI+, en capitulos posteriores. Aparte, nosotros podemos también definir nuestros pro- pios tipos. Enumeracione La mayoria de los tipos de datos intrinsecos permiten que una variable tome un valor de una lista mas o menos limitada. Una variable de tipo byte, por ejemplo, puede contener un numero entre 0 y 255, un boolean sdlo puede te- ner los valores true 0 false, y lo mismo ocurre con los tipos enteros y el tipo char. Siempre que necesitemos una variable que deba tomar un valor de una lista limitada, no existente en ninguno de los tipos intrinsecos ni enumeraciones predefinidos, podemos crear nuestra propia enumeracién. Suponiendo que en una aplicacion médica necesitemos variables que contengan valores represen- tando misculos, huesos y otros elementos, podriamos definir las enumeracio- nes apropiadas. Una de ellas podria ser la siguiente: enum Dedo {Pulgar, indice, Corazén, Anular, Mefique }; El identificador Dedo es, a partir de esta definicion, un nuevo tipo de dato. Podemos usarlo como cualquier otro, int, string, byte, etc., para declarar variables. Las variables de tipo Dedo tan sélo podran contener uno de los va- lores que aparecen en la enumeracién. FE] editor de Visual C# .NET, al efectuar una asignacién de una variable de este tipo, se ocupa de mostrar (véase la fi- gura 4.9) la lista de posibles valores. Internamente las variables de tipo Dedo almacenan un valor entero que representa a la constante que corresponda. En el caso de la enumeracion Dedo, la constante Pulgar tiene asociado el valor 0, fndice el 1 y asi sucesivamen- te. Puede comprobarlo facilmente haciendo algo asi: DedoAfectado = Dedo.Corazén Console.WriteLine((int }Dedoafectado) Si lo que quiere obtener no es el valor equivalente a Dedo . Coraz6n, en este caso, sino el nombre de la constante, puede usar el método ToString( ) conel B 4. Tipos de datos que cuentan la mayoria de los tipos de datos. Utilizando DedoAfectado.To- String(), por tanto, no obtendriamos el valor 2. sino la cadena Corazén. El mismo resultado obtendriamos facilitando a WriteLine() simplemente la va- riable DedoaAfectado, sin conversién a int ni llamada a Tostring(). nonespacs Emuneraciones ‘ enum Dedo (Pulgar, fadice, Corazén, Anulac, NeBique }+ clase Clases “ (staTnreaay static void Main(string() acas) « Dedo veacarectado; Dedoatecvedo = pedo, Console. WriveLinegg sToseedag()): , ‘coanen ’ Neti , Pr des Figura 4.9. El editor reconoce al tipo de la variable y muestra los valores que podemos asignarle Comprobacién estricta de tipos Si, partiendo de la enumeracién definida en el punto anterior, declara una variable de tipo Dedo y después le asigna un valor numérico, comprendido en- tre 0 y 4, vera que Visual C# .NET genera un error. Lo que ocurre es que no se efecttia una conversion implicita, automatica, para convertir el entero en la constante que corresponda. C# es un lenguaje con comprobacién estricta de tipos, caracteristica propia del lenguaje en si, no de la plataforma .NET. Otros lenguajes, como es e] caso de Visual Basic .NET, efecttian de manera implicita conversiones entre tipos que, en C#, deben realizarse de manera explicita. Por regla general es preferi- ble la actitud de C#, evitando efectuar conversiones automaticas entre tipos que pudieran causar efectos laterales inesperados. De hecho, aunque Visual Basic NET por defecto no efecttia una comprobacién estricta de tipos es una caracte- ristica que puede activarse mediante una opcidn de configuracién. al C# NET Programacion con Vis Para poder asignar un valor entero a una variable de tipo Dedo, por tanto, es necesario emplear una conversién explicita, cuya sintaxis seria la siguiente Dedoafectado = (Dedo } 3; En este caso el valor 3 se convierte a la constante equivalente en la enumera- cién Dedo. A veces a estas conversiones explicitas se les Hama moldeados de tipo. [BH Tnrvaraconee Meron VeunCy MET Aeon] Cum Wave Elkin Yer Borate Girma Obst Herrarreas Yertane) Arua me epee: B- | > co STDP rom co Caanrade deci | ate ES] [fgewmccines contd fut antec oo_ class classi (stararead] seaic void Main(stringf] acge) “ Dede Dedoagestade; Dedaktectado = Dedo.Pulgar: Dedohfectado = (Dedo }3: Console. WriteLine (Dedoxtectado) : Figura 4.10. Conversién explicita de un entero a una enumeracion La comprobacién estricta de tipos afecta no sélo a las enumeraciones. Tam- poco podremos asignar directamente, con conversion implicita, un numero decimal a una variable entera, por poner un caso. Bs la situacion que puede ver ena figura 4.11, en la que Visual Cé NET nos informa sobre el error de la asig- nacion directa. En estos casos tendremos que indicar, de manera explicita, que deseamos efectuar la conversion, como hemos hecho en el caso anterior. En el caso de la figura 4.11 tendriamos que utilizar (int )Pi Debe tener en cuenta que ciertas conversiones implican la pérdida de parte de la informacion original. Es lo que ocurre, por ejemplo, cuando se asigna un numero con parte decimal a una variable entera. BE 4. Tipos de datos {9TAThread) static void Nain(string{] args) ‘ Dedo Dedoatectado; float Pi = 9,2415927F; inc Envero = Bas DedoAtectado = (D > Console, WriteLine (Dedoktectado} ; Figura 4.11. La asignacién con conversién implicita no es posible Estructuras Las enumeraciones son tipos simples, al estilo de los enteros y caracteres. Una estructura, por el contrario, es un tipo complejo compuesto de uno 0 mas miembros, cada uno de ellos pudiendo ser de cualquier tipo. Una estructura puede contar incluso con constructores y métodos, como las clases, sin, por ello, dejar de ser un tipo que mantiene un valor, no una referencia. Una estructura es el tipo adecuado cuando la complejidad de la informacién no es excesiva y, por tanto, no justifica el diseno de una clase especifica para gestionarla, crean- do objetos a partir de ella. Es el caso, por ejemplo, de estructuras como Point, Size o Color, definidas para mantener la informacion de un punto, unas di- mensiones o un color. A pesar de todas las similitudes, hay que tener en cuenta que una estructura y una clase son entidades muy distintas. Las estructuras siempre estan deriva- das de System. ValueType, mientras que las clases pueden derivarse unas de otras. El fragmento de codigo siguiente, por ejemplo, define una estructura que cuenta con cuatro miembros: tres cadenas de caracteres y un valor numérico de tipo float. Al igual que ocurre con las enumeraciones, partiendo de esta defi- nicién ya podemes crear variables de tipo Libro Programacion con Visual C# .NET [EA struct Libro { public string Titulo; public string ISBN; public string Autor; public float Precio; Para acceder a los miembros con que contaria una variable de este tipo es necesario utilizar el operador . disponiéndolo entre el nombre de la variable y el del propio miembro. De esta forma, podriamos establecer u obtener los va- lores de la siguiente manera: Libro UnLibro; UnLibro.Titulo = "Guia praéctica Visual Basic .NET UnLibro.Autor = “Francisco Charte Ojeda"; UnLibro. ISBN = "84-415-1290-6"; unLibro.Precio = 10.75F; Asignacion e igualdad La variable UnLibro almacena directamente los valores asignados a !os miem- bros de la estructura, siendo posible la asignacién directa entre variables del mismo tipo, como ocurre con el resto de los tipos que hemos conocido hasta ahora. No es posible, por el contrario, conversién alguna con variables de otros tipos, caso en el cual tendriamos que acceder de manera individual a los miem- bros que nos interesen para recuperar o asignar el valor. En el cédigo siguiente ve un caso hipotético en el que quiere asignarse el con- tenido de una variable Libro a otra del mismo tipo, algo totalmente correcto, tras lo cual deseamos asignar el valor de una cadena a la primera variable, Esto no es valido. Como puede suponer, habria que escribir UnLibro.Titulo = Titulo. Libro UnLibro, OtroLibri string Titulo = “Programacién con Visual Studio .NET"; UnLibro. Titulo = "Guia practica Visual Basic .NET*; UnLibro.Autor = "Francisco Charte Ojeda"; UnLibro.ISBN = "84-415-1290-6"; UnLibro.Precio = 10.75F; OtroLibro = UnLibro; // Correcta Unbibro = (Libro )Titulo; // Incorrecta La comprobacién de igualdad entre estructuras es otra operacién que no po- demos realizar como es habitual, utilizando el operador ==. En el fragmento de cédigo anterior, por ejemplo, no podriamos codificar un condicional del si- guiente modo: if€(UnLibro == OtroLibro) | 4. Tipos de daios Todas las estructuras cuentan con un método, llamado Equals ( ), que faci- lita la comprobacion entre estructuras del mismo tipo. Una sentencia como la siguiente mostraria por la consolatrue o false, dependiendo de que UnLibro y OtroLibro sean iguales 0 no. Console.WriteLine(OtroLibro.Equals(UnLibro)); Miembros piblicos y privados Una diferencia de las estructuras de C#, respecto a las de lenguajes como C, es que los miembros no sélo cuentan con un identificador y un tipo sino que, ademas, pueden precederse de un modificador que indique su visibilidad. En la estructura Libro definida antes todos los miembros son public, de tal ma- nera que puede accederse a ellos desde cualquier punto donde se haya defini- do una variable Libro. Podriamos haber omitido el modificador public, obteniendo el mismo re- sultado. Las otras alternativas son private e internal. Con el primero los miembros ser{an privados, de tal manera que no podrian manipularse desde fuera de la propia estructura. Con el segundo tendriamos una combinacién de public y private, ya que los miembros de la estructura serian piblicos para el cédigo del mismo ensamblado en el que se ha definido la estructura, perma- neciendo como privados para otros ensamblados. Posiblemente se pregunte qué sentido tendria declarar los miembros de una estructura como privados, de tal manera que no puedan manipularse directa- mente desde el exterior. La respuesta se encuentra en el punto siguiente Métodos, constructores y propiedades A diferencia de las estructuras existentes en otros lenguajes, las de C# no sélo pueden contener miembros de datos sino que, ademas, pueden también contar con funciones y procedimientos actuando como métodos, que operan sobre los datos; constructores, que facilitan la inicializacién, y propiedades, mediante los cuales controlar el acceso a esos datos. En el capitulo dedicado a la programacién orientada a objetos nos ocupare- mos con mayor detalle, al estudiar las clases, de los constructores, la definicion de propiedades y métodos. Por ahora nos conformaremos con ver como aiiadir un método y un constructor a la estructura Libro, dejandola como se muestra a continuacién. (/ estructura para datos de un libro struct Libro { // Constructor para inicializar el contenido public Libro(string T, string I, string A, float P) ‘ Titulo = T; ISBN = Autor = A; Precio = P; Programacion con Visual C# NET 123 // Hetodo para mastrar el contenido public void Muestra() { Console.WriteLine("{0}, {1}, (2h, Titulo, ISBN, Autor, Precio); » / Hienbros private string Titulo; private string ISBN; private string Autor; private float Precio; ? Observe que ahora los miembros de datos son privados, no publicos, de tal modo que no pueden ser manipulades desde el exterior. Los dos procedimien- tos aparecen delante, aunque igualmente podriamos haberlos puesto detras. Fl primero de ellos es el constructor debido a que hemes usado como identiticador el propio nombre de la clase. El segundo es un metodo corriente, al que pode mos invocar cuando nos convenga. Observe que el constructor no tiene tipo de retorno, ni siquiera void. Si declarasemos una variable de tipo Libro sin darle un valor inicial en ese momento, posteriormente no podriamos asignar un valor a sus miembros como si haciamos en ejemplos previos. Utilizando el constructor, a través de la pa- labra clave new, podriamos efectuar esa asignacion, mientras que con el método Muestra() obtendriamos el contenido. Fs lo que se hace en el ejemplo siguien te que, al ser ejecutado, genera el resultado de la figura 4.12. La primera varia ble esta vacia, mientras que la segunda tiene los valores asignados en el momento de la creacion. static void Main(string[] args) { Libre Unbibro = new Libro(); Libro OtroLibro = new Libro("Introduccion a la programacion", "g4-415-1145-4", "Francisco Charte Ojeda", 24.046); UnLibro.Muestra()}; OtroLibro.Muestra(); Arreglos Los tipos de datos que hemos usado hasta ahora, en ejemplos previos, tan sélo pueden contener un dato, ya sea simple: un numero, un caracter o una ca- dena, o bien compuesto: una estructura. Cuando se tiene la necesidad de alma- cenar multiples valores, del mismo tipo y con informacién relacionada, se usan los arreglo Un arreglo es una lista de variables del mismo tipo que comparten el nombre, distinguiéndose unas de otras por un indice. Los arreglos también son conocidos Bt. Tipos de datos como matrices, aunque esta denominacién es mas apropiada para los arreglos de dos dimensiones. A diferencia de las estructuras, enumeraciones y demas tipos de datos conocidos hasta ahora, una variable de tipo arreglo no aloja el valor sino una referencia al bloque de memoria donde éste se encuentra Figura 4.12. Contenido de las dos estructuras Los arreglos, para ser mas exactos, cada uno de los elementos de un arreglo, pueden ser de cualquier tipo: enteros, cadenas, estructuras, referencias a obje- tos, etc. Incluso podemos tener arreglos de objetos creados a partir de una o va- rias clases. A su vez, un arreglo también puede formar parte de un tipo complejo, como pueda ser una estructura Declaracién de un arreglo Como cualquier otra variable, un arreglo debe declararse antes de ser utili- zado para almacenar valores. La declaracién es, basicamente, igual que la de una variable corriente, debiendo especificarse ¢l ambito, identificador y tipo Ademas, tras el tipo, delante del nombre de la variable, pondremos unos cor- chetes indicando asi que se trata de un arreglo. El numero de elementos del arreglo se indicara en el momento de asignarle un valor a la variable ya declarada, algo que puede ocurrir en la propia decla racién o bien posteriormente, Se usara el operador new seguido del tipo, por ejemplo int, y, entre corchetes, el numero de elementos del arreglo a crear. En ese momento se asignara el bloque de memoria necesario para crear el arreglo, suardando la direccion en la variable a la que se efectiia la asignacién. Los in- dices de esos elementos iran desde 0 hasta el numero de elementos indicado menos 1. En el ejemplo siguiente, por ejemplo, la variable DiasMes seria un arreglo con 12 elementos, desde el 0 hasta el 11 int [] DiasMes = new int{12]; No hay que olvidar que la variable DiasMes lo que contiene es una referen- cia al arreglo, y no el arreglo en si. Esa referencia podemos usarla para acceder ramacion con Visual C# NET individualmente a cualquiera de los elementos, disponiendo su indice entre corchetes: DiasMes(0] DiasMes(3} 31; // Enero 30; // abril Arreglos con varias dimensiones El arreglo DiasMes declarado en el ejemplo anterior cuenta con una sola di- mensién, de tal forma que puede representarse graficamente como una lista de valores. El rango de esa dimensién es 0-11, valores que puede tomar su indice. Un arreglo puede tener varias dimensiones, hasta un numero maximo de 60, cada una de ellas con un rango diferente. El rango de cada dimension puede contar con tantos elementos como valores posibles hay en el tipo Long. En la practica, con aplicaciones corrientes, no es habitual trabajar con arre- glos de mas de dos 0 tres dimensiones, mientras que el rango de cada una de ellas esta fisicamente limitado por la memoria disponible en el sistema, mas que por los limites propios del lenguaje. Suponga que desea contar con un arreglo en el que ir anotando una serie de datos estadisticos de cada una de las 24 horas de los 365 dias del ano. La declaracién de dicho arreglo podria ser la siguiente: // arregio con dos dimensiones float [,] Medidas - new float[365,24]; Mediante la variable Medidas podemos acceder a cualquiera de los 365 ele- mentos de la primera dimension, cada uno de los cuales cuenta con 24 elemen- tos de la segunda dimensién. Al acceder a un elemento, por tanto, es necesario facilitar dos indices: el ntimero del dia y el de la hora a la que corresponde la medida a almacenar o recuperar. El ntimero total de elementos en el arreglo sera de 365 por 24: 8760 elementos. Rangos dinamicos Aunque en los fragmentos de cédigo anterior, al declarar un arreglo, siem- pre hemos indicado el indice superior del rango de cada dimension, nada nos impide declarar arreglos sin un rango inicial. Si es necesario, sin embargo, in- dicar el ntimero de dimensiones con que contara. Por ejemplo, si no supiéramos de antemano cuantos dias vamos a tomar medidas, en el supuesto del punto anterior, ni cuantas horas de cada dia, podriamos declarar el arreglo Medidas de este modo: J 4 Tipos de datos (/ Arreglo con dos dimensiones float [,] Medidas; Mientras no establezcamos el rango de las dimensiones de este arreglo, la variable Medidas tiene una referencia nula. Cualquier acceso usando esta re- ferencia causaria una excepcion. Puede usar la constante null para compro- bar si se ha hecho una asignacién a la variable o no, o bien usar el operador is para comprobar su tipo. Fl cédigo siguiente demuestra como utilizar esas dos alternativas Arregio con dos dim static float [,] Medidas; // ~ new float/365,24]; sTathread} static void Main(string|] arcs) « // B1 tipo de Hedidas es n Console.WriteLine( Medidas null ? “null” : Medidas.ToString()); Esta expresion devuelve Palse Console.WriteLine(Medidas is Array); El resultado de ejecutar este cédigo es el de la figura 4.13. Puede ver que el valor mostrado en el primer caso es null, indicando que Medidas no tiene referencia alguna en ese momento. La comprobacién de si el tipo de la variable es Array da como resultado el valor False Figura 4.13. La variable Nedidas no tiene una referencia valida El tipoarray es una clase de la cual estan derivados implicitamente todos los arreglos que declaremos. A continuacion conocera algunos de los mé- | todos de esa clase, heredados automaticamente por los arreglos | Programacién con Visual Cé NET Ed Para establecer el numero de elementos de cada dimensién de la variable Medidas, efectuaremos una asignacién del arreglo creado con el operador new, como se ha hecho en ejemplos previos en el mismo momento de la declaracion. El numero de elementos de las dimensiones pueden ser, en lugar de constantes, datos introducidos por el usuario 0 recuperados de una base de datos. En el si- guiente fragmento de cédigo, por ejemplo, se pide por teclado el numero de dias y horas durante las que van a tomarse medidas, usando esos valores para es- tablecer el numero de elementos del arreglo. short Dias, Horas; // Solicitamos el nimero de dias y horas Console.Write("Introduzca el mimero de dias: “); Dias ~ Convert.ToInt16(Console.ReadLine()); Console.Write("Introduzca las horas por dia: "); Horas = Convert .ToInt16(Console.ReadLine()); // y los usamos para establecer el nimero de // elementos del arreglo Medidas = new float[Dias, Horas]; El método Readbine( ) de la clase Console devuelve una cadena de carac- teres con el valor introducido por el usuario. Dado que nosotros necesitamos el valor numérico, no la secuencia de caracteres que lo componen, usamos la funcién de conversién ToInt16() de Convert para realizar esa transforma- cién, Finalmente nos servimos de los datos obtenidos para establecer el nume- ro de elementos del arreglo. Si después de establecer las dimensiones del arreglo, con la sentencia ante- rior, comprobamos el tipo de la variable Medidas veremos que ya no es null, sino Single[,], y que la comprobacién Medidas is Array devuelve True en lugar de False. La técnica anterior no es util sdlo para establecer e] numero de elementos inicial de un arreglo, pudiendo utilizarse también para modificar dicho name- ro cuando interese. El rango de elementos de cada dimensién no es algo estatico, sino dinamico, de ahi que podamos alterarlo cuando nos convenga. El cambio, no obstante, implica en realidad la creacion de un nuevo arreglo, con los ele- mentos indicados, y la liberacidn del anterior, lo que implica la pérdida de la informacién que éste contuviese. Una solucién, para evitar esa pérdida, es asig- nar el nuevo arreglo a otra variable y, a continuacion, usar el método CopyTo ( ) de la clase Array para pasar los datos del arreglo que ya no interesa al nuevo Informacién sobre un arreglo Como se ha indicado antes, todos los arreglos son objetos derivados de la cla- se Array. Dicha clase cuenta con un importante numero de miembros, propie- dades y métodos principalmente, que nos permiten tanto operar sobre el arreglo como obtener informacion acerca de él. En este momento nos interesa lo segun- do, recuperar algunos datos relativos al arreglo sobre el que estamos trabajando. HB 4. Tipes de datos Esto es especialmente interesante si estamos usando un arreglo dinamico que va creciendo o decreciendo segtin las necesidades del programa. Algunos datos son realmente utiles, como el contenido en la propiedad Rank. que nos indica el nimero de dimensiones, o los devueltos por los métodos GetLength(), GetLowerBound() y GetUpperBound() que son el ntimero de elementos, el indice inferior y superior, respectivamente, de la dimension cuyo ntimero se entrega como parametro. Al igual que los indices, las dimen- siones se numeran desde 0 hasta el valor contenido en Rank menos |. Otras propiedades tan sélo son titiles en caso de que se derive una nueva clase tomando Array como base. Fs el caso de IsFixedSizeo IsReadOnly, ambas de tipo bool. La primera indica si el arreglo tiene un tamano fijo y la segunda si es de solo lectura, devolviendo siempre los valores true y false, respec tivamente. Conociendo estos miembros de Array, y sélo a titulo informative, podria mos codificar un método como el siguiente: /{ Metodo para obtener informacion de un a static void InformeArreglo(Array Arreglo) { byte Dimension; // Bjecutar solo si es un arregio no nulo if(Arreglo is Array} { Console.WriteLine(* "ye Console.WriteLine("Tipo del arreglo: {0)", Arreglo.GetType(}); Console.WriteLine("IsFixedSize - (0)", Arreglo.IsFixedSize); Console.WriteLine(*IsReadOnly = {0}", Arreglo.IsReadOnly}; Console.WriteLine("{0} dimensiones", arregqlo.Rank); for(Dimension = 0; Dimension>=, equivalentes a +, -, /, %, & |, <> pero asumiendo que el primer operando de la expresién sera la misma variable que va a recibir el re- sultado. Operadores aritmético La finalidad de esta familia de operadores es permitirnos realizar el conjun- to de operaciones matematicas mas basico, como son la suma, resta, multipli- cacion y division. Cualquiera de estos operadores siempre toma dos operandos y genera un resultado. En la tabla 5.1 podemos ver un resumen de estos opera- dores, junto con la operacién que realizan. En esta tabla N1 representa al primer parametro, el que se situa a la izquierda del operador, y N2 al segundo, a la derecha del operador amacion con Visual C& NET Pro, Tabla 5.1, Operadores aritméticos + Suma de N1 y N2 = Halla la diferencia entre N1 y N2 * Multiplica N1 por N2 / Divide N1 entre N2 % Resto de la operacion N1 \ N2 Estos operadores, como es obvio, trabajan sobre cualquiera de los tipos nu- méricos que conocemos, enteros o coma flotante, independientemente de su pre- cision. Sin embargo, cuando en una misma expresién utilicemos operandos de distinto tipo numérico C¢ realizara las conversiones necesarias para guardar la mayor precision posible. Trabajando con ntimeros los primeros cuatro opera- dores no requieren ningtn comentario adicional, se limitan a realizar las cuatro operaciones aritméticas indicadas. Para hallar el resto de la division entera entre dos ntimeros podemos utili- zar el operador %, que toma exactamente los mismos parametros que / y rea- liza una division entera devolviendo el resto que se obtendria Por medio del operador + podemos trabajar, ademas, con cadenas de carac- teres, tipo string, siendo en este caso el resultado la concatenacion de ambas. Obtendremos, por tanto, una nueva cadena formada por la primera mas la se- gunda En caso de que en una misma expresién se utilicen distintos operadores arit- méticos y no se alteren las prioridades, por medio de paréntesis, siempre se evaluaran primero los operadores /, * y % de izquierda a derecha, y por ultimo + y - de izquierda a derecha. Operaciones con variables Object Cuando realicemos operaciones aritméticas con variables del tipo object el resultado vendra dado por el tipo de dato que en ese momento contenga la variable, que puede ser numérico, de cadena, fecha u otro tipo, y el segundo operando, alterando el tipo del receptor del resultado cuando sea necesario me- diante conversiones explicitas. De no indicarse la conversién, una simple suma puede provocar una excepcion de conversion invalida Observe el cédigo siguiente: object Valor = 5; Console.WriteLine("{0} -> {1)", Valor, Valor.GetType().ToString()); valor = (long )((int )valor + 1L); Console.WriteLine("{0} -> {1)", Valor, Valor.GetType().ToString()); 5. Operaderes y ¢: valor = (fleat)((long )Valor + 1.5F); Console.WriteLine("{0} -> {1}", valor, Valor.GetType().ToString()); valor = (string)((float}Valor + * pesetas"); Console.WriteLine("{0} -> {1}", valor, Valor.GetType().ToString()); En él contamos con una variable de tipo ob ject que, inicialmente, contiene el valor numérico 5. Recuperamos el tipo, con el métode Get Type(), y lo mos- tramos como una cadena de caracteres, con ToString(). Acto seguido suma- mos un valor long indicando las conversiones adecuadas y mostramos de nuevo el tipe, que se habra visto alterado. Lo mismo ocurre al sumar un nt mero con parte decimal y al concatenar una cadena. Es algo que puede ver en la figura 5.1, que es el resultado obtenido al ejecutar ese codigo. Figura 5.1. El tipo de la variable cambia dinamicamente Légicamente, utilizando una variable de un tipo especifico, como int, esas conversiones explicitas no podrian tener lugar. En otros lenguajes, como es el caso de Visual Basic .NET, las conversiones de tipo de una variable object pueden incluso producirse implicitamente, sin necesidad de indicar la conver- sion mediante codigo. Operadores relacionales Este conjunto de operadores nos permitirdn evaluar expresiones y obtener dos resultados posibles: true, sila expresién es cierta o devuelve un valor dis- tinto de cero, o false, si la expresién es falsa 0 devuelve cero. También se les conoce como operadores de comparacién. Se utilizan principalmente en estruc turas de decisién, en las que dependiendo del valor obtenido se toma un ca mino u otro, y de control de repeticion En la tabla 5.2 se enumera cada uno de los operadores de comparacién, junto con una pequena descripcién en la que N1 representa al primer operando y N2 al segundo. Programacién con Visual C# NET 143 Tabla 5.2. Operadores relacionales o de comparacion N1 y N2 son iguales N1 y N2 son distintos t= N1 y N2 son distintos N1 y N2 son iguales < N1 es menor que N2 N1 es igual 0 mayor que N2 <- N1 es menor o igual a N2 N1 es mayor que N2 > N1 es mayor que N2 N1 es igual 0 menor que N2 De N1 es mayor o igual a N2 N1 es menor que N2 Por medio de estos operadores podemos comparar nitmeros, cadenas y fe- chas. En el caso de los ntiimeros sera su valor el que intervenga directamente en la relacion. Si comparamos dos cadenas en realidad se compararan los codigos de cada uno de los caracteres que la componen, de tal forma que "Mafiana" no sera igual a "mafana", ya que el codigo de la *M' no es el mismo que ‘m' Al trabajar con dos fechas se utilizara la representacién interna de las varia- bles tipo Date para saber si una fecha es igual, anterior o posterior a otra. Hay que tener en cuenta que una variable del tipo Date ademas de la fecha también puede contener Ia hora, por lo que al realizar una comparacién puede que no obtengamos el resultado esperado. Por ejemplo, dos variables Date pueden contener la fecha del dia de hoy, pero si una tiene una hora y otra no, o tiene una hora distinta, las variables no cumplirdn la relacion de igualdad. Es posible utilizar en una misma expresién operadores aritméticos y re- lacionales, caso éste en el que, antes de que se evaltte una expresién relacional, previamente se realizaran los calculos aritméticos necesarios para que los ope- randos a comparar sean slo dos. Operadores légicos En algunas ocasiones una expresién relacional no esta compuesta tan solo de dos operandos y un operador de comparacién, sino que son necesarios varios operadores y mas operandos. En estos casos es necesario unir las distintas sub- expresiones por medio de algtin elemento, que fije a su vez unas reglas entre cada una de las relaciones. Entre otras ésta es la finalidad de los operadores 16- gicos. Los operadores légicos, a excepcién del operador | (Not ), toman dos expre- siones normalmente relacionales, que como sabemos pueden devolver true o false. Con esta pareja de valores el operador realiza otra operacién, en este caso légica, para obtener un solo valor. En la tabla 5.3 puede encontrar los dis- tintos operadores logicos, asi como los valores que devuelven segun que las expresiones de entrada sean ciertas o falsas. E1 representa el valor devuelto por la primera expresién y E2 el devuelto por la segunda, Como ya se ha dicho estos valores sélo seran true o false. y expresiones Tabla 5.3. Operadores légicos us Et=true y E2-true En cualquier otro caso i E1= ! —1 rue 0 E2-true E1-talse y E: alse E1=true Como ve, el operador ! sélo toma un parametro y devuelve el valor inverso al devuelto por la expresion. Por ello se le llama operador de negacién. Aunque podemos usar estos operadores para obtener un resultado y almace- narlo en una variable de tipo bool1, lo habitual, como ocurre con los operadores relacionales, es que los usemos en el contexto de una sentencia condicional o de control de repeticién. Vera ese tipo de construcciones en el proximo capitulo. Operaciones entre bits Ademas de realizar operaciones Idgicas, existe un conjunto de operadores similares a los vistos en la tabla 5.3 que nos permiten manipulat los bits indivi- duales dentro de un numero. En ocasiones, sobre todo cuando se realizan ope- raciones con funciones de bajo nivel, necesitamos comprobar si un cierto bit de un dato esta encendido 0 apagado, o bien precisamos poner a 0 6 1 un cierto bit. Para poder trabajar a nivel de bits es basico conocer la base 2 0 binaria, como se pasa un numero de decimal a binario o viceversa. Partiendo de las reglas de cada uno de los operadores y asumiendo que un bit a0 indica £alse mientras que un bit a I significa true, es facil comprender el funcionamiento de las operaciones entre bits. Vamos a detallar seguidamen- te las tres actuaciones mas habituales. Si deseamos poner a 1 un bit de un determinado dato, Ilamémosle W1, uti- lizaremos el operador | (OR ldgico). Este tiene la caracteristica de actuar sobre dos operadores y si cualquiera de ellos es true (1) el resultado es true. Por lo tanto, si tenemos N1 y realizamos una operacién logica | con el numero 0 jqué ocurriria? Nada, N1 quedaria igual, ya que si en él un bit esta a 0 al realizar un | con 0 obtenemos 0, mientras que siun bit estaba a 1 al realizar un | con 0 se obtendra de nuevo 1 Partiendo de esta base supongamos que N1 contiene el conjunto de bits 00001001, que equivale al ntimero 9, y deseamos activar el segundo bit!. Ten- dremos que realizar una operacién légica | con un numero cuyo segundo bit estéa Ly el resto a 0, de tal forma que no se modifique ningiin bit, recuerde la operacién que hemos realizado antes, excepto el que hemos puesto a 1. El nit mero que necesitamos es el 4, cuya representacin binaria, 00000100, tiene a 1 s6lo el bit que necesitamos. Pruebe a ejecutar simplemente la instruccién Console.WriteLine(9 | 4), obtendrd como resultado 13, que pasado a de- cimal es 00001101. Los bite se numeran de derecha a izquierda, desde el bit D hasta el bit 7 Por Lo tantoen este caso los bits que estan, a | son el bit Oy 3. Programacién con Visual Ct NET La operacién contraria, poner un bit a 0, la llevaremos a cabo con el opera- dor que es funcionalmente contrario: & (AND légico). Si tenemos un numero, llamémosle N1, y realizamos una operacion ldgica & entre él y otro numero cu- yos bits estén todos a 1, el resultado obtenido sera de nuevo N1. Por lo tanto, para poner a 0 un cierto bit tendremos que hallar un ntimero que tenga a 1 todos sus bits excepto aquel que deseamos poner a 0. Siguiendo con el ejemplo anterior, supongamos que N1 ahora tiene el valor 00001101, después de la ope- racion efectuada, y deseamos apagar el segundo bit. Necesitariamos entonces la secuencia de bits 11111011, que es la del numero 251. Ejecute la sentencia Console.WriteLine(13 & 251) y vera cémo obtiene el 9 que teniamos ori- ginalmente Por ultimo tenemos que poder comprobar si un cierto bit esta encendido o apagado, a 0 6 1. La técnica mas facil y comun es poner a 0 todos los bits ex- cepto el que se desea comprobar, si el numero resultante es 0 es porque dicho bit estaba a 0, si se obtiene otro miimero es porque estaba a 1. Volvamos una vez mas sobre el ejemplo anterior. En este caso N1 vuelve a tener el valor 9 y queremos comprobar si el segundo bit se encuentra apagado o encendido, por lo que deberemos apagar todos los bits menos ese. La mascara de bits necesa- ria es 00000100, que corresponde de nuevo al nitmero 4. Ejecute la sentencia Console.WriteLine((9 & 4) != 0) y observe el resultado, False. Ello indica que la expresion es falsa, que el segundo bit no esta a 1 en el numero 9. Realice la misma prueba con el nimero 13 y vera como el valor devuelto es True, ya que en él si estd a 1 dicho bit. Con el fin de aclarar algo mas el concepto de trabajo con bits vamos a crear un pequefto programa cuya finalidad sera mostrar la representacién binaria de los ntimeros 0 a 255. El resultado se muestra en la figura 5.2. El codigo necesa- rio esta estructurado en tres bucles, tal y como puede verse a continuacion. Los dos primeros distribuyen la informacién en 64 filas por 4 columnas, el valor minimo de I y K es 0, siendo I=0 y K=0 la operacién I*4+K devuelve 0, mientras que el valor maximo es 255, siendo 1=63 y K=7 la misma operacion devuelve 255. Cualquier numero comprendido en este rango se puede repre- sentar con ocho bits, por ello existe un tercer bucle, controlado por la variable J, que recorre esos ocho bits pero en sentido inverso, de 7. a 0, ya que como recor- dara los bits se numeran de derecha a izquierda. Para saber si el ntimero generado por 1*4+K tiene a 1 un cierto bit, debere- mos realizar una operacién légica & con un mimero que tenga a 0 todos los bits menos el que se desea comprobar, que es el bit J. Para crear dicho niimero se realiza la operacién Pow(2,J), siendo 2 la base de numeracién binaria y J el numero de bit a comprobar. Pow() es uno de los métodos de la clase Math, de- finida en el Aambito System. Por tanto, si el resultado de la operacion es true es que el bit esta a 1 y asi se imprime, mientras que en caso contrario es 0. imt I, J, K; for(I = 0; I < 64; I++) ( // 64 filas Console.wWrite("{0}->{1}", Tea, ‘\t'); // Primer nimere de la file Operadores y expresiones for(K = 0; K < 4; K++) { // por 4 columnas for(s = 7; 0 // I*44K es el if Pow(2,7) nos dara un numero cuyo bit J esté a1 /f y los demas a 0. /{ El resultado de 1a expresién sera true / si dicho bit esta a 1 en /f en caso contrario df((I * 4+ K & (int )System.Math.Pow(2,J)) != 0) Console.write("1"); else Console.Write("0"); Console.Write(‘\t'); // Ir al proéximo punto de tabu ) // Cada mimero tiene & bits imero a comprobar, de 0 a 255 } Console.Writebine(); // Ir a la siguiente linea Figura 5.2. Representacién binaria de los nimeros 0 a 255 Programacion con Visual C# NET 147 Expresiones con referencia Los operadores relacionales, especialmente el operador == de igualdad, no siempre tendran el comportamiento que podriamos esperar, especialmente al trabajar con referencias. En los ejemplos anteriores siempre hemos tratado con variables que almacenan valores, lo cual no plantea problema alguno. Al tratar con variables que mantienen referencias, sin embargo, el caso es distinto. En C#, como en otros lenguajes .NET, existe la posibilidad de facilitar una implementacién a medida en sus clases para determinades operadores, por ejemplo el de asignacion e igualdad. Esto no implica, sin embargo, que el con- cepto de igualdad sea equivalente al que hemos visto hasta ahora. Observe el codigo siguiente int [] Listal = (1, 2}, Lista2 = (1, 2}; etType().Tostring()); // obte Console.WriteLine(Listal. fiy Console.WriteLine(Listal == Lista2); nprobanos si so // Asignamos a Lista2 la misma referencia // que tiene Listal, apuntando ambas variables // al mismo arreglo Lista2 = Listal; Console. WriteLine(Listal == Lista2}; Alejecutarlo vera que aparece el tipo del arreglo y, a continuacidn (véase la figura 5.3) quiza le sorprenda ver que el resultado de la primera comprobacion de igualdad dé false como resultado. Aparentemente Listal y Lista2 son dos arreglos idénticos: del mismo tipo y con el mismo numero de dimensiones y de elementos. Es cierto, pero no le es menos el hecho de que realmente son dos arreglos distintos, si bien con los mismos valores. Cuando asignamos el valor de Listal a Lista? el resultado si es el espe- rado, ya que ambas variables contienen una referencia al mismo arreglo. Dicho de olra manera, el operador == en este caso no comprueba la igualdad de los arreglos, sino la de las referencias que contienen las variables. En este caso la solucién es clara, tendriamos que comparar individualmente los elementos de los arreglos para saber si son iguales, no basta una expresion simple como la mostrada en el ejemplo anterior. Otro caso peculiar es el que se presenta, como veremos en el capitulo dedi- cado al trabajo con clases de objetos, cuando necesitamos comprobar el tipo de objeto al que mantenemos una referencia en una variable. Hay que tener claro que hablamos del tipo del objeto, no del valor que contiene la variable, por lo que no son titiles operadores como ==. En este caso el operador a usar seria is En la sentencia siguiente, por ejemplo, puede ver como comprobamos si el tipo del objeto al que apunta Listal es Int32[]. Console.WriteLine(Listal is System. Int32{])7 5. Operadores y expresiones Figura 5.3. Resultados de la comparacién de las dos variables Puntos clave * Una expresién constituye una combinacién de operandos y operadores que tiene por finalidad efectuar una o mas operaciones obteniendo un re- sultado. * Las expresiones simples pueden ser aritméticas, relacionales y légicas, siendo habitual la combinacién de estas categorias que forman expresio- nes mas complejas. * Existen versiones abreviadas de operadores aritméticos que toman como primer operando la variable destinataria del resultado. * Los operadores aritméticos facilitan las operaciones basicas: suma, resta, multiplicacin, divisién y resto de divisién entera. « Mediante los operadores relacionales se establece una comparacién entre los operandos, obteniendo como resultado true o false seguin que la re- lacién sea cierta o no, respectivamente. * Los operadores légicos se utilizan, principalmente, para unir multiples expresiones relacionales y obtener un resultado unico. « También podemos usar operadores légicos para manipular bits de un dato o comprobar el estado de esos bits. * Cuando se trabaja con referencias el operador valores. ¢ El operador is nos permite comprobar el tipo del objeto correspondiente a la referencia almacenada en una variable devuelve true sola- mente en el caso de que las dos variables contengan la misma referencia, no cuando los objetos apuntados, siendo distintos, contengan los mismos Programacion con Visual C# NET [RRQ Resumen Ahora que conocemos los operadores disponibles en Visual C# .NET pode- mos, en la practica, efectuar cualquier operacién sobre los datos de la aplica- cion: operaciones aritméticas, comprobaciones relacionales y composiciones logicas. Muchas de estas expresiones tienen utilidad por si mismas, por ejem- plo una operacién aritmética para obtener un resultado y almacenarlo en una variable, mientras que otras se aplican en diversas construcciones que tendra ocasién de conocer en el préximo capitulo, como los condicionales y los bucles. En la plataforma .NET existen ambitos que contienen servicios mediante los cuales se facilitan operaciones mas complejas. En el ambito System, por poner un ejemplo, existe una clase, llamada Math, en la que encontrara multitud de funciones para realizar operaciones aritméticas y trigonométricas, como Sin(), Cos(),Round(), Pow() 0 Sign(). Otras clases, como DateTime, cuentan con métodos especificos para operar sobre el tipo de dato concreto que almacenan. 6 Estructuras de control Como lenguaje derivado de C y con influencias de otros come Pascal y Java, C# cuenta con las estructuras de control clasicas en este tipo de lenguajes. Gra- cias a ellas es posible la ejecucian condicional de sentencias, la ejecucion re- petitiva o el control estructurado de excepciones: Tambien introducimos en este capitulo elementos como los métodos, ya que en cierta forma ayudan a es tructurar el codigo y suponen un elemento de primer nivel Fl objetivo de este capitulo es describir las estructuras de control basicas del lenguaje C# mostrandole, con ejemplos basics, como usarlas. Las descrip- ciones, no obstante, no son exhaustivas contemplando cada variante posible, ya que esta informacién puede encontrarla facilmente, una vez que haya leido el capitulo, en la referencia de la especificacion de C# structuras condicionales En muchas ocasiones las lineas de codigo de un método no se ejecutan de forma secuencial, sino que dependiendo de que la evaluacién de una expresion sea cierta o falsa se toman distintos caminos, o se ejecutan distintas instruccio- nes, Las sentencias que nos permiten realizar esta operacién son las condiciona- les, basadas en la evaluacién de expresiones en las que intervienen, por regla general, operadores relacionales y légicos. Para evaluar una expresion simple podemos utilizar la estructura if, que ya hemos visto en algunos de los programas de los capitulos anteriores. Tras la J 6. Estructuras de control oe sentencia if dispondremos, entre paréntesis, una expresién a evaluar, que pue- de estar formada por operandos de cualquier tipo y operadores, tanto aritméti- cos como relacionales o légicos, Como ya sabemos, cualquier expresion de este tipo se reduce a dos resultados: verdadero o distinto de 0, en caso de que la expresién se cumpla, y falso 0 0, en caso de que no sea asi. En el primer caso se ejecutard la sentencia que se haya dispuesto a continuacién, en el segundo caso no se ejecutara. Por ejemplo, suponga que desea dar el valor 1 a una variable en caso de que otra tenga o no el valor true. La sentencia necesaria podria ser la siguiente: if(Variable == true} Resultado ~ En este caso la expresion es Variable == true, una expresién relacional. En caso de que sea cierta, si la variable contiene ese valor, entonces se ejecutara lasentencia Resultado = 1. Esta expresién puede quedar atin mas reducida, puesto que Variable, asumiendo que es de tipo bool, puede contener sélo dos valores: true o false, y su valor puede ser utilizado directamente como expresion if(Variable) Resultado = 1; Obtendremos exactamente el mismo resultado, la expresién sera cierta si Variable contiene el valor true y falsa si tiene false. Esta notacion se usa a menudo para comprobar directamente si una variable tiene uno u otro valor. En cualquier caso, tanto si la expresién se cumple como si no, la ejecucién continuara por la siguiente linea de cédigo. Es decir, la sentencia if utilizada de esta forma afecta solo a la sentencia que hay inmediatamente detras, pero noa las que le siguen En caso de que necesitemos ejecutar varias sentencias si la expresién se cum- ple, en el ejemplo anterior sélo se ejecuta una, podemos disponerlas en un blo- que, delimitado entre Haves. Supongamos que ademas de darle el valor 1 a Resultado también quiera dar el valor false a la misma variable implicada en la decision. Las sentencias podrian quedar como sigue if(Vvariable) { Resultado=1; Variable=False; Esta notacién, el uso de las Ilaves para escribir un bloque de varias senten- cias, no es exclusiva de las estructuras de control, puede utilizarla en cualquier momento, siempre que la necesite La salida falsa Como ya se ha dicho, tanto si la expresion es cierta, y por lo tanto se ejecu- tan las sentencias que hay tras el i£, como si no lo es, la ejecucion del programa Programacién con Visual Ct .NET seguira por la linea de codigo que corresponda. Por lo tanto habremos conse- guido que esas sentencias se ejecuten sélo si la expresion es cierta y en ningiin otro caso. En caso de que deseemos que otra sentencia 0 sentencias se ejecuten solo si la expresién no es cierta podemos utilizar la palabra else, tras la cual dispon- dremos esa sentencia o sentencias. Por ejemplo, observe el siguiente fragmento de codigo: Console.WriteLine("Se ejecuta siempre (antes)"); if( Variable) Console.Writenine("Es cierto"); else Console.WriteLine("Es falso"); Console.WriteLine|"Se ejecuta siempre (después)"); La primera linea se ejecutara siempre, la segunda contiene una decision de- pendiendo de la cual se ejecuta una sentencia u otra, mientras que la tiltima linea se ejecutara en cualquier caso. Fijese en que si hubiésemos dispuesto la llamada Console.WriteLine("Es falso") en la linea siguiente al if sin usar la palabra else, se ejecutaria siempre, mientras que tal y como se han es- tructurado sélo lo hara si la expresion es falsa, en ningun caso mas. Condiciones anidada Se puede dar el caso de que la sentencia que sigue a un if sea otro if, o que la sentencia que sigue a un else sea otro if, y esta circunstancia puede re- petirse varias veces de forma que tengamos una serie de decisiones anidadas. En este caso la notacién de las sentenciasif ... if ... else ... if ... puede ser poco menos que criptico y puede llevar a error, ejecutandose unas instrucciones cuando se deberian ejecutar otras. En caso de duda, lo mejor es delimitar entre Ilaves cada uno de los bloques de codigo asociados a cada if 0 else, aunque el sangrado del cédigo puede ser suficiente. Observe los siguientes condicionales int A, B, f(A == 1 if(B == 5) CHA B //A=1yB=5 else CHA Bp SA yaoos else if(A =~ 3) C= At B; // A= 3 y B= else CHA SB; //A=? y B=? Fijese cémo la parte que se ejecutara si A=1 contiene otra decision, con su correspondiente if ... else. La parte falsa, si Ano es 1, es también una de- cision, por lo que se usa un nuevo if para componerla. A la derecha de cada asignacion se detallan los valores que toman A y B para que se ejecute esa linea y no las otras. J 6. Estructur Si intenta ejecutar este codigo observaraé que se produce un error de com- pilacién. Esto se debe a que a las variables a y B no se les ha asignado un valor, intentando utilizarlas sin haber hecho previamente una asignacion no parece légico. Condicionales multiples Imagine un caso en el que una hipotética variable, Iamémosla B, pueda to- mar los valores 1, 2 6 3, y que dependiendo de ello tenga que ejecutar unas u otras sentencias. Tendriamos que utilizar la estructura de if/else/if/else hasta resolver todas las posibilidades. En casos como éste nos sera muy Util la estructura condicional switch/ case, que nos permite evaluar una expresion y a continuacion enumerar po: bles resultados, de tal forma que se ejecute un grupo u otro de sentencias de pendiendo del resultado que coincida con el obtenido por la expresién. Como ejemplo supongames que dependiendo de! valor de B tengamos que imprimir un texto u otro y, ademas, asignar un determinado valor a A switeh(B) ( case 0: Console.WriteLine("El valor de B no es valido” A= 0; break; case 5: Console.WriteLine("B tiene el valor éptimo"); A= 10; break; case 1: case 4: Console.WriteLine("B esté por debajo del valor dptimo"); A= 3; break; case 6: Console.Writebine("B esta por encima del valor 6ptimo"); A= 7; break; , En el bloque de cédigo anterior primero se compara si B es 0, de ser asi se imprime un mensaje determinado y se le daa la variable A el valor 0. A con- tinuacion se compara con otra constante, en este caso 5. A continuacion hay una sucesién de case que permiten ejecutar la sentencia siguiente si los valo- res de B estan comprendidos entre 1 y 4. Finalmente comprobamos si el valor es 6. Observe que cada bloque de sentencias termina con la palabra clave break, Programacion con Visual Ct NET evitando asi que el control pase de un bloque case al siguiente por descuido. Si olvida poner los break el compilador se lo recordara. Puede darse el caso de que el resultado obtenido de la expresion no coinci- da con ninguno de los case que nosotros hemos dispuesto, caso en el que nose ejecutara ningtin cédigo existente en el bloque de la sentencia switch ano ser que exista el apartado default. Cualquier codigo que pongamos a continua- cién de esta opcidn se ejecutara siempre que no se cumpla ninguna de las otras condiciones. Por ejemplo, en el siguiente fragmento de codigo el mensaje "Va- lor no valido para B" se mostrar cuando B no sea 5 o no esté entre Ly 4 switch(B) 4 case 5: Console.Writebine("B tiene el valor 6ptimo"); A= 10; break; case | case 2 case 3 case 4: Console.WriteLine("B est4 por debajo del valor éptimo"); A= 3; break; default Console.WriteLine("El valor de B no es vaélide"); break; Estructuras de repeticion Durante la ejecucién de un programa, asumiendo que cuenta con una interfaz de usuario, el codigo que nosotros escribimos se esta repitiendo constantemen- te. Cada vez que el usuario selecciona una opcidn, pulsa un botén, usa el te- clado, ete., el mismo cédigo es ejecutado para responder a los mismos eventos. Esta repeticién se efecttia a demanda del usuario, cuando es necesario, pero en ocasiones es necesario repetir las mismas lineas de codigo un numero determi- nado de veces seguidas. Obviamente no vamos a escribir multiples veces el mismo cédigo, sino que crearemos un bucle sirviéndonos de algunas de las sen- tencias con que cuenta C# para ello. Bucles por contador Uno de los tipos de bucle mas conocidos es el basado en la instruccién for y que suele estar controlado por un contador. Tras la palabra for, y entre pa- réntesis, se facilitan tres expresiones separadas por punto y coma: la primera se ejecuta una sola vez, al entrar en el bucle, ocupandose de la inicializacién; la segunda es ejecutada a cada ciclo y dependiendo del valor que devuelva, de tipo bool, dependera que el bucle continue ejecutandose, por ultimo, la tercera BE 6. Estructuras de control al también se ejecuta a cada ciclo y suele contener alguna actualizacion, por ejem- plo el incremento de un contador. Suponga que desea imprimir en la consola los numeros 10 a 20 ambos incluidos, bastara con el siguiente bucle. for(byte Numero=10; Numero<=20; Numerot+) Console. WriteLine(Numero) ; Observe cémo se declara la variable Numero en el interior del propio bucle, de tal forma que su Ambito quedaré reducido a las sentencias que sigan a éste, en este caso solamente una. Si nos interesa ejecutar mas sentencias asociadas al bucle no tenemos mas que delimitar las sentencias entre Ilaves, como ya hicié- ramos anteriormente con las sentencias condicionales. La ultima expresion que hay entre los paréntesis, en este caso Numero++, normalmente se encarga de actualizar la variable de control. En este caso la incrementamos en una unidad, pero podriamos sumarle o restarle cualquier otro valor, o efectuar un calculo cualquiera. Un bucle que esta programado para ejecutarse un nimero determinado de veces no tiene por qué completar siempre su ejecucion, puede darse el caso de que en el interior del bucle exista un proceso por el que en un momento deter- minado interese darlo por terminado. Para ello disponemos de la sentencia break, que provocaré la salida inmediata del bucle. En el siguiente fragmento de cédigo se evalua una expresién en el interior de un bucle, cuando ésta sea verdadera se provocaré la salida. fox (byte Numero=10; Numero<=20; Numerot+) q if(Numero==16) break; Console.WriteLine(Numero) ; y Un bucle no siempre es tan simple como para estar controlado por un con- tador, a veces no es posible saber de antemano el ntimero de veces que el co- digo se debe de ejecutar. En estos casos utilizaremos los bucles condicionales, que nos permiten repetir la ejecucién de una porcién de cédigo mientras una cier- ta condicion sea cierta. En realidad la instruccién for es un tipo de bucle condicional, aunque su uso mas habitual esta asociado siempre con un contador. Laestructura while (condicié6n) nos permite realizar un bucle que se re- petird mientras la condicién especificada sea cierta, 0 dicho de otra manera, el bucle se terminara cuando la condicién sea falsa. Por ejemplo, suponga que ne- cesita pedir un dato que no puede ser una cadena vacia, obligatoriamente debe Programacion con Visual C# NET tener al menos un caracter. EI siguiente fragmento de codigo hace precisamen- te eso, presentar continuamente un mensaje de saludo y mientras el usuario no conteste con algo el proceso se repetira una y otra vez. string Saludo = ""; while(Saludo == "") { Console. WriteLine("Hola, iqué tal? Saludo = Console.ReadLine(); } Console.WriteLine(Saludo); En este caso la variable Saludo se acaba de declarar, asignandosele como valor una cadena vacia. Esto significa que al entrar en el bucle la condicion inicialmente es cierta. Pero suponga que, antes de entrar en el bucle, Saludo tiene algun otro valor. Fl bucle no Hegara a ejecutarse ninguna vez, puede pro- barlo simplemente anadiendo la linea Saludo = "Hola" justo después de la declaracién. En los casos en que interese que el bucle se cjecute por lo menos una vez, aunque la condicion no sea cierta en principio, bastara con desplazar la condicién a la parte final del cédigo, pasando asi de un bucle en el que la evaluacién de la expresién se efectiia a la entrada, a otro en el que la expresion se evaltia a la salida. El bucle quedaria como se muestra a continuacion. do { Console.WriteLine("Hola, ique tal?"); Saludo = Console. ReadLine(); } while(Saludo == ""); Todas las expresiones que se han mostrado en los ejemplos son simples, com- probando sélo una relacidn entre dos operandos. Por supuesto podemos utili- Zar expresiones mas complejas en las que se vean envueltos operadores logicos, relacionales y aritméticos. De igual forma que era posible terminar un bucle por contador desde el in- terior del propio bucle, con break, la misma instruccién es aplicable a este tipo de bucles. Bucles que recorren un arreglo A menudo cuando utilicemos un bucle sera para trabajar sobre los elemen- tos de un arreglo, asignandole un valor, realizando calculos, etc. Fl siguiente fragmento de codigo, por ejemplo, crea un arreglo de cadenas y pide valores para cada elemento. string[) Cadenas = new string( 10]; for(int [=0; I<10; I++) { 6. Estructuras de control Console.WriteLine("Texto para el elemento (0): ", 1); Cadenas[1] = Console.ReadLine(); , Aqui Cadenas[I] representa a cada uno de los elementos del arreglo, ya que T ira recorriendo los indices existentes, en este caso desde el 0 hasta el 9. A continuacién podria imprimir cada uno de los valores que se han introducido, con un bucle del mismo tipo. También podemos usar el bucle foreach .. in, cuya finalidad es recorrer todos los elementos de un arreglo o una coleccion, sin necesidad de indicarle indices ni valores minimos 0 maximos. Tras la pa- labra foreach, entre paréntesis, deberemos insertar una variable del tipo ade- cuado que ira tomando el valor de cada uno de los elementos que existan en el arreglo, ejecutando el bucle por cada uno de ellos. Para imprimir el contenido del arreglo el cédigo necesario seria el siguiente. En él la variable Elemento tomaria el valor de Cadenas[ 0] y se ejecutaria el bucle, a continuacién el va- lor de Cadenas[ 1] y se repetiria el proceso hasta llegar al ultimo elemento. foreach(string Elemento in Cadenas) Console.WriteLine(Elemento) ; En realidad, podemos usar la construcci6n foreach/ incon cualquier tipo de dato que implemente la interfaz System. IEnumerable, no sdlo con colecciones y arreglos. En un capitulo posterior conocera las interfaces, su implementaci6n y uso. Utilizar este tipo de bucle en lugar de un bucle por contador tiene algunas ventajas. Una de ellas es que si después del diseno original del programa éste se modifica y el nimero de elementos del arreglo se reduce o amplia, en un bu cle por contador seria necesario retocar los indices, mientras que en un bucle foreach esto no seria necesario ya que se recorren los elementos que existan en ese momento Control estructurado de excepciones Al igual que la mayoria de lenguajes modernos, C# incorpora una estructu- ra que nos permite controlar las posibles excepciones que pudieran producirse durante la ejecucién del cédigo. La estructura general para controlar una posi- ble, o posibles, excepcién es la siguiente: try { // sentencias } catch (Tiporxcepcion) Programacién con Visual C4 .NET finally 4 // Codigo de Linalizac } Las sentencias que aparecen después de la palabra try son las que, poten- cialmente, podrian causar una excepeién durante la ejecucién del programa. Se ejecutaran normalmente a menos que aparezca dicha excepcién, caso en el cual se transferiré el control a las sentencias del catch apropiado, dependiendo del tipo de excepcidn. Por Ultimo, las sentencias que hay tras la palabra finally se ejecutaran siempre, indistintamente de que se produzca o no una excepcion Este apartado, que es opcional, es usado generalmente para liberar algun tipo de recurso. Observe el codigo siguiente, en él se genera una excepcidn al dividir un nu- mero por cero. La excepcion es capturada y se traduce en la salida de un men- saje. Si no hubiésemos ulilizado try /catch la excepcion detendria la ejecucion del programa comunicando el error, try { Cociente = 25 / Divisor; y catch 4 Console.WriteLine("Se ha producido una divisién por cero”); La sentencia que hay tras la palabra catch se ejecutara siempre que se ge- here una excepcion en algunas de las lineas que siguen a try, en este caso sdlo una. Si nos pusiésemos en un caso algo mas complejo, en el que las sentencias a controlar pudieran generar distintas excepciones, podriamos usar una varian- te de catch para efectuar un filtrado. Tomemos como base el fragmento de codigo mostrado a continuacién. int Cociente; int Dividendo, Diviso: try £ (f Solicitamoes intreduccion de los datos Console.WriteLine("Intreduzca el dividendo: "); // y convertimos a numere Dividendo = Convert. ToInt32(Console.ReadLine()); Console. WriteLine("Introduzca el divisor: "); // ba conversién puede generar una excepcién Divisor = Convert.ToInt32(Console.ReadLine()); Bo. Estructuras de control — // Efectuamos la division Cociente = Dividendo / Divisor; // y mostramos el resultado Console.WriteLine("El resultado es {0}", Cociente); } catch { Console.WriteLine("Se ha producido una division per cero"); > Las excepciones que pueden producirse en este caso son varias, aparte de la division por cero. Al convertir el valor solicitado por teclado a numero, median- te la funcién ToInt32(), también se podria generar una excepcion si dicha conversién fallase, por ejemplo por haber introducido un dato no numérico. Por ultimo, cabe la posibilidad de que se diera otro tipo de error aritmético. Cada una de las excepciones posibles esta representada en la plataforma -NET por una clase. Puede utilizar el Examinador de objetos, como se muestra en la figura 6.1, para localizar las distintas clases de excepciones. Todas estas clases estan derivadas de una base comin: la clase Exception, que puede ver seleccionada en el panel izquierdo de Ja figura 6.1. En el panel derecho de esa misma figura se enumeran los miembros con que cuenta esta clase, algunos de los cuales alojan informacion que puede resultarnos util. BX mOlo-5- BB) [Ate tee Figura 6.1. Buscamos las clases de excepciones utilizando el Examinador de objetos Programacion con Visual C# NET [RD Conociendo algunas de las clases de excepciones existentes, al fragmento de codigo anterior podriamos afiadirle el siguiente con la finalidad de controlar tres de las categorias de excepciones que, segiin comentabamos antes, podrian producirse. Si se produce una div catch(DivideByZeroexception x) { Console.WriteLine( “se ha producido una divisién por cero"); , // $i se ha producido un desbordamiento cateh(OverflowException x) « Console.WriteLine( "Se ha producido un desbordamiento"); > // en cualquier otro error aritmético catch(Exception X) { Console.WriteLine( "Se ha producide otro error"); Console.WriteLine(x.Message); Console.WriteLine(X.ToString(}); y La X que aparece después de cada catch es una variable de la clase de ex- cepcion indicada. En lugar de Hamarla x podria tener cualquier otro nombre, puesto que es un identificador que ha sido creado por nosotros. El control del programa se transferira a uno u otro catch dependiendo de la excepcién que se produzca. Observe que el iiltimo de los catch utiliza la clase Exception, la mas genérica, recogiendo de este modo cualquier clase de excepcidn distinta a las anteriores. Si introduce un valor no numérico como dividendo o divisor dara lugar a una excepcion como la de la figura 6.2, comunicando el error Figura 6.2. Mensaje de una excepcién 6. Estructuras de contro! Funciones y métodos Hasta ahora todo el cédigo que hemos necesitado para que nuestros pro- gramas funcionen lo hemos insertado, por regla general, en el método Main() que existe por defecto en el médulo, porque en realidad se ha tratado de |levar a cabo operaciones bastante sencillas. Sin embargo, cuando el programa tenga alguna finalidad mas que la simple comprobacion o prueba de un control o un operador, la cantidad de codigo necesaria crecera y en ocasiones necesitare- mos el mismo cédigo en distintos puntos del programa. Obviamente la solucion no es introducir una y otra vez todo el cédigo, tanto si se repite como si no. Para evitarlo podemos crear nuestras propias funciones, introduciendo en ellas el cédigo que después podra ser utilizado con una simple llamada. En otros lenguajes existen los conceptos independientes de funcién y proc dimiento. La unica diferencia existente entre un procedimiento y una funcién es que el primero no puede devolver pardmetro alguno, mientras que la segunda si. En C# todo son funciones, pudiendo considerarse como procedimientos aque- llas funciones cuyo tipo de retorno es void, es decir, no tienen un valor de re- torno. Por lo tanto, si vamos a codificar un proceso que realiza una determinada accion pero no devuelve valor alguno lo definiremos como una funcién que devuelve void, pero si es necesario devolver un valor cualquiera sustituire- mos void por el tipo que corresponda La denominacién método se aplica a procedimientos y funciones que forman parte de una clase. WriteLine( ), por ejemplo, es un método de la clase Console Dado que en C¢ todas las funciones tienen, obligatoriamente, que pertenecer a alguna clase, podriamos decir que todas las funciones en C# son métodos. Por ello los términos funcion y metodo se utilizan indistintamente en este capitulo. Declaracion de un método Basicamente, podemos crear un método como miembro de una estructura o bien como parte de una clase. Esa clase puede ser, por ejemplo, un formulario Windows, un componente o un servicio Web. Los métodos, al igual que las riables, pueden ser ptiblicos o privades, segtin puedan ser utilizados slo desde la clase en que se han definido o desde cualquier otro médulo de la aplicacion Por defecto los métodos son privados, por lo que no es necesario usar ningun modificador si es ésa la visibilidad que deseamos. En caso contrario podemos usar protected, internal, protected internal o public. Profundizaremos sobre los ambitos 0 visibilidad de los métodos, analizan- do la utilizacién de modificadores como private, protected, publice internal, enel capitulo dedicado al estudiodela programacién orientada a objetos. val CH NET [RIS Programacién con Vi ee EEE EEE SEE Sabemos que todas las variables que declaremos en el interior de un méto- do seran variables locales, cuya vida comienza al entrar en el método y termi- na al salir de él, perdiéndose por lo tanto el valor que contenga. Para evitar esta pérdida podiamos crear variables al nivel de clase, tal y como vimos en un capitulo previo. Los nombres de los métodos, que deberemos poner tras el tipo del valor que devuelven, siguen las mismas reglas que los de variables, estructuras, clases e interfaces, pudiendo estar formados por letras, numeros y caracteres de subra- yado. Recepcion de parametros Muchos de los métodos que disefemos en nuestros programas estaran desti- nados a realizar algiin tipo de operacion, generalmente partiendo de datos que se facilitan en el momento de la llamada. Estos parametros deben estar enume- rados entre los paréntesis que siguen al nombre del método, indicando su tipo y nombre, Por ejemplo, suponga que va a crear un método cuya finalidad es colocar un texto en unas coordenadas especificas, por lo que necesita recibir tres parametros: la cadena de texto y dos enteros con las coordenadas. La de- finicién podria quedar como: public void Imprime(string Cadena, int xX, imt Y) { AD we y De igual forma que hemos trabajado con cadenas y enteros, es posible pasar parametros practicamente de cualquier tipo, desde estos tipos basicos hasta objetos, arreglos e incluso tipos definidos por nosotros. Si se pasa como parametro un arreglo, no importa de qué tipo, en la decla- racién pondremos delante del nombre de Ja variable unos corchetes vacios, lo que nos permitira recibir cualquier numero de elementos sin conocerlo de an- temano. El cédigo que envia el arreglo como parémetro utilizara solamente el nombre de la variable, sin paréntesis y sin indices. Por ejemplo, en el siguiente fragmento de codigo puede observar un método que recibe un arreglo de ca- denas, obtiene sus limites, inferior y superior, e imprime cada uno de los ele- mentos. private void MuestraBlementos(string [] Nombres) { for(int I = Nombres.GetLowerBound(0); I<-Nombres.GetUpperBound(0); T++) console.Writebine(Nombres[I]); , En cualquier punto en el que tengamos un arreglo de cadenas, y necesite- mos imprimirlo, no tenemos mas que Hlamar a MuestraElementos() pasan- do como parametro el nombre del arreglo. Por ejemplo, estas lineas de codigo 6. Estructuras de control inicializan un arreglo con una serie de cadenas y después Iaman al método anterior para imprimirlas. string [] Dias - ( “bunes", "Martes", “Miércoles", "Jueves", "Viernes", "S&ébado", "Domingo" } MuestraElementos(Dias}; Devolucion de valores En caso de que nuestro método deba devolver cualquier valor al codigo que le llamé, entonces tendremos que definirlo indicando el tipo de ese valor. Por ejemplo, supongamos que vamos a escribir una funcién que devuelva la suma de los cuadrados de dos ntimeros, devolviendo un Long con el resultado. La cabecera de la funcién seria la siguiente: Private long SumaCuadrados(int Ni, int N2) Una vez que nuestra funcién haya realizado las operaciones pertinentes y disponga del resultado, para devolverlo tan sdlo ha de utilizar la sentencia return disponiendo el valor detras. Nuestra funcién SumaCuadrados () po- dria quedar como se muestra a continuacién. private long SumaCuadrados(int Nl, int N2) € i£(NL == 0 || N2 == 0) return -1; el return NI * Nl + N2 * N2; Aqui puede ver cémo la funcién devuelve el valor -1 si cualquiera de los parametros es 0 0 el resultado de la operacién. Este nunca podria ser—1, ya que el cuadrado de un ntimero, aunque sea negativo, siempre es positive y la suma de dos ntimeros positivos no puede ser negativa. Puede comprobar su funcio- namiento con una simple sentencia como Console.WriteLine(SumaCuadra- dos(2,5)). Devolucion de arreglos En caso de que una funcién deba devolver un arreglo, la notacién a usar es si- milar a la utilizada para indicar que un parametro a recibir es un arreglo. Es decir, dispondremos detras del tipo unos paréntesis vacios, sin especiticar el numero de elementos. La posibilidad de devolver un arreglo desde una funcién es bastante intere- sante, ya que se pueden facilitar tareas que de otra forma serian bastante mas Programacion con Visual C& NET complejas. Imagine que precisa, por ejemplo, una funcién para crear un arre- glo int a partir de una serie de datos independientes Sabiendo que cualquier funcién propia puede devolver arreglos, codificar un método que permita generar uno a partir de una serie de ntimeros facilita- dos como parametros no parece demasiado complejo. Los datos de entrada, cuyo ntimero desconocemos de antemano, pueden recibirse usando el modifi- cador params, algo sobre lo que volveremos en un momento, En el interior de la funcién simplemente creamos un arreglo con el niimero de elementos ade- cuado y copiamos los parametros en sus elementos, devolviéndolo como resul- tado. // Funcion que genera un arreglo de enteros public int[] ArregloEnteros(params int [] Elementos) jeclaramos un indice y el arreglo int [] Arreglo = new int[Elementos.GetLength(0)1j; /] copiamos los parametros en el arreglo for(int Indice = Elementos.GetLowerBound(0); Indice <= Elementos.GetUpperBound(0); Indicet+) Arreglo[indice] = Elementos( Indice]; return Arreglo; // y la devolvemos } Disponiendo de la funcién ArregloEnteros(), crear un arreglo en cual- quier punto donde se precise seria tan sencillo como escribir dos sentencias En el fragmento siguiente ademas se recorre el arreglo para mostrar los valores de sus elementos a efectos de comprobacion. int [] Miarreglo = MiAritmetica.ArregloEnteros(2, 4, 3, 9)7 foreach(int Elemento in MiArreglo} Console .WriteLine(Flemento Parametros por valor y por referencia Cuando Hamamos a un método y pasamos como parametro una variable, no una constante, ésta se puede recibir por referencia 0 por valor. En el primer caso el metodo lo que recibe es una referencia a la misma variable que se pasa como pardmetro, o lo que es lo mismo, recibe la propia variable. Esto significa que si el método realiza cualquier modificacién la variable original se vera afec- tada, lo que en algunas ocasiones puede ser itil y en otras un problema. En caso de que una variable se reciba por valor lo que e! método obtiene es una copia del contenido de la variable, pero no la variable original, por lo que cual- quier modificacién que se efectie no alterara su valor. En Cz, por defecto, los parametros se pasan por valor, lo que significa que el método recibe una copia de los datos originales. Supongamos que hemos esc to una funcion cuya finalidad es devolver la raiz cuarta del ntimero que se pase 6. Estructuras de control como pardmetro, como podria ser la siguiente, y que desde un punto del pro- grama se uliliza con una variable que va a ser posteriormente ulilizada para otros fines. Como puede ver, la funcién RaizCuarta( ) utiliza el propio para- metro, del que recibe una referencia, para realizar una operacién intermedia y, dado que la referencia apunta a la variable Numero original, ésta se habra visto afectada, por lo que al imprimirla no aparecera el valor 625, sino 25. int Numero = 625; Console. WriteLine( "La raiz cuarta es {0}, el numero original {1}", RaizCuarta(ref Numero), Numero); t static public int RaizCuarta(ref int Operando) { Operando = (int )Math.Sart(Operando); return (int )Math.Sqrt (Operando}; La funciénsqrt ( ) de laclaseMath devuelve la raiz cuadrada del dato que se entrega como parametro. Al hallar dos veces la rafz cuadrada de un nu- mero lo que se obtiene es la rafz cuarta. Observe como se usa el modificador ref en la cabecera de! método para indicar queOperando se pasa por referencia. El mismo modificar se utiliza también en la llamada a la funcién RaizCuarta(), dando asi el consen- timiento para que se facilite la referencia en lugar del valor. Ese efecto, en este caso indeseado, normalmente no lo encontraremos ya que, como se ha dicho antes, por defecto, los parametros se pasan por valor. El p: de parametros por referencia debe indicarse de manera explicita con el mod cador ref, lo que puede resultar interesante en determinadas circunstancias A diferencia de lo expuesto con este ejemplo, en otros casos el hecho de que el método que recibe los parametros pueda modificarlos, todos, algunos o sélo uno, puede ser de interés, ya que, por ejemplo, permitiria devolver mas de un valor desde una funcion. Se Lis tas variables de parametros Al utilizar un método 0 una funci6n es necesario facilitarle tantos parametros como se hayan especificado en la declaracién, en caso contrario obtendremos un error cuando intentemos ejecutarlo. Esto es asi porque los parametros no son opcionales, sino obligatorios. En C#, a diferencia de C++ 0 Visual Basic NET, no hay posibilidad de declarar pardmetros opcionales o, incluso, parametros con valores por defecto. Si podemos, no obstante, definir métodos que aceptan Programacion con Visual C# NET yd una lista variable de parametros. La comprobacién de los tipos de éstos, y su numero, quedara en manos del cddigo del método. Para definir una serie de variables sin conocer a ciencia cierta cudntas serdn necesarias, podemos utilizar el modificador params, que nos permite definir como opcional una lista de parametros en la que podremos recibir cualquier niimero de parametros. Si el tipo es object, ademas estos parametros podran ser de cualquier tipo. Por ejemplo, el siguiente método puede recibir un nme ro indeterminado de parametros y ademas de cualquier tipo. static public void MuestraCadenas (params object[{] Cadena) { foreach(object Elemento in Cadena) Console.WriteLine("{0} -> {1}", Elemento.Get'Type().ToString(), Elemento); d Una Hamada vélida a este método podria ser la que se muestra mas abajo. Al ejecutar el programa obtendriamos el tipo de cada uno de los parametros y su contenido, como se aprecia en la figura 6.3 MuestraCadenas(1, "Hola", true, DateTime.Now, 166.386); Figura 6.3. Tipos y valores de la lista de parémetros variable Salida de un método Hasta ahora nuestros métodos se han ejecutado desde principio a fin, termi nando al llegar a la lave de cierre que provoca que el control vuelva a la sen- tencia siguiente a la que provocé la llamada. Del mismo modo que ocurria con los bucles, que en ocasiones era necesario terminarlos antes de tiempo, dispo- nemos de una sentencia que nos permitira finalizar la ejecucién de un metodo de forma anticipada. La instruccién en realidad ya la conocemos, es return, que puede ir acom- pafiada de un valor, en caso de que el método devuelva algo, o ir sola, si el tipo BG. Estructuras de control de retorno es void. Generalmente esta sentencia esta asociada a alguna estruc- tura condicional, ya que si la disponemos directamente como una sentencia ejecutable mas provocara la salida del método siempre en el mismo punto, im- pidiendo asi la ejecucién del resto del cédigo que exista. Métodos recursivos Ya hemos visto cémo podemos utilizar un método y como podemos Ilamar- lo desde cualquier punto de la clase, si es privado, o desde cualquier otra, si es global. Estas llamadas siempre son externas, desde fuera del método, que es el modo mas habitual. Sin embargo un método puede ser llamado desde el inte- rior del cédigo que lo compone, es decir, el método se puede llamar a si mis- mo. Cuando ocurre esto se dice que el método es recursivo. Cuando se hace que un método sea recursivo se esta buscando, generalmen- te, una forma simple de realizar una cierta operacién que de otra forma seria mas compleja. Hay que tener en cuenta que cada vez que llamamos a un mé- todo, indistintamente del punto desde el que se realice la llamada, en la pila se almacena una direccién de retorno, asi como el espacio necesario para las va- tiables locales que tenga el método. Por lo tanto, un método recursivo que se lame a si mismo un numero importante de veces puede provocar un desbor- damiento de la pila. Por supuesto esto ocurrira siempre que el método se lame continuamente, sin fin, por eso la lamada de un método a él mismo siempre dependera de alguna condicién. Como ejemplo suponga que queremos escribir una funcién a la que facili- tandole un numero nos devuelva su factorial, es decir, ese mismo ntimero N multiplicado por N-1, N-2 y asi sucesivamente hasta llegar a multiplicar por 1 Una posible solucién seria la funcién siguiente. static public int FactorialNoRecursivo(int N) 4 int Resultado; Resultado = 1; // Inicio de la secuencia // multiplicar por todos los demas nimeros hasta W for(imt [=2; I<=N; I++) Resultado *= 1; return Resultado; Una solucién alternativa a ésta es una funcién recursiva, que se Ilame tantas veces como sea necesario pasandose en cada Hamada el ntimero entregado menos I. Esto es lo que hace la funcién Factorial), que si prueba vera como obtiene el mismo resultado que la anterior. static public imt Factorial(int Nj) q if(N == 1) // Si ya hemos llegado a 1 return 1; // no realizar n els llamadas Programacién con Visual Cé NET return N * Factorial(N - 1); // ilamada con N-1 y El codigo de este Ultimo método puede abreviarse considerablemente susti- tuyendo el condicional if por el operador ?: que conocimos en un capitulo previo. Con él, el cuerpo del método quedaria reducido a la sentencia siguien- te, obteniendo exactamente el mismo resultado: return N==] ? 1 : N#Factorial(N-1); Puntos clave « La sentencia condicional por excelencia es if, tras la cual se dispone una expresin que devuelva true o false o un valor que pueda evaluarse con uno de esos dos. * Los apartados if y else dan paso a las listas de sentencias que deben eje- cutarse en caso de que la expresion sea cierta o falsa, respectivamente. * Cuando sabemos de antemano cuantas veces debe repetirse un bucle uti- lizamos la sentencia for, recurriendo en caso contrario a alguna de las va- riables while * Mediante la sentencia foreach in se facilita la enumeracién de los ele- mentos de un arreglo o una coleccién. * C# cuenta con un control estructurado de excepciones similar al de C++ y otros lenguajes de la familia ¢ Mediante los métodos se facilita la reutilizacion de codigo. Un método es un conjunto de sentencias al que se asigna un nombre que, posteriormen- te, puede ser usado para ejecutarlas cuando sea necesario. ¢ Los métodos pueden tomar una lista de pardmetros. Estos pueden faci- litarse por valor, que es el modo por defecto, o por referencia: ref * Cuando es necesario devolver un valor se escribe una funcién en lugar de un método, utilizando la sentencia return para devolver el resultado. * Los tipos de los parametros de entrada y salida pueden ser cualquiera de los que hemos conocido en capitulos previos. Resumen Como ha podido ver en este capitulo, C# es un lenguaje rico en estructuras de control condicionales, de repeticién y estructuracién del cédigo en métodos y funciones. Todos estos elementos van a resultar indispensables en cualquier 6. Estructuras de control aplicacién que necesitemos desarrollar, independientemente de su finalidad, ya que son fundamentales. En el capitulo siguiente seguiremos avanzando en el conocimiento del len- guaje, aprendiendo a definir nuestras propias clases de objetos y ambitos, codi- ficando métodos, que no son mas que funciones pertenecientes a una clase, y utilizando estos objetos desde nuestras propias aplicaciones. 7 Programacion rientada a objetos Cé es un lenguaje completamente orientado a objetos, incluso mas que C++ ya que, al igual que ocurre con Java, todo elemento de codigo debe encontrarse enel interior de una clase. Las definiciones de variables, estructuras, interfaces, métodos, etc., todos los elementos, incluso otras clases, se alojan en el interior de clases. Nuestro objetivo, en este capitulo, es aprender a definir nuestras propias cla- ses, utilizandolas posteriormente para crear objetos. También estudiaremos algunos temas que guardan cierta relacién con la programacién orientada a objetos o bien los elementos que puede contener una clase. Algunos de ellos son los ambitos con nombre, las interfaces o la sobrecarga de métodos. Ambitos con nombre Las aplicaciones actuales son bastante mas complejas que las que podian desarrollarse hace unos afios sobre DOS 0 las primeras versiones de Windows. En una aplicacién participan ahora un buen numero de componentes mediante los cuales se facilita el acceso a bases de datos, la conectividad en redes, comu- nicacién con otras aplicaciones, etc. La existencia de tantos componentes puede causar conflictos si hay coincidencias de nomenclatura y, por.ello, el modelo de componentes mas usado hasta ahora, COM (Component Object Model), intro- dujo los conocides come GUID (Globally Unique [Dentifier). Estos identificadores son secuencias en 128 bits, o 16 bytes, tedricamente irrepetibles. Programacion orientada a objetos Trabajar con GUIDs siempre ha sido farragoso, siendo necesario el uso de archives de cabecera donde estaban predefinidos 0 servicios que se encargaban de traducir nombres descriptivos en identificadores unicos, aunque esto no era posible en todos los casos. En la plataforma .NET se ha optado por una solucién radicalmente distinta: el uso de espacios 0 ambitos con nombre. Un dmbito con nombre, del inglés namespace, es un ambito delimitado expli- citamente al que se ha asignado un identificador. En el interior de un ambito con nombre es posible incluir tanto definiciones de tipos como otros ambitos con nombre, creando una anidacion que dara lugar a una jerarquia. En la figura 7.1 se ha representado graticamente el ambito con nombre System y algunos de los ambitos que hay en su interior, como Windows y Web. Estos contienen, a su vez, otros ambitos de nombres como Services y UI. Figura 7.1. Unos ambitos con nombre contienen otros en su interior Definicién de ambitos con nombre Para crear un ambito con nombre, incluyendo en él las definiciones que nos interesen, utilizaremos la palabra clave namespace. La estructura seria simi- lar a la siguiente: space Nombre { // definiciones Observe que todas las definiciones que se encuentren entre las dos Haves, la que sigue al nombre del ambito y la final que cierra, tan solo existen dentro del espacio con nombre. Esto significa que para hacer referencia a dichas defini- ciones, por ejemplo para crear un objeto de una cierta clase, habra que utilizar un nombre cualificado. Es un tema que abordaremos de inmediato. Como se indicaba antes, un ambito con nombre puede contener otros en su interior, creando un anidamiento que daria lugar a una cierta jerarquia. Es po- sible utilizar diferentes sintaxis para incluir un ambito con nombre en otro. Los dos siguientes fragmentos de codigo tendrian un resultado equivalente space Anaya ( space ProgramacionVSHARPNET { class HolaMundo { static void Main() { System.Console.WriteLine( "Hola desde Anaya.ProgramacionVSHARPNET" ); namespace Anaya.ProgramacionVSHARPNET { class Holamundo { static void Main() ( system.Console.WriteLine( “Hola desde Anaya.ProgramacionVSHARPNET” ); En ambos casos tenemos un ambito con nombre, llamado Anaya, que con- tiene en su interior oro, denominado ProgramacionVSHARPNET. Este, final- mente, contiene la clase HolaMundo. El resultado de ejecutar cualquiera de estos dos programas es exactamente el mismo: la salida de una cadena de carac- teres por la consola. La clase HolaMundo no esta en un ambito global, sino en un espacio con nombre denominado Anaya. ProgramacionVSHARPNET, de e Form se encuentra en el espacio con nombre una forma similar a como lac System.Windows.Forms. Para seguir los ejemplos inicie un nuevo proyecto Visual C# .NET de tipo consola, eligiendo el elemento Aplicacién de consola, y sustituya el codigo generado por el asistente por el cédigo de! ejemplo. A continuaci6n pulse Control-F5 para ejecutar el proyecto, cuyo resultado apareceré en una ven- tana de consola similar a la de la figura 7.2. Siga este mismo sistema para los ejemplos siguientes. Al crear nuevos ambitos con nombre deberemos tratar siempre de crear referencias inequivocas. En los fragmentos anteriores, por ejemplo, se ha utili- zado el nombre de una empresa seguida del nombre de un libro, de modo que dificilmente puede encontr arse la referencia Anaya. ProgramacionVSHARPNET en otra parte. En realidad, Anaya.ProgramacionVSHARPNET s ria un sub- Ambito que existiria en el ambito de primer nivel, definide automaticamente al iniciar cada proyecto. Por defecto, Visual C? genera un ambito con el nombre del proyecto, aunque al eliminar nosotros el codigo estamos también eliminan- do ese ambito, 7. Programacién orientada a objetos Figura 7.2. Resultado de ejecutar el programa Referencias a un ambito con nombre Suponiendo que la clase Hol aMundo que hemos definido fuese ptiblica, que en este momento no lo es, y desedsemos crear un objeto de dicha clase desde otro programa, tendriamos que componer una referencia completa que permitiese al compilador identificarla de manera univoca. Esto significaria anteponer al nombre de la clase el del ambito 0 ambitos con nombre donde se encuentra de- finida, como se hace en este programa class UsaHolaMundo { static void Main() ( Anaya. ProgramacionVSHARPNET.HolaMundo MitlolaNundo = new Anaya. ProgramacionVSHARPNET .HolaNundo( )}; System. Console.WriteLine(MiHolaMundo.Saludo()); En este caso Anaya . Programac ionVSHARPNET es, al igual que System, el identificador de un ambito con nombre. HolaMundo, por el contrario, es el iden- tificador de una clase, como lo es Console. Una alternativa a esta composicion de referencias cualificadas consiste en utilizar la sentencia us ing, seguida del ambito cuya referencia no deseamos repetir continuamente. El resultado, como puede ver a continuacién, es un codigo mas legible. using system; using Anaya.ProgramacionVSHARPNET; class UsaHolaMundo { static void Main() { HolaMundo MiHolaMundo = new HolaMundo(); Console. WriteLine(MitiolaMundo.Saludo()); Programacién con Visual Ct NET [Aa —$—$ EE Observe que mediante using tan sdlo puede hacerse referencia a ambitos con nombre, no a clases, estructuras 0 cualquier otra definicion de tipo. No es valido, por tanto, intentar lo siguiente. Si compilasemos este cddigo obtendria- mos el correspondiente error. using System.Console; Writebine(“Hola"); Conflictos entre ambitos con nombre Utilizar la palabra clave using para hacer visible en nuestro ambito elemen- tos contenidos en un cierto espacio con nombre, que es lo que hemos hecho en el punto anterior, puede dar origen a conilictos y ambigiiedades. Para verlo, lo mejor es servirnos de ejemplos reales con codigo. Vamos a partir de un nuevo médulo en C# con el codigo mostrado a conti- nuacién. En él tenemos, como puede verse, un ambito con nombre que tiene en su interior a otros dos. Cada uno de estos define una clase llamada HolaMundo. Podemos compilar este cédigo, generando una biblioteca de clases (véase figu- ra 7.3) sin que se produzca error alguno. Esto es asi porque aunque existen dos clases con el mismo nombre, HolaMundo, cada una se encuentra en un espacio distinto. Figura 7.3. Iniciamos un proyecto Biblioteca de clases para alojar nuestro cédigo namespace ClasesAnaya { // Clasesanaya es el espacio superior namespace ProgramacionVSNET { /{ ProgramacionVSNE? es un espacio interior public class HolaMundo { // con una clase llamada HolaMundo public System.string saludo() ¢ 7. Programacion orientada a objetos return “Hola desde el 4mbito Anaya.ProgramacionVSNET"; , } , namespace ProgramacionVBNET { // ProgramacionVBNET es otro espacio interior public class HolaMundo { // tambien tiene una clase HolaMundo public System.String Saludo() { return Hola desde el ambito Anaya.ProgramacionVBNE’ } Utilizar las clases definidas en el modulo anterior es bastante sencillo, basi- camente basta con afadir una referencia al proyecto en que se necesite y, por supuesto, incluir las respectivas referencias mediante la instruccién using Inicie un nuevo proyecto afiadiéndolo a la solucién actual, en lugar de cerrarla, de tipo aplicacién de consola. Abra el menti emergente del proyecto, en el Ex- plorador de soluciones, y seleccione la opcion Agregar referencia. En la venta- na que aparece, similar a la de la figura 7.4, elija de la pagina Proyectos la tinica opcién disponible. Finalmente, introduzca este codigo en el médulo de la apli- caeion de consola. Figura 7.4. Afiadimos en el proyecto de consola una referencia a la libreria de clases using System; using ClasesAnaya.ProgramacionVSNET; // incluimos referencias using ClasesAnaya.ProgramacionVBNET; // a los dos ampitos Programacion con Visual C# .NET cl UsaHolaMundo { static void Main() ( // Aqui ‘HolaMundo' es una referencia ambigua HolaMundo MiHolaMundo = new KolaMundo(); Console.WriteLine(MiHolaMundo.Saludo()); } Al intentar compilar este cédigo, de la manera en que se ha hecho en la fi- gura 7.5, conprobara que obtenemos un error. En el método Main() utiliza- mos la clase HolaMundo, pero resulta que existen dos clases que tienen ese nombre, una en el ambito de ClasesAnaya.ProgramacionVSNET y otra en el de ClasesAnaya. ProgramacionVBNET. La solucién a este problema pasa, logicamente, por usar referencias completas como las mostradas en un ejemplo anterior de este mismo capitulo. using Clasestnaya.ProgcanecionvSNET; // iucluims referencias Using Clasestnaya,ProgcenectonVENET! // 9 los dos dnbitor static void Main() J Aes ‘HolaMundo! ex una referencia axbigun WokaMunda MH lamundo = new Rolamunda |: -Saiuee) | Figura 7.5. En la Lista de tareas aparecen las indicaciones de error Ya vemos que la solucién es obvia, pero no lo es menos la incomodidad de tener que introducir referencias como: ClasesAnaya.ProgramacionVSNET.HolaMundo MiflolaMunde = new ClasesAnaya.ProgramacionVSNET.HolaMundo( )7 Programacion orientada a objetos —_—_——$$__$_$$—$—$_————————— para poder crear un objeto de una cierta clase. Afortunadamente, la sentencia using nos permite importar el contenido de un ambito con nombre creando. un alias, un pseudénimo al que podemos asignar el identificador que nos con- venga. Esto es lo que se hace en el ejemplo siguiente. En él puede ver como se asignan los alias VS y VB a los dos ambitos con nombre, de tal forma que, pos- teriormente, podemos usar esos alias en lugar de las referencias completas. using System; using VS = ClasesAnaya.ProgramacionVSNET; // incluimos referencias using VB = ClasesAnaya.ProgramacionVBNET; // a los dos émbitos el UsalolaMundo { static void Main() { VB.HolaMundo MiHolaMundo = new VB.HolaMundo(); Console.WriteLine(MillolaMundo.Saludo()); Ahora si que podra ejecutar el programa obteniendo el resultado que se es- pera, sin ningun error. Cla es de objetos En un capitulo previo pudimos conocer los tipos de datos intrinsecos de C4, asi como la forma de crear nuevos tipos que almacenan valor: enumeraciones y estructuras. Las clases representan otro mecanismo para crear nuevos tipos de datos, si bien en este caso las variables contendrian la referencia a los objetos creados a partir de la clase. Las clases, por tanto, se definen, igual que defini- mos una enumeracion o una estructura, describiendo los miembros con que contara. Posteriormente, usando la clase como si fuese un tipo, se crearian los objetos y accederia a sus miembros Lo que diferencia a las clases de cualquier otro tipo de dato, aparte de que se usen para crear objetos de los cuales se obtiene una referencia, es que puc- den derivarse unas de otras, posibilidad inexistente en las estructuras, por po- ner un ejemplo. No tenemos por qué crear una clase partiendo de cero, aunque podemos hacerlo. Podriamos crear una clase nueva de formulario partiendo de la clase Form ya existente, heredando todas sus caracteristicas. Al igual que las estructuras, las clases pueden implementar interfaces, tema que abordaremos en este mismo capitulo, asi como contar entre sus miembros con variables de datos, funciones y propiedades. Ademas también pueden in- cluirse delegados y eventos. Algunos de estos elementos los conocera no en éste sino en el proximo capitulo. Los puntos siguientes introducen las caracteristicas mas importantes relati- vasa la definicién de clases en C#, acompafando las explicaciones con algunos ejemplos breves. Para obtener una descripcion completamente detallada de cada modificador o técnica consulte la especificacién del lenguaje Ct