Escuela Técnica Nº 37 D.E. 11 “Hogar Naval Stella Maris” LABORATORIO I - El lenguaje de programación C# - MODULO I Introducción a Microsoft.NET Microsoft.NET Microsoft.NET es el conjunto de nuevas tecnologías en las que Microsoft ha estado trabajando durante los últimos años con el objetivo de obtener una plataforma sencilla y potente para distribuir el software en forma de servicios que puedan ser suministrados remotamente y que puedan comunicarse y combinarse unos con otros de manera totalmente independiente de la plataforma, lenguaje de programación y modelo de componentes con los que hayan sido desarrollados. Ésta es la llamada plataforma .NET, y a los servicios antes comentados se les denomina servicios Web. Para crear aplicaciones para la plataforma .NET, tanto servicios Web como aplicaciones tradicionales (aplicaciones de consola, aplicaciones de ventanas, servicios de Windows NT, etc.), Microsoft ha publicado el denominado kit de desarrollo de software conocido como .NET Framework SDK, que incluye las herramientas necesarias tanto para su desarrollo como para su distribución y ejecución y Visual Studio.NET, que permite hacer todo la anterior desde una interfaz visual basada en ventanas El concepto de Microsoft.NET también incluye al conjunto de nuevas aplicaciones que Microsoft y terceros han (o están) desarrollando para ser utilizadas en la plataforma .NET. Entre ellas podemos destacar aplicaciones desarrolladas por Microsoft tales como Windows.NET, Hailstorm, Visual Studio.NET, MSN.NET, Office.NET, y los nuevos servidores para empresas de Microsoft (SQL Server.NET, Exchange.NET, etc.) Common Language Runtime (CLR) El Common Language Runtime (CLR) es el núcleo de la plataforma .NET. Es el motor encargado de gestionar la ejecución de las aplicaciones para ella desarrolladas y a las que ofrece numerosos servicios que simplifican su desarrollo y favorecen su fiabilidad y seguridad. Las principales características y servicios que ofrece el CLR son: Modelo de programación consistente: A todos los servicios y facilidades ofrecidos por el CLR se accede de la misma forma: a través de un modelo de programación orientado a objetos. Esto es una diferencia importante respecto al modo de acceso a los servicios ofrecidos por los algunos sistemas operativos actuales (por ejemplo, los de la familia Windows), en los que a algunos servicios se les accede a través de llamadas a funciones globales definidas en DLLs y a otros a través de objetos (objetos COM en el caso de la familia Windows) Modelo de programación sencillo: Con el CLR desaparecen muchos elementos complejos incluidos en los sistemas operativos actuales (registro de Windows, GUIDs, HRESULTS, IUnknown, etc.) El CLR no es que abstraiga al programador de estos conceptos, sino que son conceptos que no existen en la plataforma .NET La plataforma .NET las versiones nuevas de las DLLs pueden coexistir con las viejas, de modo que las aplicaciones diseñadas para ejecutarse usando las viejas podrán seguir usándolas tras instalación de las nuevas. Esto, obviamente, simplifica mucho la instalación y desinstalación de software. Ejecución multiplataforma: El CLR actúa como una máquina virtual, encargándose de ejecutar las aplicaciones diseñadas para la plataforma .NET. Es decir, cualquier plataforma para la que exista una versión del CLR podrá ejecutar cualquier aplicación .NET. Microsoft ha desarrollado versiones del CLR para la mayoría de las versiones de Windows: Windows 95, Windows 98, Windows ME, Windows NT 4.0, Windows 2000, Windows XP y Windows CE (que puede ser usado en CPUs que no sean de la familia x86) Por otro lado Microsoft ha firmado un acuerdo con Corel para portar el CLR a Linux y también hay terceros que están desarrollando de manera independiente versiones de libre distribución del CLR para Linux. Asimismo, dado que la Profesores Adriana Gil, Pablo Linares, Jorge Romero 1 de 47 Escuela Técnica Nº 37 D.E. 11 “Hogar Naval Stella Maris” LABORATORIO I - El lenguaje de programación C# - MODULO I arquitectura del CLR está totalmente abierta, es posible que en el futuro se diseñen versiones del mismo para otros sistemas operativos. Integración de lenguajes: Desde cualquier lenguaje para el que exista un compilador que genere código para la plataforma .NET es posible utilizar código generado para la misma usando cualquier otro lenguaje tal y como si de código escrito usando el primero se tratase. Microsoft ha desarrollado un compilador de C# que genera código de este tipo, así como versiones de sus compiladores de Visual Basic (Visual Basic.NET) y C++ (C++ con extensiones gestionadas) que también lo generan y una versión del intérprete de JScript (JScript.NET) que puede interpretarlo. La integración de lenguajes esta que es posible escribir una clase en C# que herede de otra escrita en Visual Basic.NET que, a su vez, herede de otra escrita en C++ con extensiones gestionadas. Gestión de memoria: El CLR incluye un recolector de basura que evita que el programador tenga que tener en cuenta cuándo ha de destruir los objetos que dejen de serle útiles. Este recolector es una aplicación que se activa cuando se quiere crear algún objeto nuevo y se detecta que no queda memoria libre para hacerlo, caso en que el recolector recorre la memoria dinámica asociada a la aplicación, detecta qué objetos hay en ella que no puedan ser accedidos por el código de la aplicación, y los elimina para limpiar la memoria de “objetos basura” y permitir la creación de otros nuevos. Gracias a este recolector se evitan errores de programación muy comunes como intentos de borrado de objetos ya borrados, agotamiento de memoria por olvido de eliminación de objetos inútiles o solicitud de acceso a miembros de objetos ya destruidos. Seguridad de tipos: El CLR facilita la detección de errores de programación difíciles de localizar comprobando que toda conversión de tipos que se realice durante la ejecución de una aplicación .NET se haga de modo que los tipos origen y destino sean compatibles. Aislamiento de procesos: El CLR asegura que desde código perteneciente a un determinado proceso no se pueda acceder a código o datos pertenecientes a otro, lo que evita errores de programación muy frecuentes e impide que unos procesos puedan atacar a otros. Esto se consigue gracias al sistema de seguridad de tipos antes comentado, pues evita que se pueda convertir un objeto a un tipo de mayor tamaño que el suyo propio, ya que al tratarlo como un objeto de mayor tamaño podría accederse a espacios en memoria ajenos a él que podrían pertenecer a otro proceso. También se consigue gracias a que no se permite acceder a posiciones arbitrarias de memoria. Tratamiento de excepciones: En el CLR todos los errores que se puedan producir durante la ejecución de una aplicación se propagan de igual manera: mediante excepciones. Esto es muy diferente a como se venía haciendo en los sistemas Windows hasta la aparición de la plataforma .NET, donde ciertos errores se transmitían mediante códigos de error en formato Win32, otros mediante HRESULTs y otros mediante excepciones. El CLR permite que excepciones lanzadas desde código para .NET escrito en un cierto lenguaje se puedan capturar en código escrito usando otro lenguaje, e incluye mecanismos de depuración que pueden saltar desde código escrito para .NET en un determinado lenguaje a código escrito en cualquier otro. Por ejemplo, se puede recorrer la pila de llamadas de una excepción aunque ésta incluya métodos definidos en otros módulos usando otros lenguajes. Interoperabilidad con código antiguo: El CLR incorpora los mecanismos necesarios para poder acceder desde código escrito para la plataforma .NET a código escrito previamente a la aparición de la misma y, por tanto, no preparado para ser ejecutando dentro de ella. Estos mecanismos permiten tanto el acceso a objetos COM como el acceso a funciones sueltas de DLLs preexistentes (como la API Win32) Profesores Adriana Gil, Pablo Linares, Jorge Romero 2 de 47 Escuela Técnica Nº 37 D.E. 11 “Hogar Naval Stella Maris” LABORATORIO I - El lenguaje de programación C# - MODULO I Como se puede deducir de las características comentadas, el CLR lo que hace es gestionar la ejecución de las aplicaciones diseñadas para la plataforma .NET. Por esta razón, al código de estas aplicaciones se le suele llamar código gestionado, y al código no escrito para ser ejecutado directamente en la plataforma .NET se le suele llamar código no gestionado. Microsoft Intermediate Language (MSIL) Todos los compiladores que generan código para la plataforma .NET no generan código máquina para CPUs x86 ni para ningún otro tipo de CPU concreta, sino que generan código escrito en el lenguaje intermedio conocido como Microsoft Intermediate Lenguage (MSIL) El CLR da a las aplicaciones las sensación de que se están ejecutando sobre una máquina virtual, y precisamente MSIL es el código máquina de esa máquina virtual. Es decir, MSIL es el único código que es capaz de interpretar el CLR, y por tanto cuando se dice que un compilador genera código para la plataforma .NET lo que se está diciendo es que genera MSIL. MSIL ha sido creado por Microsoft tras consultar a numerosos especialistas en la escritura de compiladores y lenguajes tanto del mundo académico como empresarial. Es un lenguaje de un nivel de abstracción mucho más alto que el de la mayoría de los códigos máquina de las CPUs existentes, e incluye instrucciones que permiten trabajar directamente con objetos (crearlos, destruirlos, inicializarlos, llamar a métodos virtuales, etc.), tablas y excepciones (lanzarlas, capturarlas y tratarlas) Ya se comentó que el compilador de C# compila directamente el código fuente a MSIL, que Microsoft ha desarrollado nuevas versiones de sus lenguajes Visual Basic (Visual Basic.NET) y C++ (C++ con extensiones gestionadas) cuyos compiladores generan MSIL, y que ha desarrollado un intérprete de JScript (JScript.NET) que genera código MSIL. Pues bien, también hay numerosos terceros que han anunciado estar realizando versiones para la plataforma .NET de otros lenguajes como APL, CAML, Cobol, Eiffel, Fortran, Haskell, Java (J#), Mercury, ML, Mondrian, Oberon, Oz, Pascal, Perl, Python, RPG, Scheme y Smalltalk. La principal ventaja del MSIL es que facilita la ejecución multiplataforma y la integración entre lenguajes al ser independiente de la CPU y proporcionar un formato común para el código máquina generado por todos los compiladores que generen código para .NET. Sin embargo, dado que las CPUs no pueden ejecutar directamente MSIL, antes de ejecutarlo habrá que convertirlo al código nativo de la CPU sobre la que se vaya a ejecutar. De esto se encarga un componente del CLR conocido como compilador JIT (Just-In-Time). La Librería de Clase Base (BCL) es una librería incluida en el .NET Framework formada por cientos de tipos de datos que permiten acceder a los servicios ofrecidos por el CLR y a las funcionalidades más frecuentemente usadas a la hora de escribir programas. Además, a partir de estas clases prefabricadas el programador puede crear nuevas clases que mediante herencia extiendan su funcionalidad y se integren a la perfección con el resto de clases de la BCL. Por ejemplo, implementando ciertos interfaces podemos crear nuevos tipos de colecciones que serán tratadas exactamente igual que cualquiera de las colecciones incluidas en la BCL. Esta librería está escrita en MSIL, por lo que puede usarse desde cualquier lenguaje cuyo compilador genere MSIL. A través de las clases suministradas en ella es posible desarrollar cualquier tipo de aplicación, desde las tradicionales aplicaciones de ventanas, consola o servicio de Windows NT hasta los novedosos servicios Web y páginas ASP.NET. Es tal la riqueza de servicios que ofrece que puede crearse lenguajes que carezcan de librería de clases propia y sólo usen la BCL -como C#. Dado la amplitud de la BCL, ha sido necesario organizar las clases en ella incluida en espacios de nombres que agrupen clases con funcionalidades similares. Por ejemplo, los espacios de nombres más usados son: Profesores Adriana Gil, Pablo Linares, Jorge Romero 3 de 47 Escuela Técnica Nº 37 D.E. 11 “Hogar Naval Stella Maris” LABORATORIO I - El lenguaje de programación C# - MODULO I Espacio de nombres System System.Collections System.Data System.IO System.Net System.Reflection System.Runtime.Remoting System.Security System.Threading System.Web.UI.WebControls System.Winforms System.XML Utilidad de los tipos de datos que contiene Tipos muy frecuentemente usados, como los los tipos básicos, tablas, excepciones, fechas, números aleatorios, recolector de basura, entrada/salida en consola, etc. Colecciones de datos de uso común como pilas, colas, listas, diccionarios, etc. Manipulación de bases de datos. Forman la denominada arquitectura ADO.NET. Manipulación de ficheros y otros flujos de datos. Realización de comunicaciones en red. Acceso a los metadatos que acompañan a los módulos de código. Acceso a objetos remotos. Acceso a la política de seguridad en que se basa el CLR. Manipulación de hilos. Creación de interfaces de usuario basadas en ventanas para aplicaciones Web. Creación de interfaces de usuario basadas en ventanas para aplicaciones estándar. Acceso a datos en formato XML. Introducción a C# Origen y necesidad de un nuevo lenguaje C# es el nuevo lenguaje de propósito general diseñado por Microsoft para su plataforma .NET. Sus principales creadores son Scott Wiltamuth y Anders Hejlsberg, éste último también conocido por haber sido el diseñador del lenguaje Turbo Pascal y la herramienta RAD Delphi. Aunque es posible escribir código para la plataforma .NET en muchos otros lenguajes, C# es el único que ha sido diseñado específicamente para ser utilizado en ella, por lo que programarla usando C# es mucho más sencillo e intuitivo que hacerlo con cualquiera de los otros lenguajes ya que C# carece de elementos heredados innecesarios en .NET. Por esta razón, se suele decir que C# es el lenguaje nativo de .NET La sintaxis y estructuración de C# es muy similar a la C++, ya que la intención de Microsoft con C# es facilitar la migración de códigos escritos en estos lenguajes a C# y facilitar su aprendizaje a los desarrolladores habituados a ellos. Sin embargo, su sencillez y el alto nivel de productividad son equiparables a los de Visual Basic. Un lenguaje que hubiese sido ideal utilizar para estos menesteres es Java, pero debido a problemas con la empresa creadora del mismo -Sun-, Microsoft ha tenido que desarrollar un nuevo lenguaje que añadiese a las ya probadas virtudes de Java las modificaciones que Microsoft tenía pensado añadirle para mejorarlo aún más y hacerlo un lenguaje orientado al desarrollo de componentes. En resumen, C# es un lenguaje de programación que toma las mejores características de lenguajes preexistentes como Visual Basic, Java o C++ y las combina en uno solo. El hecho de ser relativamente reciente no implica que sea inmaduro, pues Microsoft ha escrito la mayor parte de la BCL usándolo, por lo que su compilador es el más depurado y optimizado de los incluidos en el .NET Framework SDK Profesores Adriana Gil, Pablo Linares, Jorge Romero 4 de 47 Escuela Técnica Nº 37 D.E. 11 “Hogar Naval Stella Maris” LABORATORIO I - El lenguaje de programación C# - MODULO I Características de C# Con la idea de que los programadores más experimentados puedan obtener una visión general del lenguaje, a continuación se recoge de manera resumida las principales características de C# Alguna de las características aquí señaladas no son exactamente propias del lenguaje sino de la plataforma .NET en general. Sin embargo, también se comentan aquí también en tanto que tienen repercusión directa en el lenguaje, aunque se indicará explícitamente cuáles son este tipo de características cada vez que se toquen: Sencillez: C# elimina muchos elementos que otros lenguajes incluyen y que son innecesarios en .NET. Por ejemplo: o El código escrito en C# es autocontenido, lo que significa que no necesita de ficheros adicionales al propio fuente tales como ficheros de cabecera o ficheros IDL o El tamaño de los tipos de datos básicos es fijo e independiente del compilador, sistema operativo o máquina para quienes se compile (no como en C++), lo que facilita la portabilidad del código. o No se incluyen elementos poco útiles de lenguajes como C++ tales como macros, herencia múltiple o la necesidad de un operador diferente del punto (.) acceder a miembros de espacios de nombres (::) Modernidad: C# incorpora en el propio lenguaje elementos que a lo largo de los años ha ido demostrándose son muy útiles para el desarrollo de aplicaciones y que en otros lenguajes como Java o C++ hay que simular, como un tipo básico decimal que permita realizar operaciones de alta precisión con reales de 128 bits (muy útil en el mundo financiero), la inclusión de una instrucción foreach que permita recorrer colecciones con facilidad y es ampliable a tipos definidos por el usuario, la inclusión de un tipo básico string para representar cadenas o la distinción de un tipo bool específico para representar valores lógicos. Orientación a objetos: Como todo lenguaje de programación de propósito general actual, C# es un lenguaje orientado a objetos, aunque eso es más bien una característica del CTS que de C#. Una diferencia de este enfoque orientado a objetos respecto al de otros lenguajes como C++ es que el de C# es más puro en tanto que no admiten ni funciones ni variables globales sino que todo el código y datos han de definirse dentro de definiciones de tipos de datos, lo que reduce problemas por conflictos de nombres y facilita la legibilidad del código. C# soporta todas las características propias del paradigma de programación orientada objetos: encapsulación, herencia y polimorfismo. a En lo referente a la encapsulación es importante señalar que aparte de los típicos modificadores public, private y protected, C# añade un cuarto modificador llamado internal, que puede combinarse con protected e indica que al elemento a cuya definición precede sólo puede accederse desde su mismo ensamblado. Respecto a la herencia -a diferencia de C++ y al igual que Java- C# sólo admite herencia simple de clases ya que la múltiple provoca más quebraderos de cabeza que facilidades y en la mayoría de los casos su utilidad puede ser simulada con facilidad mediante herencia múltiple de interfaces. De todos modos, esto vuelve a ser más bien una característica propia del CTS que de C#. Por otro lado y a diferencia de Java, en C# se ha optado por hacer que todos los métodos sean por defecto sellados y que los redefinibles hayan de marcarse con el modificador virtual (como en C++), lo que permite evitar errores derivados de redefiniciones accidentales. Profesores Adriana Gil, Pablo Linares, Jorge Romero 5 de 47 Escuela Técnica Nº 37 D.E. 11 “Hogar Naval Stella Maris” LABORATORIO I - El lenguaje de programación C# - MODULO I Además, un efecto secundario de esto es que las llamadas a los métodos serán más eficientes por defecto al no tenerse que buscar en la tabla de funciones virtuales la implementación de los mismos a la que se ha de llamar. Otro efecto secundario es que permite que las llamadas a los métodos virtuales se puedan hacer más eficientemente al contribuir a que el tamaño de dicha tabla se reduzca. Gestión automática de memoria: Como ya se comentó, todo lenguaje de .NET tiene a su disposición el recolector de basura del CLR. Esto tiene el efecto en el lenguaje de que no es necesario incluir instrucciones de destrucción de objetos. Sin embargo, dado que la destrucción de los objetos a través del recolector de basura es indeterminista y sólo se realiza cuando éste se active –ya sea por falta de memoria, finalización de la aplicación o solicitud explícita en el fuente-, C# también proporciona un mecanismo de liberación de recursos determinista a través de la instrucción using. Versionable: C# incluye una política de versionado que permite crear nuevas versiones de tipos sin temor a que la introducción de nuevos miembros provoquen errores difíciles de detectar en tipos hijos previamente desarrollados y ya extendidos con miembros de igual nombre a los recién introducidos. Si una clase introduce un nuevo método cuyas redefiniciones deban seguir la regla de llamar a la versión de su padre en algún punto de su código, difícilmente seguirían esta regla miembros de su misma signatura definidos en clases hijas previamente a la definición del mismo en la clase padre; o si introduce un nuevo campo con el mismo nombre que algún método de una clase hija, la clase hija dejará de funcionar. Para evitar que esto ocurra, en C# se toman dos medidas: o Se obliga a que toda redefinición deba incluir el modificador override, con lo que la versión de la clase hija nunca sería considerada como una redefinición de la versión de miembro en la clase padre ya que no incluiría override. Para evitar que por accidente un programador incluya este modificador, sólo se permite incluirlo en miembros que tengan la misma signatura que miembros marcados como redefinibles mediante el modificador virtual. Así además se evita el error tan frecuente en Java de creerse haber redefinido un miembro, pues si el miembro con override no existe en la clase padre se producirá un error de compilación. o Si no se considera redefinición, entonces se considera que lo que se desea es ocultar el método de la clase padre, de modo que para la clase hija sea como si nunca hubiese existido. El compilador avisará de esta decisión a través de un mensaje de aviso que puede suprimirse incluyendo el modificador new en la definición del miembro en la clase hija para así indicarle explícitamente la intención de ocultación. Eficiente: En principio, en C# todo el código incluye numerosas restricciones para asegurar su seguridad y no permite el uso de punteros. Sin embargo, y a diferencia de Java, en C# es posible saltarse dichas restricciones manipulando objetos a través de punteros. Para ello basta marcar regiones de código como inseguras (modificador unsafe) y podrán usarse en ellas punteros de forma similar a cómo se hace en C++, lo que puede resultar vital para situaciones donde se necesite una eficiencia y velocidad procesamiento muy grandes. Compatible: Para facilitar la migración de programadores, C# no sólo mantiene una sintaxis muy similar a C, C++ o Java que permite incluir directamente en código escrito en C# fragmentos de código escrito en estos lenguajes, sino que el CLR también ofrece, a través de los llamados Platform Invocation Services (PInvoke), la posibilidad de acceder a código nativo escrito como funciones sueltas no orientadas a objetos tales como las DLLs de la API Win32. Nótese que la capacidad de usar punteros en código inseguro permite que se pueda acceder con facilidad a este tipo de funciones, ya que éstas muchas veces esperan recibir o devuelven punteros. Profesores Adriana Gil, Pablo Linares, Jorge Romero 6 de 47 Escuela Técnica Nº 37 D.E. 11 “Hogar Naval Stella Maris” LABORATORIO I - El lenguaje de programación C# - MODULO I También es posible acceder desde código escrito en C# a objetos COM. Para facilitar esto, el .NET Framework SDK incluye una herramientas llamadas tlbimp y regasm mediante las que es posible generar automáticamente clases proxy que permitan, respectivamente, usar objetos COM desde .NET como si de objetos .NET se tratase y registrar objetos .NET para su uso desde COM. Finalmente, también se da la posibilidad de usar controles ActiveX desde código .NET y viceversa. Para lo primero se utiliza la utilidad aximp, mientras que para lo segundo se usa la ya mencionada regasm. Aplicaciones Aplicación básica ¡Hola Mundo! Básicamente una aplicación en C# puede verse como un conjunto de uno o más ficheros de código fuente con las instrucciones necesarias para que la aplicación funcione como se desea y que son pasados al compilador para que genere un ejecutable. Cada uno de estos ficheros no es más que un fichero de texto plano escrito usando caracteres Unicode y siguiendo la sintaxis propia de C#. Como primer contacto con el lenguaje, nada mejor que el típico programa de iniciación “¡Hola Mundo!” que lo único que hace al ejecutarse es mostrar por pantalla el mensaje ¡Hola Mundo! Su código es: 1: 2: 3: 4: 5: 6: 7: class HolaMundo { static void Main() { Console.WriteLine(“¡Hola Mundo!”); } } Todo el código escrito en C# se ha de escribir dentro de una definición de clase, y lo que en la línea 1: se dice es que se va a definir una clase (class) de nombre HolaMundo1 cuya definición estará comprendida entre la llave de apertura de la línea 2: y su correspondiente llave de cierre en la línea línea 7: Dentro de la definición de la clase (línea 3:) se define un método de nombre Main cuyo código es el indicado entre la llave de apertura de la línea 4: y su respectiva llave de cierre (línea 6:) Un método no es más que un conjunto de instrucciones a las que se les asocia un nombre, de modo que para posteriormente ejecutarlas baste referenciarlas por su nombre en vez de tener que reescribirlas. La partícula que antecede al nombre del método indica cuál es el tipo de valor que se devuelve tras la ejecución del método, y en este caso es void que significa que no se devuelve nada. Por su parte, los paréntesis que se colocado tras el nombre del método indican cuáles son los parámetros éste toma, y como en este caso están vacíos ello significa que el método no toma parámetros. Los parámetros de un método permiten variar el resultado de su ejecución según los valores que se les dé en cada llamada. La palabra static que antecede a la declaración del tipo de valor devuelto es un modificador del significado de la declaración de método que indica que el método está asociado a la clase dentro de la que se define y no a los objetos que se creen a partir de ella. Main() es lo que es denomina el punto de entrada de la aplicación, que no es más que el método por el que comenzará su ejecución. Necesita del modificador static para evitar que para llamarlo haya que crear algún objeto de la clase donde se haya definido. Profesores Adriana Gil, Pablo Linares, Jorge Romero 7 de 47 Escuela Técnica Nº 37 D.E. 11 “Hogar Naval Stella Maris” LABORATORIO I - El lenguaje de programación C# - MODULO I Finalmente, la línea 5: contiene la instrucción con el código a ejecutar, que lo que se hace es solicitar la ejecución del método WriteLine() de la clase Console definida en el espacio de nombres System pasándole como parámetro la cadena de texto con el contenido ¡Hola Mundo! Nótese que las cadenas de textos son secuencias de caracteres delimitadas por comillas dobles aunque dichas comillas no forman parte de la cadena. Por su parte, un espacio de nombres puede considerarse que es algo similar para las clases a lo que un directorio es para los ficheros; es decir, es una forma de agruparlas. El método WriteLine() se usará muy a menudo en los próximos temas, por lo que es conveniente señalar ahora que una forma de llamarlo que se utilizará en repetidas ocasiones consiste en pasarle un número indefinido de otros parámetros de cualquier tipo e incluir en el primero subcadenas de la forma {i}. Con ello se consigue que se muestre por la ventana de consola la cadena que se le pasa como primer parámetro pero sustituyéndole las subcadenas {i} por el valor convertido en cadena de texto del parámetro que ocupe la posición i+2 en la llamada a WriteLine(). Por ejemplo, la siguiente instrucción mostraría Tengo 5 años por pantalla si x valiese 5: Console.WriteLine(“Tengo {0} años”, x); Para indicar cómo convertir cada objeto en un cadena de texto basta redefinir su método ToString(). Antes de seguir es importante resaltar que C# es sensible a las mayúsculas, los que significa que no da igual la capitalización con la que se escriban los identificadores. Es decir, no es lo mismo escribir Console que COnsole o CONSOLE, y si se hace de alguna de las dos últimas formas el compilador producirá un error debido a que en el espacio de nombres System no existe ninguna clase con dichos nombres. En este sentido, cabe señalar que un error común entre programadores acostumbrados a Java es llamar al punto de entrada main en vez de Main, lo que provoca un error al compilar ejecutables en tanto que el compilador no detectará ninguna definición de punto de entrada. Puntos de entrada Ya se ha dicho que el punto de entrada de una aplicación es un método de nombre Main que contendrá el código por donde se ha de iniciar la ejecución de la misma. Hasta ahora sólo se ha visto una versión de Main() que no toma parámetros y tiene como tipo de retorno void, pero en realidad todas sus posibles versiones son: static static static static void Main() int Main() int Main(string[] args) void Main(string[] args) Compilación en línea de comandos Una vez escrito el código anterior con algún editor de textos –como el Bloc de Notas de Windows- y almacenado en formato de texto plano en un fichero HolaMundo.cs, para compilarlo basta abrir una ventana de consola (MS-DOS en Windows), colocarse en el directorio donde se encuentre y pasárselo como parámetro al compilador así: csc HolaMundo.cs csc.exe es el compilador de C# incluido en el .NET Framework SDK para Windows de Microsoft, y es posible llamarlo desde cualquier directorio en tanto que al instalarlo se añade una referencia al mismo en el path. Si utiliza otros compiladores de C# puede que varie la forma en que se realice la compilación, por lo que lo que aquí se explica en principio sólo podría ser válido para el compilador de Microsoft para Windows. Profesores Adriana Gil, Pablo Linares, Jorge Romero 8 de 47 Escuela Técnica Nº 37 D.E. 11 “Hogar Naval Stella Maris” LABORATORIO I - El lenguaje de programación C# - MODULO I Tras la compilación se obtendría un ejecutable llamado HolaMundo.exe cuya ejecución produciría la siguiente salida por la ventana de consola: ¡Hola Mundo! Compilación con Visual Studio.NET Para compilar una aplicación en Visual Studio.NET primero hay que incluirla dentro de algún proyecto. Para ello basta pulsar el botón New Project en la página de inicio que se muestra nada más arrancar dicha herramienta, tras lo que se obtendrá una pantalla con el aspecto mostrado en la siguiente figura. En el recuadro de la ventana mostrada etiquetado como Project Types se ha de seleccionar el tipo de proyecto a crear. Obviamente, si se va a trabajar en C# la opción que habrá que escoger en la misma será siempre Visual C# Projects. En el recuadro Templates se ha de seleccionar la plantilla correspondiente al subtipo de proyecto dentro del tipo indicado en Project Types que se va a realizar. Para realizar un ejecutable de consola, como es nuestro caso, hay que seleccionar el icono etiquetado como Console Application. Si se quisiese realizar una librería habría que seleccionar Class Library, y si se quieres realizar un ejecutable de ventanas habría que seleccionar Windows Application. Nótese que no se ofrece ninguna plantilla para realizar módulos, lo que se debe a que desde Visual Studio.NET no pueden crearse. Por último, en el recuadro de texto Name se ha de escribir el nombre a dar al proyecto y en Location el del directorio base asociado al mismo. Nótese que bajo de Location aparecerá un mensaje informando sobre cual será el directorio donde finalmente se almacenarán los archivos del proyecto, que será el resultante de concatenar la ruta especificada para el directorio base y el nombre del proyecto. Ventana de creación de nuevo proyecto en Visual Studio.NET Una vez configuradas todas estas opciones, al pulsar botón OK Visual Studio creará toda la infraestructura adecuada para empezar a trabajar cómodamente en el proyecto. Como puede apreciarse en la figura de abajo, esta infraestructura consistirá en la generación de una fuente que servirá de plantilla para la realización de proyectos del tipo elegido (en nuestro caso, aplicaciones de consola en C#): Profesores Adriana Gil, Pablo Linares, Jorge Romero 9 de 47 Escuela Técnica Nº 37 D.E. 11 “Hogar Naval Stella Maris” LABORATORIO I - El lenguaje de programación C# - MODULO I Plantilla para aplicaciones de consola generada por Visual Studio.NET DECLARACIÓN DE VARIABLES Una variable es un espacio asignado en la memoria RAM que se puede utilizar en el código. En C# todas las variables deben ser obligatoriamente declaradas y tener un tipo (recordar que es un lenguaje fuertemente tipado, a esto es que dicha clasificación está referida), pero no es necesario declarar todas las variables al inicio del programa. No se puede asignar un valor a una variable sin definirla, pues eso causará un error. Las variables son usadas en situaciones en las que se necesita almacenar en la memoria. La sintaxis de la declaración es la siguiente: <tipo> <nombre variable>[=<valor>]; A continuación se enumeran o muestran algunos ejemplos de declaraciones de variables: int x; string nombre; long largo; O también podemos declarar asignando un valor inicial: int x=10; string nombre=”Jose” ; char letra=’A’ ; Los tipos de datos posibles de definición son los que se pueden observar a continuación el gráfico: Profesores Adriana Gil, Pablo Linares, Jorge Romero 10 de 47 Escuela Técnica Nº 37 D.E. 11 “Hogar Naval Stella Maris” LABORATORIO I - El lenguaje de programación C# - MODULO I Es importante destacar que el C# es “Case Sensitive” a diferencia por ejemplo de cualquier versión de Visual Basic u otros lenguajes, esto quiere decir que si definimos como en el siguiente ejemplo: string apellido=”Alumnos”; string Apellido=”alumnos” ; Tenemos dos variables distintas (apellido y Apellido) ya que para C# es diferente la mayúscula de la minúscula. Ingreso de datos A continuación equivalencias para el ingreso e visualización en lenguaje C#. int a,c=20; float b; string apellido; char opc; Console.Clear(); //ingreso a = int.Parse(Console.ReadLine()); //scanf("%d",&a); b = float.Parse(Console.ReadLine()); //scanf("%f",&a); apellido = Console.ReadLine(); //scanf("%s",&apellido); opc = char.Parse(Console.ReadLine()); //scanf(“%c”,&opc); //mostrar las variables ingresadas Console.WriteLine("{0},{1},{2},{3},{4}",a,b,apellido,c,opc); Profesores Adriana Gil, Pablo Linares, Jorge Romero 11 de 47 Escuela Técnica Nº 37 D.E. 11 “Hogar Naval Stella Maris” LABORATORIO I - El lenguaje de programación C# - MODULO I ESTRUCTURAS DE CONTROL Las estructuras de control son aquellas que permiten manejar el flujo o hilo del código, es decir que con ellas podemos hacer que el mismo sea salteado, repetido, invocado, etc. Dentro de las estructuras de control podemos encontrar: Condicionales: Son aquellas que de acuerdo a la evaluación de una condición en verdadero o falso, se sigue por un camino de ejecución o por otro. De Iteración o cícilicas: Las iteraciones permiten la ejecución reiterada de un conjunto de instrucciones que se encuentre dentro de la estructura de control. Estructuras if y switch: Dichas estructuras evalúan una condición (de uno o más operadores) y la reduce a una mera expresión booleana, es decir True o False (Cierto o Falso). Dependiendo de ello se ejecutaran o no un bloque de instrucciones. Sintaxis de if: if (expresion) { Instrucciones a ejecutar si la condición fue verdadera } else { Instrucciones a ejecutar si la condición fue falsa } Sintaxis de switch: switch( expresión ) { case constante1: instrucciones; break; [case constante2: instrucciones; break;] ... [default: instrucciones;] } En ambos casos la expresión debe ser tal que tenga el tipo boolean. Notar que en el caso de las opciones del switch, es necesario especificar el break para que no ejecute las demás opciones. Estructuras for, foreach y while: Las estructuras de ciclos son utilizadas con el objeto de repetir una porción de código tantas veces como sea necesario, de acuerdo a parámetros específicos o condicionales. Profesores Adriana Gil, Pablo Linares, Jorge Romero 12 de 47 Escuela Técnica Nº 37 D.E. 11 “Hogar Naval Stella Maris” LABORATORIO I - El lenguaje de programación C# - MODULO I Sintaxis de for: for (inicialización; condición; iteración) { instrucciones; [break;] } Inicialización: se entiende como la asignación a la variable sobre la que se contabiliza la cantidad de iteraciones. Esta variable puede definirse fuera del ciclo, pero antes de la ocurrencia del mismo, o dentro de la inicialización misma, como una variable. Condición: Es una expresión booleana donde se verifica el valor de la variable sobre la que se itera. Iteración: Especifica la modalidad de variación de la variable, es decir el incremento o decremento. La instrucción break permite detener el ciclo en cualquier momento, por lo que, al se deberá utilizar condicionalmente para evitar que el ciclo se corte tan pronto como se llegue a la misma. Por ejemplo una iteración de 100 veces sería la siguiente: for (int i = 0; i < 100; i++ ) { //instrucciones; } Sintaxis de foreach: La estructura foreach es una iteración muy útil dado que se utiliza para recorrer elementos de tipo colección. Una colección es un elemento que posee subelementos que lo conforman. El ejemplo mas claro es el del vector o arreglo (se verán más adelante), pero es muy interesante apreciar que un string esta conformado por elementos de tipo char, con lo que si quisíeramos recorrer un string elemento por elemento podríamos utilizar perfectamente esta estructura. foreach (object var in collection_to_loop) { //instrucciones } object: Indica el tipo de dato que poseerá el parámetro var, así en el caso de recorrer un string, el elemento mínimo que compone este tipo de dato es el char. var: Es una expresión de tipo variable donde se asignara el subelemento actual de la colección. collection_to_loop: Especifica el elemento a recorrer por foreach. Por ejemplo el siguiente foreach recorre un string, char a char y se visualizará cada elemento en cada iteración (primero ‘A’, luego ‘d’, luego ‘r’ y así sucesivamente): string Nombre=”jorge”; foreach (char Letra in Nombre) { Console.Writeln(“{0}”,Letra); } Profesores Adriana Gil, Pablo Linares, Jorge Romero 13 de 47 Escuela Técnica Nº 37 D.E. 11 “Hogar Naval Stella Maris” LABORATORIO I - El lenguaje de programación C# - MODULO I Sintaxis de while: Se utiliza para repetir una porción de código mientras que la condición sea evaluada como True (Cierta). La instrucción break permite detener el ciclo en cualquier momento, por lo que, al se deberá utilizar condicionalmente para evitar que el ciclo se corte tan pronto como se llegue a la misma. while(condición) { instrucciones; [break;] } do { instrucciones; [break;] } while(condición); Donde la condición es una expresión booleana. Las condiciones pueden ser simples o compuestas, estas últimas son aquellas que poseen más de una condición que interactúan entre si por medio de operadores de tipo lógico, en la siguiente figura podemos apreciar la sintaxis de los mismos: OPERADOR TIPO && OPERADOR LÓGICO Y || OPERADOR LÓGICO O ! NEGACIÓN LÓGICA == IGUAL != DISTINTO Una posibilidad importante del ide, y que es muy útil, es la de presionar dos veces seguidas la tecla tab (doble tab) luego de escribir la palabra clave de cada estructura, con lo que el ide pegará automáticamente la sintaxis de cada una de ellas con el fin que luego la paramétricemos según se necesite; por ejemplo al escribir for y realizar la citada pulsación de las teclas se escribirá automáticamente lo siguiente: for (int i = 0; i < length; i++) { } con lo que solo nos queda reemplazar las características resaltadas. Manejo de Cadenas. primeramente debemos indicar que el c# (como así también lo hace su pariente c++) trata a las cadenas como una colección de caracteres. se dice colección cuando un objeto, en este caso un string, se compone de varios elementos. en el caso de los tipos string, los elementos que lo componen son los tipo char. Profesores Adriana Gil, Pablo Linares, Jorge Romero 14 de 47 Escuela Técnica Nº 37 D.E. 11 “Hogar Naval Stella Maris” LABORATORIO I - El lenguaje de programación C# - MODULO I ejemplo: string dato = "curso c#"; console.writeline("{0}", dato[1]); console.readkey(); // muestra el char: ‘u’ método ToString(): Se utiliza el método tostring() para la conversión de un dato al formato string, tal como se realizó el ejemplo previo. sintaxis: <dato>.ToString([parámetros]); los parámetros que utilizaremos (no son los únicos) permiten formatear el contenido de los datos según podemos ver a continuación. ejemplos: int a = 15; char b = 'b'; string ac = a.tostring(); string bc = b.tostring(); string ac2 = a.tostring("00.000"); se definen las variables a y b, con formatos int y char respectivamente y se convierten luego a tipo string mediante el método en las variables ac, bc y ac2. a continuación detallo los resultados de las conversiones: ac -> “15” bc -> “b” ac2 -> “15,000” importante: el contenido char se especifica entre comillas simples (por ejemplo ‘b’), mientras que el contenido de un string se especifica entre comillas (por ejemplo “laboratorio”). métodos ToUpper() y ToLower(): Se utiliza el método toupper() para la conversión de caracteres minúsculas hacia mayúsculas en un formato string, mientras que tolower() funciona de modo contrario. sintaxis: <cadena>.ToUpper(); <cadena>.ToLower(); ejemplo: string nombre="curso c#"; nombre=nombre.ToUpper(); // transformó a “CURSO C#” Console.WriteLine("{0}", nombre); nombre = nombre.ToLower(); // transformó a “curso c#” nuevamente Console.WriteLine("{0}", nombre); Console.ReadKey(); //pausa Profesores Adriana Gil, Pablo Linares, Jorge Romero 15 de 47 Escuela Técnica Nº 37 D.E. 11 “Hogar Naval Stella Maris” LABORATORIO I - El lenguaje de programación C# - MODULO I Métodos Trim(), TrimEnd() y TrimStart(): Se utilizan para eliminar espacios de un string; trim() borra todos los espacios al principio y al final de la cadena, trimend() los de la derecha o últimos y por último trimstart() elimina todos los espacios por izquierda o al comienzo de la cadena. es importante aclarar que ninguno de estos métodos elimina todos los espacios de una cadena, sino que siempre afecta a los del principio y/o los del final. sintaxis: <cadena>.Trim(); <cadena>.TrimEnd(); <cadena>.TrimStart(); ejemplo: string nombre=" laboratorio "; nombre=nombre.TrimEnd(); // transformo a “ Console.WriteLine("[{0}]", nombre); Console.ReadKey(); //pausa laboratorio” método Substring(): Este método permite la extracción en formato string de uno o mas chars contenidos, dentro de un string, según se especifique. sintaxis: <cadena>.Substring(<parámetros>) ejemplo: string nombre="curso c#"; nombre = nombre.Substring(3, 2); Console.WriteLine("[{0}]", nombre); Console.ReadKey(); //pausa // lo que extrae "so" Métodos IndexOf() y LastIndexOf(): Se utilizan para buscar una cadena de caracteres dentro de otra, brindando como resultado la posición de comienzo de la cadena encontrada, si en cambio el resultado de la búsqueda no fuera exitoso, devuelve el valor -1. la diferencia entre ambas es simplemente que indexof() comienza desde la izquierda, mientras que lastindexof() lo hace desde el final de la cadena. sintaxis: <cadena>.IndexOf(<parámetros>) <cadena>.LastIndexOf(<parámetros>) ejemplo: string nombre="curso c#"; nombre = nombre.IndexOf("c#").ToString(); Console.WriteLine("[{0}]", nombre); Console.ReadKey(); //pausa // muestra un [6] string nombre="curso c#"; nombre = nombre.LastIndexOf('#',(nombre.Length)-1).ToString(); // muestra un [7] Console.WriteLine("[{0}]", nombre); Console.ReadKey(); //pausa Profesores Adriana Gil, Pablo Linares, Jorge Romero 16 de 47 Escuela Técnica Nº 37 D.E. 11 “Hogar Naval Stella Maris” LABORATORIO I - El lenguaje de programación C# - MODULO I Método Contains(): El método contains devuelve un tipo bool, que indica si una cadena especificada se encuentra dentro de otra. ejemplo: string nombre = "curso c#"; nombre=nombre.Contains("ur").ToString(); // se muestra true por pantalla al encontrarlo Console.WriteLine("[{0}]", nombre); nombre = nombre.Contains("t").ToString(); // se muestra false por pantalla al no encontrarlo Console.WriteLine("[{0}]", nombre); Console.ReadKey(); //pausa Método Replace(): Se utiliza para reemplazar una cadena con otra, o un char por otro char. devuelve como resultado la cadena con los reemplazos efectuados. sintaxis: <cadena>.Replace(<parámetros>) ejemplo: string nombre = "curso c#"; nombre = nombre.Replace('c', 's'); Console.WriteLine("[{0}]", nombre); //muestra [surso s#] nombre = nombre.Replace("ur", "a"); Console.WriteLine("[{0}]", nombre); //saso s# Console.ReadKey(); //pausa Método Remove(): Se utiliza para eliminar caracteres de un string. devuelve como resultado la cadena sin los caracteres que se eliminan. sintaxis: <cadena>.Remove(<parámetros>) ejemplo: string nombre = "curso c#"; nombre = nombre.Remove(3); // se asigna a nombre la cadena “cur” Console.WriteLine("[{0}]", nombre); Console.ReadKey(); //pausa string nombre = "curso c#"; nombre = nombre.Remove(3,2); // se asigna a nombre la cadena “cur c#” Console.WriteLine("[{0}]", nombre); Console.ReadKey(); //pausa Método Insert(): Inserta en un string otra cadena de caracteres a partir de una posición especificada. este método no posee sobrecarga. sintaxis: <cadena>.Insert(<int inicio>,<string cadena>) Profesores Adriana Gil, Pablo Linares, Jorge Romero 17 de 47 Escuela Técnica Nº 37 D.E. 11 “Hogar Naval Stella Maris” LABORATORIO I - El lenguaje de programación C# - MODULO I ejemplo: string nombre = "curso c#"; nombre = nombre.Insert(0, "laboratorio"); nombre = nombre.Insert(11, " "); // se asigna a nombre la cadena “laboratorio curso c#” Console.WriteLine("[{0}]", nombre); Console.ReadKey(); //pausa Método Split(): Genera una collección de strings a partir de separar un string en términos, utilizando como elemento que separa, los datos pasados por parámetro. sintaxis: <cadena>.Split(<parámetros>) Ejemplo: string nombre = "curso c#"; string[] vectorCadena; vectorCadena = nombre.Split(' '); //se asigno a la posicion [0]"curso" y [1]"c#" foreach (string palabra in vectorCadena) { Console.WriteLine("{0}", palabra); } Console.ReadKey(); Método string.Compare: Se utiliza con el fin de comparar cadenas e indicar cual de ellas es tomada como la mayor de acuerdo a su contenido, de acuerdo al valor ascii que los caracteres posean. sintaxis: string.Compare(parámetros>) sintaxis parámetros: opción 1: <string a>,<string b>: indica un 1, si el dato a es mayor que el dato b, si devuelve un 0 (cero) es por que los datos son iguales, y en cambio si el resultado fuera -1 estará indicando que b es mayor que a. existen mas opciones. ejemplo: string nombre1 = "curso c#"; string nombre2 = "curso c#"; if (string.Compare(nombre1,nombre2)==0) Console.WriteLine("Iguales"); else Console.WriteLine("Distintos"); Console.ReadKey(); //pausa Profesores Adriana Gil, Pablo Linares, Jorge Romero 18 de 47 Escuela Técnica Nº 37 D.E. 11 “Hogar Naval Stella Maris” LABORATORIO I - El lenguaje de programación C# - MODULO I Definición y usos de arrays Los arrays definición posiciones variables, son espacios de memoria en los que podemos guardar información. Esto suena igual que la de variables, pero a diferencia de ellas en los arrays podemos guardar información en distintas, por lo que en lugar de tener un solo dato a la vez, como es el caso de las podremos almacenar varios datos dentro del mismo nombre asignado al array. El acceso a los datos viene dado por índices, los cuales son valores que apuntan a una celda en particular de ese tipo de entidades de memoria. Existe una diferencia dada por las dimensiones que puede tener un array, por lo tanto hablaremos de “vectores” cuando nos estemos refiriendo a los arrays unidimensionales, mientras que las “matrices” refieren a los arrays multidimensionales. En los vectores, la información se dispone a manera de un listado, mientras que en las matrices la información se almacena en forma de tabla, es decir que las celdas se referencian mediante filas, columnas y, tal vez, profundidad (en las matrices tridimensionales). Definiendo vectores y matrices Para la declaración de los arrays se deberán tener en cuenta algunas consideraciones que se detallan a continuación: 1° caso: Se conoce el contenido del array, que se carga cuando este se inicializa: No será necesario entonces definir el tamaño del array, ya que C# tomará automáticamente el tamaño del contenido de inicialización. Ejemplo: int[ ] Vec={1,2,3,4};// Vec es un vector de enteros con cuatro elementos 1 Vec[0] 2 Vec[1] 3 Vec[2] 4 Vec[3] char[,] Matr = {{ ’a’,’b’,’c’},{ ’x’,’y’,’z’}}; // Matr es una matriz de 6 dos filas y tres columnas Matr[0,0] ‘a’ ‘x’ Matr[1,0] Matr[0,1] ‘b’ ‘y’ Matr[1,1] Matr[0,2] ‘c’ ‘z’ Matr[1,2] 2° caso: Se conoce el tamaño máximo del array, aunque no su contenido: Se deberá crear un nuevo objeto del tipo determinado, indicando el tamaño. C# inicializa todos sus elementos en 0 (cero). Profesores Adriana Gil, Pablo Linares, Jorge Romero 19 de 47 elementos, en Escuela Técnica Nº 37 D.E. 11 “Hogar Naval Stella Maris” LABORATORIO I - El lenguaje de programación C# - MODULO I Ejemplo: int[] Vec= new int[5]; // Vector de enteros de 5 posiciones 0 Vec[0] 0 Vec[1] 0 Vec[2] 0 Vec[3] 0 Vec[4] float[,] Matr= new float[3,4]; // Matrices de 12 elementos de 3 filas y 4 columnas. Recorriendo los Array En los dos primeros casos, recorrer el vector podrá hacerse de la forma que conocemos, es decir, usando for como ya fue explicado int[ ] vec ={ 1, 3, 5, 7, 9 }; Veamos que, aunque podemos usar el número del tamaño del vector para controlar el for, es más conveniente utilizar la propiedad correspondiente for (int i = 0; i < vec.Length; i++) { // Código que afecta a cada elemento del vector, vec[i]; } Un caso a destacar es la posibilidad que nos ofrece esta estructura de control (for) para recorrer simultáneamente dos vectores con índices distintos. Por ejemplo, si queremos obtener un vector que tenga los mismos elementos que otro, pero en orden inverso, podríamos escribir: int[ ] v = new int[5]; int[ ] vec ={ 1, 3, 5, 7, 9 }; for (int i = 0, j=4; i < vec.Length; i++, j--) { En este caso es indistinto controlar el v[j] = vec[i]; for con esta propiedad que con } ;j>=0; ya que ambas significan la misma cantidad de iteraciones Profesores Adriana Gil, Pablo Linares, Jorge Romero 20 de 47 Escuela Técnica Nº 37 D.E. 11 “Hogar Naval Stella Maris” LABORATORIO I - El lenguaje de programación C# - MODULO I EXCEPCIONES Concepto de excepción: Las excepciones son el mecanismo recomendado en la plataforma .NET para trabajar sobre los errores que se produzcan durante la ejecución de las aplicaciones (divisiones por cero, lectura de archivos no disponibles, etc.) using System; using System.Collections.Generic; using System.Text; namespace primera { class Program { static void Main(string[] args) { int a,b,c,resultado; a = int.Parse(Console.ReadLine()); b = int.Parse(Console.ReadLine()); c = int.Parse(Console.ReadLine()); try { resultado = 2 / a; } catch { Console.WriteLine("error no puede ser un valor 0 la variable a"); } Console.ReadKey(); } } } Creación de METODOS: Ejemplo de ejercicio sin la utilización de métodos using System; using System.Collections.Generic; using System.Text; namespace ConsoleApplication1 { class Program { static void Main(string[] args) { int a,b; Console.Clear(); Console.WriteLine("Ingrese un valor.."); a = int.Parse(Console.ReadLine()); Console.WriteLine("Ingrese un valor.."); b = int.Parse(Console.ReadLine()); int sumar = a + b; Console.WriteLine("El resultado de la suma es..{0}", sumar); Console.ReadKey(); } } } Profesores Adriana Gil, Pablo Linares, Jorge Romero 21 de 47 Escuela Técnica Nº 37 D.E. 11 “Hogar Naval Stella Maris” LABORATORIO I - El lenguaje de programación C# - MODULO I El mismo ejemplo que el anterior pero usando métodos using System; using System.Collections.Generic; using System.Text; namespace ConsoleApplication1 { class Program { static void Main(string[] args) { int a,b; Borrar(); Ingreso(a,b); int sumar = Hallar_Suma(a, b); Mostrar_Resultado(sumar); Console.ReadKey(); } private static void Mostrar_Resultado(int sumar) { Console.WriteLine("El resultado de la suma es..{0}", sumar); } private static int Hallar_Suma(int a, int b) { int sumar = a + b; return sumar; } private static void Ingreso(int a,int b) { Console.WriteLine("Ingrese un valor.."); a = int.Parse(Console.ReadLine()); Console.WriteLine("Ingrese un valor.."); b = int.Parse(Console.ReadLine()); } private static void Borrar() { Console.Clear(); } } //cierra clase program } //cierra namespace Profesores Adriana Gil, Pablo Linares, Jorge Romero 22 de 47 Escuela Técnica Nº 37 D.E. 11 “Hogar Naval Stella Maris” LABORATORIO I - El lenguaje de programación C# - MODULO I Ejercitación Estructura de decisión 1 - Ingresar dos números e informar cual es: a) mayor b) Menor. 2 - Ingresar 4 números e informar si corresponde a alguna de las siguientes situaciones: a) b) c) f) d) e) Son los cuatro valores iguales. El segundo valor es el menor. Son todos distintos. Los dos valores del medio son iguales. El primero es el mayor que los otros tres. El último es el mayor de los cuatro. 3 - Escribir un programa que calcule la raíz cuadrada y el inverso multiplicativo de un número ingresado por teclado. Antes de calcular la raíz, se debe verificar que el número sea no negativo, y para el inverso, que no sea cero. Escriba un programa que calcule las raíces reales de un polinomio de segundo grado con coeficientes a, b y c. ( x=(- b (b2-4*a*c)) / (2*a)). CICLOS 4 – Dado un conjunto de valores finalizado con un valor nulo, desarrollar el programa que determine e imprima (si hubo valores). a) Valor máximo negativo. b) Valor mínimo positivo. c) Hallar el valor menor dentro del rango -17 a 26. 5 - Hacer un programa que calcule el factorial de un número. En un menú el usuario debe decidir si usa las sentencias While , Do.. While ó For. (El menú debe llamar a las distintas funciones). 6- Escriba un programa que según se indique mediante un menú apropiado, calcule y emita: - Suma - Promedio - Rango (máximo – mínimo) CADENAS 7 – Ingresar una frase e informar si es palíndromo. 8 - Realizar un programa que ingresando la fecha en el siguiente formato 04/09/2015 debe mostrar lo siguiente: cuatro de septiembre de 2015. 9 - Hacer un programa que cuente los blancos de una frase dada, y que diga cuantas vocales tiene. 10 - Hacer un programa que intercale una frase en otra, a partir de la posición que indique el usuario. 11 - Hacer un programa que cuente cuántas palabras de 4 letras tiene una frase ingresada por teclado. 12 - Implementar una función que devolverá un dato de tipo cadena que corresponderá con las siglas de la cadena que toma como argumento. Las siglas estarán formadas por las letras en mayúsculas de todas las palabras, separadas por un punto Ejemplo: Introduzca frase: tren articulado ligero (devolverá: T . A . L .) Profesores Adriana Gil, Pablo Linares, Jorge Romero 23 de 47 Escuela Técnica Nº 37 D.E. 11 “Hogar Naval Stella Maris” LABORATORIO I - El lenguaje de programación C# - MODULO I 13 – Dadas 2 fechas en el siguiente formato dd/mm/aaaa, decir cual es la mas lejana al dia de hoy. 14 - Ingresar una fecha en el formato 24/10/2010, con dicha fecha se debe informar en una clase llamada HALLAR, si esa fecha ingresada es valida o no, la confirmación o no de ser una fecha valida tiene que ser atravez de un devolucion de un dato booleano. Vectores 15 - Emitir el valor mínimo y la cantidad de veces que se repitió y en qué posiciones. 16 - Obtener la suma y el promedio de los elementos de una matriz de 3 x 4. 17- Hacer un algoritmo que llene una matriz cuadrada con números aleatorios y determine las posiciones [fila][columna] del número mayor almacenado en la matriz. 18- Cargar un vector de 20 elementos con un numero random entre 50 y 100, de forma que no contenga elementos repetidos. Mostrar el vector resultante y ordenarlo según el criterio que indique el usuario. Mostrar el vector ordenado. 19 – Cargar un vector con los números aleatorios, indicar si esta ordenado, si no esta ordenarlo según criterio del usuario. Mostrar el vector ordenado sin perder el contenido anterior. 20 – Cargar un vector en forma aleatoria entre un rango de 20 a 40(la dimensión la indica el usuario). A partir de ese vector generar otro que no contenga repetidos. Comparar ambos vectores e indicar si son iguales. 21 - La buena balancita o la balacerita Estamos trabajando en un mercado de oro en el medio del Transvaal, con todos los peligros que esta actividad acarrea. Nuestra tarea es la de recibir bolsitas de oro, y determinar con una balancita de dos platillos si no existe alguna trampa en el intercambio (que llevaría a una balacera imparable…). El tema es así: me entregan de a 4 bolsitas, y tengo que ver si existe alguna distribución de esas 4 bolistas en los platillos que equilibre la balancita. Por ejemplo: Me entregan 4 bolsitas con los siguientes pesos (en gramos): 12 36 18 6. Puedo poner en una balancita las bolsitas de 12, 18 y 6 gramos (36 gramos en total) y en el otro platillo la bolsita de 36 gramos, y la balancita quedará equilibrada. Si las bolsitas pesan: 10 20 5 30 no tengo distribución posible. Escriba un programa que lea la entrada y produzca la salida indicada a continuación: ENTRADA (por teclado) NMOP Que son los 4 números separados cada uno por un espacio, finalizando con enter. (Cada número estará entre 1 y 1000). SALIDA (por pantalla) Si hay solución posible, en una línea uno de los grupos de bolsitas, y en la línea siguiente el otro (no importa cuál de los dos grupos aparece primero). Si no hay solución, el cartel “NO HAY SOLUCION”. Ejemplos: Entrada Salida Ejemplo 1 12 36 18 6 12 18 6 36 Profesores Adriana Gil, Pablo Linares, Jorge Romero Ejemplo 2 10 20 30 40 10 40 20 30 Ejemplo 3 5 2 999 996 999 2 996 5 Ejemplo 4 6 10 12 3 No hay solución 24 de 47 Escuela Técnica Nº 37 D.E. 11 “Hogar Naval Stella Maris” LABORATORIO I - El lenguaje de programación C# - MODULO I Matrices 22 - Hacer un algoritmo que almacene números en una matriz de M x N. Imprimir la suma de los números almacenados en la matriz. 23 - Hacer un algoritmo que llene una matriz de M X N y determine la posición [fila][columna] del numero mayor almacenado en la matriz. Suponer que todos los números son diferentes. 24 - Obtener la suma y el promedio de los elementos de una matriz de N x M. 25 - Dada una matriz de N x M obtener dos vectores, uno que resulte de sumar los elementos por filas y otro sumando los elementos por columnas. 26 - Dada una matriz de N x M obtener el vector resultante de los máximos de cada columna y mostrar el mínimo de ese vector. 27 - Dada una matriz de N x M elementos determinar un vector de dos elementos formado por el promedio de los pares y el promedio de los impares. 28 - Dada una matriz de N x M donde cada fila representa un numero binario, generar el vector que corresponde a la expresión decimal del mismo. 29 - Dada una matriz de N x M, obtener su valor mínimo y una matriz de 2 columnas con las posiciones en que aparece. 30 - Dada una matriz de N x M obtener otra, tal que los elementos de la 2º sean los valores absolutos de los elementos de la 1º. 31 - Dada una matriz cuadrada de N x M, obtener el par formado por la suma de los elementos de cada diagonal. 32 - Dada una matriz de N x N se pide: Rellenar la matriz con números Copiar la diagonal principal de la matriz hacia un vector Gamma Copiar la diagonal contraria de la matriz hacia un vector Tita Transportar ambos vectores hacia un único vector Lamda Ordenar Lamda y mostrarlo por pantalla ordenado 33 - Hacer un algoritmo que llene una matriz de M x N ( los ingresa el usuario) y que almacene en la diagonal principal unos y en la demás posiciones ceros. 34 - Hacer un programa que llene una matriz cuadrada de N x N, de la siguiente forma: Profesores Adriana Gil, Pablo Linares, Jorge Romero 25 de 47 Escuela Técnica Nº 37 D.E. 11 “Hogar Naval Stella Maris” LABORATORIO I - El lenguaje de programación C# - MODULO I Bordes con *. Diagonales con X. Las demás posiciones, en blanco. 35 - Cargar una matriz con 25 valores al azar y generar dos vectores que son las suma por fila y por columna. 36 - Dada una matriz cuadrada de m x n, obtener el par formado por la suma de los elementos de cada diagonal. 37 – Cargar una matriz cuadrada con ceros y unos (0 y 1), cada fila representa un número binario, pasar a un vector llamado VectorDec, donde corresponde al número decimal de cada fila de la matriz. 38 – Cargar una matriz cuadrada, según la dimensión que indique el usuario (no superior a 25), con ‘&’ en los bordes, ‘$’ en las diagonales y ‘%’ en las restantes. Mostrar por pantalla la matriz resultante. 39 – Cargar y mostrar una matriz cuadrada, cuya dimensión se le pide al usuario y no puede ser mayor a 30, de la siguiente forma: la matriz secundaria con 0, todas las posiciones que quedan debajo con -1 y las que quedan por encima con 1. 40 - Descripción del juego – Aplicación de windows Como es conocido, el juego del ahorcado consiste en que la maquina piensa o elige una palabra y mantiene “oculta”, dando como información inicial el número de letras y el contrincante intenta descubrirla letra a letra hasta que se acierten todas las letras o hasta un número de intentos fallidos determinado. Enunciado Realizar un programa en C#, que permita leer de un vector todas las palabras a adivinar (mínimo 30 palabras). Cada vez que el contrincante de una letra puede suceder uno de los siguientes casos: A - Que se encuentre en la palabra oculta. Entonces se muestra la palabra con todas las letras ya acertadas y colocadas en su lugar correspondiente, el resto de letras se mantienen ocultas mostrando en su lugar ‘*’. B - Si la letra no está en la palabra oculta se muestra un poco más de la figura del ahorcado y de nuevo la palabra con las letras acertadas previamente y ‘*’. El juego finaliza cuando el contrincante descubre todas las letras de la palabra oculta o se muestra completa la figura del ahorcado. La figura del ahorcado consta de: Cabeza Tronco Pierna izquierda Pierna derecha Brazo derecho Brazo izquierdo 41 - TRABAJO FINAL”TATETI” – Aplicación de windows Escribir un programa que permita a una persona jugar a las tres en línea (TA-TE-TI) con la computadora. Escribir el programa de forma que la computadora pueda ser tanto el primero como el Profesores Adriana Gil, Pablo Linares, Jorge Romero 26 de 47 Escuela Técnica Nº 37 D.E. 11 “Hogar Naval Stella Maris” LABORATORIO I - El lenguaje de programación C# - MODULO I segundo jugador. Si la computadora es el primer jugador, el primer movimiento se generará al azar y el resto mediante una estrategia tiene que jugar a ganarle a la persona y tapando las jugadas posibles que realice la persona. Mostrar el estado del juego tras cada movimiento. La computadora debe avisar cuando gana cada jugador, y al final de la sesión de juego, si ha ganado la computadora o la persona. APLICACION WINDOWS VS.NET simplifica el desarrollo de aplicaciones basadas en .NET proporcionando un entorno de desarrollo simple y unificado el cual posee las siguientes características: Un solo IDE (Integrated Development Environment) Soporte para varios lenguajes .NET (VB.NET, C#,...) Desarrollo de múltiples tipos de proyectos Explorador Web integrado (basado en IE) Interfase personalizable Posee varias utilidades adicionales: Acceso a datos SQL Server, Depurador, Emuladores para móviles, etc. Al iniciar el entorno de desarrollo de Visual Studio 2005 se encontrarán con un pantalla principal en la se dispone de las opciones relacionadas a la creación o edición de proyectos. Figura 01 En dicha pantalla se podrá elegir el abrir un proyecto o sitio web, o crear alguno de ellos. En VS2005 las aplicaciones windows o web se desarrollan dentro del marco de las “soluciones”(Figura 01). A los efectos del presente apunte se detallarán los pasos para la creación de una nueva aplicación Windows Forms, pero los mismos son similares para las restantes opciones. Al crear un nuevo proyecto Windows se desplegará la siguiente ventana: Profesores Adriana Gil, Pablo Linares, Jorge Romero 27 de 47 Escuela Técnica Nº 37 D.E. 11 “Hogar Naval Stella Maris” LABORATORIO I - El lenguaje de programación C# - MODULO I Figura 02 En “Name” se especificará el nombre de la nueva aplicación, en “Location” se elegirá la carpeta destino de la misma (el botón browse nos permitirá realizar la presente operación mas fácilmente), no obstante si tildamos el check “Create Directory For Solution”, el IDE se encargará de generar una carpeta con el nombre especificado en “Name” (recomiendo esta práctica por sobre las demás). En la ventana “templates” podremos seleccionar el tipo de aplicación a desarrollar. Por el momento usaremos “Windows Application”. Asimismo podemos elegir en esta ventana el lenguaje a utilizar (en nuestro caso será C#, por lo que en la figura ejemplo dejaremos todo como esta en la ventana titulada como “Project types”(Figura 02). Luego de presionar OK en la ventana anterior, se accederá al entorno de desarrollo propiamente dicho, el cual se visualizará (de no mediar cambios en la configuración) del siguiente modo: Profesores Adriana Gil, Pablo Linares, Jorge Romero 28 de 47 Escuela Técnica Nº 37 D.E. 11 “Hogar Naval Stella Maris” LABORATORIO I - El lenguaje de programación C# - MODULO I Figura 03 Sobre el margen izquierdo se distingue el cuadro de herramientas o toolbox el cual permitirá seleccionar los diferentes controles a pegar en el formulario, los cuales se programarán con las características necesarias para la aplicación(Figura 03). Profesores Adriana Gil, Pablo Linares, Jorge Romero 29 de 47 Escuela Técnica Nº 37 D.E. 11 “Hogar Naval Stella Maris” LABORATORIO I - El lenguaje de programación C# - MODULO I A lo largo del presente año iremos utilizando los principales controles, por lo que se ampliará con mayor detalle este tema. En la zona central de la Figura 09 se aprecia el formulario de la aplicación, que es la parte principal de la interfase cliente que poseerá la aplicación; es decir que el formulario es quien al ejecutar la aplicación terminada comunicara a las tareas de la misma con el usuario. Finalmente sobre el margen derecho disponemos de dos ventanas mas, una titulada como Explorador de soluciones y la que se encuentra debajo de esta, llamada como ventana de Propiedades(Figura 04). Figura 04 El explorador de soluciones nos permite ubicarnos fácilmente en cada uno de los componentes de la solución y la ventana de propiedades nos indica las características actuales de un formulario o control, para su visualización y/o modificación. Profesores Adriana Gil, Pablo Linares, Jorge Romero 30 de 47 Escuela Técnica Nº 37 D.E. 11 “Hogar Naval Stella Maris” LABORATORIO I - El lenguaje de programación C# - MODULO I COMENZADO A GENERAR UNA INTERFAZ Si volvemos sobre la figura 03, en donde observamos todo el IDE completo, veremos, en el centro, un área blanca que posee un formulario en su esquina superior izquierda. Dicho formulario es donde, en el ámbito de WindowsForms, desarrollaremos la interfase que comunicará nuestra aplicación con el usuario, utilizando para dicho fin los controles que se nos ofrecen en el cuadro de herramientas. No nos detendremos en describir todos y cada uno de los controles, ya que lo consideramos tedioso e innecesario; si, en cambio, explicaremos el concepto de cómo se trabaja en este tema y algunos controles que consideramos básicos. Puntos a tener en cuenta: Ubicar un control en el formulario: Es muy sencillo, tanto como arrastrar el icono, del control elegido, desde la barra de controles hasta el formulario. Otro modo es hacer doble clic sobre el ícono deseado, con lo que automáticamente se pegara el control en el formulario. Propiedades de los controles (se aplica a los formularios): Las propiedades (también llamadas atributos) permiten personalizar el control utilizado. Dichas propiedades pueden ser accedidas desde la ventana correspondiente en el IDE (ver figura 11), o mediante código a través de la siguiente sintaxis: <nombre>.<propiedad>=<dato>; Los métodos: Son los procedimientos que posee un control para realizar algún topo de operación. Se accede a ellos mediante la sintaxis: <nombre>.<método>(); Los eventos: Son el nexo entre una acción (muchas veces ocasionada por el usuario) y la ejecución de tareas para atender a la misma. De este modo podremos hacer que se ejecute un código especifico para el hecho de pulsa un botón, o el escribir un texto, etc. Los eventos se encuentran en cada control y si bien la mayoría son de aplicación indistinta del control, existen eventos que son propios del control utilizado. Antes de continuar es bueno observar que los eventos tienen el formato en su sintaxis que indica que se trata de un procedimiento o subprograma, por lo que a continuación se explica que son los procedimientos y como funcionan. Procedimientos y funciones Estas estructuras se utilizan para evitar la escritura repetida en un código, esto quiere decir que el código inserto en ellas se utilizará cada vez que sean invocadas mediante el nombre que el desarrollador les haya dado. La diferencia entre el concepto de procedimiento y el de función radica en que las funciones devuelven por si mismas un resultado, mientras que el procedimiento no lo hace. Profesores Adriana Gil, Pablo Linares, Jorge Romero 31 de 47 Escuela Técnica Nº 37 D.E. 11 “Hogar Naval Stella Maris” LABORATORIO I - El lenguaje de programación C# - MODULO I Sintaxis Procedimiento: <ámbito> void <nombre>([parámetros>]) { } Sintaxis Función: <ámbito> <tipo> <nombre>([parámetros>]) { return <valor>; } Explicación de la sintaxis: <ámbito> : Indica el alcance de la ejecución, por el momento utilizaremos la palabra private. Oportunamente profundizaremos sobre este tema. void en el procedimiento y <tipo> en la función: Como el procedimiento no devuelve un resultado es que se le indica void, lo cual significa vacío. Mientras que para la función debemos indicar un tipo de dato (se verá más en detalle en el capítulo siguiente) <nombre>: Indica cual es el nombre que le daremos al procedimiento o función. <parámetros>: Son opcionales y permiten el ingreso de información al procedimiento o a la función. <return> (funciones): Se utiliza para determinar el valor de retorno o respuesta de que dispondrá una función; dato que deberá respetar el <tipo> que se ha especificado en la declaración de la función. Procedimientos eventuales: Los procedimientos por evento son aquellos que se ejecutan en relación a una acción que desencadena el evento del procedimiento. La sintaxis que utilizan los eventos es la que se detalla a continuación: <ámbito> void <nombre del control>_<Evento>(<parámetros>) { } Notese que la diferencia con el procedimiento normal se basa en que se escribe el nombre del control y seguido de un guión bajo el nombre del evento. Por lo general no nos tomaremos el trabajo de escribirlo, sino que pulsaremos doble click sobre el control a trabajar y automáticamente aparecerá el procedimiento en el IDE. Desarrollando nuestra primera interfase: Un buen ejemplo sería el de armar un sencillo cliente que permita ingresar un nombre, agregarle la cadena “hola” y concatenar el nombre a continuación: Profesores Adriana Gil, Pablo Linares, Jorge Romero 32 de 47 Escuela Técnica Nº 37 D.E. 11 “Hogar Naval Stella Maris” LABORATORIO I - El lenguaje de programación C# - MODULO I Pasos: Buscar un control de tipo textbox y pegarlo en el formulario. Buscar un control de tipo button y luego de pegarlo en el formulario, realizar doble clic sobre el mismo, con lo que obtendremos el siguiente resultado: private void button1_Click_1(object sender, EventArgs e) { } Finalmente ubicar el ícono que representa al control label y hacer lo mismo que en la primera tarea. Debió, entonces, quedar confeccionado un formulario que posee una casilla para ingresar el texto (nombre en este caso) llamada textbox1, un botón llamado button1 que el usuario accionará para aceptar el ingreso, y finalmente un control de etiqueta llamado label1 donde se visualizará el mensaje final de la aplicación. Luego debemos simplemente cambiar algunas propiedades de los controles con el fin de lograr una interfase bien terminada, para ello desde la ventana de propiedades realizar las siguientes operaciones: Borrar el contenido de las propiedades Text de los controles TextBox1 y Label1 Cambiar el contenido de la propiedad Text del control Button1 por “Aceptar” Si hemos seguido correctamente los pasos precedentes debemos poder visualizar un formulario como el siguiente: Figura 12 Ahora habrá que hacer doble clic en el botón y escribir dentro del procedimiento eventual, el siguiente código: label1.Text = "Hola! " + textBox1.Text; Con lo que quedaría el código siguiente: private void button1_Click_1(object sender, EventArgs e) { label1.Text = "Hola! " + textBox1.Text; // Este procedimiento se ejecutará toda vez que el usuario // presione el botón de aceptar!!!! } Profesores Adriana Gil, Pablo Linares, Jorge Romero 33 de 47 Escuela Técnica Nº 37 D.E. 11 “Hogar Naval Stella Maris” LABORATORIO I - El lenguaje de programación C# - MODULO I Existen muchos otros controles; los hay para el ingreso y visualización de fechas, de chequeo, de opción, para la visualización de imágenes, etc, etc, etc. Muchos se explicarán en clase, pero nos será de mucho agrado el ver que uds. poseen la proactividad necesaria para investigar los que queden fuera de las clases de que disponemos. COMENZANDO A DESARROLLAR Como en la mayoría de los lenguajes visuales, podemos desarrollar la interfaz del usuario sin tener que tipear código, valiéndonos para ello de herramientas gráficas. La programación en Visual C#, a diferencia de otros lenguajes, no es solamente lineal sino que es además por eventos. ¿Qué significa esto?. Simplemente que mientras en Turbo Pascal o Turbo C++ el compilador leía línea por línea desde el principio hasta el final del código, terminando por lo general en ese momento la ejecución, el Visual C# lee procedimientos de código ante determinadas acciones del usuario (eventos que suceden durante la ejecución del programa), como por ejemplo la simple pulsación de un botón o la elección de una opción entre varias otras que el programa ofrezca. Veamos un clarificador ejemplo en el que muestro un sencillo programa en Turbo C++ y su equivalente en Visual C#: /* Ejemplo 1 en Turbo C*/ #include<stdio.h> void main(void) { printf(“Este es el primer programa”); } ... y a continuación un equivalente posible en Visual C#: private void button1_Click(object sender, EventArgs e) { MessageBox.Show("Este es el primer programa"); } La pregunta obvia que surge de esto es ¿y cuál es la diferencia entre ejecución lineal y eventual?. Bien, con ustedes la respuesta : los dos programas emiten un mensaje (“Este es el primer programa”) sólo que lo hace en momentos bien diferentes, cuando en C++ ejecuten este programa el mensaje en cuestión se muestra de inmediato. En cambio en Visual C# se espera el evento Click() del control button1 para mostrar el mensaje. Esto no es más que la pulsación (Click) de un botón llamado button1 que se creó con la barra de herramientas que posee el Visual y que se situó en el Formulario. Veamos los pasos que llevó el desarrollo: Primeramente se ubicó en el formulario un control llamado button1. Esto es un botón clásico de los que se utilizan a menudo en Windows, luego se efectuó un doble click sobre el botón “button1” con lo que el IDE pasa a la ventana de codificación, en lugar de seguir mostrando el formulario. Nos ubicará entonces dentro del procedimiento eventual Click del control Button1. Luego, al ejecutar (pulsar F5) la aplicación, el formulario se quedará esperando a que Profesores Adriana Gil, Pablo Linares, Jorge Romero 34 de 47 Escuela Técnica Nº 37 D.E. 11 “Hogar Naval Stella Maris” LABORATORIO I - El lenguaje de programación C# - MODULO I suceda un “evento”. En este caso el único evento que hemos programado es “click” del control button1, pero como se imaginarán existen muchos otros tipos de eventos y controles. Al pulsar el botón el usuario de la aplicación, estará entonces haciendo que se ejecute el código encerrado entre las llaves del Private Sub Button1_Click. A esto es lo que se le ha llamado “programación por eventos”, este tipo de codificación brinda una mayor flexibilidad que la forma tradicional, ya que programamos para las acciones que el usuario realice. No obstante C# no es solamente un modelo eventual de programación ya que además se encuentra orientado a objetos y es también un lenguaje fuertemente tipado, aunque dichos conceptos serán tratados en capítulos más avanzados del presente manual. Como Genera una clase en C# Pasaremos a desarrollar un paso a paso de cómo crear una clase. - Realizamos click sobre nuevo. Le damos un nombre al proyecto(CreacionDeClase). Le damos una ubicación(4to). Profesores Adriana Gil, Pablo Linares, Jorge Romero 35 de 47 Escuela Técnica Nº 37 D.E. 11 “Hogar Naval Stella Maris” LABORATORIO I - El lenguaje de programación C# - MODULO I - Colocamos ACEPTAR y genera nuestra solución. - Colocamos un button1 (cambiamos la propiedad Text y le colocamos ACEPTAR), textbox1, label1(cambiamos propiedad Text le borramos u contenido). Doble click sobre button1 donde empezaremos a escribir nuestro código. - Profesores Adriana Gil, Pablo Linares, Jorge Romero 36 de 47 Escuela Técnica Nº 37 D.E. 11 “Hogar Naval Stella Maris” LABORATORIO I - El lenguaje de programación C# - MODULO I - Vamos ahora a agregar el formulario de clase, hacemos ARCHIVO-AGREGAR - NUEVO PROYECTO. - Elijo Biblioteca de Clase. - Le doy un nombre a esa clase si quiero, en este caso de vamos dar el nombre AVERIGUACION. Profesores Adriana Gil, Pablo Linares, Jorge Romero 37 de 47 Escuela Técnica Nº 37 D.E. 11 “Hogar Naval Stella Maris” LABORATORIO I - El lenguaje de programación C# - MODULO I - Se agrego la biblioteca de clase llamada AVERIGUACION. - Dentro de public class class1, vamos a escribir el método que nos de él resultado solicitado. Profesores Adriana Gil, Pablo Linares, Jorge Romero 38 de 47 Escuela Técnica Nº 37 D.E. 11 “Hogar Naval Stella Maris” LABORATORIO I - El lenguaje de programación C# - MODULO I - - Adaptamos que problema que teníamos hecho para que nos funcione la validación que la va a generar la clase AVERIGUACION. Referenciamos el formulario con la clase, nos paramos sobre CreacionDeClase, Boton derecho de mouse, agregar referencia, en las solapas de la ventana que nos apareció, presionamos sobre la solapa Proyectos, y vemos dentro de dicha solapa nuestra clase llamada AVERIGUACION, la marcamos y presionamos Aceptar. Colocamos en el nombre de la clase en el sector using AVERIGUACION. Instancio para poder visualizar los métodos de la clase AVERIGUACION Class1 Valida=new Class1(); Profesores Adriana Gil, Pablo Linares, Jorge Romero 39 de 47 Escuela Técnica Nº 37 D.E. 11 “Hogar Naval Stella Maris” LABORATORIO I - El lenguaje de programación C# - MODULO I - Ejecutamos nuestra aplicación, visualizamos que funciona y nos devuelve la clase TRUE o FALSE según el código solicitado. Utilización de los datos tipo de fecha CLASE DateTime Dejando para lo último de este tema, tenemos algo muy importante… La clase DateTime, la cual permite el manejo integro de los datos del tipo Fecha; datos que poseen ciertas particularidades que los alejan de los demás. Primeramente la clase se encarga de las validaciones y el control de fechas correctas, es decir que no podremos especificar un valor para día, por ejemplo, que sea igual a 51 o un mes mayor a 12, ahorrando mucho tiempo en validaciones y por supuesto favoreciendo a la integridad de la información. Del mismo modo, también, controla que por ejemplo no pongamos un día mayor a la capacidad del mes, o si intentamos especificar día 29 para un febrero no bisiesto, entre otras muchas utilidades y facilidades que nos brinda la clase. Para poder utilizar todo lo antedicho (y mas!) debemos generar una instancia de la clase (un objeto fecha) de acuerdo a lo descripto en lo que sigue: Sintaxis: DateTime <Nombre>=new DateTime(<Parámetros>) Sintaxis Parámetros: Opción 1: <Sin Parametros>: Indica que se genera una instancia de la clase, la cual aún no posee otra cosa que null. Opción 4: <int year, int month, int day>: Carga en la declaración una fecha especificada en el orden año, mes y día. Opción 6: <int year, int month, int day, int hour, int minutes, int seconds>: Muy similar al caso anterior, salvo que se le especifican además la hora, los minutos y los segundos. Profesores Adriana Gil, Pablo Linares, Jorge Romero 40 de 47 Escuela Técnica Nº 37 D.E. 11 “Hogar Naval Stella Maris” LABORATORIO I - El lenguaje de programación C# - MODULO I Obviamente existen mas opciones de sobrecarga, ya que en este caso asciende a la cantidad de 12. Ejemplo: DateTime Fecha = new DateTime(1977, 5, 21); // Fecha posee el date igual al 21 de mayo de 1977 La clase ademas posee una serie de métodos con los que se podrán realizar distintas operaciones sobre fechas. Método AddDays(<double N>): Permite mediante un double especificar un incremento de N dias en la fecha contenida en el objeto. Si se especifica un número negativo se restarán los días especificados. Del mismo modo se dispone de los métodos AddMonth(), AddMonths(), AddYears(), AddMinutes(), etc… Ejemplo: DateTime Fecha = new DateTime(1977, 5, 21); // Se define la fecha 21/05/1977 Fecha = Fecha.AddDays(-10); // Ahora la fecha se atrasa 10 días MessageBox.Show(Fecha.ToString ()); // Se visualiza 11/05/1977 Propiedad DaysInMonth(int Año, int Mes): Devuelve un int con la cantidad de días que posee el mes especificado. Ejemplo: int dias = DateTime.DaysInMonth(2008, 2); label1.Text = dias.ToString(); // Muestra 29 Propiedades Now y Today: Devuelven un DateTime con el momento actual (Now) o con el día actual (Today). Ejemplo: DateTime Ahora = DateTime.Now; // Carga en Ahora la fecha y hora actual DateTime Hoy = DateTime.Today; // Carga en Ahora la fecha actual, a las 00:00 hs. // Notese que por tratarse de propiedades y no tener parametros // no se utilizan parentesis. Profesores Adriana Gil, Pablo Linares, Jorge Romero 41 de 47 Escuela Técnica Nº 37 D.E. 11 “Hogar Naval Stella Maris” LABORATORIO I - El lenguaje de programación C# - MODULO I CONVERSIONES DE FORMATOS En el presente apartado trataremos lo inherente a conversiones de datos y asimismo aspectos relativos a otros tipos de datos que no son de formato string o su relacionado char. Es aquí donde podremos observar manejo de numéricos y fechas, como así también el cambiar los tipos de datos de la información. Las conversiones nos permiten que una expresión de un tipo sea tratada como una expresión de otro tipo, dichas conversiones pueden ser implícitas o explícitas, por ejemplo la conversión de un tipo int a long es implícita, sin embargo la conversión de un tipo long a un tipo int es explícita, esto debido a que un int puede ser expresado en formato long sin que haya perdida de precisión en la operación, sin embargo si intentamos convertir un numero long a int puede haber perdida de precisión y se necesita una conversión explícita, es como una forma de obligarnos a demostrar que estamos conscientes de que existe tal perdida de precisión y en verdad es muy útil. Método Parse: Parse posee la capacidad de convertir datos desde un string a un tipo numérico. Las conversiones serán realizadas a través del tipo que se necesita (int,double, long, etc) Sintaxis: Sobrecarga 1: <tipo>.Parse(<string>) Dada la magnitud de operaciones posibles, se darán una serie de ejemplos orientativos ya que creemos que no tiene mucho sentido explayarse durante varias páginas con conceptos tales como int32.Parse convierte un string a formato integer de 32 bytes. De todas formas, en cada ejemplo se detalla que es lo que se hace en cada uno: Ejemplos: string b = "2"; // Se define la variable b con contenido “2” string c = "3"; // Se define la variable c con contenido “3” MessageBox.Show((int.Parse (c) +int.Parse(b)).ToString()); // Se muestra como resultado el número 5 Como vemos se “parsearon” las dos variables que originariamente eran string. Si no hubieramos efectuado la presente conversión, todo habría sido tratado como cadena, con lo que el resultado final habría sido “”32”. Ahora bien, ¿qué hubiera sucedido si definíamos, por decir algo, la variable c con un valor igual a “2.5”? Sencillamente nos generaría un error ya que el tipo int no soporta datos números con decimales (es en parte lo que se menciona en el recuadro superior cuando habla de conversiones implícitas y explícitas). En tal caso hubiera sido necesario algo como lo que sigue: string b = "2,5"; string c = "2,2"; MessageBox.Show((double.Parse(c) + double.Parse(b)).ToString()); // Se muestra como resultado el número 4,7 Profesores Adriana Gil, Pablo Linares, Jorge Romero 42 de 47 Escuela Técnica Nº 37 D.E. 11 “Hogar Naval Stella Maris” LABORATORIO I - El lenguaje de programación C# - MODULO I Operador Cast Se puede forzar un dato, variable o una expresión a convertirse o cambiarse a un nuevo tipo de dato. El operador cast realiza este proceso entre numéricos. Sintaxis: (tipo)<dato> Ejemplo: double a = 101.90; // Se declara a con el tipo double y el valor 101.90 int b = (int)a; // Se “castea” b al tipo int, con lo que se // fuerza el dato y pierde los decimales MessageBox.Show(b.ToString()); // Al mostrar b se comprueba que su valor es 101 En el ejemplo que precede se ve claramente una conversión de tipo explícita. int b = 101; // Se declara a con el tipo double y el valor 101 double a = (double)b; // Se “castea” a al tipo double En el nuevo caso se genera un casteo que pasa un valor int a double, a diferencia del primer caso, aquí no era obligatorio realizar la operación ya que el C# puede en esta ocasión realizar una conversión de tipo implícita. A continuación veremos como habría sido el código para tal caso. Int b = 101; // Se declara b con el tipo double y el valor 101 double a = b; // Se “castea” a al tipo double pero en esta ocasión de manera implícita CLASE Convert Finalmente se dispone de la clase Convert, la cual tiene múltiples posibilidades en cuanto a la conversión de datos. Con ella se puede transformar a casi cualquier dato en cualquier tipo de información. Profesores Adriana Gil, Pablo Linares, Jorge Romero 43 de 47 Escuela Técnica Nº 37 D.E. 11 “Hogar Naval Stella Maris” LABORATORIO I - El lenguaje de programación C# - MODULO I Por el volumen de operaciones que posee, necesitaríamos un capítulo exclusivo para la clase, por lo que se mostrarán ejemplos de uso con el fin de orientar sobre su uso y aprovechamiento. En la figura 14 se aprecian en parte la cantidad de posibilidades que ofrece la clase Convert. Cada uno de dichos métodos poseen su propia parametrización y sus correspondientes sobrecargas. Sintaxis: Convert.<método>(<parámetros>) Ejemplos: string a = "101.9"; double b=Convert.ToDouble(a); MessageBox.Show(b.ToString()); Profesores Adriana Gil, Pablo Linares, Jorge Romero 44 de 47 Escuela Técnica Nº 37 D.E. 11 “Hogar Naval Stella Maris” LABORATORIO I - El lenguaje de programación C# - MODULO I Creación de un archivo de texto using using using using System; System.Collections.Generic; System.Text; System.IO; // se agrega System.IO para la utilización de archivos namespace ConsoleApplication1 { class Program { const string path = "d:\\datos.txt"; //se define una constante llamada path que va contener los datos del archivo principal const string path2 = "d:\\datosresg.txt"; static void Main(string[] args) { char opc; bool salir = false; do { Console.Clear(); Console.WriteLine("1 - Ingresar"); Console.WriteLine("2 - Borrar"); Console.WriteLine("3 - Modificar"); Console.WriteLine("4 - Consultar"); Console.WriteLine("5 - Salir"); opc = char.Parse(Console.ReadLine()); salir = true; switch (opc) { case '1':{Ingresar(); salir = true; break;} case '2':{Borrar(); salir = true; break;} case '3':{Modificacion(); salir = true; break;} case '4':{Consultar(); salir = true; break;} case '5':{salir = false; break;} } } while (salir == true); Console.ReadKey(); } public static void Ingresar() { string ape, nom, dom, altura, cp; StreamWriter file = new StreamWriter(path,true);//ruta=donde lo guardo+true=append //abro el archivo datos.txt para escritura Console.Write("Ingrese apellido.."); ape = (Console.ReadLine().Replace(' ','_')); Console.Write("Ingrese nombre.."); nom = (Console.ReadLine().Replace(' ', '_')); Console.Write("Ingrese domicilio.."); dom = (Console.ReadLine().Replace(' ', '_')); Console.Write("Ingrese altura.."); altura = (Console.ReadLine().Replace(' ', '_')); Console.Write("Ingrese codigo postal.."); cp = (Console.ReadLine().Replace(' ', '_')); file.WriteLine(ape + " " + nom + " " + dom + " " + altura + " " + cp); file.Close(); //guardo en el archivo datos.txt //cierro datos.txt } Profesores Adriana Gil, Pablo Linares, Jorge Romero 45 de 47 Escuela Técnica Nº 37 D.E. 11 “Hogar Naval Stella Maris” LABORATORIO I - El lenguaje de programación C# - MODULO I public static void Borrar() { string[] datos; string ape="",cadena = ""; char opc; StreamReader file = new StreamReader(path,true); //abro el archivo para lectura StreamWriter resguardo = new StreamWriter(path2); //crea un numero archivo Console.Write("Ingrese el apellido a buscar.."); ape = (Console.ReadLine().Replace(' ', '_')); do { cadena = file.ReadLine(); //leo una linea de datos.txt datos = cadena.Split(' '); //guardo en un vector cortado por espacios if (ape == datos[0]) { Console.WriteLine("Encontrado!!!"); foreach (string variable in datos) { Console.WriteLine(variable.Replace('_',' ')); } Console.WriteLine("Desea borrarlo!!(s/n)"); opc = char.Parse(Console.ReadLine().ToLower()); if (opc == 's') { Console.WriteLine("Eliminado!!"); } Else { resguardo.WriteLine(datos[0] + " " + datos[1] + " " + datos[2] + " " + datos[3] + " " + datos[4]); } else resguardo.WriteLine(datos[0] + " " + datos[1] + " " + datos[2] + " " + datos[3] + " " + datos[4]); } while (!file.EndOfStream); file.Close(); //cierro archivo datos.txt resguardo.Close(); //cierro archivo resguardo.txt File.Delete(path); //borro el arhivo datos.txt File.Copy(path2, path); //copio el contenido de resguardo.txt en datos.txt File.Delete(path2); //borro el archivo resguardo.txt } public static void Modificacion() { string[] datos; string ape="", nom="", dom="", altura="", cp="",cadena=""; char opc; StreamReader file = new StreamReader(path,true); StreamWriter resguardo = new StreamWriter(path2); //crea un numero archivo Console.Write("Ingrese el apellido a buscar.."); ape = (Console.ReadLine().Replace(' ', '_')); do { cadena = file.ReadLine(); datos = cadena.Split(' '); if (ape == datos[0]) { Console.WriteLine("Encontrado!!!"); foreach (string variable in datos) { Console.WriteLine(variable.Replace('_',' ')); } Console.WriteLine("Desea modificarlo!!(s/n)"); opc = char.Parse(Console.ReadLine().ToLower()); Profesores Adriana Gil, Pablo Linares, Jorge Romero 46 de 47 Escuela Técnica Nº 37 D.E. 11 “Hogar Naval Stella Maris” LABORATORIO I - El lenguaje de programación C# - MODULO I if (opc == 's') { Console.WriteLine("Reingrese los datos!!"); Console.Write("Ingrese apellido.."); ape = (Console.ReadLine().Replace(' ', '_'));//Reemplazo el espacio por guion bajo Console.Write("Ingrese nombre.."); nom = (Console.ReadLine().Replace(' ', '_')); Console.Write("Ingrese domicilio.."); dom = (Console.ReadLine().Replace(' ', '_')); Console.Write("Ingrese altura.."); altura = (Console.ReadLine().Replace(' ', '_')); Console.Write("Ingrese codigo postal.."); cp = (Console.ReadLine().Replace(' ', '_')); resguardo.WriteLine(ape + " " + nom + " " + dom + " " + altura + " " + cp); } //guardo en el archivo auxiliar else resguardo.WriteLine(ape + " " + nom + " " + dom + " " + altura + " " + cp); } //guardo en el archivo auxiliar else resguardo.WriteLine(datos[0] + " " + datos[1] + " " + datos[2] + " " + datos[3] + " "+datos[4]); } while (!file.EndOfStream); file.Close(); resguardo.Close(); File.Delete(path); File.Copy(path2, path); File.Delete(path2); } public static void Consultar() { string ape; string cadena = ""; string[] datos; StreamReader file = new StreamReader(path); Console.Write("Ingrese el apellido a buscar.."); ape = (Console.ReadLine().Replace(' ', '_')); do { cadena = file.ReadLine(); datos = cadena.Split(' '); if (ape == datos[0]) { Console.WriteLine("Encontrado!!!"); foreach (string variable in datos) { Console.WriteLine(variable.Replace('_',' ')); } } } while (!file.EndOfStream); file.Close(); Console.ReadKey(); } } } Profesores Adriana Gil, Pablo Linares, Jorge Romero 47 de 47