Curso Completo de C# y .NET
Curso Completo de C# y .NET
Tabla de contenidos
n 1 C sharp NET
n 1.1 El lenguaje C#
n 1.2 Tabla de Contenidos
n 1.3 Pre-requisitos necesarios para este curso
n 1.4 Autores
n 1.5 Licencia
n 1.6 Referencias
n 2 Introduccion a los lenguajes
n 2.1 Una Breve Introducción a los Lenguajes de Programación
n 3 Introduccion
n 4 Capítulo 1
n 4.1 La plataforma .NET
n 4.1.1 Independencia de lenguaje
n 4.1.2 Librería de clases común:
n 4.1.3 Multiplataforma
n 4.1.4 Windows Forms, Web Forms, Web Services
n 4.1.5 Estandarización
n 4.2 Un resúmen introductorio sobre el lenguaje C#
n 4.2.1 C# frente a Java
n 4.2.2 C# frente a C++
n 4.2.3 ¿Porqué C#?
n 4.3 Instalando lo necesario para empezar
n 4.3.1 Otras utilidades
n 5 Primer Programa ¡Hola Mundo!
n 5.1 CAPÍTULO 2
n 5.1.1 Primer programa ¡Hola Mundo!
n 5.1.2 Comentarios
n 5.1.3 Clases, Objetos y tipos
n 5.1.4 Métodos o Funciones
n 5.1.4.1 Crear nuevos métodos o funciones
n 5.1.5 Aplicaciones de consola
n 5.1.6 Namespaces
n 5.1.7 La palabra clave using
n 5.1.8 Caracteres sensibles
n 6 Fundamentos del lenguaje
n 6.1 CAPÍTULO 3
n 6.1.1 Tipos
n 6.1.1.1 Importancia de los tipos de datos
n 6.1.1.2 Tipos en C#
n 6.1.1.3 Tipos básicos o internos
n 6.1.1.4 Escogiendo qué tipo usar
n 6.1.1.5 Enteros
n 6.1.1.6 Tipos de coma flotante
n 6.1.1.7 El tipo decimal
http://es.wikibooks.org/wiki/C_sharp_NET_/_Texto_Completo 16/05/2007
C sharp NET / Texto Completo - Wikilibros Page 2 of 72
http://es.wikibooks.org/wiki/C_sharp_NET_/_Texto_Completo 16/05/2007
C sharp NET / Texto Completo - Wikilibros Page 3 of 72
http://es.wikibooks.org/wiki/C_sharp_NET_/_Texto_Completo 16/05/2007
C sharp NET / Texto Completo - Wikilibros Page 4 of 72
C sharp NET
El lenguaje C#
Los primeros rumores de que Microsoft estaba desarrollando un nuevo lenguaje de programación
surgieron en 1998, haciendo referencia a un lenguaje que entonces llamaban COOL y que decían era
muy similar a Java. En junio de 2000, Microsoft despejó todas las dudas liberando la especificación
de un nuevo lenguaje llamado C#. A esto le siguió rápidamente la primera versión de prueba del
entorno de desarrollo estándar (SDK) .NET, que incluía un compilador de C#. El nuevo lenguaje
estaba diseñado por Anders Hejlsberg ( creador de Turbo Pascal y arquitecto de Delphi ), Scott
Wiltamuth y Peter Golde. Entonces describieron el lenguaje como "...simple, moderno, orientado a
objetos, de tipado seguro y con una fuerte herencia de C/C++".
Una muestra de esta nueva tecnología es el nuevo lenguaje de programación C#. Este nuevo lenguaje
orientado a objetos con énfasis en internet se basa en las lecciones aprendidas de los lenguajes C,
C++, Java y Visual Basic. Por ello se trata de un lenguaje que combina todas las cualidades que se
pueden esperar de un lenguaje moderno (orientación a objetos, gestión automática de memoria, etc.)
a la vez que proporciona un gran rendimiento.
En este curso intentaremos examinar las cualidades de este lenguaje desde lo más básico a lo más
avanzado incluyendo la versión 2.0. Examinaremos paso a paso cómo crear poderosas aplicaciones
de escritorio o basadas en web.
Tabla de Contenidos
1. Capítulo 0: Breve introducción a los lenguajes de programación
2. Capítulo 1: Introducción
3. Capítulo 2: Primer programa
4. Capítulo 3: Fundamentos del lenguaje
5. Capítulo 4: Estructuras de control
6. Capítulo 5: Introducción a las clases
7. Capítulo 6: Herencia y Polimorfismo
8. Capítulo 7: Sobrecargando operadores
9. Capítulo 8: Estructuras
10. Capítulo 9: Interfaces
11. Capítulo 10: Estructuras de datos
12. Capítulo 11: Cadenas y Expresiones regulares
13. Capítulo 12: Manejo de excepciones
14. Capítulo 13: Delegación y Eventos
15. Capítulo 14: Creando Aplicaciones gráficas usando Windows.Forms
16. Capítulo 15: Creando Aplicaciones gráficas usando Gtk
17. Capítulo 16: Accediendo a la información usando ADO.NET
18. Capítulo 17: Programando Aplicaciones WEB con ASP.NET 2.0
19. Capítulo 18: Programando Servicios del Web
20. Capítulo 19: XML
http://es.wikibooks.org/wiki/C_sharp_NET_/_Texto_Completo 16/05/2007
C sharp NET / Texto Completo - Wikilibros Page 5 of 72
n Texto Completo
Versión para imprimir de este libro
Autores
Editores principales (si has colaborado añade tu nombre a esta lista):
David Cañar - Creación del libro, Capitulo 2 y varias porciones del capítulo 1, 3 y 4
Licencia
Se incluye una copia en inglés de esta licencia en el artículo Text of the GNU Free
Documentation License.
Referencias
Este Wikilibro tiene extenso material tomado del tutorial de C# del proyecto MonoHispano
(http://monohispano.org/tutoriales/csharp/).
n http://monohispano.org
n http://monohispano.org/tutoriales/csharp/
n http://cougarpc.net/csharp (copia original)
http://es.wikibooks.org/wiki/C_sharp_NET_/_Texto_Completo 16/05/2007
C sharp NET / Texto Completo - Wikilibros Page 6 of 72
La forma en que un ordenador recibe instrucciones es una manera peculiar. **** Añadir más sobre
el lenguaje binario (bajo nivel) y los lenguajes de alto nivel**** (en construcción)
Ya que hemos recalcado las similitudes entre los lenguajes de programación y los lenguajes hablados
también hay que tener presente que un lenguaje de programación es mucho más estricto que uno
hablado en el sentido de que no pueden existir ambigüedades. Es muy fácil en el idioma Español
tener frases que impliquen algo que ya conocemos o que signifiquen cosas diferentes. Por el
contrario los lenguajes de programación son claros, específicos y directos, no se admiten
ambigüedades ni suposiciones.
Para poder dominar un lenguaje de programación (al igual que con los lenguajes hablados) se
requiere mucho estudio pero por sobre todo muchísima práctica. Vosotros podréis leer este manual
una 500 veces pero si no ponéis en práctica ni investigáis por vosotros mismos, núnca podréis llegar
a dominar este maravilloso lenguaje de programación. Así que ¡a practicar se ha dicho!
Introduccion
<- Anterior (MENU PRINCIPAL) | Siguiente (Capítulo 2) ->
Capítulo 1
Como hemos dicho C# (C Sharp) es parte de la plataforma .NET. C# es un lenguaje orientado a
objetos simple, seguro, moderno, de alto rendimiento y con especial énfasis en internet y sus
estándares (como XML). Es también la principal herramienta para programar en la plataforma .NET.
http://es.wikibooks.org/wiki/C_sharp_NET_/_Texto_Completo 16/05/2007
C sharp NET / Texto Completo - Wikilibros Page 7 of 72
Tal vez os habréis preguntado ¿Qué es la plataforma .NET? ¿Porqué Microsoft está invirtiendo tanto
en esta nueva tecnología? ¿Qué es lo que es tan novedoso? ¿Como es que con .NET se pueden
producir aplicaciones multi-plataforma? A continuación hablaremos un poco de la plataforma .NET
La plataforma .NET
La plataforma .NET es una plataforma de
desarrollo de software con especial
énfasis en el desarrollo rápido de
aplicaciones, la independencia de
lenguaje y la transparencia a través de
redes.
n Un conjunto de lenguajes de
programación (C#, J#, JScript,
C++ gestionado, Visual
Básic.NET, y otros proyectos
independientes).
n Un conjunto de herramientas de
desarrollo (entre ellos Visual Marco de trabajo .NET
Studio.NET de Microsoft o
Monodevelop)
n Una libreria de clases amplia y común para todos los lenguajes.
n Un sistema de ejecucion de Lenguaje Común. (CLR).
n Un conjunto de servidores .NET
n Un conjunto de servicios .NET
n Dispositivos electrónicos con soporte .NET (?)
Independencia de lenguaje
Todos los lenguajes que conformen con los estándares .NET, sin importar cual, podrán interoperar
entre sí de forma totalmente transparente, las clases podrán ser heredadas entre unos lenguajes y
otros, y se podrá disfrutar de polimorfismo entre lenguajes. Por ejemplo, si yo tengo una clase en C#,
esta clase podrá ser heredada y utilizada en Visual Basic o JScript o cualquier lenguaje .NET. Todo
esto es posible por medio de una de las características de .NET llamado Common Type System
(CTS). También tiene la cualidad de que se pueden incluir más lenguajes a la plataforma. En la
actualidad existen proyectos independientes de incluir PHP, Python, Ada y otros lenguajes en la
plataforma.
Más de 4000 clases, objetos y métodos incluidos en la plataforma .NET están disponibles para todos
los lenguajes.
Multiplataforma
http://es.wikibooks.org/wiki/C_sharp_NET_/_Texto_Completo 16/05/2007
C sharp NET / Texto Completo - Wikilibros Page 8 of 72
El CLR compilará estos archivos IL nuevamente en código de máquina en un proceso que se conoce
como JIT (justo a tiempo) el cual se ejecutará cuando se requiera. Este proceso producirá código de
máquina bien eficiente que se reutilizará si es que hubiera código que se repitiera, haciendo que los
programas sean ejecutados muy eficientemente.
La plataforma .NET incluye un conjunto de clases especial para datos y XML que son la base de 3
tecnologías claves: Servicios Web (Web Services), Web Forms, y Windows Forms los cuales son
poderosas herramientas para la creación de aplicaciones tanto para la plataforma como para el Web.
Estandarización
Además de los méritos técnicos, una de las razones del éxito de la plataforma .NET ha sido por el
proceso de estandarización que Microsoft ha seguido (y que ha sorprendido a más de uno).
Microsoft, en lugar de reservarse todos los derechos sobre el lenguaje y la plataforma, ha publicado
las especificaciones del lenguaje y de la plataforma, que han sido posteriormente revisadas y
ratificadas por la Asociación Europea de Fabricantes de Computadoras (ECMA). Esta especificación
(que se puede descargar libremente de Internet) permite la implementación del lenguaje C# y de la
plataforma .NET por terceros, incluso en entornos distintos de Windows. Mono Hispano mantiene
una traducción del estándar que describe el lenguaje C# en http://monohispano.org/ecma/
http://es.wikibooks.org/wiki/C_sharp_NET_/_Texto_Completo 16/05/2007
C sharp NET / Texto Completo - Wikilibros Page 9 of 72
C# provee soporte para acceder directamente a la memoria usando el estilo de punteros de C++ y
mucho más.
C# frente a Java
C# y Java son lenguajes similares, de sintaxis basada en C/C++, orientados a objetos, y ambos
incluyen las características más importantes de los lenguajes modernos, como son la gestión
automática de memoria y la compilación a código intermedio. Pero por supuesto, también hay
diferencias.
Una de las diferencias más importantes es que C# es mucho más cercano a C++ en cuanto a diseño
se refiere. C# toma casi todos sus operadores, palabras reservadas y expresiones directamente de
C++. También se han mantenido algunas características que en Java se han desestimado. Por
ejemplo las enumeraciones. No hay enumeraciones en Java y sin embargo era un concepto muy
usado en C/C++. En C# se han mantenido las enumeraciones, y se han adaptado al nuevo lenguaje,
de forma que ahora las enumeraciones no son simplemente enteros, sino que son tipos de tipado
seguro que derivan de System.Enum en la librería de clases base. Una enumeración de tipo "ej1" no
se puede cambiar con una enumeración de tipo "ej2" sin una conversión.
Otra característica que no está presente en Java es la posibilidad de trabajar directamente con
direcciones de memoria. Si bien tanto Java como .NET proporcionan gestión automática de
memoria, en C# es posible usar lo que se denomina "código no seguro". Cuando se usa código no
seguro en C# es posible operar con punteros de forma muy similar a como se haría en C/C++, pero el
código que utiliza punteros se queda marcado como no seguro y no se ejecuta en entornos en los que
no tiene permisos.
C# frente a C++
Puesto que C# se ejecuta en una máquina virtual, ésta se hace cargo de la gestión de memoria y por
lo tanto el uso de punteros es mucho menos importante en C# que en C++. C# también es mucho
más orientado a objetos, hasta el punto de que todos los tipos usados derivan en última instancia el
tipo 'object'. Además, muchos tipos se usan de forma distinta. Por ejemplo, en C# se comprueban los
límites de los arrays antes de usarlos, evitando así que se pueda escribir pasado el final del vector.
Al igual que Java, C# renuncia a la idea de herencia múltiple de clases presente en C++. Sin
embargo, referido a clases, C# implementa 'propiedades' del tipo de las que existen en Visual Basic,
y los métodos de las clases son accedidos mediante '.' en lugar de '::'.
¿Porqué C#?
La plataforma .NET acepta varios lenguajes. Por ahora, C#, Visual Basic, C++ gestionado, Nemerle,
FORTRAN, Java, Python, etc. , y con capacidad para aceptar prácticamente cualquier lenguaje.
Entonces la pregunta es, ¿porqué se eligió C# en lugar de cualquier otro lenguaje?.
La razón fundamental es que C# se diseñó para la plataforma .NET y es capaz de utilizar todo su
potencial. También es cierto que es un lenguaje "limpio" en el sentido de que al no tener que
proporcionar compatibilidad hacia atrás se ha tenido más libertad en el diseño y se ha puesto especial
hincapié en la simplicidad. Por ejemplo, en C# hay un tipo de clase y siempre se le aplica el
recolector de basura mientras que en C++ gestionado hay dos tipos de clases, una a la que se aplica
el recolector y otra a la que no.
http://es.wikibooks.org/wiki/C_sharp_NET_/_Texto_Completo 16/05/2007
C sharp NET / Texto Completo - Wikilibros Page 10 of 72
Para Windows:
http://msdn.microsoft.com/netframework/downloads/updates/default.aspx
Proyecto Mono
Proyecto dotGNU
http://dotgnu.org/pnet-packages.html
Otras utilidades
Además de los archivos básicos para poder compilar y ejecutar vuestros programas, os
recomendamos que instaléis un entorno de programación (IDE) que os ayudará a programar. Los
siguientes programas son recomendados:
Para Windows:
Para Linux:
Estos programas son opcionales, os ayudarán con vuestra tarea de programación pero no son
indispesables. En este curso no daremos intrucciones especiales de como utilizar ninguno de ellos
por lo que correrá por vuestra cuenta el aprender a utilizarlos. En este curso daremos instrucciones
de como compilar y ejecutar vuestros programas sin la ayuda de estos entornos.
http://es.wikibooks.org/wiki/C_sharp_NET_/_Texto_Completo 16/05/2007
C sharp NET / Texto Completo - Wikilibros Page 11 of 72
CAPÍTULO 2
Primer programa ¡Hola Mundo!
En un alarde de originalidad, empezaremos con un simple programa que desplegará la frase “¡Hola
Mundo!”. Con este programa introduciremos las bases de nuestro estudio. Debido a que la
plataforma .NET es independiente del sistema operativo en este libro procuraremos mantenernos
imparciales en cuanto este asunto, eso si, cuando llegue el tiempo de compilar y ejecutar daremos
ejemplos de como hacerlo tanto en Windows como en Linux (en otras plataformas como MacOS
será lo mismo que en Linux).
Si estáis utilizando un entorno de desarrollo integrado debéis abrir un nuevo proyecto de consola en
C#, escribir o copiar lo que se muestra en el ejemplo 2.1 y compilad el proyecto para ver su
resultado. Si preferís programar con un editor de textos, abrid vuestro editor de texto favorito y
grabad en un directorio conocido lo que se encuentra en el ejemplo 2.1 como Programa.cs, abrid una
ventana de terminal (en linux) o una ventana de comandos (Ejecutar(Run) -> cmd) en Windows y
compilad vuestro proyecto con el siguiente comando:
mcs Programa.cs
csc Programa.cs
de esta forma obtendréis vuestro primer programa. Para ejecutarlo simplemente escribid:
con MONO:
mono Programa.exe
con dotGNU:
ilsrun Programa.exe
o en Windows:
Programa
http://es.wikibooks.org/wiki/C_sharp_NET_/_Texto_Completo 16/05/2007
C sharp NET / Texto Completo - Wikilibros Page 12 of 72
class HolaMundo
{
static void Main()
{
string var="Mundo";
System.Console.WriteLine ("Hola {0}!", var);
}
}
Comentarios
En la primera línea de nuestro programa encontramos lo siguiente: //Ejemplo 2.1 .... Esta línea
es un ejemplo de comentarios. Un comentario es una parte en vuestro programa que será ignorado
por el compilador.
Existen tres tipos de comentarios en C#. El primer tipo es comentario de un sola línea. El segundo es
comentario de varias líneas. El tercer tipo es para crear documentación. Este último tipo de
comentario lo estudiaremos en el capítulo 13 de este libro.
Los comentarios de una sola línea pueden ser incluidos en líneas independientes, en líneas que ya
incluyen código para comentar sobre lo que hace esa línea o para comentar una línea de código que
no necesitamos.
Los comentarios de varias líneas sirven para incluir muchas líneas de texto o código como un
comentario. Tienen una marca de inicio que dice cuando empieza el comentario y una marca que
indica el final de dicho comentario. La marca de inicio es /* y la marca para finalizar es */ Así por
ejemplo tenemos:
/*
este comentario
abarca varias lineas
*/
class HolaMundo
{
static void Main()
{
string var="Mundo";
System.Console.WriteLine ("Hola {0}!", var); //Este comentario puede describir lo que esta función hace
//System.Console.WriteLine ("y esta linea no la vamos a desplegar");
}
}
http://es.wikibooks.org/wiki/C_sharp_NET_/_Texto_Completo 16/05/2007
C sharp NET / Texto Completo - Wikilibros Page 13 of 72
varios botones del mismo tipo como por ejemplo botones de Aceptar, Cancelar, etc. Porque son del
mismo tipo estos botones tienen propiedades y comportamientos similares. Pueden tener propiedades
como cambiar de "tamaño", "posición", etc. Las propiedades son las mismas pero los valores
almacenados en sus atributos pueden ser diferentes. Por ejemplo, un botón puede tener tamaño 10 y
otro tamaño 6. Podemos decir entonces que tenemos varias instancias del mismo componente (o
varios botones del mismo tipo) con diferentes valores en sus atributos.
La programación orientada a objetos es esto. Crear componentes que puedan ser reusados. Así no
tenemos que programar varios componentes que cumplan funciones similares sino solo uno que
podrá llevar diferentes atributos y que podrá ser reproducido (o instanciado) tantas veces como lo
necesitemos.
Como en varios lenguajes de programación orientado a objetos, en C# los tipos o componentes son
definidos por una clase (class en inglés). Las diferentes reproducciones o instancias de un
componente del mismo tipo se conoce como objetos. Posteriormente en nuestro estudio veremos que
en C# hay más tipos además de las clases. Aprenderemos sobre enums, structs y delegates. Pero por
el momento nos dedicaremos a las clases.
Como hemos visto en nuestro primer programa (Ejemplo 2.1), empezamos nuestro programa
declarando el tipo de componente que vamos a utilizar (un componente de tipo class) y su nombre
HolaMundo. Para declarar nuestro componente como una clase, primero introducimos la palabra
clave class, y después el nombre de nuestro componente, después de lo cual declaramos las
funciones que va a cumplir su comportamiento y sus propiedades. Todas las funciones,
comportamiento y propiedades de nuestro componente (en este caso nuestra clase) deberán estar
encerrados entre corchetes { }. Los corchetes delimitan el inicio y el final de dicho componente.
Métodos o Funciones
Los métodos o funciones son trozos de código que realizan una acción, esto es, toman unos
argumentos y devuelven un valor. En C#, las funciones deben ser declaradas dentro de un objeto,
normalmente dentro de una clase.
Las funciones normalmente llevan nombre que definen su función. Por ejemplo, la función
WriteLine() de la clase Console como debéis suponer "Escribe una Linea en la consola". De forma
similar se pueden declarar clases a las que se le añaden un número ilimitado de métodos. En nuestro
ejemplo 2.1 la única función que hemos definido lleva el nombre de Main() la cual es una función
especial que indica la entrada principal de ejecución de un programa. Cada programa en C# debe
tener una función Main().
de acuerdo con nuestro ejemplo 2.1, la función Main() cumple con el formato establecido:
http://es.wikibooks.org/wiki/C_sharp_NET_/_Texto_Completo 16/05/2007
C sharp NET / Texto Completo - Wikilibros Page 14 of 72
n entorno: static
n tipo_a_retornar: void
n Nombre_de_la_Función: Main
n Argumentos: ninguno
En nuestro ejemplo la función Main() tiene como entorno la palabra clave static y como
tipo_a_retornar la palabra clave void. Cuando la función no retorna ningún tipo, utilizamos la
palabra void. Más adelante veremos más tipos además de void. La palabra static también la veremos
más adelante en nuestro estudio, por el momento debéis confiar en el ejemplo y utilizarla aún sin
saber lo que hace.
Podemos añadir a nuestro componente o clase un ilimitado número de funciones. Por ejemplo, para
añadir más funciones a nuestro primer ejemplo procederemos a crear una función que suma dos
valores. Como ya habéis aprendido en esta sección, crearemos nuestra función de la forma
establecida. Después del final de la función Main crearemos una función con entorno static que
retorne el tipo int, que se llame Suma y que acepte dos argumentos de tipo int. Para hacerla
funcionar vamos a llamarla desde nuestra función principal:
namespace Programa1
{
class HolaMundo
{
static void Main()
{
string var="Mundo";
System.Console.WriteLine ("Hola {0}!", var);
int num1 = 1;
int num2 = 3;
int resultado = Suma (num1, num2);
System.Console.WriteLine ("{0}+{1} = {2}", num1, num2, resultado);
}
Hola Mundo!
1 + 3 = 4
Ésta es una pequeña introducción a funciones, más adelante estudiaremos más detalladamente como
crear y utilizar funciones.
Aplicaciones de consola
http://es.wikibooks.org/wiki/C_sharp_NET_/_Texto_Completo 16/05/2007
C sharp NET / Texto Completo - Wikilibros Page 15 of 72
Las aplicaciones de consola no poseen una interfaz gráfica, no tienen botones o ventanas, poseen una
interfaz basada simplemente en texto. El ejemplo que hemos realizado hasta ahora es una aplicación
de consola que despliega texto en la pantalla, para ello hemos utilizado la función WriteLine.
Como habíamos visto en la introducción, la plataforma .NET posee más de 4000 componentes cada
cual con diferentes funciones internas. En el caso de nuestro programa hemos usado la función
WriteLine que se encuentra dentro del componente Console. Para poder hacer uso de funciones
estáticas que se encuentran en otros componentes, en C# como en la mayoría de lenguajes de
programación orientados a objetos, debemos especificar el nombre del componente en primer lugar
seguido por un punto y a continuación en el nombre de la función. Es por esto que utilizamos la frase
Console.WriteLine. Dentro del componente Console la plataforma .NET tiene disponibles
muchísimas otras funciones que nos ayudan a diseñar programas de consola. El lenguaje C# esta
orientado con el paradigma de objetos y hereda muchos elementos de C++.
Namespaces
Quizá algunos de vosotros os habréis preguntado ¿que significa la palabra System que está al inicio
de cada programa?. Púes bien, System en este caso representa un Espacio de nombres (namespace
en inglés).
Los espacios de nombres (namespaces) se crearon principalmente para dar más organización a los
componentes. La plataforma .NET tiene incorporados muchísimos componentes y sería una tarea
imposible tratar de memorizar todos los nombres de ellos para no repetirlos. Tarde o temprano
querréis crear un componente y no sabréis si el nombre que queréis darle ya existe o no. Para
evitarnos este problema y para poder distinguir a dónde pertenecen ciertos componentes se han
creado los espacios de nombres.
Pongamos un ejemplo para comprender este concepto. Supongamos que deseamos crear varios
componentes para una institución educativa que se compone de educación primaria y educación
secundaria. ¿Cómo podríamos crear un componente que se llame Presidente si existen 2
presidentes que tienen funciones distintas uno para la sección primaria y otro para la sección
secundaria? En este caso podríamos aplicar un espacio de nombres para poder crear los componentes
Presidente que cumplen distintas funciones. Podríamos crear el espacio de nombres Primaria y
dentro de éste el componente Presidente. De igual forma el espacio de nombres Secundaria y
dentro de éste el componente Presidente cada uno componentes podrá tener definiciones distintas.
Para acceder a las funciones de los componentes Presidente podríamos usar:
Primaria.Presidente.nombre_de_la_función();
y
Secundaria.Presidente.otra_función();
Cada una de las dos definiciones de Presidente son independientes, no tienen relación entre sí ya
que pertenecen a dos espacios de nombre distintos.
De ésta forma podremos crear componentes y funciones con el nombre que deseemos siempre y
cuando especifiquemos a qué espacio de nombres pertenecen.
http://es.wikibooks.org/wiki/C_sharp_NET_/_Texto_Completo 16/05/2007
C sharp NET / Texto Completo - Wikilibros Page 16 of 72
Algo importante que debemos notar es que los espacios de nombres pueden tener sub-espacios de
nombres y estos a su vez sub-espacios de nombres. El objetivo de esto, como lo hemos dicho, es
mantener una organización de los componentes. Los espacios de nombres, componentes y métodos
se accederán de la misma forma como lo hemos visto a través de un punto.
En ciertos proyectos tendremos que usar cierto espacio de nombres muchas veces. Supongamos que
estamos implementando un programa de consola y tenemos que usar el componente Console
repetidamente. Una forma de ahorrarnos escribir System varias veces es especificar el espacio de
nombres que vamos a usar al inicio de nuestro programa con la palabra clave using. Por ejemplo en
nuestro ejemplo 2.2 si añadimos la línea de código using System; al inicio de nuestro programa,
podemos llamar al componente Console sin escribir System al inicio:
using System;
namespace Programa1
{
class HolaMundo
{
static void Main()
{
string var="Mundo";
Console.WriteLine ("Hola {0}!", var);
int num1 = 1;
int num2 = 3;
int resultado = Suma (num1, num2);
Console.WriteLine ("{0}+{1} = {2}", num1, num2, resultado);
}
static int Suma(int valor1, int valor2)
{
return valor1+valor2;
}
}
}
Comparando con nuestro ejemplo 2.2 original las líneas en negrita muestran esta ventaja.
Algo importante para tener en cuenta es que la palabra clave using no puede ser utilizada para
ahorrarse el escribir el nombre de la clase. Por ejemplo la línea de código using System.Console
es inválida y producirá errores de compilación.
Caracteres sensibles
C# como todos los lenguajes de programación derivados de C hace diferencia entre caracteres en
mayúscula y caracteres en minúscula. Esto quiere decir que las palabras Using y using son distintas
y por lo tanto no cumplen la misma función. Debido a esto debemos tener mucho cuidado cuando
escribimos nuestros programas.
Finalizada esta pequeña introducción a nuestro primer programa en C#, pasamos al capítulo 3 en
http://es.wikibooks.org/wiki/C_sharp_NET_/_Texto_Completo 16/05/2007
C sharp NET / Texto Completo - Wikilibros Page 17 of 72
CAPÍTULO 3
En el capítulo 2 hemos introducido nuestro primer programa en C#, un programa sencillo el cual
incorpora muchos temas que hemos cubierto básicamente y solamente en parte. En esta sección del
libro procuraremos ver más a fondo las partes básicas de C#. Nos internaremos más a fondo en la
sintaxis y la estructura de C#.
En este capítulo cubriremos lo que son los tipos. Hablaremos de tipos básicos o internos y de cómo
crear nuevos tipos. También hablaremos en general de la manipulación de datos. Hablaremos sobre
condicionales, operadores matemáticos y varios otros temas relacionados. Empecemos entonces
nuestro estudio con lo que son tipos.
Tipos
Los tipos son la base de cualquier programa. Un tipo no es más que un espacio en el que se almacena
una información, ya sean números, palabras o tu fecha de nacimiento.
Tipos en C#
C# es un lenguaje de tipeado seguro (o fuertemente tipado) lo cual quiere decir que el programador
debe definir a que tipo pertenece cada pedazo de información o cada objeto que se crea. De esta
forma podemos crear objetos de tipo número entero, de tipo cadenas de texto, de tipo ventana, de
tipo botones, entre otros. Haciendo esto, C# nos ayudará a mantener nuestro código seguro en donde
cada tipo cumple con su función. En todas las operaciones el compilador comprueba los tipos para
ver su compatibilidad. Las operaciones no válidas no se compilan. De esta forma se evitan muchos
errores y se consigue una mayor fiabilidad. Esto también permite a C# anticipar de antemano la
cantidad de recursos del sistema que nuestro programa utilizará haciendo nuestro código seguro y
eficiente.
Los tipos en C# al igual que C++ y Java se clasifican en dos secciones: Tipos básicos o internos y
tipos creados por el usuario.
Los tipos básicos no son más que alias para tipos predefinidos en la librería base de la
plataforma .NET. Así, el tipo número entero (que se representa con la palabra clave int), no es más
que una forma rápida de escribir System.Int32.
Dentro de estas dos secciones los tipos del lenguaje C# también son divididos en dos grandes
categorías: tipos por valor y tipos por referencia. Existe una tercera categoría de tipos, disponible
solo cuando se usa código no seguro: los punteros, que se discutirán más adelante cuando hablemos
de los objetos COM.
http://es.wikibooks.org/wiki/C_sharp_NET_/_Texto_Completo 16/05/2007
C sharp NET / Texto Completo - Wikilibros Page 18 of 72
Los tipos por valor difieren de los tipos por referencia en que las variables de los tipos por valor
contienen directamente su valor, mientras que las variables de los tipos por referencia almacenan la
dirección donde se encuentran los objetos, es por eso que se las llaman referencias. Más adelante
describiremos como funcionan cada una de estas categorías.
Los tipos básicos como hemos dicho son espacios predefinidos y categorizados donde se almacena
información. En C# tenemos los siguientes tipos internos:
C# tiene una ventaja y característica especial sobre los demás lenguajes de programación modernos y
es que cada vez que se crea un objeto de un tipo básico, éstos son mapeados internamente a un tipo
primitivo de la plataforma .NET el cual es parte del CLS (Especificación común del lenguaje) lo cual
nos permite acceder y hacer uso de estos desde cualquier lenguaje de la plataforma .NET. Es decir si
es que creamos un objeto de tipo int (entero) en C#, ese objeto podrá ser usado como tal dentro de
J#, JScript, Visual Basic .NET y cualquier otro lenguaje que conforme los requisitos de .NET.
A la hora de programar deberéis decidir qué tipo de variables querréis usar. Generalmente esta
decisión se basa en el tipo de información que vayáis a usar y en el tamaño de la información. Por
ejemplo en nuestro ejemplo 2.2 del capítulo anterior necesitábamos hacer la suma de dos valores
numéricos por lo que usamos dos tipos básicos de número entero (usando la palabra clave int) los
cuales de acuerdo con nuestra tabla 3.1 son números enteros (no pueden llevar valores decimales) y
podrán aceptar valores entre -2,147,483,648 y 2,147,483,647 lo cual es más que suficiente para
http://es.wikibooks.org/wiki/C_sharp_NET_/_Texto_Completo 16/05/2007
C sharp NET / Texto Completo - Wikilibros Page 19 of 72
nuestro ejemplo de añadir dos números. En el caso de que necesitáramos hacer uso de números
reales (los cuales poseen una parte entera y una parte decimal como el número 10.22) podremos
hacer uso del tipo float, double y decimal de acuerdo con el tamaño del número que necesitemos y
así cada uno de los tipos tiene su uso y capacidad de acuerdo con la tabla 3.1.
Enteros
Los tipos que sirven para almacenar números enteros son: byte, sbyte. short, ushort, int, uint, long y
ulong. Como se aprecia en la tabla, C# define versiones con y sin signo para tipos con los mismos
bytes utilizados. Cada tipo se distingue por la capacidad de almacenaje.
Probablemente el tipo más utilizado es el int, púes se utiliza para controlar matrices, indizar arreglos
(arrays) además de las operaciones normales con enteros. Además, se trata de un entero de tamaño
medio: más pequeño que long y ulong, pero más grande que byte, sbyte, short y ushort.
El siguiente ejemplo muestra la declaración y uso de algunos tipos enteros calculando el número de
segundos en una hora, dia y en un año.
De nuevo hemos usado el método Console.WriteLine para imprimir los resultados por la consola. El
identificador {0} dentro de la cadena de texto indica que se sustituye {0} por el primer argumento. si
hubiera más de un argumento, se seguiría con {1}, y así sucesivamente. Por ejemplo, las dos líneas
que utilizan Console.WriteLine se pueden simplificar así:
Los tipos de coma flotante sirven para representar a números con parte fraccionaria. La
representación por supuesto puede no ser exacta, bien por errores de la máquina, bien porque el
número de decimales que se puede alojar es finito.
Existen tres clases de tipos de punto flotante : float, double y decimal. De los dos, el más usado es
double, púes es el valor que devuelven la mayoría de las funciones matemáticas de la librería base.
http://es.wikibooks.org/wiki/C_sharp_NET_/_Texto_Completo 16/05/2007
C sharp NET / Texto Completo - Wikilibros Page 20 of 72
class Flotante{
public static void Main()
{
int a = 2;
double log2 = Math.Log(a);
double raiz2 = Math.Sqrt(a);
Console.WriteLine("El logaritmo de dos es {0}", log2 );
Console.WriteLine("La raiz de dos es {0}", raiz2 );
}
}
si intentamos cambiar el tipo de log2 a otro de menos precisión, como float o int, el compilador
protestará. Esto se debe, como hemos dicho a que el valor devuelto por Math.Log() es de tipo double
y si se quiere convertir a float, pués se perderán datos. Lo mismo ocurre con la mayoría de los
miembros de la clase Math, como Math.Sin(), Math.Tan(), etc.
El tipo decimal
El tipo decimal es un tipo "nuevo" en el sentido de que no tiene equivalente en C/C++. Es muy
parecido a los tipo de coma flotante float y double.
En la aritmética de los tipos de coma flotante ordinarios, se pueden producir leves errores de
redondeo. El tipo decimal elimina estos errores y puede representar correctamente hasta 28 lugares
decimales. Esta capacidad para representar valores decimales sin errores de redondeo lo hace
especialmente eficaz para cálculos monetarios.
El tipo bool
El tipo bool sirve para expresar los valores verdadero/falso, que en C# se muestran con las palabras
reservadas true y false.
En C#, por ejemplo, una instrucción de condición solo puede estar gobernada por un valor bool, no
como en C/C++, que lo puede estar también por un entero. De esta forma se ayuda a eliminar el error
tan frecuente en programadores de C/C++ cuando usa "=" en lugar de "==". En definitiva, la
inclusión del tipo bool en el lenguaje ayuda a la claridad del código y evita algunos errores muy
comunes.
http://es.wikibooks.org/wiki/C_sharp_NET_/_Texto_Completo 16/05/2007
C sharp NET / Texto Completo - Wikilibros Page 21 of 72
En la última línea se muestra que el operador "==" también devuelve un valor booleano. El resultado
debería ser el siguiente:
b es True
esto saldrá
2==2 es True
El tipo char
El tipo char permite almacenar un carácter en formato simple, unicode de 16 bits o caracteres de
escape. Usando el formato unicode nos garantiza que los acentos se ven de forma adecuada y además
permite la representación de otros alfabetos, como el japonés, griego, cirílico, etc. Para introducir un
carácter se utilizan comillas simples, de forma que declarar un carácter sigue la estructura
Para una lista completa de caracteres unicode podréis visitar la siguiente página:
http://unicode.coeurlumiere.com/
\' apostrofe
\" Comillas
\\ Backslash
\0 Null (nulo)
\a Alerta
\b Retroceso
\f Form feed
\n Línea nueva
\r Retorno del carro
\t Tabulación Horizontal
\v Tabulación Vertical
Tipo Cadenas
Los tipos cadena (palabra clave string) son tipos que almacenan un grupo de caracteres. En C# los
http://es.wikibooks.org/wiki/C_sharp_NET_/_Texto_Completo 16/05/2007
C sharp NET / Texto Completo - Wikilibros Page 22 of 72
tipos cadena se crean con la palabra clave string seguido por el nombre de la variable que deseamos
instanciar. Para asignar un valor a este tipo debemos hacerlo entre comillas de la siguiente forma:
Debido a que el tipo cadena (string) es uno de los tipos más usados en C#, lo estudiaremos
detalladamente más adelante.
Convirtiendo tipos
En nuestros programas muchas veces necesitaremos cambiar de tipo a los objetos que hayamos
creado. Esto lo podremos hacer implícitamente o explícitamente. Una conversión de tipos implícita
sucede automáticamente, es decir el compilador se hará cargo de esto. Una conversión explicita en
cambio se llevará a cabo únicamente cuando nosotros lo especifiquemos. Hay que tomar en cuenta
que no siempre podremos hacer una conversión de un tipo hacia otro.
Como regla general las conversiones implícitas se llevan a cabo cuando se desea cambiar un tipo de
menor capacidad hacia un tipo de mayor capacidad de la misma especie. Por ejemplo si
deseamos crear 2 tipos enteros (misma clase) el uno que lleve el tipo short (menor capacidad) y el
otro que lleve el tipo int (mayor capacidad) una conversión implicita de short a int se lleva a cabo en
el siguiente ejemplo:
short corto = 3;
int entero = corto; //compilará sin ningún problema
aquí sucede una conversión implícita, el valor de la variable corto (en este caso 3) que es de tipo
short es asignado a la variable de tipo int sin que el compilador nos de ningún problema ya que hará
una conversión de short a int implícitamente por nosotros debido a la regla anteriormente citada.
En el caso que queramos hacer de forma inversa, es decir asignar un valor int a una variable short,
estaríamos violando la regla de asignar un tipo de mayor capacidad a una variable de tipo de menor
capacidad aunque sean de la misma clase (enteros). Asi el siguiente ejemplo no compilará dándonos
un error:
En estos casos es cuando podremos hacer una conversión explícita. Debido a que la información
almacenada en la variable entero de tipo int está también en el rango de capacidad del tipo short y los
dos tipos son de la misma clase (enteros) podremos hacer una conversión explicita designando entre
paréntesis a que tipo queremos convertir de la siguiente manera:
En el ejemplo anterior, el compilador no nos dará ningún problema. Cada uno de los tipos básicos
citados a continuación soportará una conversión implícita o explícita como se lo expresa en la
siguiente tabla:
http://es.wikibooks.org/wiki/C_sharp_NET_/_Texto_Completo 16/05/2007
C sharp NET / Texto Completo - Wikilibros Page 23 of 72
Arreglos
En C# se pueden construir arreglos de prácticamente cualquier tipo de dato. Los arreglos, también
llamados vectores o arrays, no son más que una sucesión de datos del mismo tipo. Por ejemplo, el
concepto matemático de vector es una sucesión de números y por lo tanto es un arreglo
unidimensional. Así, podemos construir arreglos de objetos, de cadenas de texto, y, por supuesto,
arreglos de enteros:
using System;
class Arreglo{
public static void Main()
{
int[] arr = new int[3];
arr[0] = 1;
arr[1] = 2;
arr[2] = 3;
Console.WriteLine( arr[1] );
}
}
Para crear un arreglo debemos especificar de qué tipo deseamos crear el arreglo seguido por
corchetes [ ] que es el distintivo del arreglo (en nuestro ejemplo usamos int[]), seguido por la palabra
clave new y el tipo y la cantidad de parámetros que tendrá nuestro arreglo. En el ejemplo anterior,
por ejemplo, se creó un arreglo arr unidimensional con capacidad para 3 enteros (especificado por
new int[3]), y luego se le asignó a cada parámetro un entero distinto (nótese que se comienza a
contar a partir de 0 y el número del parametro se encuentran entre corchetes).
Existe una forma más corta para declarar el arreglo y asignarle los valores:
También se pueden crear arreglos bidimensionales (y de la misma forma para más dimensiones). En
ese caso la sintaxis para declarar un arreglo bidimensional de enteros será
http://es.wikibooks.org/wiki/C_sharp_NET_/_Texto_Completo 16/05/2007
C sharp NET / Texto Completo - Wikilibros Page 24 of 72
using System;
class Arreglo2{
public static void Main()
{
int[,] arr = new int[2,2];
arr[0,0] = 1;
arr[1,0] = 2;
arr[0,1] = 3;
arr[1,1] = 4;
Console.WriteLine("El valor que posee la variable arr[1,1] es {0}", arr[1,1] );
}
}
el resultado será:
igual que el ejemplo anterior, podemos declarar todo el arreglo de la siguiente forma:
Identificadores
En una aplicación siempre se deben crear variables, constantes, métodos, objetos, etc. Para poder
crearlos debemos asignar nombres o identificadores. Estos identificadores deben seguir ciertas
reglas:
Después de que el identificador empiece con una letra o un simbolo _, el identificador puede tener
cualquier cantidad de letras, líneas o números.
Ejemplo:
http://es.wikibooks.org/wiki/C_sharp_NET_/_Texto_Completo 16/05/2007
C sharp NET / Texto Completo - Wikilibros Page 25 of 72
EsteIdentificadorEsValido
_este_tambien
esteEsOtro1
esteEsOtro2
Esto es invalido
123_Otro_inválido
int
en los ejemplos que no son válidos, el primero contiene espacios, el segundo empieza con numeros y
el tercero es una palabra clave lo cual no es permitido.
Nota: Es recomendado que las variables siempre empiecen con minusculas y que sigan el patrón
llamado Camello es decir que el nombre de la variable que tenga varias palabras debe ser formado de
la siguiente manera: la primera palabra empezará con minúsculas pero la segunda, tercera, etc
palabras estarán unidas a la primera y tendrán su primera letra en mayúsculas ejemplo: miVariable.
También se ha recomendado que el nombre de Métodos, Clases y demás nombres que necesitamos
especificar deberán llevar el mismo formato anterior con la excepción de que la Primera letra deberá
ser mayúscula.
Variables
Una variable es el nombre que se le da al espacio donde se almacena la información de los tipos. Las
variables pueden llevar cualquier nombre que deseemos, eso sí no se podrá hacer uso de palabras
claves de C#. En los ejemplos anteriores hemos usado varias variables con diferentes tipos y
diferentes valores.
Para crear una variable debemos especificar a qué tipo pertenece antes del nombre que le vamos a
dar. Por ejemplo si deseamos crear una variable que se llame var y que sea del tipo entero (int)
procederemos de la siguiente manera:
int var;
Una vez creada la variable podemos almacenar la información que deseamos. Para hacerlo
utilizamos el símbolo = después del nombre de la variable.
var = 10;
Hay que tener presente que la variable como su nombre lo indica podrá tomar otros valores. Por
ejemplo si deseamos que nuestra variable cambie de valor a 5 hacemos lo que habíamos hecho en el
ejemplo anterior pero con el nuevo valor:
var = 5;
http://es.wikibooks.org/wiki/C_sharp_NET_/_Texto_Completo 16/05/2007
C sharp NET / Texto Completo - Wikilibros Page 26 of 72
Para simplificar el proceso de creación y asignación de valor de una variable podemos especificar
estos dos procesos en una misma línea.
La primera vez que una variable recibe un valor se llama inicialización de la variable. En C# todas
las variables que van a ser utilizadas deben ser inicializadas para que vuestro programa pueda
funcionar.
En caso anterior hemos creado la variable var e inicializado la variable con el valor 10. Hay que
tener cuidado que la creación de una variable se la hace 1 sola vez y la asignación de diferentes
valores se puede hacer cuantas veces queramos.
Constantes
Las constantes como su nombre lo indica son variables cuyo valor no puede ser alterado. Éstas se
utilizan para definir valores que no cambian con el tiempo. Por ejemplo podemos definir una
constante para especificar cuantos segundos hay en una hora de la siguiente forma:
Esta constante no podrá ser cambiada a lo largo de nuestro programa. En el caso de que queramos
asignarle otro valor, el compilador nos dará un error.
Enumeraciones
Supongamos que estamos diseñando un juego y necesitamos crear una variable para saber cuál es el
estado del tanque de combustible de nuestro automóvil. Suponiendo que tenemos 4 niveles en el
tanque: lleno, medio, bajo y crítico. ¿Qué tipo de variable podríamos usar para especificar estos
estados? Una forma de hacerlo podría ser si especificamos una variable de tipo int (entero) que tome
los valores de 1 para lleno, 2 para medio, 3 para bajo y 4 para crítico. Esta alternativa funcionaría
pero a la larga nos olvidaremos qué número representaba qué. Una forma muy elegante de solucionar
este problema es utilizando el tipo enum o enumeraciones. Veamos el siguiente ejemplo para
comprender este concepto:
http://es.wikibooks.org/wiki/C_sharp_NET_/_Texto_Completo 16/05/2007
C sharp NET / Texto Completo - Wikilibros Page 27 of 72
using System;
namespace Autos
{
class Control
{
enum tanque
{
lleno,
medio,
bajo,
critico,
}
auto1 = tanque.critico;
RevisarEstadoTanque(auto1);
}
Este programa sencillo crea una enumeración llamada tanque y dentro de ella crea 4 constantes:
lleno, medio, bajo, y critico. Dentro de nuestro programa creamos la variable de tipo tanque llamada
auto1 la cual podrá tomar los valores especificados dentro de la enumeración. Cuando asignamos a
la variable auto1 el valor de tanque.lleno y revisamos el estado del tanque llamando a la función
RevisarEstadoTanque, podremos comprobar cuál es el estado actual del tanque de combustible.
Ésta es una forma muy descriptiva de cómo crear variables que cambien de estado, una solución
elegante y sencilla a nuestro problema.
En realidad las constantes dentro de las enumeraciones tienen valores enteros asignados. Estos
valores pueden ser inicializados con distintos valores que nosotros deseemos e incluso podemos
especificar qué tipo de entero queremos usar. En nuestro ejemplo anterior los valores de la
enumeración son valores enteros del tipo int el primer elemento dentro de la enumeración tiene
asignado el valor de 1, el siguiente el valor 2 y así sucesivamente. Esto sucede cuando no
especificamos a qué tipo queremos inicializar nuestra enumeración y tampoco asignamos valores a
las constantes. En el siguiente ejemplo podemos ver cómo especificar otro tipo de constantes y otros
valores.
Supongamos que queremos especificar cuantos segundos hay en un minuto, cuantos segundos hay en
una hora y cuantos segundos hay en 24 horas. Con enumeraciones lo podemos hacer de la siguiente
manera:
http://es.wikibooks.org/wiki/C_sharp_NET_/_Texto_Completo 16/05/2007
C sharp NET / Texto Completo - Wikilibros Page 28 of 72
using System;
namespace Ejemplos
{
class Enumeraciones
{
enum segundos :uint
{
minuto = 60,
hora = 3600,
dia = 86400,
}
static void Main()
{
Console.WriteLine("Existen {0} segundos en 1 minuto, {1} segundos en 1 hora y {2} segundos en 24 horas",(uin
}
}
}
El resultado es el siguiente:
El ejemplo anterior nos muestra otra forma de usar una enumeración. Hay que tener en cuenta que el
tipo que va a tener la enumeración se encuentra después del nombre de la enumeración precedido por
dos puntos. De esa forma podremos especificar de qué tipo son. Como habíamos dicho anteriormente
se podrá utilizar cualquier tipo de la clase enteros como byte, sbyte, short, ushort, int, uint, long o
ulong. En el caso de que no se especifique a qué tipo pertenece el compilador le dará el tipo int.
También se debe tomar en cuenta que los valores de las constantes están asignados con el signo = y
están separadas por comas.
Como habéis visto la forma de acceder al valor numérico de las enumeraciones es especificando
entre parentesis a qué tipo pertenecen, en este caso (uint). Después de lo cual especificamos el
nombre de la enumeración seguido por un punto que separa al nombre de la constante. En el caso de
que deseemos desplegar sólo el nombre de la constante y no su valor, se debe omitir el nombre del
tipo como: segundos.hora sin (uint) al inicio.
enum numeros
{
uno, //toma el valor de 1
dos, //toma el valor de 2
diez = 10, //toma el valor de 10
once, //toma el valor de 11
}
Operadores
Los operadores son símbolos con los cuales C# tomará una acción. Por ejemplo existen operadores
matemáticos para sumar, restar, multiplicar y dividir números. Existen tambien operadores de
comparación que analizará si un valor es igual, mayor o menor que otro y operadores de asignación
los cuales asignarán nuevos valores a los objetos o variables. A continuación explicaremos un poco
más detalladamente los operadores en C#:
Operadores matemáticos
http://es.wikibooks.org/wiki/C_sharp_NET_/_Texto_Completo 16/05/2007
C sharp NET / Texto Completo - Wikilibros Page 29 of 72
Casi todos los lenguajes de programación soportan operadores matemáticos. Estos operadores se
utilizan para realizar operaciones matemáticas sencillas entre números. Entre estos operadores
tenemos los de suma, resta, multiplicación, división y módulo (o residuo): +,-,*,/,%, y se los usa de
la siguiente manera:
using System;
class operadoresMatematicos
{
public static void Main()
{
int a = 7;
int b = 4;
int c = a + b;
int d = a - b;
int e = a * b;
int f = a / b;
int g = a % b;
Console.WriteLine ("De los números: {0} y {1} la suma es: {2}, la resta es:{3}, la multiplicación
}
}
Operadores de asignación
Los operadores de asignación son aquellos que sirven para asignar el valor del objeto o variable de la
derecha al objeto o variable de la izquierda. Un ejemplo sencillo de este tipo de operadores es la
inicialización de variables. Como habíamos visto, para asignar el valor a una variable simplemente
utilizamos el símbolo (u operador) igual =
Además de estos operadores de asignación sencillos, existen otros operadores de asignación que
realizan operaciones matemáticas antes de asignar el valor a la variable u objeto. Entre ellos
tenemos: +=, -=, *=, /=, %=, ++, --. Ejemplos:
Operadores de comparación
Estos operadores son múy utiles cuando tenemos que cambiar el flujo de nuestro programa. Con
ellos podemos comparar si un objeto o variable es igual (==), no es igual (!=), es mayor o igual (>=),
es menor o igual (<=), es mayor (>) o es menor (<) que otro objeto. El resultado de esta comparación
es de tipo bool es decir verdadero o falso (true o false). Estos operadores se los usa de la siguiente
forma:
http://es.wikibooks.org/wiki/C_sharp_NET_/_Texto_Completo 16/05/2007
C sharp NET / Texto Completo - Wikilibros Page 30 of 72
int a = 10;
int b = 20;
bool resp;
resp = (a == b); // compara si a es igual a b y retorna el valor bool false (o falso), tómese en cuenta que a==b
resp = (a != b); // compara si a es diferente a b y retorna el valor bool true (o verdadero)
resp = (a <= b); // compara si a es menor o igual a b y retorna el valor bool true (o verdadero)
resp = (a >= b); // compara si a es mayor o igual a b y retorna el valor bool false (o falso)
resp = (a < b); // compara si a es menor a b y retorna el valor bool true (o verdadero)
resp = (a > b); // compara si a es mayor a b y retorna el valor bool false (o falso)
Operadores lógicos
Para entender como funcionan los operadores lógicos tenemos que aprender un poco lo que son los
números binarios. En esta parte del libro no cubriremos en detalle este extenso tema de los números
binarios ni del Algebra que gobierna estos números ni mucho menos de como se comportan las
puertas lógicas dentro de un ordenador porque nos tomaría uno o dos libros completos, pero nos
gustaría dar un poco de bases de como es que los números binarios forman parte de los operadores
lógicos. Toda información que el ordenador opera internamente es representada por números
binarios (por unos y ceros que son conocidos tambien por verdadero y falso), así la letra A el
ordenador internamente lo representa en código binaro ASCII como 01000001 que en números
"normales" o decimales es 65. Para manipular esta información en unos y ceros, el ordernador tiene
operadores lógicos los cuales permiten cambiar la información de una manera que nos convenga. Por
medio de estos operadores lógicos el ordenador es capáz de tomar decisiones, procesar cualquier
información, hacer complicadas operaciones matemáticas, o en otras palabras, por medio de estos
operadores lógicos, el ordenador hace todo lo que vosotros le habéis visto hacer.
AND
Representado por el simbolo &. Comprueba si todos los números binarios son 1 (o verdadero)
entonces la respuesta es 1 (o verdadero)
OR
Representado por el simbolo | (barra vertical de la tecla del 1). Comprueba si cualquiera de los
números binarios es 1 (o verdadero) entonces la respuesta es 1 (o verdadero)
NOT
Representado por el simbolo ~ y !. Invierte la respuesta. En operaciones con tipos bool, el operador !
cambia la variable de verdadero a falso o viceversa, pero en números binarios, el operador ~ cambia
cada uno de los unos y ceros por su opuesto, cuando encuentra un uno lo cambia por un cero y
viceversa, asi por ejemplo si tenemos el numero binario 01000001 y aplicamos el operador NOT ~
obtendremos 10111110, pero si tenemos una expresion que se evalua como true (o verdadera) y si se
aplica el operador !, se obtiene una respuesta false (o falsa). Por ejemplo (!(10==10)) esta expresión
tiene como resultado false
XOR
Representado por el simbolo ^. En dos números, comprueba si los dos números binarios son iguales,
entonces la respuesta es 0 (o falso).
<<
http://es.wikibooks.org/wiki/C_sharp_NET_/_Texto_Completo 16/05/2007
C sharp NET / Texto Completo - Wikilibros Page 31 of 72
Desplazar a la izquierda desplaza todos los bits hacia la izquierda introduciendo ceros al final de la
derecha y descartando los ultimos números. Asi el número 01000001 si se lo desplaza a la izquierda
una vez 01000001 << 1, se convierte en 10000010
>>
Al igual que el operador anterior, desplazar a la derecha desplaza todos los bits hacia la derecha
introduciendo ceros al final de la izquierda y descartando los ultimos números. Asi el número
01000001 si se lo desplaza a la derecha una vez 01000001 >> 1, se convierte en 00100000
En el caso de que deseamos comparar varios valores para saber si todos son verdaderos o si alguno
es verdadero podemos usar los operadores lógicos de unión && y ||
a && b // esta línea compara si a y b son verdaderos retorna el valor true (o verdadero) si los dos lo son
a || b // esta línea compara si a o b son verdaderos retorna el valor true (o verdadero) si alguno de los dos es
!a // esta línea compara si a es verdadero retorna falso si lo es y viceversa.
a y b pueden representar variables, constantes, números, funciones, expresiones, etc. que den como
resultado un valor de decisión (true o false). Asi por ejemplo, el siguiente ejemplo es válido:
int a = 0;
int b = 10;
int c = 20;
Estructuras de control
<- Anterior (Capítulo 3) | Siguiente (Capítulo 5) ->
Estructuras de control
Hay dos maneras de cambiar el rumbo de ejecución de un programa, estos pueden ser saltos
incondicionales y saltos condicionales. En este capítulo se describen algunas de estas sentencias.
Algunas son muy similares a las existentes en otros lenguajes, como las sentencias if, for, while, etc.
y otras, como foreach, throw o continue, son algo más específicas.
Saltos incondicionales
Las instrucciones de un programa se ejecutan sentencia por sentencia empezando desde el método o
función principal llamado Main() hasta terminar con el programa. El programa sin embargo, tomará
otros rumbos incondicionalmente en dos oportunidades: 1. Cuando encuentre la llamada a otros
métodos (Ejemplo 4.1) y 2. Con el uso de las palabras claves como goto, break, continue, return y
http://es.wikibooks.org/wiki/C_sharp_NET_/_Texto_Completo 16/05/2007
C sharp NET / Texto Completo - Wikilibros Page 32 of 72
using System;
namespace Ejemplos{
class Ejemplo4_1{
static void Main(){
Console.WriteLine ("Esta parte se ejecuta primero");
LlamadaOtraFuncion();
Console.WriteLine ("Esta parte se ejecuta al final");
}
En el ejemplo anterior el programa ejecuta sentencia por sentencia el método principal Main() hasta
que encuentra la llamada a otro método. Después de que el método llamado haya terminado el
método Main continuará con la ejecución de las sentencias restantes.
La sentencia goto
En los inicios de los lenguajes de programación la sentencia goto fue la más popular para ir de un
lugar a otro dentro del programa. Sin embargo esto creaba una tremenda confusión al momento de
diseñar la aplicación. Si el programador quería hacer un esquema de como funcionaba dicha
aplicación, se veía con un laberinto tipo espagueti de líneas y símbolos conectados entre si. Es por
esto que esta sentencia es un poco "problemática" y fuera de "moda" entre los lenguajes de
programación modernos. C# sin embargo soporta esta sentencia. Os recomendamos no utilizarla a
menos que se necesario o si os sentís cómodos haciéndolo, pero cuando os cree un laberinto difícil
de depurar, no digáis que no os advertimos de no utilizarla. Hay muchas otras mejores maneras de
cumplir con el mismo propósito (la sentencia while por ejemplo es una de ellas), las cuales son más
elegantes y más sencillas de depurar.
Primero se crea una etiqueta al inicio de cierto bloque de código y después en otro lugar podemos
saltar hacia esa etiqueta usando la palabra clave goto. El siguiente ejemplo ilustra la sentencia goto:
using System;
namespace Ejemplos
{
class Ejemplo4_2
{
static void Main()
{
int contador=0;
REPETIR:
Console.WriteLine ("Esta línea se repetirá 100 veces, esta es la linea numero: {0}", contador);
if (contador++ < 100)
goto REPETIR;
Console.WriteLine ("Despues de que el contador sea igual o mayor que 100 se imprimirá esta línea");
}
}
}
Esta sentencia es un ejemplo de salto incondicional ya que por si solo saltará a la etiqueta
seleccionada incondicionalmente.
http://es.wikibooks.org/wiki/C_sharp_NET_/_Texto_Completo 16/05/2007
C sharp NET / Texto Completo - Wikilibros Page 33 of 72
Saltos condicionales
Los saltos condicionales sirven para ejecutar cierto código solamente si se cumple con alguna
condición. Entre otros tenemos:
Instrucción if
Esta sentencia sirve para ejecutar unas instrucciones en caso de que se cumpla determinada
condición. La forma completa de la instrucción if es
if( condición ) {
instrucciones;
...
}
else {
instrucciones;
...
}
class InstruccionIf{
Console.WriteLine("Introduce un numero");
d = Double.Parse( Console.ReadLine() );
if( d>0 )
{
Console.WriteLine("El numero {0} es positivo", d);
}
else
{
Console.WriteLine("El numero {0} es negativo", d);
}
}
}
te pide que introduzcas un número y dependiendo de si se cumple que dicho número es mayor que
cero (condición), se ejecuta un bloque u otro.
Las intrucciones if se pueden anidar, y existe también una extensión de la sentencia if, la sentencia
if-else-if. Su formato es el siguiente:
http://es.wikibooks.org/wiki/C_sharp_NET_/_Texto_Completo 16/05/2007
C sharp NET / Texto Completo - Wikilibros Page 34 of 72
if( condicion1 )
{
instrucciones;
}
else if( condicion2 )
{
instrucciones;
}
...
else
{
instrucciones;
}
Las instrucciones condicionales se evalúan de arriba a abajo. Tan pronto como se encuentra una
condición true, se ejecuta la instrucción asociada con ella, y el resto de la escalera se omite. Si
ninguna de las condiciones es true, se ejecutará la última instrucción else. La última instrucción else
actúa como condición predeterminada, es decir, si no funciona ninguna de las otras pruebas
condicionales, se realiza esta última instrucción. Si no existe esta instrucción else final y el resto de
de las condiciones son falsas, entonces no se realizará ninguna acción. El siguiente ejemplo
using System;
class IfElseIf{
public static void Main()
{
string opcion;
if( opcion=="si" )
{
Console.WriteLine( "Muy bien, ha elegido si" );
}
else if( opcion=="no" )
{
Console.WriteLine( "Ha elegido no" );
}
else{
Console.WriteLine("No entiendo lo que ha escrito");
}
}
}
le pide al usuario que elija una opción si/no y la procesa usando una estructura if-else-if. Si la opción
no es ni "si" ni "no", entonces se ejecuta la sentencia else por defecto, que imprime por pantalla el
mensaje "No entiendo lo que ha escrito"
Nota: Hay que tener mucho cuidado que el simbolo = no es igual a ==, el primero sirve para asignar un valor a una
Instrucción switch
La instrucción switch es muy parecida a la estructura if-else-if, sólo que permite seleccionar entre
varias alternativas de una manera más cómoda. Funciona de la siguiente manera: el valor de una
expresión se prueba sucesivamente con una lista de constantes. Cuando se encuentra una
coincidencia, se ejecuta la secuencia de instrucciones asociada con esa coincidencia. La forma
general de la instrucción switch es la siguiente:
http://es.wikibooks.org/wiki/C_sharp_NET_/_Texto_Completo 16/05/2007
C sharp NET / Texto Completo - Wikilibros Page 35 of 72
switch( expresión ){
case constante1:
instrucciones;
break;
case constante2:
instrucciones;
break;
...
default:
instrucciones;
break;
}
La sentencia default se ejecutará sólo si ninguna constante de las que siguen a case coincide con
expresión. Es algo similar al else final de la instrucción if-else-if.
using System;
class InstruccionSwitch{
public static void Main()
{
string s;
s = Console.ReadLine();
switch(s){
case "+":
Console.WriteLine("El resultado es {0}", 2+3);
break;
case "-":
Console.WriteLine("El resultado es {0}", 2-3);
break;
case "*":
Console.WriteLine("El resultado es {0}", 2*3);
break;
case "/":
Console.WriteLine("El resultado es {0}", 2/3);
break;
default:
Console.WriteLine("No te entiendo");
break;
}
}
}
El cual solicita al usuario que inserte uno de los símbolos +-*/ , y con un switch compara los
resultados para hacer diferentes acciones dependiendo del valor de s, que es la cadena de caracteres
que almacena la elección del usuario. El resultado debería ser algo parecido a esto:
Como habrá notado, al final de todo case siempre hay una sentencia break. Esto no es obligatorio,
puede haber en su lugar otra sentencia de salto como un goto inclusive en el caso default.
http://es.wikibooks.org/wiki/C_sharp_NET_/_Texto_Completo 16/05/2007
C sharp NET / Texto Completo - Wikilibros Page 36 of 72
Siempre se deberá tener un break o un goto en cada caso a menos que la sentencia esté vacía. En esta
situación se ejecutará el siguiente caso que viene en la lista. Si no se toma en cuenta ésto se obtiene
un error en tiempo de compilación. Otros lenguajes, como C/C++ o Java no tienen esta restricción.
La razón de adoptarla en C# es doble: por un lado, elimina muchos errores comunes y en segundo
lugar permite al compilador reorganizar las sentencias de los case, y así permitir su optimización.
Ejemplo:
using System;
class InstruccionSwitch{
public static void Main()
{
int voto;
Console.WriteLine( "Qué tipo de musica te gusta más");
Console.WriteLine( "1 - Rock" );
Console.WriteLine( "2 - Clásica (clasica cuenta como instrumental)" );
Console.WriteLine( "3 - Instrumental" );
Console.WriteLine( "4 - Alternativa (alternativo cuenta como Rock)" );
voto = Int32.Parse(Console.ReadLine());
switch(voto){
case 1:
Console.WriteLine("Has votado por Rock o Alternativo");
break;
case 2: //Debido a que no tiene ni un goto ni break y está vacía va al siguiente caso
case 3:
Console.WriteLine("Has votado por Clásica o Instrumental");
break;
case 4:
goto case 1;
default:
Console.WriteLine("No te entiendo");
break;
}
}
}
Bucle for
El bucle for de C# es idéntico al encontrado en los lenguajes C/C++ y Java. El formato general es
Las sentencias de inicialización se ejecutan una vez al principio y sirven principalmente para asignar
valores a las variables que servirán de contador. Las sentencias de condición, por su parte, se
ejecutan cada vez que el bucle vuelve al principio y sirven para controlar el bucle: éste seguirá
realizándose siempre y cuando estas condiciones sean true. Las sentencias de iteración se ejecutan
también cada vez que se realiza una nuevo ciclo en el bucle, y sirven para cambiar el estado de las
variables que gobiernan las sentencias de condición. Pero todo esto se entiende mejor con un
ejemplo
http://es.wikibooks.org/wiki/C_sharp_NET_/_Texto_Completo 16/05/2007
C sharp NET / Texto Completo - Wikilibros Page 37 of 72
using System;
class BucleFor{
public static void Main()
{
int i; //el contador
Este ejemplo imprime por pantalla los 10 primero enteros positivos. Es un caso muy simple del bucle
for. Por cierto, el operador ++ lo que hace es que añade una unidad a la variable a la que acompaña,
de forma que, por ejemplo, 9++ es 10. De esta forma, la variable i se incrementa a cada vuelta.
En el ejemplo anterior, las sentencias de inicialización y de iteración eran únicas, pero esto no tiene
por qué ser así, de hecho se pueden utilizar varias sentencias separadas por comas. Por ejemplo, se
pueden usar dos variables para controlar el bucle
using System;
class BucleFor2{
public static void Main()
{
int i;
int j;
Por su parte, la expresión condicional del bucle for puede ser cualquier expresión que genere un
valor booleano. En este caso se ha usado "i<j", pero también hubiera sido válida "i==5", "true" (el
bucle se realizará indefinidamente) o "false" (el bucle no se realizará).
Bucle while
El bucle while es un bucle que se realiza hasta que se cumpla determinada condición. Tiene la forma
while( condición )
{
instrucciones;
}
Donde la condición tiene que ser un valor booleano. Tiene una estructura muy sencilla, así que
vamos a ver directamente un ejemplo.
http://es.wikibooks.org/wiki/C_sharp_NET_/_Texto_Completo 16/05/2007
C sharp NET / Texto Completo - Wikilibros Page 38 of 72
using System;
class BucleWhile{
public static void Main()
{
int i = 0;
while( i<10)
{
Console.WriteLine( i );
i = i+1;
}
}
}
En el que se realiza lo mismo que en el ejemplo anterior, sólo que ahora con un bucle while.
Bucle do-while
Se trata de una ligera variante del bucle anterior, con la diferencia de que ahora primero se ejecutan
las instrucciones y luego se evalúa la condición, de forma que tiene tiene una estructura:
do{
instrucciones;
}
while( condición );
El siguiente ejemplo
class BucleDoWhile{
public static void Main()
{
string s = "";
do
{
Console.WriteLine( "Introduce si para salir del bucle" );
s = Console.ReadLine();
}
while( s != "si" );
}
}
muestra un programa que ejecuta un bucle hasta que el usuario introduce "si". Por cierto, != es lo
contrario de ==, es decir, != devuelve true cuando los valores comparados son distintos.
Bucle foreach
El bucle foreach se utiliza para hacer iteraciones sobre elementos de una colección, como pueden ser
los enteros dentro de un arreglo de enteros. La sintaxis sigue la siguiente estructura:
Como hemos comentado, el uso más inmediato es iterar sobre un arreglo de números:
http://es.wikibooks.org/wiki/C_sharp_NET_/_Texto_Completo 16/05/2007
C sharp NET / Texto Completo - Wikilibros Page 39 of 72
using System;
class BucleForeach{
public static void Main()
{
int[,] arr = {{1,2},{2,3}};
Este ejemplo sólo imprime los valores de una matriz, pero como se puede comprobar mejora mucho
la claridad del código comparándolo con una implementación con bucles for como esta
using System;
class BucleForeach{
public static void Main()
{
int i, j; //seran los indexadores de la matriz
Además, es posible utilizar el bucle foreach con cualquier tipo que sea una colección, no solo con
arreglos, como veremos más adelante.
continue y break son dos palabras clave que nos permiten saltar incondicionalmente al inicio de un
bucle (continue) o fuera de un bucle (break) cuando se necesite. Por ejemplo:
using System;
class continueBreak
{
public static void Main()
{
for(int i = 0; i<10; i++ )
{
if (i==5)
continue;
if (i==9)
break;
Console.Write("{0},",i);
}
}
}
Este pequeño programa entrará en un bucle for que hará que la variable i tome los valores del 1 al
10, pero al llegar al número 5 el bucle saltará incondicionalmente al inicio del bucle sin ejecutar las
líneas que siguen más adelante por lo que no ejecutará la línea que imprime en la pantalla el número
http://es.wikibooks.org/wiki/C_sharp_NET_/_Texto_Completo 16/05/2007
C sharp NET / Texto Completo - Wikilibros Page 40 of 72
5. Cosa similar sucede cuando llega al número 9: el bucle será detenido por el salto incondicional
break que romperá el bucle cuando encuentre esta palabra. El resultado será el siguiente:
0,1,2,3,4,6,7,8,
El bucle saltó la línea que imprime 5 y terminó cuando llegó a 9 gracias a las palabras clave
continue y break.
Una clase es como una plantilla que describe cómo deben ser las instancias de dicha clase, de forma
que cuando creamos una instancia, ésta tendrá exactamente los mismos métodos y variables que los
que tiene la clase.Los datos y métodos contenidos en una clase se llaman miembros de la clase y se
accede a ellos siempre mediante el operador "." . En el siguiente ejemplo, se definirá una clase,
Clase1 y en el método Main se creará una instancia de Clase1 llamada MiClase. Una buena idea es
jugar un poco con el código para ver que la instancia de la clase efectivamente tiene los mismos
miembros que la clase Clase1 (que sería la plantilla de la que hablábamos antes)
using System;
public int a = 1;
private double b = 3;
public char c = 'a';
}
los identificadores public delante de los tipos que hay dentro de Clase1 son necesarios para luego
poder ser llamados desde otra clase, como en este caso, que estamos llamando a los miembros de una
instancia de Clase1 desde UsoClase. Pero en las clases no solo hay variables, también podemos
incluir métodos.
http://es.wikibooks.org/wiki/C_sharp_NET_/_Texto_Completo 16/05/2007
C sharp NET / Texto Completo - Wikilibros Page 41 of 72
using System;
public int a = 1;
public double b = 3;
public char c = 'a';
Podemos hacer más cosas con las clases, como heredar otras clases o implementar interfaces, pero en
este capítulo nos centraremos en el uso de métodos y variables.
Métodos
Los métodos, también llamados funciones, son trozos de código que reciben unos datos, hacen algo
con esos datos, y a veces devuelven algún valor. En C#, todos los métodos se encuentran contenidas
dentro de un objeto.
* Tipo devuelto
* Nombre del método
* Parámetros (puede ser vacío)
* Cuerpo del método
devuelve un tipo double, tiene por nombre Divide, los parámetos son a y b, ambos del tipo double, y
el cuerpo del método es simplemente "return a/b;".
Cuando queramos llamar a un método, debemos simplemente poner el nombre del método y sus
argumentos dentro de un paréntesis separados por comas. Para llamar al método Divide declarado
antes, simplemente debemos escribir Divide(8, 2);
Según lo que hemos visto, el ejemplo del método Divide() completo necesita tener una clase donde
definirse y un método Main() donde ejecutarse.
http://es.wikibooks.org/wiki/C_sharp_NET_/_Texto_Completo 16/05/2007
C sharp NET / Texto Completo - Wikilibros Page 42 of 72
using System;
class Metodo{
public double Divide( double a, double b )
{
return a/b;
}
}
class Principal{
public static void Main()
{
Metodo m = new Metodo();
Console.WriteLine( m.Divide(8, 2) );
}
}
Parámetros
La declaración formal de parámetros también define variables. Hay cuatro tipos de parámetros:
parámetros por valor, por referencia, parámetros de salida, y arreglos de parámetros.
El paso de parámetros por valor es usado por defecto para pasar parámetros a métodos. Cuando se
pasa un parámetro por valor a una función realmente se está pasando una copia de dicho parámetro,
por lo que las modificaciones que le hagamos al parámetro dentro del método no afectarán al
parámetro original. El ejemplo
using System;
class Test {
static void F(int p) {
p++;
Console.WriteLine("p = {0}", p);
}
static void Main() {
int a = 1;
Console.WriteLine("pre: a = {0}", a);
F(a);
Console.WriteLine("post: a = {0}", a);
}
}
muestra un método F que tiene un parámetro por valor llamado p. El ejemplo produce la salida:
pre: a = 1
p = 2
post: a = 1
aunque el valor del parámetro p haya sido modificado dentro del método, éste parámetro solamente
tenía una copia del valor del parámetro a que pasamos al método; por lo que cuando imprimimos el
parámetro a vemos que éste parámetro ha mantenido su valor original.
El paso de parámetros por referencia es la contraposición lógica al paso por valor. En el paso por
http://es.wikibooks.org/wiki/C_sharp_NET_/_Texto_Completo 16/05/2007
C sharp NET / Texto Completo - Wikilibros Page 43 of 72
referencia no se realiza ninguna copia del objeto, sino que lo que se le pasa a la función es una
referencia del objeto, de forma que el parámetro pasa directamente a la función y cualquier
modificación sobre el parámetro dentro de la función afectará al parámetro original
using System;
class Test {
static void Swap(ref int a, ref int b) {
// intercambia los dos valores
int t = a;
a = b;
b = t;
}
static void Main() {
int x = 1;
int y = 2;
muestra un método swap que tiene dos parámetros por referencia. La salida producida es:
pre: x = 1, y = 2
post: x = 2, y = 1
La palabra clave ref debe de ser usada tanto en la declaración formal de la función como en los usos
que se hace de ésta.
Parámetro de salida
El parámetro de salida es similar al parámetro por referencia, salvo que el valor inicial de dicho
argumento carece de importancia. Un argumento de salida se declara con el modificador out. El
ejemplo
using System;
class Test {
static void Divide(int num1, int num2, out int result, out int resid) {
result = num1 / num2;
resid = num1 % num2;
}
static void Main() {
int valor1 = 10;
int valor2 = 3;
int respuesta, residuo;
Divide(valor1, valor2, out respuesta, out residuo);
Console.WriteLine("La división de {0} para {1} = {2} con un residuo de {3}", valor1, valor2, respuesta,
}
}
muestra un método Divide que incluye dos parámetros de salida. Uno para el resultado (variable
result) de la división y otro para el resto (variable resid). Vemos que estos resultados son asignados a
las variables respuesta y residuo respectivamente.
Arreglo de parámetros
http://es.wikibooks.org/wiki/C_sharp_NET_/_Texto_Completo 16/05/2007
C sharp NET / Texto Completo - Wikilibros Page 44 of 72
Habrá ocasiones que necesitemos pasar varios parámetros a un método (o función) pero no sabremos
con anticipación cuantos parámetros tendremos que pasar; para esto podremos usar un arreglo de
parámetros. Un arreglo de parámetros permite guardar una relación de varios a uno: varios
argumentos pueden ser representados por un único arreglo de parámetros. En otras palabras, los
arreglos de parámetros permiten listas de argumentos de tamaño variable.
Un arreglo de parámetros se declara con el modificador params. Sólo puede haber un arreglo de
parámetros en cada método, y siempre debe ser el último parámetro especificado. El tipo del arreglo
de parámetros debe ser siempre un tipo arreglo unidimensional. Al llamar a la función se puede
pasar uno o varios argumentos del tipo del arreglo. El ejemplo
using System;
class Test
{
static void F(params int[] args) {
Console.WriteLine("nº de argumentos: {0}", args.Length);
for (int i = 0; i < args.Length; i++)
Console.WriteLine("args[{0}] = {1}", i, args[i]);
}
static void Main() {
F();
F(1);
F(1, 2);
F(1, 2, 3);
F(new int[] {1, 2, 3, 4});
}
}
muestra un método F que toma un número variable de argumentos int, y varias llamadas a este
método. La salida es:
nº de argumentos: 0
nº de argumentos: 1
args[0] = 1
nº de argumentos: 2
args[0] = 1
args[1] = 2
nº de argumentos: 3
args[0] = 1
args[1] = 2
args[2] = 3
nº de argumentos: 4
args[0] = 1
args[1] = 2
args[2] = 3
args[3] = 4
La mayoría de los ejemplos presentes en este capítulo utilizan el método WriteLine de la clase
Console. El comportamiento para las sustituciones, como muestra el ejemplo
int a = 1, b = 2;
Console.WriteLine("a = {0}, b = {1}", a, b);
http://es.wikibooks.org/wiki/C_sharp_NET_/_Texto_Completo 16/05/2007
C sharp NET / Texto Completo - Wikilibros Page 45 of 72
using System;
namespace System
{
public class Console
{
public static void WriteLine(string s) {...}
public static void WriteLine(string s, object a) {...}
public static void WriteLine(string s, object a, object b) {...}
...
public static void WriteLine(string s, params object[] args) {...}
}
}
using System;
class Metodo{
public double Divide( double a, double b )
{
return a/b;
}
}
class Principal{
public static void Main()
{
Metodo m = new Metodo();
Console.WriteLine( m.Divide(8, 2) );
}
}
Si por ejemplo intentamos declarar el método Divide sin el modificador public, obtendremos un
error en tiempo de compilación. El modificador complementario de public es private, que provoca
que el método o dato solo sea accesible desde la clase en la que está declarado. Si no se especifica
nada, se toma por defecto el modificador private
De esta forma podríamos separar las clases Metodo y Principal en dos archivos separados, llamados
por ejemplo metodo.cs y principal.cs . Para compilar esto, bastará compilar ambos archivos al mismo
tiempo, de forma similar a esto: mcs principal.cs metodo.cs
Además, tampoco es necesario crear una instancia de la clase sólo para acceder a un método
declarado en ella. Para eso debemos anteponer a la declaración del método el modificador static. Los
métodos estáticos se caracterizan por no necesitar una instancia de la clase para cumplir su función,
pero como contrapartida, no pueden acceder a datos propios de la clase.
http://es.wikibooks.org/wiki/C_sharp_NET_/_Texto_Completo 16/05/2007
C sharp NET / Texto Completo - Wikilibros Page 46 of 72
using System;
class Metodo{
public static double Divide( double a, double b )
{
return a/b;
}
}
class Principal{
public static void Main()
{
Console.WriteLine( Metodo.Divide(8, 2) );
}
}
Como hemos visto, las instancias de una clase se crean con la sintaxis
donde nombreclase es el nombre que le hemos dado a la definición de la clase, argumentos es una
lista de argumentos posiblemente vacía y objeto es el nombre que queremos darle a la instancia de la
clase.
Una vez creada una clase, sus miembros se inicializan a sus valores predeterminados ( cero para
valores numéricos, cadena vacía para el tipo string, etc. ). La siguiente clase representa un punto
sobre el plano, de forma que tiene dos valores públicos X e Y, y un método que calcula la distancia
al origen del punto (módulo)
http://es.wikibooks.org/wiki/C_sharp_NET_/_Texto_Completo 16/05/2007
C sharp NET / Texto Completo - Wikilibros Page 47 of 72
using System;
class Punto{
public double X;
public double Y;
class Principal{
public static void Main()
{
Punto A = new Punto();
A.X = 1;
A.Y = -1;
}
}
Ahora bien, la forma en la que se crea la instancia, es decir, inicializando los datos a cero (ejercicio:
comprobar esto), se puede personalizar, de forma que podemos construir nuestro propio constructor
que le diga a la clase los valores por defecto que debe tomar. Esto se realiza simplemente escribiendo
dentro de la clase un método que tenga el mismo nombre que la clase y en el que no se especifica el
valor devuelto. La clase Punto con un constructor sería así:
using System;
class Punto{
public double X;
public double Y;
de forma que ahora al crear una instancia de la clase se crea el punto (1,1) en lugar del (0,0), que era
el que se creaba por defecto. De esta forma, al crear la instancia, par ya contendrá los valores (1,1) .
En la práctica se utilizan mucho constructores con parámetos, de forma que al crear la instancia se le
asignan valores según los parámetros. La siguiente implementación de Par contiene un constructor
que acepta un par de valores, que servirán para inicializar los valores A y B
http://es.wikibooks.org/wiki/C_sharp_NET_/_Texto_Completo 16/05/2007
C sharp NET / Texto Completo - Wikilibros Page 48 of 72
class Punto{
public Punto( double val1, double val2)
{
X = val1;
Y = val2;
}
...
}
También tenemos la posibilidad de declarar una clase con varios constructores (cada uno con
diferentes parámetros) Lo que hará el compilador de C# es buscar el constructor que se adecúe a los
parámetros que le llegan, y ejecutarlo como si fuera un método más. Dependiendo de la llamada que
se haga en el "new", usaremos un constructor u otro.
Sobrecarga de métodos
En C#, al igual que en C++ y en Java es posible definir varios métodos con el mismo nombre pero
con distintos parámetros, de forma que el compilador decide a cuál se llama dependiendo de los
parámetros que le lleguen.
Esto es muy práctico, pues no tienes que renombrar cada función según el tipo de valor que acepta.
El siguiente ejemplo implementa un par de métodos que elevan al cuadrado el valor que reciben, y se
implementan para tipos double y para int. En C, que es un lenguaje que no soporta sobrecarga de
métodos, se tendría que haber llamado distinto a ambos métodos, por ejemplo alcuadrado_double y
alcuadrado_int
using System;
class Eleva{
public static double AlCuadrado( int a )
{
return a*a;
}
class Principal{
public static void Main()
{
Console.WriteLine("4 al cuadrado es {0}", Eleva.AlCuadrado(4) );
Console.WriteLine("3.2 al cuadrado es {0}", Eleva.AlCuadrado(3.2) );
}
}
La palabra reservada this sirve para hacer referencia a miembros de la clase en caso de que se quiera
especificar, ya sea por motivos de colisión de nombres o por la claridad del código. Su sintaxis es
this.campo
http://es.wikibooks.org/wiki/C_sharp_NET_/_Texto_Completo 16/05/2007
C sharp NET / Texto Completo - Wikilibros Page 49 of 72
En el siguiente ejemplo, declaramos un constructor para la clase Punto, que toma dos argumentos X
e Y. Entonces es obligado el uso de this para distinguir entre el X de la clase y el X tomado como
parámetro
class Complejo
{
double X;
double Y;
Complejo(double X, double Y)
{
this.X = X;
this.Y = Y;
}
}
Propiedades e indizadores
Propiedades
Las propiedades son una característica de C# que permiten aparentemente el acceso a un miembro de
la clase mientras mantiene el control asociado al acceso mediante métodos.
Para los programadores de Java hay que decir que esto no es más que la formalización del patrón de
asignación (setter) y método de lectura (getter)
Las propiedades son como métodos que se declaran dentro de un bloque asociado a una variable
mediante las palabras reservadas get (se encarga de devolver algo cuando se llama al tipo que lo
contiene ) y set (que hace algo cuando se le asigna un valor a la variable que lo contiene. Este valor
viene especificado en la variable value )
using System;
class TestProperties {
private static string clave;
public string Clave {
get
{
Console.WriteLine ("Acceso a la propiedad clave");
return clave;
}
set
{
Console.WriteLine ("Cambio del valor de clave");
clave = value;
}
}
}
class Test {
public static void Main () {
TestProperties tp = new TestProperties();
string c = "ClaveClave";
tp.Clave = c;
Console.WriteLine (tp.Clave);
}
}
En realidad, lo que se hace es declarar una variable privada de forma que no se puede acceder de
forma directa, y se crean dos métodos ( o uno si solo se requiere acceso de lectura) que permiten
acceder al contenido de la variable y tal vez modificarla. Si no queremos que se pueda modificar la
http://es.wikibooks.org/wiki/C_sharp_NET_/_Texto_Completo 16/05/2007
C sharp NET / Texto Completo - Wikilibros Page 50 of 72
Indexadores
Hemos visto, en el apartado en el que tratamos las propiedades, que podemos acceder a una variable
privada de una clase a través de eventos que nos permiten controlar la forma en la que accedemos a
dicha variable.
Los indexadores nos van a permitir hacer algo parecido. Nos van a permitir acceder a una clase como
si se tratara de un arreglo. Lo vemos de forma más sencilla con un ejemplo:
using System;
class PruebaIndexadores
{
private int[] tabla = {1, 2, 3, 4};
Tenemos una clase PruebaIndexadores en la que hay un array llamado "tabla", declarado como
privado, por lo que no podremos acceder a él desde fuera de nuestra clase. Pero hemos declarado
también un indexador (public int this [int indice]), que nos permitirá acceder a él de forma más
controlada.
Para probar esta clase, creamos otra clase con un punto de entrada (public static void Main ()), que
será donde hagamos las pruebas.
int a = obj[3];
Esta línea lo que hace es llamar al indexador, pasándole como parámetro el índice, en este caso 3. Al
ser una consulta de lectura, se ejecuta el código que haya en la parte "get" del indexador. Una vez
ejecutado, lo que nos aparece por pantalla es esto:
http://es.wikibooks.org/wiki/C_sharp_NET_/_Texto_Completo 16/05/2007
C sharp NET / Texto Completo - Wikilibros Page 51 of 72
obj[3] = 6;
Lo que se ejecuta ahora es la parte "set" del indexador. Lo que aparecerá en pantalla una vez
ejecutado esto será:
Nótese que tenemos que hacer explícitamente el acceso al array (tabla[indice]=value) en el set, ya
que el indexador no tiene forma de saber qué variable se supone que tiene que manejar. Si no
pusiéramos esa línea, en realidad el indexador no cambiaría el valor del array.
a = obj[3];
Herencia y polimorfismo
<- Anterior (Capítulo 5) | Siguiente (Capítulo 7) ->
Herencia
La herencia es un concepto fundamental de la programación orientada a objetos. Cuando se dice que
una cierta clase A hereda otra clase B significa que la clase A contiene todos los miembros de la
clase B más algunos que opcionalmente puede implementar ella misma
Las clases en C# soportan herencia simple, de forma que una clase puede derivar de otra, pero no de
varias (como si era posible en C++). De hecho, en C# todas las clases derivan implícitamente de la
clase object.
http://es.wikibooks.org/wiki/C_sharp_NET_/_Texto_Completo 16/05/2007
C sharp NET / Texto Completo - Wikilibros Page 52 of 72
En el siguiente ejemplo definimos una clase A con un método F(). Posteriormente definimos una
clase B que hereda A y además define un método G(). Finalmente creamos una clase con un método
Main() que llamará a los dos métodos de B, al implementado por B y al heredado
using System;
class A{
public void F()
{
Console.WriteLine("Soy F() de A");
}
}
class B : A{
public void G()
{
Console.WriteLine("Soy G() de B");
}
}
class Principal{
public static void Main()
{
B clase_heredada = new B();
clase_heredada.F();
clase_heredada.G();
}
}
La palabra reservada base sirve para acceder a miembros de la clase heredada de la misma forma que
this sirve para acceder a miembros de la propia clase. Su sintaxis es idéntica a la de this, esto es:
base.nombre_del_miembro
En el siguiente ejemplo declaramos una clase B que hereda A y que utiliza el método F() de A.
class B : A{
public void H()
{
base.F();
Console.WriteLine("soy H() de B");
}
}
Clases Abstractas
Las clases abstractas son clases que contienen algún método incompleto, esto es, que está definido
pero no implementado. Por lo tanto, no se pueden instanciar y su único propósito es servir de clase
base de las que se derivarán otras clases.
http://es.wikibooks.org/wiki/C_sharp_NET_/_Texto_Completo 16/05/2007
C sharp NET / Texto Completo - Wikilibros Page 53 of 72
Las clases que heredan una clase abstracta deben implementar los métodos incompletos. Las clases
abstractas se declaran con la palabra reservada abstract
using System;
abstract class A{
public void F(); //metodo no implementado
}
class B : A{
//error en tiempo de compilación, B tiene que definir un método F()
}
Miembros virtual
Métodos, propiedades e indexadores pueden ser virtual, lo que significa que su implementación
puede ser sobreescrita en clases derivadas. El ejemplo
using System;
class A {
public virtual void F()
{
Console.WriteLine("A.F");
}
}
class B: A {
public override void F()
{
base.F();
Console.WriteLine("B.F");
}
}
class Test {
public static void Main()
{
B b = new B();
b.F();
A a = b;
a.F();
}
}
muestra una clase A con un método virtual F, y una clase B que sobreescribe F. El método
sobreescrito en B contiene una llamada, base.F(), el cual llama al método sobreescrito en A.
Problemas propuestos
Sobrecargando operadores
<- Anterior (Capítulo 6) | Siguiente (Capítulo 8) ->
Sobrecarga de operadores
http://es.wikibooks.org/wiki/C_sharp_NET_/_Texto_Completo 16/05/2007
C sharp NET / Texto Completo - Wikilibros Page 54 of 72
La sobrecarga de operadores ya era posible en c++ y en otros lenguajes, pero sorprendentemente java
no lo incorpora, así que podemos decir que esta característica es una ventaja de c# respecto a java,
aunque mucha gente, esta posibilidad, no lo considera una ventaja porque complica el código.
A la hora de hablar de operadores vamos a distinguir entre dos tipos, los unarios y los binarios. Los
unarios son aquellos que solo requieren un operando, por ejemplo a++, en este caso el operando es 'a'
y el operador '++'. Los operadores binarios son aquellos que necesitan dos operadores, por ejemplo
a+c , ahora el operador es '+' y los operandos 'a' y 'c'. Es importante esta distinción ya que la
programación se hará de forma diferente.
Los operadores que podemos sobrecargar son los unarios, +, -, !, ~, ++, --; y los binarios +, -, *, /, %,
&, |, ^, <<, >>. Es importante decir que los operadores de comparación, ==, !=, <, >, <=, >=, se
pueden sobrecargar pero con la condición que siempre se sobrecargue el complementario, es decir, si
sobrecargamos el == debemos sobrecargar el !=.
http://es.wikibooks.org/wiki/C_sharp_NET_/_Texto_Completo 16/05/2007
C sharp NET / Texto Completo - Wikilibros Page 55 of 72
// constructor de la clase
public ComplexNum(float real, float img)
{
this.real = real;
this.img = img;
}
// propiedad Real
public float Real{
get{
return real;
}
set{
real = value;
}
}
// propiedad Img
public float Img{
get{
return img;
}
set{
img = value;
}
}
En el ejemplo hemos puesto la clase, con un constructor , dos propiedades para obtener los datos
privados de la clase y un método que nos transfoma el número complejo a una cadena de caracteres
para que se pueda visualizar fácilmente. Finalmente hemos sobrecargado el operador '+', de forma
que podremos sumar dos números complejos como si se tratara de números usuales.
Operadores binarios
Para empezar vamos a sobrecargar el operador suma('+') para que al sumar dos objetos de la clase
ComplexNum, es decir dos números complejos obtengamos un número complejo que será la suma
de ambas partes. Cabe destacar que los prototipos para sobrecargar operadores serán:
Este es el prototipo para el operador +, el resto de operadores binarios van a seguir el mismo patrón.
Por tanto el código del método de sobrecarga será el siguiente:
http://es.wikibooks.org/wiki/C_sharp_NET_/_Texto_Completo 16/05/2007
C sharp NET / Texto Completo - Wikilibros Page 56 of 72
Este método sobrecarga el operador suma para que podamos sumar dos números complejos. Un dato
a tener en cuenta es que los métodos que sobrecargan operadores deben ser static. Como se ve en el
código los operandos son 'a' y 'b', que se reciben como parámetro y el resultado de la operación es
otro número complejo que es el que retorna el método. Por tanto se limita a crear un nuevo número
complejo con ambas partes operadas. De la misma forma podemos crear la sobrecarga del operador
resta('-') para que lleve a cabo la misma función:
Como vemos el método es idéntico solo que sustituyendo los + por -. En este caso el trabajo que
hacemos dentro del método es trivial pero podría ser tan complejo como se quisiera.
Operadores Unarios
En esta sección se verá cómo sobrecargar los operadores unarios, es decir aquellos que toman un
solo operando, como por ejemplo a++. El prototipo de los métodos que van a sobrecargar operadores
unarios será:
Como antes sustituyendo el ++ por cualquier operador unario. El ejemplo dentro de nuestra clase de
números complejos sería:
A primera vista puede quedar la duda si estamos sobrecargando la operacion ++a o a++. Este aspecto
se encarga el compilador de resolverlo, es decir, se sobrecarga la operación ++ y el compilador se
encarga de "sumar y asignar" o "asignar y sumar". Este problema no ocurría en C++, cosa que
teníamos que manejar nosotros.
http://es.wikibooks.org/wiki/C_sharp_NET_/_Texto_Completo 16/05/2007
C sharp NET / Texto Completo - Wikilibros Page 57 of 72
Como hemos dicho antes, la operación que hagamos dentro del método que sobrecarga el operador
es totalmente libre, se puede poner el ejemplo de multiplicar dos matrices lo que es mas complejo
que sumar dos números complejos.
Estructuras
Estructuras
La lista de similitudes entre clases y estructuras es larga: las estructuras pueden implementar
interfaces, y pueden tener el mismo tipo de miembros que las clases. Sin embargo, las estructuras
difieren de las clases en algunos puntos importantes: las estructuras son tipos por valor en lugar de
tipos por referencia, y no permiten la herencia. Los valores de las estructuras quedan almacenados
"en la pila" o "alineados". Los programadores cuidadosos pueden a veces mejorar el rendimiento
mediante un uso meditado de las estructuras.
Por ejemplo, el uso de una estructura más bien que una clase para un Punto puede producir una gran
diferencia en el número de asignaciones producias en memoria en tiempo de ejecución. El siguiente
programa crea e inicializa un arreglo de 100 puntos. Con Punto implementado como clase, 101
objetos separados son inicializados ( uno para el vector y uno para cada uno de los 100 elementos )
class Punto
{
public int x, y;
public Punto(int x, int y) {
this.x = x;
this.y = y;
}
}
class Test
{
static void Main() {
Punto[] Puntos = new Punto[100];
for (int i = 0; i < 100; i++)
{
Puntos[i] = new Punto(i, i*i);
}
}
}
struct Punto
{
public int x, y;
public Punto(int x, int y) {
this.x = x;
this.y = y;
}
}
únicamente un objeto es inicializado: el elemento del arreglo. Las instancias de Punto se almacenan
http://es.wikibooks.org/wiki/C_sharp_NET_/_Texto_Completo 16/05/2007
C sharp NET / Texto Completo - Wikilibros Page 58 of 72
de forma alineada en el arreglo. Esta optimización puede ser mal usada. Usar estructuras en lugar de
clases también puede hacer que una aplicación funcione más lento o utilice más memoria, pues pasar
una instancia de estructura por valor provoca que una copia de esa estructura sea creada.
Rendimiento
Como hemos dicho, la principal ventaja por la que se usan en determinadas circunstancias
estructuras y no clases es que en circunstancias particulares éstas demuestran mucho mejor
rendimiento.
Interfaces
<- Anterior (Capítulo 8) | Siguiente (Capítulo 10) ->
Definición
Una Interfaz es una colección de miembros abstractos relacionados semánticamente. Una interfaz
representa un comportamiento que una clase dada puede soportar.
El número de miembros de una interfaz dependen del comportamiento que queramos soportar, por
ejemplo todos los objetos que sean móviles podrían querer soportar los métodos acelerar y frenar.
También podríamos declarar dentro de la interfaz una propiedad que nos permita leer y/o escribir la
velocidad que queremos que tome nuestro objeto.
Dado que una interfaz es una colección de miembros abstractos cualquier clase o estructura que
quiera implementar una interfaz está obligada a implementar cada uno de los métodos que se
declaran en la interfaz. De esta forma se consigue un cierto tipo de polimorfismo ya que si varias
clases implementan la misma estructura tenemos la posibilidad de tratar con todas ellas de la misma
forma.
Seguramente alguien se preguntara por que usar interfaces pudiendo usar una clase base abstracta
definiendo los métodos anteriores como abstractos, la primera razón es simplicidad, una clase base
abstracta suele hacer más que definir una colección de métodos, es capaz de definir métodos
públicos, privados, protegidos y también metodos concretos (estáticos) a los que pueden acceder
todas las clases que deriven de ella mientras que una interfaz se limita a definir una colección de
http://es.wikibooks.org/wiki/C_sharp_NET_/_Texto_Completo 16/05/2007
C sharp NET / Texto Completo - Wikilibros Page 59 of 72
métodos sin ninguna implementación. La segunda razón es que C# solamente soporta herencia
simple, pero sin embargo podemos hacer que una clase implemente múltiples interfaces.
He aquí como haríamos para heredar de una clase base e implementar una interfaz, teniendo en
cuenta que VehiculoDeMotor sera nuestra clase base e IMovil nuestra interfaz.
bool Acelerar(int n)
{
//implementación de Acelerar
}
bool Frenar(int n)
{
//implementación de Frenar
}
}
Hay que tener en cuenta que siempre hay que poner la clase base antes de las interfaces.
Ahora nuestra clase CocheDeportivo así como cualquier otra clase que implemente IMovil podra
acelerar y frenar, hay que tener en cuenta que si implementamos IMovil tendremos que implementar
absolutamente todos sus métodos.
En caso de que nuestro objeto implemente la interfaz podríamos operar sobre él con todos los
métodos de la misma, pero en caso de que no la soporte tendríamos un error en tiempo de ejecución,
con lo cual la forma correcta de hacerlo es:
Otra forma de hacerlo sin tener que recurrir a la gestión de excepciones sería utilizando la palabra
reservada as de C#:
http://es.wikibooks.org/wiki/C_sharp_NET_/_Texto_Completo 16/05/2007
C sharp NET / Texto Completo - Wikilibros Page 60 of 72
La palabra reservada as pone la variable de tipo interfaz a null si la interfaz dada no está soportada
por el objeto.
Por último también podemos usar la palabra reservada is de C# para descubrir si un objeto
implementa o no una interfaz:
bool Acelerar(int n)
{
//Implementación de Acelerar
}
bool Frenar(int n)
{
//Implementación de frenar
}
void GirarDerecha(int grados)
{
//Implementación de GirarDerecha
}
void GirarIzquierda(int grados)
{
//Implementación de GirarIzquierda
}
}
Como hemos visto para soportar otra interfaz simplemente la añadimos al final después de una ",".
Ahora supongamos que queremos hacer un método que nos provea de utilidades para el giro por
http://es.wikibooks.org/wiki/C_sharp_NET_/_Texto_Completo 16/05/2007
C sharp NET / Texto Completo - Wikilibros Page 61 of 72
ejemplo hacer trompos, le podríamos pasar una interfaz IGiro de la siguiente forma
Como se puede ver nuestra interfaz implementa un método Turbo. ¿Qué pasaría si una clase
heredase a su vez de la clase Formula Uno que también implemente el metodo void Turbo (bool)?
Bueno vamos a verlo:
Ambas veces se llamaría al mismo método, el definido en la clase Formula1, pero como haríamos si
quisiéramos tener dos Turbos diferentes? la respuesta es hacer que los métodos definidos en la
interfaz sean sólo accesibles desde una referencia a la interfaz, esto es lo que se llama
implementación explícita de una interface.
http://es.wikibooks.org/wiki/C_sharp_NET_/_Texto_Completo 16/05/2007
C sharp NET / Texto Completo - Wikilibros Page 62 of 72
El segundo método sólo podrá ser llamado si usamos una referencia de tipo IAltaVelocidad mientras
que el primero podrá ser llamado usando una referencia a Campeon o a Formula1 (su clase base).
Existen algunas reglas extra al hacer esto, por ejemplo no podemos usar modificadores de
accesibilidad (public, private, protected) ya que si intentamos que sólo se pueda acceder al método
desde una referencia a la interfaz hacerlo sería contraproducente.
También hay que tener en cuenta que pueden haber colisiones de nombres entre clases base e
interfaces y entre interfaces entre si, técnicamente no existe ninguna diferencia y todas pueden ser
tratadas como hemos explicado arriba.
Jerarquías de interfaces
Las interfaces pueden servir de base para otras interfaces al igual que las clases, e igual que en éstas
la idea es que vayamos de lo general a lo particular.
Por ejemplo:
interface IVehiculo
{
void Acelerar();
void Frenar();
}
Al implementar una de estas interfaces en nuestra clase tenemos que implementar todos los métodos
de esta interfaz y de sus ancestros.
http://es.wikibooks.org/wiki/C_sharp_NET_/_Texto_Completo 16/05/2007
C sharp NET / Texto Completo - Wikilibros Page 63 of 72
void IVehiculo.Acelerar(int n)
{
//Gestión del acelerado
}
void IVehiculo.Frenar(int n)
{
//Gestión del frenado
}
void IVehiculoGasolina.CambiarVelocidadInyeccion(int velocidad)
{
//Gestión de la inyeccion
}
void IVehiculo4x4.Activar4x4(bool activar)
{
//Gestión de 4x4
}
}
Estructuras de datos
<- Anterior (Capítulo 9) | Siguiente (Capítulo 11) ->
Enumeraciones
Estructuras
http://es.wikibooks.org/wiki/C_sharp_NET_/_Texto_Completo 16/05/2007
C sharp NET / Texto Completo - Wikilibros Page 64 of 72
Manejo de excepciones
C sharp NET / Capítulo 12
Delegacion y eventos
Programando con delegados
Otra cuestión a tener en cuenta cuando programemos con delegados, es que éstos no tienen en cuenta
la visibilidad de los métodos. Esto permite llamar a métodos privados desde otros si ambos tienen
acceso al delegado. Es decir, imaginemos que una clase guarda en un delegado referencia a uno de
sus métodos privados. Si desde otra clase que tenga acceso al delegado (pero no al método privado)
se convoca a éste, se ejecutará ese método. En verdad no se está violando la privacidad del método,
porque no es la clase quien lo convoca, sino el delegado, que sí tiene acceso al mismo.
Hasta el momento hemos visto como hacer que un delegado guarde referencia de un sólo método.
Sin embargo, existe una clase, System.MulticastDelegate, que deriva de System.Delegate, que se
diferencia de esta última en que puede tener múltiples métodos en su lista de invocaciones.
Para poder hacer esto usaremos los operadores sobrecargados '+=' y '-=' que, respectivamente,
añaden o eliminan a un método de la lista de invocaciones de un delegado.
Para intentar asimilar esto mejor, veámoslo con un ejemplo más completo.
http://es.wikibooks.org/wiki/C_sharp_NET_/_Texto_Completo 16/05/2007
C sharp NET / Texto Completo - Wikilibros Page 65 of 72
using System;
class Ejemplo {
class ClaseA {
class ClaseB {
public ClaseB () {
http://es.wikibooks.org/wiki/C_sharp_NET_/_Texto_Completo 16/05/2007
C sharp NET / Texto Completo - Wikilibros Page 66 of 72
Podemos ver que, en este caso, nuestro delegado sólo manipula métodos que no devuelvan nada y
que reciban como único parámetro una cadena. Si observamos los métodos que componen ClaseA y
ClaseB, el denominado MetodoNoValido no concuerda con el delegado, ya que recibe un entero y
no una cadena. Eso implica que no vamos a poder llamarlo desde ninguna instancia del delegado que
hemos declarado. Sin embargo, con las otras no tendremos ningún problema.
Bien, observemos paso a paso lo que hace el programa. Fijemos nuestra atención en el método
principal (Main). Primero insertamos un método estático. Como sabemos, para llamar a un método
de este tipo, se hace a partir del nombre de la clase y no de una instancia. Bien, hasta aquí nada que
no hayamos visto ya, pero ahora insertemos un segundo módulo en el delegado.
Como hemos dicho, hemos usado el operador '+=' para incluir otro método más en nuestro delegado,
en este caso MetodoPublico. Si usaramos de nuevo el operador '=', borraríamos la antigua lista de
invocaciones y crearíamos una nueva con sólo una función referenciada. Ahora tenemos dos
métodos en la lista de invocaciones de nuestro delegado. Por último, creamos una instancia de
ClaseB, la cual en su constructor incluye una referencia más al delegado, en este caso a
MetodoPrivado.
Como vemos, aunque hemos convocado al delegado desde la clase Ejemplo, que no tiene acceso a
MetodoPrivado, éste ha sido ejecutado. Como explicamos, esto es así porque realmente quien lo está
haciendo es el delegado y no el método Main.
Por último, una cuestión más. Hasta el momento hemos visto a delegados que gestionan miembros
que no devuelven ningún valor. Pero, ¿qué ocurre cuando los devuelven? En este caso, la ejecución
del delegado no devuelve todos esos valores, sólo el que retorne el último método de su lista de
invocación.
XML
http://es.wikibooks.org/wiki/C_sharp_NET_/_Texto_Completo 16/05/2007
C sharp NET / Texto Completo - Wikilibros Page 68 of 72
XML
Cuando Microsoft lanzó las primeras versiones de su plataforma .NET, nos sorprendió a todos por su
apuesta por los estándares, lo cual contrastaba claramente con prácticas anteriores.
El estándar más importante adoptado en la plataforma .NET es sin duda XML (eXtensible Markup
Language, Lenguaje Extensible de Marcas). XML es una tecnología tan integrada en .NET, que la
propia plataforma utiliza XML internamente para sus archivos de configuración y para su propia
documentación. XML es, por lo tanto, una tecnología con una importancia fundamental en .NET.
XML es un lenguaje para estructurar datos. Sirve, por ejemplo, para almacenar en un archivo de
texto una hoja de cálculo, una libreta de direcciones o un dibujo vectorial. XML hace mucho más
fácil al ordenador el proceso de generar datos, leer los datos y asegurarse de que la estructura de los
datos no es ambigua. A su vez, contiene características que aseguran su validez durante mucho
tiempo: es ampliable, independiente de plataforma, no pertenece a ninguna firma concreta de
software y soporta internacionalización.
El aspecto de un archivo XML es muy similar al de un archivo HTML, con texto encerrado entre
etiquetas. Las etiquetas no son más que palabras rodeadas por < y >. El siguiente podría ser un
ejemplo de archivo XML que describe a la persona que escribe éste tutorial.
<?xml version="1.0"?>
<persona>
<nombre>Fabian</nombre>
<apellido>Seoane</apellido>
<organizacion>Mono Hispano</organizacion>
<pagina>http://fseoane.net</pagina>
</persona>
La diferencia fundamental con HTML es que XML no tiene etiquetas predefinidas, sino que éstas
dependen de la implementación. Por ejemplo, en el archivo que acabamos de ver, las etiquetas
disponibles podrían ser persona, nombre, apellido, ..., mientras que en un archivo XML que describa
una librería, las etiquetas podrían ser ensamblado, clase, metodo, etc.
Todo ésto podría parecer un lío increible si no se dispusiera de un mecanismo para traducir entre los
diversos formatos XML, por ejemplo, entre el archivo persona y un archivo HTML que muestra la
información sobre la persona. Por fortuna, esto existe, se llaman hojas XSL y la librería de clases
dispone de métodos para transformar entre XML a partir de hojas XSL.
Si quieres saber más sobre XML te sugiero que mires las siguientes páginas: http://w3.org/XML/,
http://xml.com
XML en .Net
A lo largo de este capítulo utilizaremos de forma extensiva el espacio de nombres System.Xml. Los
estándares cubiertos por este espacio de nombres son:
http://es.wikibooks.org/wiki/C_sharp_NET_/_Texto_Completo 16/05/2007
C sharp NET / Texto Completo - Wikilibros Page 69 of 72
DTDs.
Comenzaremos por escribir un sencillo archivo XML. En éste caso será el ejemplo que acabamos de
utilizar.
El código siguiente crea un documento llamado ejemplo.xml con un documento xml como el del
ejemplo anterior.
using System;
using System.Xml;
class EjemploXml{
writer.WriteEndElement();
writer.Flush();
writer.Close();
}
}
http://es.wikibooks.org/wiki/C_sharp_NET_/_Texto_Completo 16/05/2007
C sharp NET / Texto Completo - Wikilibros Page 70 of 72
Ensamblados y Versiones
C sharp NET / Capítulo 20
Atributos y Reflexión
C sharp NET / Capítulo 21
Programando en Redes
C sharp NET / Capítulo 22
.NET y COM
C sharp NET / Capítulo 23
Texto de titular
lo que pasa es que quiero que me digan como obtener un menu principal realizado en c sharp y con
el codigo fuente para su mayor comrension
http://es.wikibooks.org/wiki/C_sharp_NET_/_Texto_Completo 16/05/2007
C sharp NET / Texto Completo - Wikilibros Page 71 of 72
Media:Ejemplo.ogg
OpenGL y Direct3D
y = mx + n
Una de las nuevas criaturas de ADO.NET es el DataSet que representa un conjunto de tablas y
relaciones de manera desconectada de la fuente de datos de modo que podamos interactuar con los
datos, modificarlos y devolverlos a la fuente primaria usando el ya conocido data adapter.
Otra de las grandes caracteristicas añadidas es el soporte completo para XML, los datos usan
internamente esta representacion para moverse entre las capas de aplicacion a traves de HTTP por
ejemplo.
Finalmente nos queda por destacar que ADO.NET es una libreria manejada (managed library) lo que
hace que su uso sea exactamente igual en cualquiera de los lenguajes soportados por .NET.
http://es.wikibooks.org/wiki/C_sharp_NET_/_Texto_Completo 16/05/2007
C sharp NET / Texto Completo - Wikilibros Page 72 of 72
Los tipos que componen ADO.NET tienen por objetivo obtener datos de la base de datos rellenar un
DataSet, manipular dicho elemento y devolver los datos manipulados a la base de datos, con la
particularidad de que dentro del DataSet podemos tener la representacion de tablas y relaciones entre
ellas hasta llegar a tener una representacion completa de toda una base de datos.
Para poder trabajar correctamente con un DataSet estan definidas dentro del namespace System.Data
algunas interfaces como son IDbCommand, IDbDataAdapter, IDbConnection y IDataReader.
Hay dos proveedores que vienen con .Net predeterminados SQL que permite acceder a SQL Server
7.0 o superior y OleDb que permite acceder a cualquier base de datos que soporte OLE DB, tambien
es comun encontrarnos con proveedores para bases de datos Oracle por ejemplo.
Categorías: Libros con versión para imprimir | C sharp NET | Textos GFDL | Programación
n Esta página fue modificada por última vez el 23:21, 27 sep 2006.
n El contenido está disponible bajo los términos de GNU Free Documentation License
http://es.wikibooks.org/wiki/C_sharp_NET_/_Texto_Completo 16/05/2007