0% encontró este documento útil (0 votos)
430 vistas467 páginas

C# Curso Completo

Este documento introduce la plataforma Microsoft .NET, describiendo sus componentes principales como .NET Framework, los servidores .NET empresariales y los servicios básicos. También cubre temas como los clientes compatibles con .NET y las ventajas de usar esta plataforma.

Cargado por

Sandro Soares
Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd
0% encontró este documento útil (0 votos)
430 vistas467 páginas

C# Curso Completo

Este documento introduce la plataforma Microsoft .NET, describiendo sus componentes principales como .NET Framework, los servidores .NET empresariales y los servicios básicos. También cubre temas como los clientes compatibles con .NET y las ventajas de usar esta plataforma.

Cargado por

Sandro Soares
Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd

Introduccin a Microsoft .

NET

Contenido
Notas generales

Leccin: Introduccin a la plataforma .NET

Leccin: Introduccin a servicios Web XML 14


Leccin: Dentro de .NET Framework

20

Leccin: Compilacin y ejecucin


en .NET

25

Introduccin a Microsoft .NET

Notas para el instructor


Este mdulo ofrece a los estudiantes una introduccin a Microsoft .NET. El
mdulo identifica problemas de las tecnologas actuales que se pueden resolver
con la iniciativa .NET, y describe los servicios y prestaciones bsicas que
ofrece la plataforma .NET. Describe tambin las caractersticas y ventajas de
los servicios Web XML y los clientes con los que es compatible la plataforma
.NET. Los estudiantes aprendern las ventajas y los componentes de .NET
Framework.
Al final de este mdulo, los estudiantes sern capaces de:
Identificar los requisitos de empresa que satisface la iniciativa .NET.
Describir las caractersticas y servicios bsicos de la plataforma .NET.
Identificar las caractersticas y ventajas de los servicios Web XML.
Identificar clientes vlidos para la plataforma .NET y los distintos tipos de
dispositivos inteligentes compatibles con .NET.
Identificar las ventajas de .NET Framework.
Describir los componentes de .NET Framework.
Describir el proceso de compilacin y ejecucin en .NET.
Identificar las formas en que .NET simplifica la programacin con respecto
a otras plataformas.

Introduccin a Microsoft .NET

Notas generales

Introduccin

Introduccin a la plataforma .NET

Introduccin a servicios Web XML

Dentro de .NET Framework

Compilacin y ejecucin en .NET

Gua bsica 2002-04 para Microsoft Developer Tools

Microsoft .NET es una plataforma que le proporciona todas las herramientas y


tecnologas necesarias para crear aplicaciones Web distribuidas que utilizan
protocolos Web estndar. Estas aplicaciones pueden comunicarse con una gran
variedad de clientes, como telfonos mviles y PCs de bolsillo. La plataforma
.NET ofrece tambin un nivel de integracin sin precedentes entre lenguajes de
programacin, adems de distintos servicios en tiempo de ejecucin.
En este mdulo conocer la plataforma .NET de Microsoft para servicios Web
con lenguaje de marcado extensible (XML).

Objetivos

Al final de este mdulo, usted ser capaz de:


Identificar los requisitos de empresa que satisface la iniciativa .NET.
Describir las caractersticas y servicios bsicos de la plataforma .NET.
Identificar las caractersticas y ventajas de los servicios Web XML.
Identificar clientes vlidos para la plataforma .NET y los distintos tipos de
dispositivos inteligentes compatibles con .NET.
Identificar las ventajas de .NET Framework.
Describir los componentes de .NET Framework.
Describir el proceso de compilacin y ejecucin en .NET.
Identificar las formas en que .NET simplifica la programacin con respecto
a otras plataformas.

Introduccin a Microsoft .NET

Leccin: Introduccin a la plataforma .NET

Por qu necesita .NET

La plataforma .NET

.NET Framework

.NET Enterprise Servers

Servicios de base (Building Block Services)

Clientes para la plataforma .NET

Introduccin

Esta leccin presenta los componentes de la plataforma Microsoft .NET, que


est pensada para simplificar el desarrollo Web.

Objetivos de la leccin

Al final de esta leccin, usted ser capaz de:


Identificar problemas de las tecnologas actuales que se pueden resolver con
la iniciativa .NET.
Describir los.NET Enterprise Servers.
Definir los servicios de base (building block services) de .NET Framework.
Identificar los clientes que se pueden utilizar en la plataforma .NET.

Introduccin a Microsoft .NET

Por qu necesita .NET

Microsoft .NET:
z
z

Resuelve muchos problemas de la tecnologa actual


Proporciona aplicaciones compatibles con servicios Web
XML interoperables
Proporciona aplicaciones compatibles con clientes
inteligentes

Introduccin

Microsoft .NET est pensado para facilitar el trabajo con la Internet mediante la
integracin de estndares de Internet y la compatibilidad con servicios Web
XML. La plataforma .NET tambin le permite acceder ms fcilmente a sus
datos y escribir aplicaciones Web que se pueden ejecutar en una gran variedad
de exploradores y dispositivos. El tiempo de ejecucin de .NET simplifica los
procesos de instalacin y actualizacin, aumentando la facilidad de uso y la
fiabilidad.

Problemas de las
tecnologas actuales

Las aplicaciones Web de hoy en da tienen interfaces de usuario interactivas


creadas con HTML dinmico (DHTML) y tecnologa Microsoft ActiveX. El
uso de servicios COM+ proporciona escalabilidad de los servicios de fondo.
Aunque la mayor parte de estas aplicaciones se comunican de forma eficaz,
muchas de ellas pueden presentar los siguientes problemas:
Cada aplicacin es un cdigo diferenciado en un gran nmero de
dispositivos.
Las soluciones estn formadas por grandes grupos de aplicaciones,
dispositivos y servicios.
La integracin, si se consigue, resulta demasiado complicada, demasiado
cara, demasiado lenta y demasiado rgida.

Servicios Web XML


interoperables

La interoperabilidad es la clave para la prxima generacin de aplicaciones. Las


organizaciones virtuales necesitan aplicaciones Web que sean capaces de
interactuar con otras aplicaciones, presentando una interfaz programable que
reaccione ante otros servicios en la Web. Lneas areas, hoteles y empresas de
alquiler de coches, por ejemplo, pueden ofrecer sus servicios como servicios
Web XML, de manera que una agencia de viajes pueda emplearlos para
encontrar la mejor combinacin de precios y servicios para sus clientes.

Introduccin a Microsoft .NET

Compatibilidad con
clientes inteligentes

La tecnologa tambin ha avanzado con gran rapidez, lo que ha provocado una


reduccin en el coste de hardware informtico y mejores conexiones con la
Internet. La necesidad de acceso instantneo a datos por parte de las empresas
ha extendido el uso de dispositivos como telfonos mviles, asistentes digitales
personales (PDAs) y PCs porttiles. Las aplicaciones desarrolladas para .NET
aprovechan los ltimos avances tecnolgicos porque son compatibles con
clientes inteligentes y se pueden ejecutar sobre distintos sistemas operativos.

Introduccin a Microsoft .NET

La plataforma .NET

Internet
Visual Studio .NET

.NET
Framework

Introduccin

.NET Enterprise
Servers

.NET Building
Block Services

Microsoft .NET est formado por las siguientes tecnologas bsicas:


.NET Framework
.NET Enterprise Servers
Servicios de base (Building Block Services)
Microsoft Visual Studio .NET ofrece un entorno de desarrollo de alto nivel
para la creacin de aplicaciones en .NET Framework. Utiliza tecnologas
fundamentales para simplificar la creacin, instalacin y evolucin continua de
aplicaciones Web y servicios Web XML que son seguros, escalables y tienen
una gran disponibilidad. Estas aplicaciones se pueden instalar en distintas
plataformas, incluyendo .NET Enterprise Servers, y pueden hacer uso de
servicios de base .NET.

Introduccin a Microsoft .NET

.NET Framework
.NET Framework
Windows UI

ASP.NET

ADO.NET: Datos y XML


Biblioteca de clases de .NET Framework
Runtime de lenguaje comn
(Common Language Runtime)

Introduccin

.NET Framework es un entorno de ejecucin y biblioteca de componentes


independiente del lenguaje de programacin utilizado. Le permite crear
aplicaciones integradas y orientadas a servicios que satisfacen las necesidades
actuales de las empresas de Internet reuniendo informacin de una gran
variedad de fuentes con las que adems interacta, independientemente de las
plataformas o lenguajes que se empleen.
.NET Framework est formado por los siguientes componentes:
Entorno comn de ejecucin (Common Language Runtime)
Biblioteca de clases de .NET Framework
Microsoft ADO.NET (datos y XML)
Microsoft ASP.NET

Runtime de lenguaje
comn (Common
Language Runtime)

Common Language Runtime (CLR) simplifica el desarrollo de aplicaciones,


proporciona un entorno de ejecucin robusto y seguro, es compatible con gran
variedad de lenguajes y simplifica la instalacin y gestin de aplicaciones.
Tambin se conoce como un entorno gestionado que proporciona
automticamente servicios comunes como seguridad y recoleccin de
elementos no utilizados.

Biblioteca de clases de
.NET Framework

.NET Framework proporciona un conjunto unificado, orientado a objetos,


jerrquico y extensible de bibliotecas de clases para desarrolladores. Hasta
ahora, los desarrolladores de C++ empleaban MFC (Microsoft Foundation
Classes) y los de Microsoft Visual Basic usaban clases del runtime de Visual
Basic, mientras que para otros lenguajes se utilizaban sus propias bibliotecas de
clases y frameworks. Bsicamente, .NET Framework unifica los distintos
frameworks ofrecidos anteriormente por Microsoft. El resultado es que los
desarrolladores ya no necesitan conocer distintos frameworks para hacer su
trabajo.

Introduccin a Microsoft .NET

Por otra parte, la creacin de un conjunto de interfaces de programacin de


aplicaciones (API) comn para todos los lenguajes de programacin en .NET
Framework permite la depuracin, el tratamiento de errores y la herencia de un
lenguaje a otro. De esta forma todos los lenguajes de programacin, desde
Microsoft JScript hasta Visual C++, son iguales en la prctica y los
desarrolladores tienen libertad para elegir el lenguaje que quieren usar.

Introduccin a Microsoft .NET

ADO.NET: Datos y XML

ADO.NET es la prxima generacin de la tecnologa ActiveX Data Object


(ADO). El elevado nivel de integracin de ADO.NET en XML permite a los
desarrolladores transferir conjuntos de datos (cachs de datos en memoria) entre
los distintos componentes de una solucin de empresa.

ASP.NET

ASP.NET se basa en las clases de programacin de .NET Framework para


proporcionar un modelo de aplicaciones Web en la forma de un conjunto de
controles e infraestructura que facilita la creacin de aplicaciones Web. Los
desarrolladores pueden acceder a un conjunto de controles Web de ASP.NET
con funciones comunes de interfaces de usuario en lenguaje de marcado de
hipertexto (HTML), como cuadros de texto y mens desplegables. Estos
controles se ejecutan en el servidor Web y proyectan su interfaz de usuario a un
navegador como HTML.
En el servidor, los controles muestran un modelo de programacin orientada a
objetos que pone su potencia a disposicin de los desarrolladores de Web.
ASP.NET proporciona adems servicios de infraestructura, como gestin de
estados de sesin y reciclaje de procesos, lo que reduce an ms la cantidad de
cdigo que debe escribir el desarrollador y aumenta la fiabilidad de las
aplicaciones. ASP.NET utiliza tambin estos mismos conceptos para hacer que
los desarrolladores puedan ofrecer el software como un servicio.
Utilizando servicios Web XML, los desarrolladores pueden simplemente
escribir su lgica de empresa (business logic) y dejar que la infraestructura de
ASP.NET se encargue de ofrecer el servicio mediante el protocolo simple de
acceso a objetos (Simple Object Access Protocol, SOAP).

Introduccin a Microsoft .NET

.NET Enterprise Servers

Los .NET Enterprise Servers incluyen:


z

Application Center

BizTalk Server

Commerce Server

Exchange Server

Host Integration Server

Internet Security and Acceleration Server

SQL Server

Introduccin

Los .NET Enterprise Servers forman la completa gama de aplicaciones de


servidor de Microsoft para la creacin, instalacin y gestin de soluciones Web
escalables e integradas. Diseados para ofrecer las ms altas prestaciones, los
.NET Enterprise Servers ofrecen escalabilidad, fiabilidad y facilidad de uso
para las empresas globales que trabajan en la Web. Estn pensados
especficamente para que sean interoperables, ya que utilizan estndares
abiertos de Web como XML. Esto permite a Microsoft ofrecer la infraestructura
de una nueva plataforma de desarrollo que ayudar a los desarrolladores a crear
e instalar rpidamente aplicaciones distribuidas en tiempo de Internet.

Enterprise Servers

A continuacin se ofrece una descripcin de los distintos .NET Enterprise


Servers:
Microsoft Windows 2000 Server: Windows 2000 Server aprovecha las
posibilidades de la tecnologa Microsoft Windows NT para integrar
servicios basados en estndares de directorios, aplicaciones Web,
comunicaciones, archivos e impresin con alta fiabilidad, gestin eficaz y
compatibilidad con los ltimos adelantos en hardware de red. El sistema
operativo para servidores de prxima generacin, Windows .NET Server,
ofrecer un nivel de integracin con .NET todava ms alto.
Microsoft Application Center: Application Center hace que las
aplicaciones Web creadas en Microsoft Windows 2000 tengan la mxima
disponibilidad (99,999 por ciento de tiempo activo) mediante adaptacin de
software, al tiempo que reduce la complejidad y los costes de operacin.
Microsoft BizTalk Server: BizTalk Server es una plataforma basada en
estndares que utiliza XML como formato comn de documentos para
desarrollar y gestionar la integracin de aplicaciones en y entre
organizaciones.
Microsoft Commerce Server: Commerce Server es un sistema completo
que permite crear rpidamente soluciones escalables y personalizadas de

Introduccin a Microsoft .NET

10

comercio electrnico Business-to-Consumer (B2C) y Business-to-Business


(B2B) en Windows 2000.
Exchange Server: Esta completa aplicacin de mensajera y colaboracin
para organizaciones de todos los tamaos ofrece los mejores niveles de
interoperabilidad, facilidad de uso y gestin a bajo coste.

Introduccin a Microsoft .NET

11

Microsoft Host Integration Server: Esta completa plataforma de


integracin es el mejor sistema para adoptar rpidamente tecnologas de
Internet, intranet y cliente/servidor y rentabilizar al mximo las inversiones
realizadas en sistemas heredados.
Microsoft Internet Security and Acceleration Server: Internet Security
and Acceleration (ISA) Server le ofrece conectividad a Internet segura y
fcil de administrar y acelera la presentacin de contenido Web por medio
de una cach Web escalable y fiable.
Microsoft SQL Server: La conocida base de datos de Microsoft para
Windows le ofrece la posibilidad de tomar decisiones ms informadas a
todos los niveles de su empresa con soluciones de empresa escalables, gran
capacidad de almacenamiento de datos e integracin en Microsoft Office.
Microsoft Mobile Information Server 2002: Este servidor de aplicaciones
extiende a los usuarios mviles el alcance de los Microsoft .NET Enterprise
Servers, los datos de empresa y los contenidos de intranet. Lleva la intranet
de empresa a la ltima generacin de dispositivos mviles, lo que permite a
los usuarios acceder de forma segura y en tiempo real a su correo
electrnico, contactos, calendarios, tareas o a cualquier aplicacin de
intranet para unidades de negocio desde cualquier lugar.
Microsoft Windows .NET Server: Windows .NET Server es la prxima
generacin de productos para servidores Windows. Estar incluido en .NET
Framework y aprovecha las ventajas que ofrece la compatibilidad con
XML y la escalabilidad de la actual generacin de servidores Windows
para aumentar el nivel de integracin de Microsoft Active Directory
Directory Service y el sistema de autenticacin Microsoft Passport. La
siguiente versin de Windows .NET Server es Windows .NET Server 2003,
un sistema operativo polivalente con capacidad para una gran variedad de
servidores segn las necesidades, tanto de forma centralizada como
distribuida.
Supplier Accelerator: Es una parte muy importante de la iniciativa EBusiness Acceleration que resuelve el problema de la conexin a mltiples
e-marketplaces. Ofrece un modelo inteligente para gestionar la publicacin
de catlogos y el procesamiento de pedidos en los principales emarketplaces directamente con aplicaciones de compradores, y es
ampliable para poder incluir nuevos canales de ventas en e-business.
Supplier Accelerator est basado en Commerce Server 2000, BizTalk
Server 2000 y SQL Server 2000 y es una excelente base para el comercio
electrnico.

Introduccin a Microsoft .NET

12

Servicios de base (Building Block Services)

Introduccin

Servicios de base (Building Block Services)


z

Permiten que el usuario controle los datos

Utilizan Microsoft Passport

Los servicios de base son un conjunto de servicios Web XML que traspasan de
las aplicaciones a los usuarios el control sobre los datos de los usuarios. Estos
servicios permiten la personalizacin y garantizan la coherencia en
aplicaciones, servicios y dispositivos. Microsoft ha desarrollado en torno a la
identidad, la notificacin y el almacenamiento servicios privados y seguros que
pueden servir de base para otros servicios Web XML y experiencias .NET.
Microsoft Passport es la iniciativa de Microsoft .NET para facilitar la
integracin de distintas aplicaciones.

Microsoft Passport

Passport es un componente bsico de la iniciativa Microsoft .NET. Permite a las


empresas desarrollar y ofrecer servicios Web XML distribuidos en una amplia
gama de aplicaciones, dispositivos y servicios complementarios, todos ellos
basados en una experiencia de Internet comn.
El servicio de inicio de sesin nico (Single Sign-In, SSI) de Microsoft
Passport permite a las empresas ofrecer a sus clientes un sistema rpido y
prctico de iniciar una sesin y realizar transacciones de forma segura, ya que
pueden emplear un solo nombre y contrasea en todos los sitios Web a los que
accedan. Adems, los nombres de inicio de sesin de Passport se asignan a
personas y no a sistemas, lo que significa que los miembros pueden acceder a
sitios Passport en cualquier momento y desde muchos tipos de dispositivos.
El uso de Passport en su sitio Web le permitir:
Aumentar el trfico al simplificar el proceso de inicio de sesin y registro.
Aumentar el nivel de retencin de clientes al ofrecer contenidos
personalizados a partir de datos de perfiles en Passport.
Aumentar las ventas al simplificar el proceso de compra.
Ofrecer a millones de miembros de Passport un sistema ms fcil y seguro
de inicio de sesin y compra.

Introduccin a Microsoft .NET

13

Clientes para la plataforma .NET

La plataforma .NET es compatible con los siguientes


dispositivos inteligentes:
z

PCs porttiles

Estaciones de trabajo

PCs de bolsillo

PDAs

Telfonos mviles inteligentes

Consolas de juegos

Tablet PCs

Introduccin

Como apoyo para la plataforma .NET, Microsoft esta creando software de


dispositivos que permitir a los clientes utilizar distintos dispositivos
complementarios en lugar de un solo dispositivo o cliente. Microsoft est
desarrollando software para todo tipo de aparatos, desde telfonos y PDAs hasta
otros dispositivos y clientes, como PCs porttiles, estaciones de trabajo, PCs de
bolsillo, telfonos mviles inteligentes, consolas de juegos (Microsoft Xbox)
y Tablet PCs. Microsoft est trabajando actualmente en los siguientes productos
de software para estos dispositivos: Embedded Windows XP, Windows CE 4.0,
.NET Framework y .NET Compact Framework.

Dispositivos inteligentes

Todos ellos reciben el nombre de dispositivos inteligentes porque pueden


recordar quin es el usuario y utilizan la Web en lugar del servidor como
plataforma para computacin.
Los dispositivos inteligentes permiten acceder a datos, analizarlos y actuar
sobre ellos en cualquier momento y en cualquier lugar. Utilizan la red de forma
inteligente y reaccionan ante limitaciones del ancho de banda, permiten el uso
de aplicaciones con o sin conexin, y saben qu servicios estn disponibles.
Estos dispositivos son programables y personalizables, realizan actualizaciones
automticamente y no requieren ninguna administracin.
Los dispositivos inteligentes presentan y renen informacin de la forma ms
adecuada para cada dispositivo, desde la conversin de texto en voz en un
telfono mvil hasta el reconocimiento de escritura a mano en un Tablet PC.
Pueden utilizar servicios Web XML y descubrir qu servicios estn disponibles,
ya que emplean XML, SOAP y UDDI.
Los dispositivos inteligentes crecern de forma explosiva en los prximos cinco
aos, a medida que se vayan integrando en el dispositivo inteligente por
excelencia para Internet: el PC.

Introduccin a Microsoft .NET

14

Leccin: Introduccin a servicios Web XML

Notas generales sobre servicios Web XML

Caractersticas de los servicios Web XML

Ventajas de los servicios Web XML

Introduccin

Uno de los principales desafos a los que se enfrentan hoy en da los


desarrolladores es la integracin de aplicaciones; es decir, el proceso de tomar
un grupo de aplicaciones y convertirlas en aplicaciones Web fciles de usar,
aunque se ejecuten en distintos sistemas operativos, estn escritas en distintos
lenguajes de programacin y hayan sido creadas con distintos modelos de
objetos.

Objetivos de la leccin

Los servicios Web XML permiten crear aplicaciones Web de forma que
distintos usuarios con diferentes plataformas puedan acceder a ellas y
utilizarlas.
Al final de esta leccin, usted ser capaz de:
Comprender los servicios Web XML.
Describir las caractersticas de los servicios Web XML.
Describir las ventajas de los servicios Web XML.

Introduccin a Microsoft .NET

15

Notas generales sobre servicios Web XML

Introduccin

Los servicios Web XML utilizan los siguientes


estndares:
z

XML

HTTP

SOAP

Los servicios Web XML proporcionan un mecanismo intrnseco para crear un


servicio o sitio Web de manera que colabore perfectamente con otros servicios
y sitios Web. XML Aprovechan la infraestructura y las aplicaciones existentes
para ofrecer un modelo simple, flexible y basado en estndares para la
vinculacin de aplicaciones Web en la Internet.
Las aplicaciones Web se pueden ensamblar fcilmente empleando servicios
desarrollados de forma local y servicios ya existentes, independientemente de
las plataformas, lenguajes de programacin o modelos de objetos que se hayan
utilizado para crear cada servicio o aplicacin.
Si, por ejemplo, su empresa est especializada en la creacin de sistemas muy
precisos de conversin de moneda para prcticamente todos los pases del
mundo, usted puede dedicarse a desarrollar servicios Web XML a los que
acceden otros sitios Web para ofrecer conversiones de precios a sus usuarios.
De esta forma combina distintos servicios y la experiencia del usuario en la
Web es mucho ms rica.

Estndares

Los servicios Web XML utilizan lo siguientes estndares:


XML fue diseado para documentos Web y permite a los desarrolladores
crear sus propias etiquetas personalizadas, lo que hace posible la definicin,
transmisin, validacin e interpretacin de datos entre aplicaciones y entre
organizaciones.
HTTP define el formato y el modo de transmisin de mensajes y las
acciones que los servidores y exploradores Web deben realizar en respuesta
a distintos comandos.
SOAP permite la interoperabilidad de una gran variedad de programas y
plataformas, y hace que las aplicaciones existentes sean accesibles a un
mayor nmero de usuarios.

Introduccin a Microsoft .NET

16

La especificacin UDDI se utiliza para publicar y descubrir informacin sobre


servicios Web XML. UDDI es la base que permite a las empresas buscar y
hacer negocios entre s de forma rpida, sencilla y dinmica utilizando las
aplicaciones que prefieran.

Introduccin a Microsoft .NET

17

Caractersticas de los servicios Web XML

Los servicios Web XML se caracterizan por:


z

Elementos programables

Datos compartidos

Interoperabilidad

Independencia de lenguaje y plataforma

Disponibilidad universal

Introduccin

Los servicios Web XML llevan a un nuevo nivel el desarrollo de aplicaciones


distribuidas.

Caractersticas de los
servicios Web XML

Los servicios Web XML se pueden emplear para:


Colocar elementos programables en sitios Web donde otros pueden acceder
a comportamientos distribuidos.
Invocar funciones de otras aplicaciones, adems de hacer que las
aplicaciones puedan compartir datos independientemente de las
herramientas empleadas para crear esas aplicaciones.
Ofrecer como un servicio Web XML las funciones y datos de cada una de
las aplicaciones existentes. De esta forma se podra crear una aplicacin
compuesta que utilizara ese grupo de servicios Web XML para lograr la
interoperabilidad de las aplicaciones que la forman. El resultado es que los
servicios Web XML resuelven varios problemas bsicos, como
interoperabilidad, integracin y extensibilidad de aplicaciones.
Ser utilizados por aplicaciones creadas en cualquier lenguaje y para
cualquier plataforma. Es posible invocar un servicio Web XML desde
cualquier aplicacin Web, incluyendo otro servicio Web XML. El cliente
de un servicio Web XML no tiene que ser necesariamente una aplicacin
basada en clientes; en realidad, casi todos los clientes son aplicaciones
basadas en servidores, como Web Forms y servicios Web XML.
Promover la comunicacin universal. Un sistema operativo que se desarrolle
ahora o en el futuro incluir sin duda la posibilidad de conectar a la
Internet. Esto significa que la capacidad de los servicios Web XML para
conectar prcticamente cualquier sistema o dispositivo a la Internet
garantizar la disponibilidad universal de esos sistemas operativos para
cualquier otro sistema o dispositivo que est conectado a la Internet.

Introduccin a Microsoft .NET

18

Ventajas de los servicios Web XML

El uso de servicios Web XML presenta las siguientes


ventajas:
z

Una colaboracin ms sencilla para los usuarios

Integracin de aplicaciones de empresa externas

Mayor productividad de los desarrolladores

Introduccin

Los servicios Web XML son un elemento integral del modelo de programacin
.NET. La integracin Best-of-Breed (lo mejor de lo mejor) permite a Microsoft
.NET convertir en una ventaja competitiva las infraestructuras existentes de
tecnologas de la informacin. El objetivo de la iniciativa Microsoft .NET es
conseguir que desarrolladores, empresas y usuarios puedan aprovechar la
tecnologa para acceder a informacin en cualquier momento, en cualquier
lugar y en cualquier dispositivo.

Ventajas

El uso de servicios Web XML presenta las siguientes ventajas:


Da ms posibilidades a los usuarios
Permite la integracin de aplicaciones de otras empresas
Ofrece nuevas oportunidades de desarrollo

Una colaboracin ms
sencilla para los
usuarios

La plataforma .NET utiliza XML para situar en primer plano la experiencia del
usuario y dejar la tecnologa en un segundo plano. Los servicios Web XML:
Permiten a los usuarios interactuar con sus datos a travs de tecnologas de
visin, voz y escritura a mano.
Datos seguros de los usuarios en la Internet para que puedan acceder a ellos
desde el trabajo con sus PCs y desde casa con sus telfonos mviles,
localizadores o PDAs. Esto da a los usuarios un mayor control, capacidad
para tomar mejores decisiones y una colaboracin ms sencilla.
Permite ejecutar aplicaciones en una gran variedad de dispositivos. Esto
hace que los usuarios puedan realizar transacciones fcilmente desde
telfonos inteligentes, PDAs y muchos otros dispositivos inteligentes.

Ejemplo

Por ejemplo, un paciente podra usar una aplicacin basada en .NET para
buscar clnicas cercanas que utilicen servicios Web XML para ofrecer sus

Introduccin a Microsoft .NET

19

calendarios de citas. El paciente puede encontrar de forma rpida y sencilla un


servicio sanitario que satisfaga sus necesidades, mientras que las empresas que
ofrecen sus principales procesos como servicios Web XML crean experiencias
de usuario ms personales e inteligentes y amplan las posibles interacciones de
los clientes con la empresa.
Integracin de
aplicaciones de empresa

Los servicios Web XML ofrecen importantes ventajas a organizaciones y


empresas, ya que aumentan sus posibilidades de alcance y exposicin y crean
nuevas oportunidades de negocio. Esto puede producir un ahorro considerable
en los costes de desarrollo, adems de generar nuevos ingresos.
Las organizaciones pueden integrar ms fcilmente sus aplicaciones internas,
as como acceder a servicios ofrecidos por otras empresas. La combinacin de
servicios Web XML ofrecidos en la Internet permite a las empresas crear para
la Web una gran variedad de aplicaciones con valor aadido.
En el ejemplo anterior, una clnica que intenta ofrecer un mejor servicio
convierte su calendario de citas en un servicio Web XML y lo ofrece en la Web.
Otras empresas, como organizaciones de gestin sanitaria, directorios de
empresas y clnicas, podran crear sistemas que utilizaran o consumieran el
servicio, lo que permitira a los posibles clientes reservar una cita ms
eficazmente.
Por otra parte, esa misma clnica puede usar servicios Web XML creados por
empresas de seguros y organizaciones de gestin sanitaria para enviar facturas
directamente. Tambin podra contratar un sistema de contabilidad con una
tercera empresa para integrarlo en sus propios sistemas, ahorrando tiempo y
recursos.

Mayor productividad de
los desarrolladores

Desde el punto de vista tcnico, Microsoft .NET cambiar la forma en que los
desarrolladores crean aplicaciones.
Visual Studio .NET y .NET Framework permite a los desarrolladores
aprovechar su experiencia y conocimientos para crear de forma rpida y
sencilla avanzados servicios Web XML y aplicaciones. Estas herramientas
ayudarn a los desarrolladores a transformar la Web de un sistema de
presentacin esttica de informacin en un mundo rico en servicios Web
XML interactivos.
La aplicacin de tcnicas de desarrollo rpido de aplicaciones (Rapid
Application Development, RAD) a servicios y aplicaciones Web aumentan
la productividad de los desarrolladores y ahorra tiempo y dinero. Al ser
compatibles con cualquier lenguaje de programacin, estas herramientas
aprovechan los conocimientos de los desarrolladores y les permiten utilizar
la herramienta ms adecuada para cada tarea.
A los desarrolladores independientes de software, .NET les ofrece la
oportunidad de crear nuevos servicios avanzados para la era de la Internet.
Los desarrolladores pueden crear servicios que accedan automticamente a
informacin y hagan uso de ella de forma local o remota, trabajando con
cualquier dispositivo o lenguaje sin tener que reescribir el cdigo para cada
entorno.

Introduccin a Microsoft .NET

20

Leccin: Dentro de .NET

Introduccin

Runtime de lenguaje comn (Common Language Runtime)

La biblioteca de clases de .NET Framework

Espacios de nombres de ADO.NET

Espacios de nombres de ASP.NET

.NET Framework consta de los siguientes componentes:


Runtime de lenguaje comn (Common Language Runtime, CLR)
Biblioteca de clases de .NET Framework

Objetivos de la leccin

Al final de esta leccin, usted ser capaz de:


Comprender la funcin del CLR en el desarrollo y la simplificacin de
aplicaciones Web mediante .NET.
Identificar los espacios de nombres en la biblioteca de clases de .NET
Framework..

Introduccin a Microsoft .NET

21

Runtime de lenguaje comn (Common Language Runtime)

Soporte de biblioteca de clases de .NET Framework


Soporte de subprocesos

COM Marshaler

Corrector de tipos

Administrador de excepciones

Motor de seguridad

Motor de depuracin

MSIL para
compiladores
nativos

Gestor de cdigo

Recolector de
elementos no
utilizados

Cargador de clases

Introduccin

Los runtimes no son nada nuevo en programacin. Muchos otros lenguajes de


programacin han empleado runtimes, incluyendo Microsoft Visual Basic
(VBRUN hasta la versin 4.0 y MSVBVM hasta la versin 6.0), Visual C++
(MSVCRT), Visual FoxPro y JScript, adems de lenguajes de otras empresas
como SmallTalk, Perl y Java.
La funcin ms importante de .NET Framework, y lo que realmente lo
diferencia de otros runtimes, es que proporciona un entorno unificado para
todos los lenguajes de programacin. Este entorno se conoce tambin como
entorno gestionado.

CLR simplifica el
proceso de desarrollo

A pesar de su nombre, el CLR no slo acta en tiempo de ejecucin, sino


tambin durante el desarrollo de un componente. Mientras se ejecuta el
componente, el CLR es responsable de administrar la asignacin de memoria,
iniciar y terminar subprocesos y procesos, aplicar las directivas de seguridad y
satisfacer las dependencias del componente respecto a otros componentes.
La funcin del runtime cambia ligeramente durante el desarrollo. Debido a que
automatiza muchas funciones (como la administracin de memoria), el CLR
facilita el trabajo de los desarrolladores. En particular, el CLR garantiza la
correccin del cdigo y la seguridad de tipos. El CLR tambin reduce
drsticamente la cantidad de cdigo que tiene que escribir un desarrollador para
transformar lgica de empresa en un componente reutilizable.

Introduccin a Microsoft .NET

22

A continuacin se indican algunas de las funciones de programacin que hasta


ahora necesitaban los sistemas operativos pero que el CLR hace innecesarias:
No se necesita registrar el sistema, ya que las aplicaciones se describen por
s mismas.
No se necesitan identificadores nicos globales (GUID), ya que las clases se
organizan utilizando un sistema jerrquico con nombres que pueden leer las
personas.
No se necesitan archivos de lenguaje de definicin de interfaz (IDL), ya que
el sistema y los lenguajes utilizan las mismas representaciones.
No se utilizan HRESULTs, ya que el CLR utiliza control estructurado de
excepciones.
No se necesita IUnknown, ya que sus funciones las realiza el System.Object
raz.
No se necesita aadir y liberar referencias a objetos, ya que el CLR sabe qu
objetos se estn usando y si es necesario pueden limpiar los objetos no
utilizados.
El mtodo COM CoCreateInstance se convierte en un operador ms.

Introduccin a Microsoft .NET

23

La biblioteca de clases de .NET Framework

System

Collections

IO

Security

Runtime

Configuration

Net

ServiceProcess

InteropServices

Diagnostics

Reflection

Text

Remoting

Globalization

Resources

Threading

Serialization

Introduccin

La biblioteca de clases de .NET Framework es una coleccin de clases


reutilizables, o tipos, con un alto grado de integracin en el CLR. La biblioteca
contiene varios espacios de nombres. A modo de ejemplo examinaremos el
espacio de nombres System.

Espacio de nombres
System

El espacio de nombres System.IO se encuentra bajo el espacio de nombres


System y contiene servicios de entrada/salida (I/O). El espacio de nombres
System.Collections proporciona listas ordenadas, tablas hash y otros grupos de
datos. El espacio de nombres System.Net da soporte para TCP/IP y sockets.
La biblioteca de clases de .NET Framework se dise para:
Habilitar la factorizacin y extensibilidad.
Activar como base prcticas y estndares Web.
Unificar modelos de aplicaciones.
Aumentar la productividad de los desarrolladores ofreciendo un solo modelo
de programacin jerrquico e intuitivo.
Permitir la herencia y depuracin entre lenguajes.
Facilitar la adicin y modificacin de funciones de .NET Framework.
Permitir la creacin de aplicaciones seguras.

Funcionalidad

La biblioteca de clases de .NET Framework proporciona una gran cantidad de


funciones, incluyendo las siguientes:
Gestin de colecciones de objetos
Acceso a bases de datos
Salida a pantalla

Introduccin a Microsoft .NET

24

Seguridad y cifrado

Introduccin a Microsoft .NET

25

Leccin: Compilacin y ejecucin en .NET

El modelo de ejecucin CLR

Demostracin: Uso de MSIL Disassembler

Examen de cdigo: Programacin en .NET

Introduccin

Esta leccin describe los procesos de ejecucin y compilacin empleados en


.NET.

Objetivos de la leccin

Al final de esta leccin, usted ser capaz de:


Comprender el modelo de ejecucin CLR.
Definir un ensamblado y cmo se utiliza en .NET.
Comprender la compilacin y ejecucin de aplicaciones .NET.
Usar el MSIL Disassembler para ver un archivo porttil ejecutable.

Introduccin a Microsoft .NET

26

El modelo de ejecucin CLR

Introduccin

Esta leccin los procesos de ejecucin y compilacin empleados en .NET.

Ensambles y metadatos

La unidad bsica de una aplicacin basada en .NET recibe el nombre de


ensamblado. Un ensamblado es la unidad de versin e instalacin. En general,
el cdigo fuente se puede compilar en un archivo .exe o un DLL (tambin es
posible crear mdulos para vincularlos posteriormente a un archivo .exe o un
DLL), que son las formas ms sencillas de un ensamblado.
Los compiladores generan ensamblados que contienen lenguaje intermedio de
Microsoft (Microsoft Intermediate Language, MSIL). Pero adems del cdigo
MSIL, el compilador tambin inserta metadatos en el ensamblado. Un metadato
es una coleccin de informacin que describe todos los tipos, clases, mtodos,
campos y eventos contenidos en el ensamblado, de forma similar a una
biblioteca de tipos. Pero al contrario de un servidor COM, que puede o no
incluir una biblioteca de tipos, un ensamblado y sus metadatos son inseparables.
Esto significa que el ensamblado se describe por s mismo.

Ensamblados de un
archivo y multiarchivo

En muchos casos es posible considerar un ensamblado como un solo archivo


.exe o DLL. En algunas situaciones, un solo ensamblado puede hacer que la
instalacin sea mucho ms simple, ya que todos los componentes necesarios
estn juntos. Sin embargo, algunos ensamblados (por ejemplo, DLLs) se
pueden vincular en un ensamblado que recibe el nombre de ensamblado
multiarchivo.
Para ello se utiliza el vinculador de ensamblados, AL.exe. En algunos casos,
como en aplicaciones basadas en Web, el hecho de que los ensamblados estn
contenidos en archivos separados puede resultar muy ventajoso, porque es
posible descargar nicamente los mdulos que se necesitan.

Introduccin a Microsoft .NET

El modelo de ejecucin
CLR

27

Antes de ejecutar el cdigo MSIL, es preciso convertirlo en instrucciones


binarias nativas. La compilacin se realiza normalmente con un compilador
Just-in-Time (JIT).
El cdigo fuente escrito en C#, Visual Basic .NET u otro lenguaje apropiado
para el CLR se transforma primero en MSIL usando el compilador del lenguaje
correspondiente. Antes de la ejecucin, este cdigo MSIL se compila en cdigo
nativo con un compilador JIT para el procesador en que se vaya a ejecutar el
cdigo. El compilador JIT no compila todo el cdigo a la vez. La opcin por
defecto es hacer una compilacin JIT de cada mtodo la primera vez que se
invoca, pero tambin es posible hacer una compilacin JIT previa del cdigo
IL empleando Native Image Generator (NGEN.exe). Con esta opcin todos los
mtodos se compilan antes de que se cargue la aplicacin, lo que evita la
compilacin JIT cada vez que se invoca un mtodo por primera vez.
Hay que tener en cuenta que todos los lenguajes para el CLR deben tener unas
prestaciones similares. Aunque algunos compiladores pueden crear mejor
cdigo MSIL que otros, es poco probable que haya grandes diferencias en la
velocidad de ejecucin.

Herencia en C#

Contenido
Descripcin general
Derivacin de clases

1
3

Implementacin de mtodos

11

Uso de clases selladas

22

Uso de interfaces

24

Uso de clases abstractas

31

Herencia en C#

Notas para el instructor


Este mdulo proporciona a los estudiantes informacin detallada sobre la
herencia de clases en C# y explica cmo derivar nuevas clases a partir de otras
ya existentes. Tambin discute el uso de los tipos de mtodos virtual, override
y new. Explica brevemente las clases selladas y describe conceptos de
interfaces. Los estudiantes aprendern a declarar una interfaz y a implementar
los dos tipos de mtodos de interfaz. Finalmente, el mtodo discute las clases
abstractas y explica cmo implementar mtodos y clases abstractas en una
jerarqua de clases.
Al final de este mdulo, los estudiantes sern capaces de:
Derivar una clase nueva a partir de una clase base y hacer llamadas a
miembros y constructores de la clase base desde la clase derivada.
Declarar mtodos como virtuales y sustituirlos (override) u ocultarlos,
segn las necesidades.
Sellar una clase para que de ella no pueda derivar ninguna otra.
Implementar interfaces de forma implcita y explcita.
Describir el uso de clases abstractas y su implementacin de interfaces.

Herencia en C#

Descripcin general
Objetivo del tema

Ofrecer una introduccin a


los contenidos y objetivos
del mdulo.

Explicacin previa

En este mdulo
estudiaremos la herencia de
clases en C#.

Derivacin de clases

Implementacin de mtodos

Uso de clases selladas

Uso de interfaces

Uso de clases abstractas

En un sistema orientado a objetos, la herencia es la capacidad de un objeto de


heredar datos y funcionalidad de su objeto padre. De esta forma, el objeto padre
puede ser sustituido por un objeto hijo. La herencia tambin permite crear
nuevas clases a partir de otras ya existentes, en lugar de crearlas partiendo de
cero, y aadir luego el cdigo que sea necesario para la nueva clase. La clase
padre en la que est basada la nueva clase se llama clase base, mientras que la
clase hija se conoce como clase derivada.
Cuando se crea una clase derivada hay que tener en cuenta que puede sustituir
al tipo de clase base. Esto significa que la herencia no slo es un mecanismo
para la reutilizacin de cdigo, sino tambin un mecanismo de clasificacin de
tipos. Este ltimo aspecto es ms importante que el primero.
En este mdulo aprenderemos a derivar una clase de una clase base. Tambin
veremos cmo implementar mtodos en una clase derivada, definindolos como
mtodos virtuales en la clase base y sustituyndolos u ocultndolos, segn el
caso, en la clase derivada. Aprenderemos a sellar una clase para que no pueda
derivar de ella ninguna otra. Finalmente, estudiaremos cmo implementar
interfaces y clases abstractas, que definen las condiciones de un contrato al que
estn sujetas las clases derivadas.
Al final de este mdulo, usted ser capaz de:
Derivar una clase nueva a partir de una clase base y hacer llamadas a
miembros y constructores de la clase base desde la clase derivada.
Declarar mtodos como virtuales y sustituirlos (override) u ocultarlos,
segn las necesidades.
Sellar una clase para que de ella no pueda derivar ninguna otra.
Implementar interfaces de forma implcita y explcita.

Herencia en C#

Describir el uso de clases abstractas y su implementacin de interfaces.

Herencia en C#

Derivacin de clases
Objetivo del tema

Ofrecer una introduccin a


los temas tratados en esta
seccin.

Explicacin previa

En esta seccin
discutiremos cmo derivar
una clase de una clase
base.

Extensin de clases base

Acceso a miembros de la clase base

Llamadas a constructores de la clase base

Slo es posible derivar una clase a partir de una clase base si sta ha sido
diseada para permitir la herencia. Esto se debe a que los objetos deben tener la
estructura adecuada, ya que de lo contrario la herencia no resultar eficaz. Este
hecho tiene que quedar claro en una clase base que est diseada para herencia.
Si se deriva una nueva clase de una clase base que no est bien diseada,
cualquier cambio futuro en la clase base podra hacer que la clase derivada
fuese inutilizable.
Al final de esta leccin, usted ser capaz de:
Derivar una clase nueva a partir de una clase base.
Acceder a los miembros y constructores de la clase base desde la clase
derivada.

Herencia en C#

Extensin de clases base


Objetivo del tema

Explicar el procedimiento
para extender una clase
base.

Explicacin previa

Es fcil entender la sintaxis


de C# para derivar una
clase de otra.

Sintaxis para derivar una clase desde una clase base

class
class Token
Token
Clase
Clase
{{
Clasederivada
derivada
Clasebase
base
...
...
}}
class
class ComentToken:
ComentToken: Token
Token
{{
22puntos
...
puntos
...
}}

Token
Token
concrete
concrete

ComentToken
ComentToken
concrete
concrete

Una clase derivada hereda la mayor parte de los


elementos de su clase base

Una clase derivada no puede ser ms accesible que su


clase base

La derivacin de una clase desde una clase base se conoce tambin como
extensin de la clase base. Una clase C# se puede extender como mximo una
clase.

Sintaxis para la derivacin de una clase


Para indicar que una clase deriva de otra se emplea la siguiente sintaxis:
class Derived: Base
{
...
}

Los elementos de esta sintaxis se indican en la transparencia. Cuando se declara


una clase derivada, la clase base se especifica despus de dos puntos. Los
blancos antes y despus de los dos puntos no tienen importancia. El estilo
recomendado para esta sintaxis es no poner espacios antes de los dos puntos y
poner un espacio despus de ellos.

Herencia de la clase derivada


Una clase derivada hereda todo de su clase base, salvo los constructores y
destructores. Los miembros pblicos de la clase base se convierten
implcitamente en miembros pblicos de la clase derivada. Slo los miembros
de la clase base tienen acceso a los miembros privados de esta clase, aunque la
clase derivada tambin los hereda.

Herencia en C#

Accesibilidad de una clase derivada


Una clase derivada no puede ser ms accesible que su clase base. Por ejemplo,
no es posible derivar una clase pblica de una clase privada, como se ve en el
siguiente cdigo:
class Example
{
private class NestedBase { }
public class NestedDerived: NestedBase { } // Error
}

La sintaxis de C# para derivar una clase de otra tambin est permitida en C++,
donde indica implcitamente una relacin de herencia privada a entre la clase
base y la derivada. C# no incluye herencia privada; toda la herencia es pblica.

Herencia en C#

Acceso a miembros de la clase base


Objetivo del tema

Explicar la herencia con


proteccin.

Explicacin previa

Al igual que otros lenguajes


de programacin orientados
a objetos, C# tiene
modificador de acceso
protected (protegido),
adems de public y
private.

class
class Token
Token
{{ ...
class
...
class Outside
Outside
protected
string
name;
{
protected string name; {
}}
void
void Fails(Token
Fails(Token t)
t)
class
ComentToken:
Token
{
class ComentToken: Token
{
{{ ...
...
...
...
public
string
Name(
)
t.name
public string Name( )
t.name
{{
...
...
return
name;
}
return name;
}
}}
}}
}}

Los miembros heredados con proteccin estn implcitamente


protegidos en la clase derivada

Los miembros de una clase derivada slo pueden acceder a sus


miembros heredados con proteccin

En una struct no se usa el modificador de acceso protected

El significado del modificador de acceso protected depende de la relacin entre


la clase que tiene el modificador y la clase que intenta acceder a los miembros
que usan el modificador.
Los miembros de una clase derivada pueden acceder a todos los miembros
protegidos de su clase base. Para una clase derivada, la palabra reservada
protected es equivalente a la palabra public. En el fragmento de cdigo de la
transparencia, el mtodo Name de ComentToken puede acceder a la cadena
nombre, que est protegida dentro de Token, porque Token es la clase base de
ComentToken.
Entre dos clases que no tengan una relacin base-derivada, por el contrario, los
miembros protegidos de una clase se comportan como miembros privados para
la otra clase. En el otro fragmento de cdigo de la transparencia, el mtodo
Fails de Outside no puede acceder a la cadena nombre, que est protegida
dentro de Token, porque Token no est especificada como clase base de
Outside.

Herencia en C#

Miembros heredados con proteccin


Cuando una clase derivada hereda un miembro con proteccin, ese miembro
tambin es implcitamente un miembro protegido de la clase derivada. Esto
significa que todas clases que deriven directa o indirectamente de la clase base
pueden acceder a los miembros protegidos, como se muestra en el siguiente
ejemplo:
class Base
{
protected string name;
}
class Derived: Base
{
}
class FurtherDerived: Derived
{
void Compiles( )
{
Console.WriteLine(name); // Okay
}
}

Miembros protegidos y mtodos


Los mtodos de una clase derivada slo tienen acceso a sus propios miembros
heredados con proteccin. No pueden acceder a los miembros protegidos de la
clase base a travs de referencias a sta. Por ejemplo, el siguiente cdigo
generar un error:
class ComentToken: Token
{
void Fails (Token t)
{
Console.WriteLine(t.name); // Error al compilar
}
}

Consejo Muchas guas de programacin recomiendan mantener todos los


datos privados y usar acceso protegido slo para mtodos.

Miembros protegidos y structs


Una struct no permite la herencia. Como consecuencia no se puede derivar de
una struct y, por lo tanto, no es posible usar el modificador de acceso
protected en una struct. Por ejemplo, el siguiente cdigo generar un error:
struct Base
{
protected string name; // Error al compilar
}

Herencia en C#

Llamadas a constructores de la clase base


Objetivo del tema

Explicar cmo hacer


llamadas a los constructores
de la clase base.

Explicacin previa

C# tiene una palabra


reservada para llamar a un
constructor de la clase
base.

Las declaraciones de constructores deben usar la palabra base

class
class Token
Token
{{
protected
protected Token(string
Token(string name)
name) {{ ...
... }}
...
...
}}
class
class ComentToken:
ComentToken: Token
Token
{{
public
public ComentToken(string
ComentToken(string name)
name) :: base(name)
base(name) {{ }}
...
...
}}

Una clase derivada no puede acceder a un constructor privado de


la clase base

Se usa la palabra base para habilitar el mbito del identificador

Para hacer una llamada a un constructor de la clase base desde un constructor


de la clase derivada se usa la palabra reservada base, que tiene la siguiente
sintaxis:
C(...): base( ) {...}

El conjunto formado por los dos puntos y la llamada al constructor de la clase


base recibe el nombre de inicializador del constructor.

Declaraciones de constructores
Si la clase derivada no hace una llamada explcita a un constructor de la clase
base, el compilador de C# usar implcitamente un inicializador de constructor
de la forma :base( ). Esto implica que una declaracin de constructor de la
forma
C(...) {...}

es equivalente a
C(...): base( ) {...}

Este comportamiento implcito es vlido en muchos casos porque:


Una clase sin clases base explcitas extiende implcitamente la clase
System.Object, que contiene un constructor pblico sin parmetros.
Si una clase no contiene ningn constructor, el compilador utilizar
inmediatamente un constructor pblico sin parmetros llamado constructor
por defecto.

Herencia en C#

El compilador no crear un constructor por defecto si una clase tiene su propio


constructor explcito. No obstante, el compilador generar un mensaje de error
si el constructor indicado no coincide con ningn constructor de la clase base,
como se ve en el siguiente cdigo:
class Token
{
protected Token(string name) { ... }
}
class ComentToken: Token
{
public ComentToken(string name) { ... } // Error aqu
}

El error se debe a que el constructor ComentToken contiene de forma implcita


un inicializador de constructor :base( ), pero la clase base Token no contiene
ningn constructor sin parmetros. El cdigo mostrado en la transparencia
permite corregir este error.

Reglas de acceso a constructores


Las reglas de acceso de un constructor derivado a un constructor de la clase
base son exactamente las mismas que para los mtodos normales. Por ejemplo,
si el constructor de la clase base es privado, la clase derivada no tendr acceso a
l:
class NoDerivable
{
private NoDerivable( ) { ... }
}
class Imposible: NoDerivable
{
public Impossible( ) { ... } // Error al compilar
}

En este caso, es imposible que una clase derivada pueda hacer una llamada al
constructor de la clase base.

Herencia en C#

10

mbito de un identificador
Tambin es posible utilizar la palabra reservada base para habilitar el mbito de
un identificador. Esto puede resultar til, puesto que una clase derivada puede
declarar miembros con los mismos nombres que miembros de la clase base. El
siguiente cdigo muestra un ejemplo:
class Token
{
protected string name;
}
class ComentToken: Token
{
public void Method(string name)
{
base. name = name;
}
}

Nota Al contrario de lo que ocurre en C++, no se utiliza el nombre de la clase


base (como Token en el ejemplo de la transparencia). La palabra reservada
base hace referencia claramente a la clase base porque, en C#, una clase puede
extender como mximo una clase.

Herencia en C#

11

Implementacin de mtodos
Objetivo del tema

Ofrecer una introduccin a


los temas tratados en esta
seccin.

Explicacin previa

En esta leccin veremos


cmo implementar mtodos
en clases derivadas.

Definicin de mtodos virtuales

Uso de mtodos virtuales

Sustitucin de mtodos (override)

Uso de mtodos override

Uso de new para ocultar mtodos

Uso de la palabra reservada new

Los mtodos de una clase base se pueden redefinir en una clase derivada si han
sido diseados para permitir la sustitucin (override).
Al final de esta leccin, usted ser capaz de:
Usar el tipo de mtodo virtual.
Usar el tipo de mtodo override.
Usar el tipo de mtodo hide.

Herencia en C#

12

Definicin de mtodos virtuales


Objetivo del tema

Explicar cmo implementar


mtodos virtuales.

Explicacin previa

Los mtodos virtuales se


pueden emplear para hacer
que las clases sean
polimrficas.

Sintaxis: Se declara como virtual

class
class Token
Token
{{
...
...
public
public int
int LineNumber(
LineNumber( ))
{{ ...
...
}}
public
public virtual
virtual string
string Name(
Name( ))
{{ ...
...
}}
}}

Los mtodos virtuales son polimrficos

Un mtodo virtual especifica una implementacin de un mtodo que puede ser


sustituida por polimorfismo en una clase derivada. Del mismo modo, un
mtodo no virtual especifica la nica implementacin de un mtodo. No es
posible sustituir por polimorfismo un mtodo no virtual en una clase derivada.
Nota En C#, el hecho de que una clase contenga o no un mtodo virtual es una
buena indicacin de si el autor la ha diseado para que sea utilizada como clase
base.

Sintaxis de la palabra reservada


Para declarar un mtodo virtual se usa la palabra clave virtual, cuya sintaxis se
muestra en la transparencia.
Recomendacin al
profesor

El ejercicio de la prctica
combinar el contenido de
los tres temas sobre las
palabras reservadas virtual,
override y new.

Un mtodo virtual debe contener un cuerpo cuando se declara. De lo contrario,


el compilador generar un error:
class Token
{
public virtual string Name( ); // Error al compilar
}

Herencia en C#

13

Uso de mtodos virtuales


Objetivo del tema

Describir las restricciones


de los mtodos virtuales.

Explicacin previa

Vamos a estudiar con ms


detalle los mtodos
virtuales.

Para usar mtodos virtuales:


z

No se puede declarar mtodos virtuales como estticos

No se puede declarar mtodos virtuales como privados

Para usar eficazmente los mtodos virtuales hay que tener en cuenta lo
siguiente:
No se puede declarar mtodos virtuales como estticos.
Los mtodos virtuales no pueden ser estticos porque en ese caso seran
mtodos de clase y el polimorfismo se aplica a objetos, no a clases.
No se puede declarar mtodos virtuales como privados.
Los mtodos virtuales no pueden ser privados porque en ese caso no podran
ser sustituidos por polimorfismo en una clase derivada. A continuacin se
muestra un ejemplo:
class Token
{
private virtual string Name( ) { ... }
// Error al compilar
}

Herencia en C#

14

Sustitucin de mtodos (override)


Objetivo del tema

Explicar cmo sustituir


mtodos.

Explicacin previa

Se pueden sustituir los


mtodos que estn
declarados como virtuales
en la clase base.

Sintaxis: Se usa la palabra reservada override

class
class Token
Token
{{ ...
...
public
public virtual
virtual string
string Name(
Name( )) {{ ...
... }}
}}
class
class ComentToken:
ComentToken: Token
Token
{{ ...
...
public
public override
override string
string Name(
Name( )) {{ ...
... }}
}}

Un mtodo override especifica otra implementacin de un mtodo virtual. Los


mtodos virtuales definidos en una clase base pueden ser sustituidos por
polimorfismo en una clase derivada.

Sintaxis de la palabra reservada


Para declarar un mtodo override se usa la palabra clave override, como se ve
en el siguiente cdigo:
class Token
{
...
public virtual string Name( ) { ... }
}
class ComentToken: Token
{
...
public override string Name( ) { ... }
}

Como ocurre con los mtodos virtuales, un mtodo override debe contener un
cuerpo cuando se declara, ya que de lo contrario el compilador genera un error:
class Token
{
public virtual string Name( ) { ... }
}
class ComentToken: Token
{
public override string Nombre( ); // Error al compilar
}

Herencia en C#

15

Uso de mtodos override


Objetivo del tema

Describir las restricciones


de los mtodos override.

Explicacin previa

El uso de los mtodos


override si rige por ciertas
reglas.

Slo se sustituyen mtodos virtuales heredados idnticos

class
class Token
Token
{{ ...
...
public
public int
int LineNumber(
LineNumber( )) {{ ...
... }}
public
public virtual
virtual string
string Name(
Name( )) {{ ...
... }}
}}
class
class ComentToken:
ComentToken: Token
Token
{{ ...
...
public
public override
override int
int LineNumber(
LineNumber( )) {{ ...
... }}
public
public override
override string
string Name(
Name( )) {{ ...
... }}
}}

8
9

Un mtodo override debe coincidir con su mtodo virtual


asociado

Se puede sustituir un mtodo override

No se puede declarar explcitamente un override como virtual

No se puede declarar un mtodo override como static o private

Para usar eficazmente los mtodos override hay que tener en cuenta las
siguientes restricciones importantes:
Slo se pueden sustituir mtodos virtuales heredados idnticos.
Un mtodo override debe coincidir con su mtodo virtual asociado.
Se puede sustituir un mtodo override.
No se puede declarar explcitamente un mtodo override como virtual.
No se puede declarar un mtodo override como static o private.
A continuacin se describe con ms detalle cada una de estas restricciones.

Slo se pueden sustituir mtodos virtuales heredados


idnticos
Un mtodo override se puede emplear para sustituir nicamente un mtodo
virtual heredado idntico. En el cdigo de la transparencia, el mtodo
LineNumber en la clase derivada ComentToken causa un error de
compilacin porque el mtodo heredado Token.LineNumber no est marcado
como virtual.

Herencia en C#

Recomendacin al
profesor

Las palabras aqu


empleadas han sido
elegidas cuidadosamente:
Un mtodo override debe
sustituir a un mtodo virtual
heredado idntico.

16

Un mtodo override debe coincidir con su mtodo virtual


asociado
Una declaracin de override debe ser en todo punto idntica al mtodo virtual al
que sustituye. Deben tener el mismo nivel de acceso, el mismo tipo de retorno,
el mismo nombre y los mismos parmetros.
Por ejemplo, en el siguiente ejemplo la sustitucin falla porque los niveles de
acceso son diferentes (protected frente a public), los tipos de retorno cambian
(string frente a void) y los parmetros son distintos (none frente a int):
class Token
{
protected virtual string Name( ) { ... }
}
class ComentToken: Token
{
public override void Name(int i) { ... } // Errores
}

Se puede sustituir un mtodo override


Un mtodo override es virtual de forma implcita y por tanto se puede sustituir,
como se ve en el siguiente ejemplo:
class Token
{
public virtual string Name( ) { ... }
}
class ComentToken: Token
{
public override string Name( ) { ... }
}
class OneLineCommentToken: ComentToken
{
public override string Name( ) { ... }
}

// Okay

Herencia en C#

17

No se puede declarar explcitamente un mtodo override


como virtual
Un mtodo override es virtual de forma implcita, pero no puede estar declarado
explcitamente como virtual, como se ve en el siguiente ejemplo:
class Token
{
public virtual string Name( ) { ... }
}
class ComentToken: Token
{
public virtual override string Name( ) { ... } // Error
}

No se puede declarar un mtodo override como static o


private
Un mtodo override nunca puede estar declarado como static porque en ese
caso sera un mtodo de clase y el polimorfismo se aplica a objetos, no a clases.
Del mismo modo, un mtodo override nunca puede ser private, ya que debe
sustituir a un mtodo virtual y ste no puede ser privado.

Herencia en C#

18

Uso de new para ocultar mtodos


Objetivo del tema

Explicar cmo ocultar


mtodos heredados.

Explicacin previa

Si se declara un mtodo
que tiene la misma
signatura que un mtodo de
una clase base, es posible
ocultar el mtodo base sin
utilizar override.

Sintaxis: Para ocultar un mtodo se usa la palabra


reservada new

class
class Token
Token
{{ ...
...
public
public int
int LineNumber(
LineNumber( )) {{ ...
... }}
}}
class
class ComentToken:
ComentToken: Token
Token
{{ ...
...
new
new public
public int
int LineNumber(
LineNumber( )) {{ ...
... }}
}}

Es posible ocultar un mtodo heredado idntico introduciendo un nuevo mtodo


en la jerarqua de clases. De esta forma, el mtodo original heredado por la
clase derivada desde la clase base es sustituido por un mtodo totalmente
distinto.

Sintaxis de la palabra reservada


La palabra reservada new se emplea para ocultar un mtodo y tiene la siguiente
sintaxis:
class Token
{
...
public int LineNumber( )

{ ... }

}
class ComentToken: Token
{
...
new public int LineNumber( ) { ... }
}

Herencia en C#

19

Uso de la palabra reservada new


Objetivo del tema

Explicar cmo usar la


palabra reservada new para
ocultar mtodos de forma
eficaz.

Explicacin previa

Para hacer un buen uso de


la palabra reservada new
hay que tener en cuenta sus
caractersticas y las
restricciones que impone.

Ocultar tanto mtodos virtuales como no virtuales

class
class Token
Token
{{ ...
...
public
public int
int LineNumber(
LineNumber( )) {{ ...
... }}
public
public virtual
virtual string
string Name(
Name( )) {{ ...
... }}
}}
class
class ComentToken:
ComentToken: Token
Token
{{ ...
...
new
new public
public int
int LineNumber(
LineNumber( )) {{ ...
... }}
public
public override
override string
string Name(
Name( )) {{ ...
... }}
}}

Resolver conflictos de nombre en el cdigo

Ocultar mtodos que tengan signaturas idnticas

El uso de la palabra reservada new permite:


Ocultar tanto mtodos virtuales como no virtuales.
Resolver conflictos de nombre en el cdigo.
Ocultar mtodos que tengan signaturas idnticas.
A continuacin se describe con ms detalle cada una de estas tareas.

Herencia en C#

20

Ocultar tanto mtodos virtuales como no virtuales


Emplear la palabra reservada new para ocultar un mtodo tiene implicaciones si
se hace uso del polimorfismo. En el cdigo de la transparencia, por ejemplo,
ComentToken.NumeroLinea es un mtodo new que no tiene ninguna relacin
con el mtodo Token. LineNumber. Aunque Token. LineNumber fuera un
mtodo virtual, ComentToken. LineNumber seguira siendo un mtodo new
sin ninguna relacin.
En este ejemplo, ComentToken. LineNumber no es virtual. Esto significa que
otra clase derivada no puede sustituir ComentToken. LineNumber. Sin
embargo, el mtodo new ComentToken. LineNumber se podra declarar
como virtual, en cuyo caso otras clases derivadas podran sustituirlo, como se
ve:
Recomendacin al
profesor

En gran parte, el punto ms


importante de este tema es
el consejo, que hace
hincapi en el significado
ortogonal del new.
Este tema incluye muchos
otros detalles, aunque no es
necesario discutir todos
ellos en la clase.

class ComentToken: Token


{
...
new public virtual int LineNumber ( ) { ... }
}
class OneLineCommentToken: ComentToken
{
public override int LineNumber ( ) { ... }
}

Consejo El estilo recomendado para mtodos virtuales con new es


new public virtual int LineNumber ( ) { ... }

mejor que
public new virtual int LineNumber ( ) { ... }

Resolver conflictos de nombre en el cdigo


Los conflictos de nombre suelen generar avisos durante la compilacin.
Consideremos por ejemplo el siguiente cdigo:
class Token
{
public virtual int LineNumber ( ) { ... }
}
class ComentToken: Token
{
public int LineNumber( ) { ... }
}

Al compilar, se recibe un aviso que indica que ComentToken. LineNumber


oculta Token. LineNumber. Este aviso revela el conflicto de nombres. Se
puede elegir entre tres opciones:
1. Aadir un calificador override a ComentToken. LineNumber.
2. Aadir un calificador new a ComentToken. LineNumber. En este caso, el
mtodo contina ocultando el mtodo idntico en la clase base, pero el new
explcito comunica al compilador y al personal de mantenimiento del cdigo
que el conflicto de nombres es intencionado.
3. Cambiar el nombre del mtodo.

Herencia en C#

21

Ocultar mtodos que tengan signaturas idnticas


El modificador new slo es necesario si un mtodo de una clase derivada oculta
un mtodo visible de la clase base que tiene una signatura idntica. En el
siguiente ejemplo, el compilador avisa de que new no es necesario porque los
mtodos reciben parmetros diferentes y por tanto sus signaturas no son
idnticas:
class Token
{
public int LineNumber(short s) { ... }
}
class ComentToken: Token
{
new public int LineNumber(int i) { ... } // Warning
}

Del mismo modo, si dos mtodos tienen signaturas idnticas el compilador


avisar sobre la posibilidad de usar new porque el mtodo de la clase base est
oculto. En el siguiente ejemplo, los dos mtodos tienen signaturas idnticas
porque los tipos de retorno no forman parte de la signatura de un mtodo:
class Token
{
public virtual int LineNumber( ) { ... }
}
class ComentToken: Token
{
public void LineNumber( ) { ... } // Warning
}

Nota La palabra reservada new se puede emplear tambin para ocultar campos
y clases anidadas.

Herencia en C#

22

Uso de clases selladas


Objetivo del tema

Explicar cmo prevenir la


herencia accidental.

Ninguna clase puede derivar de una clase sellada

Las clases selladas sirven para optimizar operaciones


en tiempo de ejecucin

Muchas clases de .NET Framework son selladas: String,


StringBuilder, etc.

Sintaxis: Se usa la palabra reservada sealed

Explicacin previa

No siempre es conveniente
permitir que una clase sea
heredada por otra.

namespace
namespace System
System
{{
public
public sealed
sealed class
class String
String
{{
...
...
}}
}}
namespace
namespace Mine
Mine
{{
class
class FancyString:
FancyString: String
String {{ ...
... }}
}}

No es fcil crear una jerarqua de herencia flexible. La mayor parte de las clases
son autnomas y no estn diseadas para que otras clases deriven de ellas. En
trminos de sintaxis, sin embargo, el procedimiento para la derivacin de una
clase es muy sencillo y se puede escribir en muy poco tiempo. Esto hace que los
programadores puedan caer a veces en la tentacin de derivar desde una clase
que no est pensada para funcionar como clase base.
Para prevenir este problema, y para que el programador pueda comunicar mejor
sus intenciones al compilador y a otros programadores, C# permite declarar una
clase como sealed (sellada). La derivacin de una clase sellada no est
permitida.

Herencia en C#

23

Sintaxis de la palabra reservada


Para sellar una clase se utiliza la palabra reservada sealed, cuya sintaxis es la
siguiente:
namespace System
{
public sealed class String
{
...
}
}

Microsoft .NET Framework contiene muchos ejemplos de clases selladas. La


transparencia muestra la clase System.String, cuyo alias es la palabra reservada
string. Esta clase est sellada y, por tanto, ninguna otra clase puede derivar de
ella.

Optimizacin de operaciones en tiempo de ejecucin


El modificador sealed permite hacer ciertas optimizaciones en tiempo de
ejecucin. En particular, el hecho de que una clase sellada nunca tenga clases
derivadas hace posible transformar llamadas a miembros virtuales de clases
selladas en llamadas a miembros no virtuales.

Herencia en C#

24

Uso de interfaces
Objetivo del tema

Ofrecer una introduccin a


los temas tratados en esta
seccin.

Explicacin previa

En esta leccin
aprenderemos el
procedimiento para definir y
usar interfaces en C#.

Declaracin de interfaces

Implementacin de varias interfaces

Implementacin de mtodos de interfaz

Una interfaz especifica un contrato sintctico y semntico al que estn sujetas


todas las clases derivadas. Ms concretamente, en ese contrato la interfaz
describe el qu, mientras que las clases que implementan la interfaz describen el
cmo.
Al final de esta leccin, usted ser capaz de:
Usar la sintaxis para declarar interfaces.
Usar las dos tcnicas de implementacin de mtodos de interfaz en clases
derivadas.

Herencia en C#

25

Declaracin de interfaces
Objetivo del tema

Explicar cmo declarar


interfaces.

Explicacin previa

Las interfaces son similares


a las clases.

Sintaxis: Para declarar mtodos se usa la palabra


reservada interface

Los
Losnombres
nombresde
deinterfaces
interfaces
empiezan
empiezancon
conImayscula
Imayscula

interface
interface IToken
IToken
{{
int
int LineNumber(
LineNumber( );
);
string
string Name(
Name( );
);
}}
Sin
Sinespec.
espec.de
deacceso
acceso

Para su informacin

No est permitido declarar


tipos (como enums) dentro
de una interfaz.

IToken
IToken
interface
interface
LineNumber(
LineNumber( ))
Name(
Name( ))

Mtodos
Mtodossin
sincuerpo
cuerpo

Una interfaz en C# se parece a una clase que no tiene cdigo y se declara de


forma similar, pero se usa la palabra reservada interface en vez de class. La
sintaxis de esta palabra reservada est explicada en la transparencia.
Nota Se recomienda que todos los nombres de interfaces comiencen con una
"I" mayscula. Por ejemplo, IToken es mejor que Token.

Caractersticas de las interfaces


Las interfaces tienen las dos siguientes caractersticas importantes.

Los mtodos de interfaz son implcitamente pblicos


Los mtodos que se declaran en una interfaz son pblicos de forma implcita.
Como consecuencia no se permite el uso de modificadores de acceso public
explcitos, como se ve en el siguiente ejemplo:
interface IToken
{
public int LineNumber ( ); // Error al compilar
}

Herencia en C#

26

Los mtodos de interfaz no contienen cuerpo


Los mtodos que se declaran en una interfaz no pueden contener cuerpo. Por
ejemplo, el siguiente cdigo no estara permitido:
interface IToken
{
int LineNumber ( ) { ... } // Error al compilar
}

Estrictamente hablando, las interfaces pueden contener declaraciones de


propiedades de interfaz (que son declaraciones de propiedades sin cuerpo),
declaraciones de eventos de interfaz (que son declaraciones de eventos sin
cuerpo) y declaraciones de indizadores de interfaz (que son declaraciones de
indizadores sin cuerpo).

Herencia en C#

27

Implementacin de varias interfaces


Objetivo del tema

Explicar cmo se puede


heredar de varias interfaces.

Explicacin previa

Una clase implementa una


interfaz.

Una clase puede implementar cero o ms interfaces

interface
interface IToken
IToken
{{
IToken
IVisitable
IVisitable
IToken
string
string Name(
Name( );
);
interface

interface
interface
interface
}}
interface
interface IVisitable
IVisitable
{{
void
void Accept(IVisitante
Accept(IVisitante v);
v);
}}
Token
class
Token
class Token:
Token: IToken,
IToken, IVisitable
IVisitable
{{ ...
concrete
...
concrete
}}

Una interfaz puede extender cero o ms interfaces

Una clase puede ser ms accesible que sus interfaces base

Una interfaz no puede ser ms accesible que su interfaz base

Una clase implementa todos los mtodos de interfaz heredados

Aunque C# permite nicamente la herencia sencilla, es posible implementar


varias interfaces en una sola clase. Este tema discute las diferencias entre una
clase y una interfaz con respecto a la implementacin y extensin de interfaces,
respectivamente, adems de su accesibilidad en comparacin con sus interfaces
base.

Implementacin de interfaces
Una clase puede implementar cero o ms interfaces, pero no puede extender
ms de una clase de forma explcita. La transparencia muestra un ejemplo de
este punto.
Nota Estrictamente hablando, una clase extiende siempre una clase. Si no se
especifica la clase base, una clase heredar de object implcitamente.

Herencia en C#

Recomendacin al
profesor

28

Por el contrario, una interfaz puede extender cero o ms interfaces. Por ejemplo,
el cdigo de la transparencia se podra reescribir de la siguiente manera:

Asegrese de que los


delegados usan la
terminologa correcta. Una
clase extiende otra clase e
implementa una interfaz.

interface IToken { ... }


interface IVisitable { ... }
interface IVisitableToken: IVisitable, IToken { ... }
class Token: IVisitableToken { ... }

En la transparencia se han
dejado intencionadamente
en blanco los mtodos de
Token. Las dos formas de
implementar una interfaz se
discutirn en las dos
transparencias siguientes.

Accesibilidad

Un aspecto importante en
este tema es que una clase
debe implementar todos los
mtodos de interfaz
heredados.
Probablemente tambin sea
conveniente mencionar que
una interfaz puede heredar
de otras interfaces. D un
ejemplo.

Una clase puede ser ms accesible que sus interfaces base. Por ejemplo, es
posible declarar una clase pblica que implemente una interfaz privada, como
se ve:
class Example
{
private interface INested { }
public class Anidada: INested { } // Okay
}

Sin embargo, una interfaz no puede ser ms accesible que sus interfaces base.
Es un error declarar una interfaz pblica que extiende una interfaz privada,
como se muestra en el siguiente ejemplo:
class Example
{
private interface INested { }
public interface IAlsoNested: INested { }
// Error al compilar
}

Mtodos de interfaz
Una clase debe implementar todos los mtodos de todas las interfaces que
extienda, independientemente de que las interfaces se hereden directa o
indirectamente.

Herencia en C#

29

Implementacin de mtodos de interfaz


Objetivo del tema

Discutir la implementacin
de interfaces.

Explicacin previa

Hay una serie de reglas que


se deben cumplir cuando se
implementa una interfaz en
una clase.

El mtodo que implementa debe ser igual que el mtodo


de interfaz

El mtodo que implementa puede ser virtual o no virtual

class
class Token:
Token: IToken,
IToken, IVisitable
IVisitable
{{
public
public virtual
virtual string
string Name(
Name( ))
{{ ...
...
}}
public
public void
void Accept(IVisitante
Accept(IVisitante v)
v)
{{ ...
...
}}
}}

Mismo
Mismoacceso
acceso
Mismo
Mismoretorno
retorno
Mismo
Mismonombre
nombre
Mismos
metros
par
Mismospar
parmetros

Si una clase implementa una interfaz, tiene que implementar todos los mtodos
declarados en esa interfaz. Este requisito es muy conveniente, ya que las
interfaces no pueden definir los cuerpos de sus propios mtodos.
El mtodo que la clase implementa debe ser absolutamente idntico al mtodo
de la interfaz. Tiene que ser igual en:
Acceso
Un mtodo de interfaz es pblico de forma implcita, lo que significa que el
mtodo que lo implementa debe estar declarado explcitamente como
pblico. Si se omitiera el modificador de acceso, el mtodo sera privado
por defecto.
Tipo de retorno
Si el tipo de retorno en la interfaz est declarado como T, el tipo de retorno
en la clase que la implementa no puede estar declarado como un tipo
derivado de T, sino que debe ser T. En otras palabras, C# no permite la
covarianza de tipos de retorno.
Nombre
No hay que olvidar que C# distingue maysculas y minsculas en los
nombres.
Lista de parmetros

Herencia en C#

30

El siguiente cdigo cumple todos estos requisitos:


interface IToken
{
string Name( );
}
interface IVisitable
{
void Accept(IVisitante v);
}
class Token: IToken, IVisitable
{
public virtual string Name( )
{ ...
}
public void Accept(IVisitante v)
{ ...
}
}

El mtodo que implementa puede ser virtual, como Name en el cdigo anterior.
En ese caso, es posible sustituir el mtodo en otras clases derivadas. Por otro
lado, el mtodo que implementa tambin puede ser no virtual, como Accept en
el mismo cdigo. En este ltimo caso, no es posible sustituir el mtodo en otras
clases derivadas.

Herencia en C#

31

Uso de clases abstractas


Objetivo del tema

Ofrecer una introduccin a


los temas tratados en esta
seccin.

Explicacin previa

En esta leccin
aprenderemos a usar clases
abstractas.

Declaracin de clases abstractas

Uso de clases abstractas en una jerarqua de clases

Comparacin de clases abstractas e interfaces

Implementacin de mtodos abstractos

Uso de mtodos abstractos

Las clases abstractas se emplean para proporcionar implementaciones parciales


de clases que se completan con clases derivadas concretas. Las clases abstractas
son especialmente tiles para la implementacin parcial de una interfaz que
puede ser reutilizada por varias clases derivadas.
Al final de esta leccin, usted ser capaz de:
Usar la sintaxis para la declaracin de una clase abstracta.
Explicar el uso de clases abstractas en una jerarqua de clases.

Herencia en C#

32

Declaracin de clases abstractas


Objetivo del tema

Describir la sintaxis para


declarar una clase
abstracta.

Explicacin previa

Una clase abstracta es una


clase de la que no se
pueden crear instancias.

Se usa la palabra reservada abstract

abstract
abstract class
class Token
Token
{{
...
...
}}
class
class Test
Test
{{
static
static void
void Main(
Main( ))
{{
new
new Token(
Token( );
);
}}
}}

Token
Token
{{ abstract
abstract }}
No
Nose
sepueden
puedencrear
crearinstancias
instancias
de
deuna
unaclase
claseabstracta
abstracta

Para declarar una clase abstracta se utiliza la palabra reservada abstract, como
se muestra en la transparencia.
Las reglas que rigen el uso de una clase abstracta son prcticamente las mismas
que se aplican a una clase no abstracta. Las nicas diferencias entre usar clases
abstractas y no abstractas son:
No est permitido crear una instancia de una clase abstracta.
En este sentido, las clases abstractas son como interfaces.
Se puede crear un mtodo abstracto en una clase abstracta.
Se puede declarar un mtodo abstracto en una clase abstracta, pero no en
una que no lo sea.
Las clases abstractas comparten las siguientes caractersticas con las clases no
abstractas:
Extensibilidad limitada
Una clase abstracta puede extender como mximo otra clase o clase
abstracta. Obsrvese que una clase abstracta puede extender una clase que
no sea abstracta
Mltiples interfaces
Una clase abstracta puede implementar varias interfaces
Mtodos de interfaz heredados
Una clase abstracta debe implementar todos los mtodos de interfaz
heredados

Herencia en C#

33

Uso de clases abstractas en una jerarqua de clases


Objetivo del tema

Ilustrar el uso de clases


abstractas en la
implementacin de
interfaces.

Explicacin previa

Las clases abstractas se


emplean a menudo para la
implementacin parcial de
interfaces.

Ejemplo 1

interface
interface IToken
IToken
{{
string
string Name(
Name( );
);
}}

IToken
IToken
interface
interface

abstract
abstract class
class Token:
Token: IToken
IToken
{{
string
string IToken.Name(
IToken.Name( ))
{{ ...
...
}}
...
...
}}
class
class ComentToken:
ComentToken: Token
Token
{{ ...
...
}}
class
class KeywordToken:
KeywordToken: Token
Token
{{ ...
...
}}

Token
Token
{{ abstract
abstract }}

Coment
Coment
Token
Token
concrete
concrete

Keyword
Keyword

Token
Token
concrete
concrete

La funcin de las clases abstractas en una jerarqua clsica de tres niveles,


formada por una interfaz, una clase abstracta y una clase concreta, es
proporcionar una implementacin completa o parcial de una interfaz.

Una clase abstracta que implementa una interfaz


Consideremos el Ejemplo 1 en la transparencia, en el que la clase abstracta
implementa una interfaz. Es una implementacin explcita del mtodo de
interfaz. La implementacin explcita no es virtual y por tanto no se puede
sustituir en las dems clases derivadas, como ComentToken.
Sin embargo, CommentToken puede reimplementar la interfaz IToken de la
siguiente manera:
interface IToken
{
string Name( );
}
abstract class Token: IToken
{
string IToken.Name( ) { ... }
}
class ComentToken: Token, IToken
{
public virtual string Name( ) { ... }
}

Como se ve, en este caso no es necesario marcar ComentToken.Name como


mtodo new. Esto se debe a que una clase derivada slo puede ocultar un
mtodo de clase base visible, pero la implementacin explcita de Name en
Token no es directamente visible en ComentToken.

Herencia en C#

34

Uso de clases abstractas en una jerarqua de clases (cont.)


Objetivo del tema

Ilustrar el uso de clases


abstractas en la
implementacin de
interfaces.

Explicacin previa

Aqu se da otro ejemplo del


uso de clases abstractas
para la implementacin
parcial de interfaces.

Ejemplo 2

interface
interface IToken
IToken
{{
string
string Name(
Name( );
);
}}
abstract
abstract class
class Token
Token
{{
public
virtual
public virtual string
string Name(
Name( ))
{{ ...
...
}}
...
...
}}

IToken
IToken
interface
interface

Token
Token
{{ abstract
abstract }}

Coment
Coment
class
class ComentToken:
ComentToken: Token,
Token, IToken
IToken
{{ ...
Token
Token
...
}}

concrete

concrete
class
class KeywordToken:
KeywordToken: Token,
Token, IToken
IToken
{{ ...
...
}}

Keyword
Keyword

Token
Token
concrete
concrete

Esta transparencia muestra otro ejemplo para continuar la discusin de la


funcin de las clases abstractas en una jerarqua clsica de tres niveles.

Una clase abstracta que no implementa una interfaz


Recomendacin al
profesor

La discusin del Ejemplo 2


tiene dos objetivos
principales:
1. Mostrar la sintaxis que se
utiliza para extender una
clase e implementar una
o ms interfaces.
2. Explicar que una clase
derivada puede heredar
su implementacin de
una interfaz desde la
clase base que extiende,
incluso en caso de que
esa clase base no
implemente esa interfaz.

Consideremos el Ejemplo 2 en la transparencia, en el que la clase abstracta no


implementa la interfaz. Esto significa que la nica forma de que proporcione
una implementacin de la interfaz a otra clase derivada concreta es mediante un
mtodo pblico. Opcionalmente, el mtodo puede estar declarado como virtual
en la clase abstracta para que sea posible sustituirlo en las clases, como se
muestra en el siguiente cdigo:
interface IToken
{
string Name( );
}
abstract class Token
{
public virtual string Name( ) { ... }
}
class ComentToken: Token, IToken
{
public override string Name( ) { ... } // Okay
}

Como se ve, una clase puede heredar su interfaz y su implementacin de esa


interfaz desde distintas ramas de la herencia.

Herencia en C#

35

Comparacin de clases abstractas e interfaces


Objetivo del tema

Comparar clases abstractas


e interfaces.

Explicacin previa

Entre las clases abstractas


y las interfaces existen
algunos parecidos, pero
tambin muchas
diferencias.

Parecidos
z

No se pueden crear instancias de ninguna de ellas

No se puede sellar ninguna de ellas

Diferencias
z

Las interfaces no pueden contener implementaciones

Las interfaces no pueden declarar miembros no pblicos

Las interfaces no pueden extender nada que no sea una


interfaz

Tanto las clases abstractas como las interfaces existen para derivar otras clases
de ellas (o ser implementadas). Sin embargo, una clase puede extender como
mximo una clase abstracta, por lo que hay que tener ms cuidado cuando se
deriva de una clase abstracta que cuando se deriva de una interfaz. Las clases
abstractas se deben utilizar solamente para implementar relaciones del tipo es
un.
Los parecidos entre clases abstractas e interfaces son:
No se pueden crear instancias de ellas.
Esto significa que no es posible usarlas directamente para crear objetos.
No se pueden sellar.
Esto es normal, ya que no es posible implementar una interfaz sellada.
La siguiente tabla resume las diferencias entre clases abstractas e interfaces.
Interfaces

Clases abstractas

No pueden contener implementacin

Pueden contener implementacin

No pueden declarar miembros no pblicos

Pueden declarar miembros no pblicos

Pueden extender slo otras interfaces

Pueden extender otras clases, que pueden


no ser abstractas

Cuando se comparan clases abstractas e interfaces, se puede pensar en las clases


abstractas como clases sin terminar que contienen los planes para lo que falta
por hacer.

Herencia en C#

36

Implementacin de mtodos abstractos


Objetivo del tema

Explicar cmo se
implementan mtodos
abstractos.

Explicacin previa

Una clase derivada puede


sustituir un mtodo virtual,
pero debe sustituir un
mtodo abstracto.

Sintaxis: Se usa la palabra reservada abstract

abstract
abstract class
class Token
Token
{{
public
public virtual
virtual string
string Name(
Name( )) {{ ...
... }}
public
public abstract
abstract int
int Longitud(
Longitud( );
);
}}
class
class ComentToken:
ComentToken: Token
Token
{{
public
public override
override string
string Name(
Name( )) {{ ...
... }}
public
override
int
Longitud(
)
{
public override int Longitud( ) { ...
... }}
}}

Slo clases abstractas pueden declarar mtodos abstractos

Los mtodos abstractos no pueden tener cuerpo

Para declarar un mtodo abstracto hay que aadir el modificador abstract a la


declaracin del mtodo. La sintaxis del modificador abstract se muestra en la
transparencia.
Slo clases abstractas pueden declarar mtodos abstractos, como se ve en este
ejemplo:
interface IToken
{
abstract string Name( ); // Error al compilar
}
class CommentToken
{
abstract string Name( ); // Error al compilar
}

Recomendacin al
profesor

Es obligatorio sustituir un
mtodo abstracto, pero no
es necesario sustituir un
mtodo virtual.

Nota Los desarrolladores en C++ pueden considerar los mtodos abstractos


como equivalentes a los mtodos virtuales puros de C++.

Los mtodos abstractos no pueden tener cuerpo


Los mtodos abstractos no pueden contener ninguna implementacin, como
queda claro en el siguiente cdigo:
abstract class Token
{
public abstract string Name( ) { ... }
// Error al compilar
}

Herencia en C#

37

Uso de mtodos abstractos


Objetivo del tema

Describir las restricciones


de los mtodos abstractos.

Explicacin previa

Antes de implementar un
mtodo abstracto hay que
tener en cuenta sus
caractersticas y las
restricciones que impone.

Los mtodos abstractos son virtuales

Los mtodos override pueden sustituir a mtodos


abstractos en otras clases derivadas

Los mtodos abstractos pueden sustituir a mtodos de


la clase base declarados como virtuales

Los mtodos abstractos pueden sustituir a mtodos de


la clase base declarados como override

Al implementar mtodos abstractos hay que tener en cuenta lo siguiente:


Los mtodos abstractos son virtuales.
Los mtodos override pueden sustituir a mtodos abstractos en otras clases
derivadas.
Los mtodos abstractos pueden sustituir a mtodos de la clase base
declarados como virtuales.
Los mtodos abstractos pueden sustituir a mtodos de la clase base
declarados como override.
A continuacin se describe en detalle cada uno de estos puntos.

Los mtodos abstractos son virtuales


Los mtodos abstractos se consideran implcitamente virtuales pero no pueden
estar marcados como virtuales de forma explcita, como se ve en el siguiente
cdigo:
abstract class Token
{
public virtual abstract string Name( ) { ... }
// Error al compilar
}

Herencia en C#

38

Los mtodos override pueden sustituir a mtodos


abstractos en otras clases derivadas
Al ser implcitamente virtuales, es posible sustituir mtodos abstractos en clases
derivadas. A continuacin se muestra un ejemplo:
Recomendacin al
profesor

Puede utilizar el siguiente


fragmento para ver hasta
qu punto los estudiantes
comprenden este aspecto:
abstract class A
{
public
abstract
void M( );
}
abstract class B:
A
{
public
abstract
void M( );
}

Esto no est permitido. Una


clase no podra implementar
A.M y B.M.

class ComentToken: Token


{
public override string Name( ) {...}
}

Los mtodos abstractos pueden sustituir a mtodos de


la clase base declarados como virtuales
La sustitucin de un mtodo de clase base declarado como virtual fuerza a otra
clase derivada a tener su propia implementacin del mtodo, y hace que no se
pueda utilizar la implementacin original del mtodo. A continuacin se
muestra un ejemplo:
class Token
{
public virtual string Name( ) { ... }
}
abstract class Force: Token
{
public abstract override string Name( );
}

Los mtodos abstractos pueden sustituir a mtodos de


la clase base declarados como override
La sustitucin de un mtodo de clase base declarado como override fuerza a
otra clase derivada a tener su propia implementacin del mtodo, y hace que no
se pueda utilizar la implementacin original del mtodo. A continuacin se
muestra un ejemplo:
class Token
{
public virtual string Name( ) { ... }
}
class AnotherToken: Token
{
public override string Name( ) { ... }
}
abstract class Force: AnotherToken
{
public abstract override string Name( );
}

Herencia en C#

Prctica : Uso de herencia para implementar una interfaz


Objetivos
Al final de esta prctica, usted ser capaz de:
Definir y usa interfaces, clases abstractas y clases concretas.
Implementar una interfaz en una clase concreta.
Saber cmo y cundo usar las palabras reservadas virtual y override.
Definir una clase abstracta y usarla en una jerarqua de clases.
Crear clases selladas para impedir la herencia.

Requisitos previos
Antes de realizar la prctica debe estar familiarizado con los siguientes temas:
Creacin de clases en C#.
Definicin de mtodos para clases.

Ejercicio 1
Conversin de un archivo fuente de C# en un archivo HTML con
sintaxis en color
La gran utilidad de los marcos de trabajo se debe a que proporcionan cdigo
flexible y fcil de utilizar. Al contrario de una biblioteca, que se usa mediante
una llamada directa a un mtodo, un marco de trabajo se emplea creando una
nueva clase que implementa una interfaz. El cdigo del marco de trabajo realiza
entonces llamadas polimrficas a los mtodos de la clase por medio de las
operaciones de la interfaz. Esto hace que haya muchos usos posibles de un
marco de trabajo bien diseado, mientras que un mtodo de biblioteca slo se
puede usar de una forma.

Resumen
Este ejercicio emplea una jerarqua (ya escrita) de clases e interfaces que
forman un marco de trabajo en miniatura. El marco de trabajo divide una
archivo fuente de C# en unidades lxicas (lo tokeniza) y almacena los
distintos tipos de tokens en una coleccin contenida en la clase SourceFile.
Tambin se dispone de una interfaz ITokenVisitor con operaciones Visit que,
combinada con el mtodo Accept de SourceFile, permite visitar y procesar
secuencialmente cada token del archivo de origen. Cuando se visita un token,
una clase puede utilizarlo para efectuar todo el procesamiento necesario.
Se ha creado una clase abstracta llamada NullTokenVisitor, que implementa
todos los mtodos Visit de ITokenVisitor utilizando mtodos vacos. Si no se
desea implementar todos los mtodos de ITokenVisitor, es posible derivar una
clase de NullTokenVisitor y sustituir slo los mtodos Visit que se elija.
Este ejercicio derivar una clase HTMLTokenVisitor a partir de la interfaz
ITokenVisitor. Implementar todos los mtodos Visit sobrecargados en esta
clase derivada para enviar a la consola el token entre corchetes por marcadores

Herencia en C#

<span class=...> y </span> del lenguaje de marcado de hipertexto (HTML).


Ejecutar un sencillo archivo de proceso por lotes (batch) que iniciar el
ejecutable creado y redireccionar la salida de consola para crear una pgina
HTML que use una hoja de estilos en cascada. Finalmente, abrir la pgina
HTML en Microsoft Internet Explorer para ver el archivo fuente original con
sintaxis en color.

Herencia en C#

Cmo acceder a las interfaces


1. Abra el proyecto ColorTokeniser.sln en la carpeta carpeta de
Starter\ColorTokeniser dentro del fichero lab10.zip.
2. Examine las clases e interfaces en los archivos Itoken.cs, Itoken_visitor.cs y
source_file.cs. La jerarqua establecida es la siguiente:

Herencia en C#

Cmo crear una clase abstracta NullTokenVisitor


1. Abra el archivo null_token_visitor.cs.
Observe que NullTokenVisitor deriva de la interfaz ITokenVisitor, pero
no implementa ninguna de las operaciones especificadas en la interfaz. Para
poder construir HTMLTokenVisitor tendr que implementar todas las
operaciones heredadas como mtodos vacos.

2. Aada a la clase NullTokenVisitor un mtodo virtual pblico llamado


Visit. Este mtodo devolver void y recibir un solo parmetro
ILineStartToken. El cuerpo del mtodo tiene que estar vaco. El cdigo del
mtodo ser:
public class NullTokenVisitor : ITokenVisitor
{
public virtual void Visit(ILineStartToken t) { }
...
}

3. Repita el paso 2 para todos los dems mtodos Visit sobrecargados que
estn declarados en la interfaz ITokenVisitor.
Implemente todos los mtodos Visit en NullTokenVisitor como mtodos
vacos.
4. Guarde el trabajo realizado.
5. Compile null_token_visitor.cs.
La compilacin no dar ningn error si ha implementado todas las
operaciones Visit de la interfaz ITokenVisitor. Si ha omitido alguna
operacin, el compilador mostrar un mensaje de error.

Herencia en C#

6. Aada a la clase NullTokenVisitor un mtodo privado, esttico y void


llamado Test.
Este mtodo no recibir ningn parmetro y contendr una sola instruccin
que cree un objeto new NullTokenVisitor. Esta instruccin comprobar
que la clase NullTokenVisitor ha implementado todas las operaciones Visit
y que es posible crear instancias de NullTokenVisitor. El cdigo para este
mtodo ser el siguiente:
public class NullTokenVisitor : ITokenVisitor
{
...
static void Test( )
{
new NullTokenVisitor( );
}
}

7. Guarde el trabajo realizado.


8. Compile null_token_visitor.cs y corrija los posibles errores.
9. Cambie la definicin de NullTokenVisitor.
Puesto la clase NullTokenVisitor no se va a utilizar para crear instancias
sino para derivar otra clase de ella, es preciso cambiar la definicin para que
sea una clase abstracta.
10. Vuelva a compilar null_token_visitor.cs.
Compruebe tambin que ahora la instruccin new dentro del mtodo Test
causa un error, ya que no est permitido crear instancias de una clase
abstracta.
11. Borre el mtodo Test.
12. NullTokenVisitor tiene que quedar de esta forma:
public abstract class NullTokenVisitor : ITokenVisitor
{
public virtual void Visit(ILineStartToken t) { }
public virtual void Visit(ILineEndToken
t) { }
public
public
public
public
public

virtual
virtual
virtual
virtual
virtual

void
void
void
void
void

Visit(ICommentToken
Visit(IDirectiveToken
Visit(IIdentifierToken
Visit(IKeywordToken
Visit(IWhiteSpaceToken

t)
t)
t)
t)
t)

public virtual void Visit(IOtherToken t) { }


}

{
{
{
{
{

}
}
}
}
}

Herencia en C#

Cmo crear una clase HTMLTokenVisitor


1. Abra el archivo html_token_visitor.cs.
2. Modifique la clase HTMLTokenVisitor de forma que derive de la clase
abstracta NullTokenVisitor.

3. Abra el archivo main.cs file y aada dos instrucciones al mtodo esttico


InnerMain.
a. La primera instruccin declarar una variable llamada visitor de tipo
HTMLTokenVisitor y la inicializar con un objeto
HTMLTokenVisitor de nueva creacin.
b. La segunda instruccin pasar visitor como parmetro al mtodo Accept
llamado en la variable ya declarada source.
4. Guarde el trabajo realizado.
5. Compile el programa y corrija los posibles errores.
Ejecute el programa desde la lnea de comandos, pasando como argumento
el nombre de un archivo fuente .cs de la carpeta bin\debug del proyecto
ColorTokeniser.
No ocurrir nada, puesto que todava no ha definido ningn mtodo en la
clase HTMLTokenVisitor!

Herencia en C#

6. Aada un mtodo Visit pblico y no esttico a la clase


HTMLTokenVisitor. Este mtodo devolver void y recibir un solo
parmetro ILineStartToken llamado line.
Implemente el cuerpo del mtodo con una sola instruccin que llame a
Write (no WriteLine) para mostrar el valor de line.Number( ) en la
consola. Observe que Number es una operacin declarada en la interfaz
ILineStartToken. No utilice las palabras reservadas virtual ni override
para declarar el mtodo. El siguiente cdigo muestra este mtodo:
public class HTMLTokenVisitor : NullTokenVisitor
{
public void Visit(ILineStartToken line)
{
Console.Write(line.Number( )); // No WriteLine
}
}

7. Guarde el trabajo realizado.


8. Compile el programa.
Vuelva a ejecutar el programa igual que antes. No ocurrir nada, ya que el
mtodo Visit en HTMLTokenVisitor est ocultando el mtodo Visit en la
clase base NullTokenVisitor.
9. Modifique HTMLTokenVisitor.Visit(ILineStartToken) de forma que
sustituya a Visit de su clase base.
Esto har que HTMLTokenVisitor.Visit sea polimrfico, como se ve en el
siguiente cdigo:
public class HTMLTokenVisitor : NullTokenVisitor
{
public override void Visit(ILineStartToken line)
{
Console.Write(line.Number( ));
}
}

10. Guarde el trabajo realizado.


11. Compile el programa y corrija los posibles errores.
Ejecute el programa igual que antes. El resultado contendr nmeros en
orden creciente y sin espacios intermedios (los nmeros son los de las lneas
generadas para el archivo indicado).

Herencia en C#

12. En HTMLTokenVisitor, defina un mtodo sobrecargado Visit pblico y no


esttico que devuelva void y reciba un solo parmetro ILineEndToken.
Esta revisin aade una nueva lnea entre las lneas de tokens. Observe que
esta operacin est declarada en la interfaz ITokenVisitor. Implemente el
cuerpo de este mtodo para imprimir una sola nueva lnea en la consola,
como se muestra (este mtodo usa WriteLine, no Write):
public class HTMLTokenVisitor : NullTokenVisitor
{
...
public override void Visit(ILineEndToken t)
{
Console.WriteLine( ); // No Write
}
}

13. Guarde el trabajo realizado.


14. Compile el programa y corrija los posibles errores.
Ejecute el programa igual que antes. Cada nmero de lnea terminar esta
vez con una lnea aparte.
Cmo usar HTMLTokenVisitor para mostrar tokens del archivo fuente de
C#
1. Aada a la clase HTMLTokenVisitor un mtodo Visit pblico y no
esttico. Este mtodo devolver void y recibir un solo parmetro
IIdentifierToken llamado token. Debe sustituir al mtodo correspondiente
en la clase base NullTokenVisitor.
2. Implemente el cuerpo del mtodo con una sola instruccin que llame a
Write para mostrar token en la consola como string:
public class HTMLTokenVisitor : NullTokenVisitor
{
...
public override void Visit(IIdentifierToken token)
{
Console.Write(token.ToString( ));
}
}

Nota Abra el archivo IToken.cs y observe que IIdentifierToken deriva de


IToken y que IToken declara un mtodo ToString.
3. Guarde el trabajo realizado.
4. Compile el programa y corrija los posibles errores.
Ejecute el programa igual que antes. Esta vez la salida incluir todos los
identificadores.
5. Repita los pasos 1 a 4, aadiendo a HTMLTokenVisitor otros cuatro
mtodos Visit sobrecargados.
Cada uno de ellos recibir un solo parmetro de tipo ICommentToken,
IKeywordToken, IWhiteSpaceToken y IOtherToken, respectivamente.
Los cuerpos de estos mtodos sern iguales al descrito en el paso 2.

Herencia en C#

Cmo convertir un archivo fuente de C# en un archivo HTML


1. La carpeta bin\debug del proyecto ColorTokeniser contiene una secuencia
de comandos llamada generate.bat, que ejecuta el programa ColorTokeniser
usando el parmetro que se le indique en la lnea de comandos. Tambin
efecta algn procesamiento previo y posterior del archivo resultante,
empleando una hoja de estilos en cascada (code_style.css) para convertir la
salida en HTML.
Ejecute el programa desde la lnea de comandos utilizando el archivo
generate.bat y pasando como parmetro el archivo token.cs (que es en
realidad una copia de parte del cdigo fuente para el programa, pero que
usaremos como archivo .cs de ejemplo). Capture la salida en otro archivo
que tenga la extensin .html. Por ejemplo:
generate token.cs > token.html

2. Use Internet Explorer para ver el archivo .html que acaba de crear
(token.html en el ejemplo del paso anterior). Puede hacerlo escribiendo
token.html en la lnea de comandos.
El resultado tendr muchos errores de formato. La indentacin de las lneas
posteriores a 9 es diferente a la de las anteriores. Esto se debe a que los
nmeros inferiores a 10 tienen un solo dgito, mientras que los nmeros
mayores que 9 tienen dos dgitos. Observe tambin que los nmeros de lnea
aparecen con el mismo color que los tokens del archivo de origen, lo que no
resulta demasiado til.
Cmo encontrar y corregir problemas de nmero de lnea e indentacin
1. Cambie la definicin del mtodo Visit(ILineStartToken) como se indica a
continuacin para corregir estos problemas en el resultado:
public class HTMLTokenVisitor : NullTokenVisitor
{
public override void Visit(ILineStartToken line)
{
Console.Write("<span class=\"line_number\">");
Console.Write("{0,3}", line.Number( ));
Console.Write("</span>");
}
...
}

2. Guarde el trabajo realizado.


3. Compile el programa y corrija los posibles errores.

Herencia en C#

10

4. Vuelva a crear el archivo token.html a partir del archivo de origen token.cs


desde la lnea de comandos:
generate token.cs > token.html

5. Abra token.html en Internet Explorer.


Todava hay un problema. Al comparar el aspecto de token.html en Internet
Explorer con el archivo token.cs original, se observa que el primer
comentario en token.cs (/// <summary>) aparece en el explorador como
///. Se ha perdido <summary>. El problema es que, en HTML, algunos
caracteres tienen un significado especial. El cdigo fuente en HTML para
mostrar los parntesis angulares de apertura (<) y cierre (>) es,
respectivamente &lt; y &gt;, mientras que para el ampersand (&) hay que
escribir &amp;.
Cmo hacer los cambio necesarios para mostrar correctamente los
caracteres de parntesis angulares y ampersand
1. Aada a HTMLTokenVisitor un mtodo privado y no esttico llamado
FilteredWrite que devuelva void y reciba un solo parmetro de tipo
IToken llamado token.
Este mtodo crear una string llamada dst a partir de token y recorrer uno
por uno todos los caracteres de dst aplicando las transformaciones descritas
anteriormente. El cdigo ser como ste:
public class HTMLTokenVisitor : NullTokenVisitor
{
...
private void FilteredWrite(IToken token)
{
string src = token.ToString( );
for (int i = 0; i != src.Length; i++) {
string dst;
switch (src[i]) {
case '<' :
dst = "&lt;"; break;
case '>' :
dst = "&gt;"; break;
case '&' :
dst = "&amp;"; break;
default :
dst = new string(src[i], 1); break;
}
Console.Write(dst);
}
}
}

Herencia en C#

11

2. Cambie la definicin de HTMLTokenVisitor.Visit(ICommentToken)


para usar el nuevo mtodo FilteredWrite en lugar de Console.Write:
public class HTMLTokenVisitor : NullTokenVisitor
{
public override void Visit(ICommentToken token)
{
FilteredWrite(token);
}
...
}

3. Cambie la definicin de HTMLTokenVisitor.Visit(IOtherToken) para


usar el nuevo mtodo FilteredWrite en lugar de Console.Write:
public class HTMLTokenVisitor : NullTokenVisitor
{
public override void Visit(IOtherToken token)
{
FilteredWrite(token);
}
...
}

4. Guarde el trabajo realizado.


5. Compile el programa y corrija los posibles errores.
6. Vuelva a crear el archivo token.html a partir del archivo de origen token.cs
desde la lnea de comandos:
generate token.cs > token.html

7. Abra token.html en Internet Explorer y compruebe que ahora aparecen


correctamente los caracteres de parntesis angulares y ampersand.

Herencia en C#

12

Cmo aadir comentarios en color al archivo HTML


1. Use el Bloc de Notas para abrir la hoja de estilos code_style.css en la
carpeta bin\debug del proyecto ColorTokeniser.
Para aadir color al archivo HTML se usar el archivo de hoja de estilos en
cascada code_style.css . Este archivo ha sido creado antes de la prctica y su
contenido es como el que se muestra en el siguiente ejemplo:
...
SPAN.LINE_NUMBER
{
background-color: white;
color: gray;
}
...
SPAN.COMMENT
{
color: green;
font-style: italic;
}

El mtodo HTMLTokenVisitor.Visit(ILineStartToken) ya utiliza esta


hoja de estilos:
public class HTMLTokenVisitor : NullTokenVisitor
{
public override void Visit(ILineStartToken line)
{
Console.Write("<span class=\"line_number\">");
Console.Write("{0,3}", line.Number( ));
Console.Write("</span>");
}
...
}

Observe que este mtodo escribe las palabras span y line_number, y


que la hoja de estilos contiene una entrada para SPAN.LINE_NUMBER.
2. Modifique el cuerpo de HTMLTokenVisitor.Visit(ICommentToken) para
que reciba lo siguiente:
public class HTMLTokenVisitor : NullTokenVisitor
{
public override void Visit(ICommentToken token)
{
Console.Write("<span class=\"comment\">");
FilteredWrite(token);
Console.Write("</span>");
}
...
}

3. Guarde el trabajo realizado.


4. Compile el programa y corrija los posibles errores.

Herencia en C#

13

5. Vuelva a crear el archivo token.html a partir del archivo de origen token.cs


desde la lnea de comandos:
generate token.cs > token.html

6. Abra token.html en Internet Explorer.


Compruebe que los comentarios del archivo de origen aparecen ahora en
verde y en cursiva.
Cmo aadir palabras reservadas en color al archivo HTML
1. Observe que el archivo code_style.css file contiene la siguiente entrada:
...
SPAN.KEYWORD
{
color: blue;
}
...

2. Modifique el cuerpo de HTMLTokenVisitor.Visit(IKeywordToken) para


que use el estilo indicado en la hoja de estilos:
public class HTMLTokenVisitor : NullTokenVisitor
{
public override void Visit(IKeywordToken token)
{
Console.Write("<span class=\"keyword\">");
FilteredWrite(token);
Console.Write("</span>");
}
...
}

3. Guarde el trabajo realizado.


4. Compile el programa y corrija los posibles errores.
5. Vuelva a crear el archivo token.html a partir del archivo de origen token.cs
desde la lnea de comandos:
generate token.cs > token.html

6. Abra token.html en Internet Explorer y compruebe que las palabras


reservadas aparecen ahora en azul.

Herencia en C#

14

Cmo modificar los mtodos Visit para eliminar repeticiones


1. Observe que en los dos mtodos Visit anteriores hay repeticiones, ya que
ambos escriben cadenas span en la consola.
Es posible modificar los mtodos Visit para evitar esta duplicacin. Defina
un nuevo mtodo privado y no esttico llamado SpannedFilteredWrite que
devuelva void y reciba dos parmetros, uno string llamado spanName y un
IToken llamado token. El cuerpo de este mtodo contendr tres
instrucciones: la primera escribir la cadena span en la consola usando el
parmetro spanName, la segunda llamar al mtodo FilteredWrite pasando
token como argumento, y la tercera escribir en la consola la cadena span
de cierre. El cdigo ser como se indica a continuacin:
public class HTMLTokenVisitor : NullTokenVisitor
{
...
private void SpannedFilteredWrite(string spanName,
IToken token)
{
Console.Write("<span class=\"{0}\">", spanName);
FilteredWrite(token);
Console.Write("</span>");
}
...
}

2. Modifique HTMLTokenVisitor.Visit(ICommentToken) para utilizar este


nuevo mtodo, como se indica:
public class HTMLTokenVisitor : NullTokenVisitor
{
...
public override void Visit(ICommentToken token)
{
SpannedFilteredWrite("comment", token);
}
...
}

3. Modifique HTMLTokenVisitor.Visit(IKeywordToken) para utilizar este


nuevo mtodo, como se indica:
public class HTMLTokenVisitor : NullTokenVisitor
{
...
public override void Visit(IKeywordToken token)
{
SpannedFilteredWrite("keyword", token);
}
...
}

Herencia en C#

15

4. Modifique el cuerpo del mtodo HTMLTokenVisitor.


Visit(IIdentifierToken) para que llame al mtodo SpannedFilteredWrite.
Esto es necesario porque el archivo code_style.css file tambin contiene una
entrada para tokens de identificadores.
public class HTMLTokenVisitor : NullTokenVisitor
{
...
public override void Visit(IIdentifierToken token)
{
SpannedFilteredWrite("identifier", token);
}
...
}

5. Guarde el trabajo realizado.


6. Compile el programa y corrija los posibles errores.
7. Vuelva a crear el archivo token.html a partir del archivo de origen token.cs
desde la lnea de comandos:
generate token.cs > token.html

8. Abra token.html en Internet Explorer.


Compruebe que los comentarios siguen apareciendo en verde y que las
palabras reservadas an estn en azul.
Cmo implementar HTMLTokenVisitor directamente desde ITokenVisitor
1. Abra el archivo html_token_visitor.cs.
2. Modifique el cdigo de forma que la clase HTMLTokenVisitor derive de
la interfaz ITokenVisitor. Puesto que ha implementado prcticamente todos
los mtodos Visit de HTMLTokenVisitor, ya no es necesario que herede
de la clase abstracta NullTokenVisitor (que proporciona una
implementacin vaca por defecto para todos los mtodos de
ITokenVisitor) y puede derivar directamente de la interfaz ITokenVisitor.

Herencia en C#

16

La clase ser como se indica:


public class HTMLTokenVisitor : ITokenVisitor
{
...
}

3. Guarde el trabajo realizado.


4. Compile el programa.
Habr muchos errores. El problema es que los mtodos Visit en
HTMLTokenVisitor siguen estando declarados como override, pero no
est permitido sustituir una operacin en una interfaz.
5. Elimine la palabra reservada override de la definicin de todos los mtodos
Visit.
6. Compile el programa.
Todava quedar un error. El problema en esta ocasin es que
HTMLTokenVisitor no implementa la operacin Visit(IDirectiveToken)
heredada de su interfaz ITokenVisitor. Anteriormente,
HTMLTokenVisitor heredaba desde NullTokenVisitor una
implementacin vaca de esta operacin.
7. En HTMLTokenVisitor, defina un mtodo pblico no esttico llamado
Visit que devuelva void y reciba un solo parmetro de tipo
IDirectiveToken llamado token. Esto resolver el problema de
implementacin.
El cuerpo de este mtodo contendr una llamada al mtodo
SpannedFilteredWrite pasndole dos parmetros: la directiva literal
string y la variable token.
public class HTMLTokenVisitor : ITokenVisitor
{
...
public void Visit(IDirectiveToken token)
{
SpannedFilteredWrite("directive", token);
}
...
}

8. Guarde el trabajo realizado.


9. Compile el programa y corrija los posibles errores.
10. Vuelva a crear el archivo token.html a partir del archivo de origen token.cs
desde la lnea de comandos:
generate token.cs > token.html

11. Abra token.html en Internet Explorer.


Compruebe que los comentarios siguen apareciendo en verde y que las
palabras reservadas an estn en azul.

Herencia en C#

17

Cmo impedir el uso de HTMLTokenVisitor como clase base


1. Declare HTMLTokenVisitor como clase sellada.
Dado que los mtodos de HTMLTokenVisitor ya no son virtuales, parece
razonable declarar HTMLTokenVisitor como una clase sellada como se
muestra en el siguiente cdigo:
public sealed class HTMLTokenVisitor : ITokenVisitor
{
...
}

2. Compile el programa y corrija los posibles errores.


3. Vuelva a crear el archivo token.html a partir del archivo de origen token.cs
desde la lnea de comandos:
generate token.cs > token.html

4. Abra token.html en Internet Explorer y compruebe que los comentarios


siguen apareciendo en verde y que las palabras reservadas an estn en azul.

Herencia en C#

18

Ejercicio 2
Conversin de un archivo fuente de C# en un archivo HTML con
sintaxis en color
En este ejercicio examinar otra aplicacin que usa el mismo marco de trabajo
empleado en el Ejercicio 1.

Resumen
En esta aplicacin, la clase ColorTokenVisitor deriva de la interfaz
ITokenVisitor. Los mtodos Visit de esta clase escriben tokens en color en un
RichTextBox dentro de una aplicacin de formularios de Microsoft Windows.
Las clases forman la siguiente jerarqua:

Cmo acceder a las interfaces:


1. Abra el proyecto ColorSyntaxApp.sln en la carpeta
Solution\ColourSyntaxApp dentro del fichero lab10.zip.
2. Estudie los contenidos de los dos archivos .cs files. Observe que la clase
ColorTokenVisitor es muy similar a la clase HTMLTokenVisitor creada
en el Ejercicio 1. La diferencia ms importante es que ColorTokenVisitor
escribe los tokens en color en un componente de formulario RichTextBox
en lugar de la consola.
3. Cree el proyecto.
4. Ejecute la aplicacin.
a. Pulse Open File (Abrir archivo).
b. En el cuadro de dilogo que aparece, elija un archivo fuente .cs.
c. Pulse Open (Abrir).
Los contenidos del archivo .cs seleccionado aparecern en color.

Introduccin a C#

Contenido
Descripcin general

Estructura de un programa C#

Operaciones bsicas de entrada/salida

Compilacin, ejecucin y depuracin

18

Introduccin a C#

Notas para el instructor


Este mdulo presenta a los estudiantes el lenguaje de programacin C#. Los
estudiantes aprendern los elementos bsicos de un programa C# elemental.
Tambin se discutirn buenas prcticas y estilo de programacin.
Finalmente, los estudiantes aprendern a usar Microsoft Visual Studio
para editar, compilar, ejecutar y depurar un programa C#.
Al final de este mdulo, los estudiantes sern capaces de:
Explicar la estructura de un programa C# sencillo.
Utilizar la clase Console del espacio de nombres System para realizar
operaciones bsicas de entrada/salida.
Tratar excepciones en un programa C#.
Generar documentacin en lenguaje de marcado extensible (XML) para un
programa C#.
Compilar, vincular y ejecutar un programa C#.
Utilizar el Visual Studio Debugger para seguir paso a paso un programa C#.

Introduccin a C#

Notas generales
Objetivo del tema

Ofrecer una introduccin a


los contenidos y objetivos
del mdulo.

Explicacin previa

En este mdulo aprender


los elementos bsicos de
C# y cmo compilar,
vincular y ejecutar un
programa C#.

Estructura de un programa C#

Operaciones bsicas de entrada/salida

Prcticas recomendadas

Compilacin, ejecucin y depuracin

En este mdulo estudiar la estructura bsica de un programa C# analizando un


ejemplo de trabajo sencillo. Aprender a usar la clase Console para realizar
algunas operaciones bsicas de entrada y salida. Aprender tambin algunas
prcticas recomendadas para el tratamiento de errores y la documentacin del
cdigo, y finalmente compilar, ejecutar y compilar un programa C#.
Al final de este mdulo, usted ser capaz de:
Explicar la estructura de un programa C# sencillo.
Utilizar la clase Console del espacio de nombres System para realizar
operaciones bsicas de entrada/salida.
Tratar excepciones en un programa C#.
Generar documentacin en lenguaje de marcado extensible (XML) para un
programa C#.
Compilar y ejecutar un programa C#.
Utilizar el depurador para seguir paso a paso la ejecucin de un programa.

Introduccin a C#

Estructura de un programa C#
Objetivo del tema

Ofrecer una introduccin a


los temas tratados en esta
seccin.

Explicacin previa

En esta seccin estudiar la


estructura bsica de un
programa C#.

Recomendacin al
profesor

En esta leccin se hacen


muchas comparaciones
entre C# y otros lenguajes
con los que los estudiantes
pueden estar familiarizados.
Es recomendable sealar
las similitudes y las
pequeas (y no tan
pequeas) diferencias.

Hola, mundo

La clase

El mtodo Main

La sentencia using y el espacio de nombres System

Demostracin: Uso de Visual Studio para crear


un programa C#

En esta leccin estudiar la estructura bsica de un programa C# analizando un


programa simple que contiene todas las caractersticas esenciales. Tambin
aprender a usar Microsoft Visual Studio para crear y editar un programa C#.

Introduccin a C#

Hola, mundo
Objetivo del tema

Mostrar un programa C#
que funciona.

Explicacin previa

El primer programa que se


suele escribir en un
lenguaje nuevo es el
inevitable Hola, mundo.

using
using System;
System;
class
class Hola
Hello
{{
public
public static
static void
void Main()
Main()
{{
Console.WriteLine("Hola,
Console.WriteLine("Hello mundo);
, World");
}}
}}

Recomendacin al
profesor

ste es el estilo, diseo y


definicin de Main que
emplea Visual Studio para
crear un nuevo programa
C#.
Puede escribir el cdigo,
compilarlo y ejecutarlo
desde la lnea de
comandos.

El primer programa que se suele escribir cuando se aprende un lenguaje nuevo


es el inevitable Hola, mundo. En este mdulo tendr la oportunidad de
examinar la versin en C# de este primer programa.
El cdigo de ejemplo en la transparencia contiene todos los elementos
esenciales de un programa C# y es muy fcil de probar. Lo nico que hace
cuando se ejecuta desde la lnea de comandos es mostrar el siguiente mensaje:
Hola, mundo

En los temas que siguen analizaremos este programa simple para aprender ms
sobre los componentes de un programa C#.

Introduccin a C#

La clase
Objetivo del tema

Destacar que todas las


aplicaciones C# son una
coleccin de clases.

Explicacin previa

Una aplicacin C# es una


coleccin de una o ms
clases.

Una

aplicacin C# es una coleccin de clases, estructuras


y tipos

Una

clase es un conjunto de datos y mtodos

Sintaxis

class
name
class nombre
{{
...
...
}}

Recomendacin al
profesor

No inicie todava una


discusin completa sobre la
definicin de una clase.
Limtese a la explicacin
sencilla que se da en las
notas de los estudiantes.

Una

aplicacin C# puede incluir muchos archivos

Una

clase no puede abarcar ms de un archivo

En C#, una aplicacin es una coleccin de una o ms clases, estructuras de


datos y otros tipos. En este mdulo se define una clase como un conjunto de
datos combinados con mtodos (o funciones) que pueden manipular esos datos.
En mdulos posteriores aprenderemos ms sobre clases y todo lo que pueden
ofrecer al programador de C#.
Un examen del cdigo para la aplicacin Hola, mundo revela que hay una sola
clase llamada Hola. Esta clase se introduce con la palabra clave class. Despus
del nombre de la clase hay una llave de apertura ({). Todo lo que hay hasta la
correspondiente llave de cierre (}) forma parte de la clase.
Las clases para una aplicacin C# se pueden extender a uno o ms archivos. Es
posible poner varias clases en un archivo, pero una sola clase no puede abarcar
ms de un archivo.
Nota para programadores en Java No es necesario que el nombre del archivo
de la aplicacin coincida con el nombre de la clase.
Nota para programadores en C++ C# no distingue entre la definicin y el uso
de una clase de la misma forma que C++. No existe el concepto de archivo de
definicin (.hpp). Todo el cdigo para la clase se escribe en un solo archivo.

Introduccin a C#

El mtodo Main
Objetivo del tema

Explicar dnde comienza


una aplicacin C# cuando
se ejecuta.

Explicacin previa

Cuando se ejecuta una


aplicacin C#, la ejecucin
se inicia con el mtodo
Main.

Al

escribir Main hay que:

Utilizar una M mayscula, como en Main

Designar un Main como el punto de entrada al programa

Declarar Main como public static void Main

Un

Main puede pertenecer a mltiple clases

La

aplicacin termina cuando Main acaba o ejecuta


un return

Consejo para el
profesor

Al tratar este tema, haga


hincapi en que muchos de
los puntos discutidos se
tratarn en detalle ms
adelante. El objetivo de este
tema es simplemente
destacar las reglas bsicas
del mtodo Main.

Recomendacin al
profesor

Es posible poner Main en


una estructura en lugar de
una clase. Las estructuras
se tratarn ms adelante en
este mdulo.

Todas las aplicaciones tienen que empezar por algn sitio. Cuando se ejecuta
una aplicacin C#, la ejecucin se inicia en el mtodo llamado Main. Si est
acostumbrado a programar en C, C++ o incluso en Java, este concepto le
resultar familiar.
El lenguaje C# distingue entre maysculas y minsculas. Main debe estar
escrito con una M mayscula y con las dems letras en minsculas.
Aunque en una aplicacin C# puede haber muchas clases, no puede haber ms
que un punto de entrada. Es posible tener muchas clases con Main en la misma
aplicacin, pero se ejecutar slo un Main. Al compilar la aplicacin hay que
especificar cul se va a utilizar.
Tambin es importante la firma de Main. Si se emplea Visual Studio, se crear
automticamente como static void (como veremos ms adelante en el curso).
No se debe cambiar la firma si no hay una buena razn para hacerlo.
Consejo Hasta cierto punto es posible cambiar la firma, pero debe ser siempre
static, ya que de lo contrario es posible que el compilador no la reconozca como
punto de entrada a la aplicacin.
La aplicacin se ejecuta hasta llegar al final de Main o hasta que Main ejecuta
una instruccin return.

Introduccin a C#

La sentencia using y el espacio de nombres System


Objetivo del tema

Explicar el empleo de la
sentencia using para
acceder a espacios de
nombres.

Explicacin previa

C# incluye muchas clases


de utilidad que estn
organizadas en espacios de
nombres.

.NET

Framework ofrece muchas clases de utilidad

z Organizadas
System
Se

en espacios de nombres

es el espacio de nombres ms utilizado

hace referencia a clases por su espacio de nombres

System.Console.WriteLine("Hola,
mundo);
, World");
La

sentencia using

using
using System;
System;

Console.WriteLine("Hola,
mundo);
Console.WriteLine("Hello
, World");

Recomendacin al
profesor

Los espacios de nombres


se tratarn con detalle en el
mdulo 11, Agregacin,
espacios de nombres y
mbito avanzado, del curso
2124C, Programacin en
C#. La informacin que se
da aqu es suficiente para
entender la sentencia
using.

Como parte de Microsoft .NET Framework, C# incluye muchas clases de


utilidad que realizan una gran variedad de operaciones tiles. Estas clases estn
organizadas en espacios de nombres, que son conjuntos de clases relacionadas.
Un espacio de nombres tambin puede contener otros espacios de nombres.
.NET Framework est compuesto por muchos espacios de nombres, el ms
importante de los cuales se llama System. El nombre de espacios System
contiene las clases que emplean la mayor parte de las aplicaciones para
interactuar con el sistema operativo. Las clases ms utilizadas son las de entrada
y salida (E/S). Como ocurre en muchos otros lenguajes, C# no tiene funciones
propias de E/S y por tanto depende del sistema operativo para ofrecer una
interfaz compatible con C#.
Para hacer referencia a objetos en espacios de nombres se utiliza un prefijo
explcito con el identificador del espacio de nombres. Por ejemplo, el espacio
de nombres System contiene la clase Console, que a su vez contiene varios
mtodos, como WriteLine. Se puede acceder al mtodo WriteLine de la clase
Console de la siguiente manera:
System.Console.WriteLine("Hola, mundo");

Sin embargo, el uso de un nombre completo para referirse a objetos puede


resultar poco manejable y propicio a errores. Para hacerlo ms sencillo, se
puede especificar un espacio de nombres poniendo una sentencia using al
comienzo de la aplicacin, antes de la definicin de la primera clase. Una
sentencia using especifica el espacio de nombres que se examinara si una clase
no est definida explcitamente en la aplicacin. Es posible poner ms de una
sentencia using en el archivo de origen, pero todas tienen que ir al principio del
archivo.

Introduccin a C#

Recomendacin al
profesor

Asegrese de que los


programadores de C y C++
entienden la diferencia entre
la sentencia using y la
declaracin #include. Los
desarrolladores de Java
estarn ms familiarizados
con este punto, ya que es
similar a la sentencia
import.

Con la sentencia using se puede escribir el cdigo anterior de la siguiente


manera:
using System;
...
Console.WriteLine("Hola, mundo");

En la aplicacin Hola, mundo, la clase Console no est definida explcitamente.


Cuando se compila la aplicacin, el compilador busca Console en el espacio de
nombres System y genera cdigo que hace referencia al nombre completo
System.Console.
Nota Las clases del espacio de nombres System, as como las dems funciones
bsicas a las que se accede en tiempo de ejecucin, residen en un ensamblado
llamado mscorlib.dll que es el que se utiliza por defecto. Es posible referirse a
clases de otros ensamblados, pero para ello hay que especificar las ubicaciones
y los nombres de esos ensamblados al compilar la aplicacin.

Introduccin a C#

Uso de Visual Studio para crear un programa C#


Cmo crear una aplicacin C#
1. Inicie Visual Studio .NET.
2. En el men File (Archivo), seale New (Nuevo) y pulse Project (Proyecto).
3. En el cuadro de dilogo New Project (Nuevo proyecto), escriba la
informacin indicada en la siguiente tabla y pulse OK.
Elemento

Valor

Tipo de proyecto (vista de rbol)

Visual C# Projects

Plantillas (icono)

Console Application

Nombre

Hola

Ubicacin

C:\temp

4. Una vez generado el proyecto, seale y discuta las siguientes caractersticas


de Visual Studio:
La ventana Solution Explorer (Explorador de soluciones)
i. Cierre la ventana de cdigo Class1.cs.
ii. Cambie el nombre de Class1.cs a Hola.cs.
iii. Haga doble clic en Hola.cs para volver a abrir la ventana de cdigo.
La ventana Properties (Propiedades)
Las barras de herramientas
El men View (Ver)
El men Build (Compilar)
El men Debug (Depurar)
El men Help (Ayuda)
5. Utilizando la ventana de cdigo Hola.cs, seale y discuta lo siguiente:
El espacio de nombres Hola
Menciones que los espacios de nombres se discutirn ms adelante.
Podra borrar esta lnea y las llaves correspondientes, pero por el
momento djelas como estn.
La sentencia using
Los comentarios de XML
Use esta seccin para describir brevemente el programa. Los
comentarios se discutirn en detalle ms adelante.
La definicin de clase
El nombre por defecto de la clase es Class1. Cmbielo a Demonstrator.
El mtodo Main
Escriba el siguiente cdigo:
Console.WriteLine("Hola, mundo");

Microsoft IntelliSense
6. En el men File, seleccione Save All (Guardar todo).
7. Cierre Visual Studio.

Introduccin a C#

Operaciones bsicas de entrada/salida


Objetivo del tema

Ofrecer una introduccin a


los temas tratados en esta
seccin.

Explicacin previa

En esta leccin aprender a


realizar en C# operaciones
bsicas de E/S orientadas a
la consola.

La

clase Console

Los

mtodos Write y WriteLine

Los

mtodos Read y ReaLine

En esta leccin aprender a realizar en C# operaciones de entrada/salida


basadas en comandos utilizando la clase Console. Tambin aprender a mostrar
informacin con los mtodos Write y WriteLine, as como a obtener
informacin introducida desde el teclado con los mtodos Read y ReadLine.

Introduccin a C#

10

La clase Console
Objetivo del tema

Explicar el empleo de la
clase Console.

Explicacin previa

Puede emplear mtodos de


la clase Console para leer
datos introducidos desde el
teclado o para escribir datos
en la pantalla.

Permite acceder a las secuencias estndar de entrada,


salida y error

Slo tiene sentido para aplicaciones de consola


z Entrada
z Salida
z Error

Recomendacin al
profesor

Insista en que la clase


Console se debe utilizar
nicamente para
aplicaciones de lnea de
comandos. Los
desarrolladores que
escriban aplicaciones de
interfaz grfica de usuario
(GUI) tienen que usar
clases del espacio de
nombres
System.Windows.Forms.

estndar: teclado

estndar: Pantalla

estndar: Pantalla

Es posible redireccionar todas las secuencias

La clase Console hace que una aplicacin C# pueda acceder a las secuencias
estndar de entrada, salida y error.
La entrada estndar est asociada normalmente con el teclado, de forma que
todo lo que el usuario escribe en el teclado se puede leer desde la secuencia de
entrada estndar. Del mismo modo, la secuencia de salida estndar suele estar
dirigida a la pantalla, al igual que la secuencia de error estndar.
Nota Estas secuencias y la clase Console slo tienen sentido para aplicaciones
de consola, que son las que se ejecutan en una ventana Command (Comandos).
Es posible direccionar cualquiera de las tres secuencias (entrada estndar, salida
estndar, error estndar) a un archivo o dispositivo, tanto durante la
programacin como al ejecutar la aplicacin.

Introduccin a C#

11

Los mtodos Write y WriteLine


Objetivo del tema

Explicar los mtodos Write


y WriteLine de la clase
Console.

Explicacin previa

Los mtodos Write y


WriteLine permiten enviar
informacin a la secuencia
de salida estndar.

Recomendacin al
profesor

Puede ser conveniente


buscar paralelismos con
cout en C++, printf en C y
System.out.print en Java,
dependiendo de los
estudiantes. En Visual Basic
no hay ninguna funcin que
sea realmente equivalente.
Procure tambin que la
discusin sobre sobrecarga
de mtodos sea corta y
simple. Es posible que
algunos estudiantes an no
la entiendan, y adems se
tratar con ms detalle en
un mdulo posterior.

Console.Write y Console.WriteLine muestran informacin


en la pantalla de la consola
z WriteLine enva un fin de lnea/retorno de carro

Ambos mtodos son sobrecargados

Es posible emplear una cadena de formato y parmetros


z

Formatos de texto

Formatos numricos

Los mtodos Console.Write y Console.WriteLine se pueden utilizar para


mostrar informacin en la pantalla de la consola. Los dos mtodos son muy
similares; la diferencia ms importante es que WriteLine aade un fin de
lnea/retorno de carro al final de la salida, mientras que Write no lo hace.
Ambos mtodos son sobrecargados. Puede explicarlo con nmeros variables y
tipos de parmetros. Por ejemplo, puede usar el siguiente cdigo para escribir
99 en la pantalla:
Console.WriteLine(99);

Tambin puede usar el siguiente cdigo para escribir Hola, mundo en la


pantalla:
Console.WriteLine("Hola, mundo");

Formatos de texto
Existen formas de Write y WriteLine ms potentes, que toman una cadena de
formato y parmetros adicionales. La cadena de formato especifica cmo
aparecen los datos y puede contener marcadores, que son sustituidos por los
parmetros que siguen. Por ejemplo, puede usar el siguiente cdigo para
mostrar el mensaje La suma de 100 y 130 es 230:
Console.WriteLine("La suma de {0} y {1} es {2}", 100, 130,
100+130);

Importante El primer parmetro que sigue a la cadena de formato se referencia


como parmetro cero: {0}.

Introduccin a C#

12

Se puede utilizar el parmetro de la cadena de formato para especificar


anchuras de campos y para indicar si los valores en esos campos deben ir
justificados a derecha o a izquierda, como se ve en el siguiente cdigo:
Console.WriteLine("\"Justificacin a la izquierda en un campo
de anchura 10: {0, -10}\"", 99);
Console.WriteLine("\"Justificacin a la derecha en un campo de
anchura 10: {0,10}\"", 99);

Esto har que en la consola aparezca lo siguiente:


Justificacin a la izquierda en un campo de anchura 10: 99
Justificacin a la derecha en un campo de anchura 10:

99

Nota Para desactivar el significado especial de un carcter en una cadena de


formato se puede usar una barra diagonal inversa (\) antes de ese carcter. Por
ejemplo, "\{" har que aparezca un "{" literal y "\\" mostrar un "\" literal.
Tambin se puede emplear el carcter @ para representar al pie de la letra una
cadena entera. Por ejemplo, @"\\server\share" dar como resultado
"\\server\share."

Formatos numricos
Es posible utilizar la cadena de formato para especificar el formato de datos
numricos. La sintaxis completa para la cadena de formato es {N,M:
FormatString}, donde N es el nmero del parmetro, M es la anchura y
justificacin del campo, y FormatString indica cmo se deben mostrar los
datos numricos. La tabla siguiente resume los valores que puede adoptar
FormatString. Opcionalmente, en todos estos formatos se puede especificar el
nmero de dgitos que se desea mostrar o al que se debe redondear.
Valor

Significado

Muestra el nmero como una unidad monetaria, usando el smbolo y las


convenciones de la moneda local.

Muestra el nmero como un entero decimal.

Muestra el nmero como usando notacin exponencial (cientfica).

Muestra el nmero como un valor en coma fija.

Muestra el nmero como un valor entero o en coma fija, dependiendo del


formato que sea ms compacto.

Muestra el nmero con comas incorporadas.

Muestra el nmero utilizando notacin hexadecimal.

Introduccin a C#

13

El siguiente cdigo muestra algunos ejemplos de formatos numricos:


Console.WriteLine("Formato
-888.8);
Console.WriteLine("Formato
Console.WriteLine("Formado
Console.WriteLine("Formato
888.8888);
Console.WriteLine("Formato
Console.WriteLine("Formato
Console.WriteLine("Formato

de moneda - {0:C}

{1:C4}", 88.8,

entero - {0:D5}", 88);


exponencial - {0:E}", 888.8);
de punto fijo - {0:F3}",
general - {0:G}", 888.8888);
de nmero - {0:N}", 8888888.8);
hexadecimal - {0:X4}", 88);

El resultado de ejecutar este cdigo es el siguiente:


Formato
Formato
Formado
Formato
Formato
Formato
Formato

de moneda - $88.80 ($888.8000)


entero - 00088
exponencial - 8.888000E+002
de punto fijo - 888.889
general - 888.8888
de nmero - 8,888,888.80
hexadecimal 0058

Nota Para ms informacin sobre formatos, busque cadenas de formato en la


ayuda de Microsoft MSDN.

Introduccin a C#

14

Los mtodos Read y ReadLine


Objetivo del tema

Explicar los mtodos Read


y ReadLine de la clase
Console.

Explicacin previa

Los mtodos Read y


ReadLine permiten obtener
informacin introducida por
el usuario con el teclado.

Console.Read

y Console.ReadLine leen informacin


introducida por el usuario
z Read lee el siguiente carcter
z

Recomendacin al
profesor

No se ofrece ningn
ejemplo de Read porque,
para tener algn sentido, el
ejemplo tendra que mostrar
cmo pasar de un entero
(devuelto por Read) a un
carcter:
int i;
char c;
i = Console.Read( );
c = (char) i;
Console.WriteLine(c);

ReadLine lee toda la lnea introducida

Los mtodos Console.Read y Console.ReadLine se pueden utilizar para


mostrar informacin introducida por el usuario con el teclado.

El mtodo Read
Read lee el siguiente carcter desde el teclado. Devuelve el valor int 1 si ya
no hay ms informacin. De lo contrario, devuelve un int que representa el
carcter ledo.

El mtodo ReadLine
ReadLine lee todos los caracteres hasta el final de la lnea introducida (el
retorno de carcter de carro). La informacin introducida se devuelve como una
cadena de caracteres. El siguiente cdigo se puede utilizar para leer una lnea de
texto desde el teclado y mostrarla en la pantalla:
string input = Console.ReadLine( );
Console.WriteLine("{0}", input);

Introduccin a C#

15

Comentarios a aplicaciones
Objetivo del tema

Explicar cmo hacer


comentarios a aplicaciones.

Explicacin previa

Todas las aplicaciones


deben llevar comentarios
adecuados.

Los comentarios son importantes


z

Una aplicacin con los comentarios adecuados


permite a un desarrollador comprender perfectamente
la estructura de la aplicacin

Comentarios de una sola lnea

//
nombre
del usuario
// Obtener
Get the el
users
name
Console.WriteLine("Cmo
llama?
Console.WriteLine("What
is se
your
name?");
");
name
);
name ==Console.ReadLine(
Console.ReadLine
( );

Comentarios de varias lneas

/*
la mayor
de la
/* Encontrar
Find the higher
rootraz
of the
ecuacin
cuadrtica
*/
quadratic equation */
xx == ();
();

Recomendacin al
profesor

Los comentarios son


importantes, pero su
distribucin y densidad
dependen de las
preferencias del
desarrollador. Pregunte a
los estudiantes cules son
las normas sobre
comentarios seguidas en
sus organizaciones.

Es importante que todas las aplicaciones tengan una documentacin adecuada.


Siempre hay que incluir suficientes comentarios para que un desarrollador que
no participara en la creacin de la aplicacin original pueda seguir y
comprender su funcionamiento. Los comentarios deben ser exhaustivos y
pertinentes. Unos buenos comentarios aaden informacin que no es fcil de
expresar usando slo las instrucciones del cdigo, ya que explican el porqu
en lugar del qu. Siga las normas de su organizacin para comentar cdigo (si
las tiene).
C# ofrece varios mecanismos que permiten aadir comentarios al cdigo de
aplicaciones: comentarios de una sola lnea, comentarios de varias lneas y
documentacin generada en XML.
Para aadir un comentario de una sola lnea se pueden utilizar los caracteres de
barra diagonal (//). Al ejecutar la aplicacin, se ignora todo lo que sigue a estos
dos caracteres hasta el final de la lnea.
Tambin es posible hacer comentarios en bloques de varias lneas. Un
comentario en bloque empieza con el par de caracteres /* y contina hasta
llegar al el par de caracteres */ correspondiente. Los comentarios en bloques no
pueden estar anidados.

Introduccin a C#

16

Tratamiento de excepciones
Objetivo del tema

Explicar cmo capturar


excepciones de tiempo de
ejecucin en C#.

Explicacin previa

Una buena aplicacin C#


debe tener capacidad para
enfrentarse a lo inesperado.

Recomendacin al
profesor

En este tema se ofrecen


comentarios generales
sobre el tratamiento de
excepciones. Se darn ms
detalles en el mdulo 4,
Instrucciones y
excepciones, del curso
2124C, Programacin en
C#.

using
using System;
System;
public
public class
class Hello
Hello
{{
public
public static
static void
void Main(string
Main(string[[ ]] args
args))
{{
try{
try{
Console.WriteLine(args[0]);
Console.WriteLine(args[0]);
}}
catch
catch (Exception
(Exception e)
e) {{
Console.WriteLine("Excepcin
Console.WriteLine("Exception enat

{0}",
{0}", e.StackTrace
e.StackTrace );
);
}}
}}
}}

Una buena aplicacin C# debe tener capacidad para enfrentarse a lo inesperado.


Por muchas comprobaciones de error que se aadan al cdigo, siempre habr
algo que pueda ir mal. El usuario puede dar una respuesta imprevista a una
pregunta, por ejemplo, o tratar de escribir a un archivo en una carpeta que ha
sido borrada. Las posibilidades son infinitas.
Si se produce un error de tiempo de ejecucin en una aplicacin C#, el sistema
operativo lanza una excepcin. Las excepciones se pueden capturar con una
combinacin de las instrucciones try y catch, como se muestra en la
transparencia. Si alguna de las instrucciones en la parte try de la aplicacin
hace que se produzca una excepcin, la ejecucin pasar al bloque catch.
Para obtener informacin sobre la excepcin producida se pueden emplear las
propiedades StackTrace, Message y Source del objeto Exception. El
tratamiento de excepciones se tratar con ms detalle en un mdulo posterior.
Nota Si se imprime una excepcin, utilizando por ejemplo
Console.WriteLine, la excepcin se dar formato automticamente y mostrar
las propiedades StackTrace, Message y Source.

Introduccin a C#

17

Consejo Incluir el tratamiento de excepciones en aplicaciones C# desde el


principio es mucho ms sencillo que tratar de aadirlo despus.
Si no se utiliza tratamiento de excepciones se producir una excepcin en
tiempo de ejecucin. Si en lugar de ello se prefiere depurar un programa
utilizando depuracin Just-in-Time, es preciso activarla antes. Una vez
activada, depuracin Just-in-Time indicar el depurador que hay que utilizar
dependiendo del entorno y de las herramientas instaladas.

Ejecute los siguientes pasos para activar la depuracin Just-in-Time:


1. En el men Tools (Herramientas), pulse Options (Opciones).
2. En el cuadro de dilogo Options, haga clic en la carpeta Debugging
(Depuracin).
3. En la carpeta Debugging, pulse Just-In-Time Debugging (Depuracin
Just-in-Time).
4. Active o desactive la depuracin Just-in-Time (JIT) para distintos tipos de
programas y pulse OK.
El depurador se estudiar en detalle ms adelante en este mdulo.

Introduccin a C#

18

Compilacin, ejecucin y depuracin


Objetivo del tema

Ofrecer una introduccin a


los temas tratados en esta
seccin.

Explicacin previa

En esta seccin aprender


a compilar, ejecutar y
depurar programas C#.

Llamadas

al compilador

Ejecucin

de la aplicacin

Demostracin:

Compilacin y ejecucin de un

Demostracin:

Uso del depurador de Visual Studio

programa C#
Depuracin
Las

herramientas del SDK

Demostracin:

Uso del ILDASM

En esta leccin aprender a compilar y depurar programas C#. Ver cmo se


ejecuta el compilador desde la lnea de comandos y desde el entorno
Visual Studio. Aprender algunas opciones comunes de compilador y conocer
el Visual Studio Debugger. Finalmente, aprender a utilizar algunas de las otras
herramientas del kit de desarrollo de software (SDK) de Microsoft .NET
Framework..

Introduccin a C#

19

Llamadas al compilador
Objetivo del tema

Explicar cmo compilar una


aplicacin C# y las
diferentes opciones de
compilador disponibles.

Explicacin previa

En preciso compilar las


aplicaciones C# antes de
ejecutarlas.

Conmutadores comunes del compilador

Compilacin desde la lnea de comandos

Compilacin desde Visual Studio

Localizacin de errores

Antes de ejecutar una aplicacin C# es necesario compilarla. El compilador


convierte el cdigo fuente escrito por usted en cdigo mquina que puede
entender el sistema. Se pueden hacer llamadas al compilador de C# desde la
lnea de comandos o desde Visual Studio.
Nota Estrictamente hablando, las aplicaciones C# se compilan a lenguaje
intermedio de Microsoft (MSIL) y no al cdigo mquina nativo. El cdigo
MSIL se compila a su vez a cdigo mquina con el compilador Just-in-Time
(JIT) cuando se ejecuta la aplicacin. No obstante, tambin es posible compilar
directamente a cdigo mquina y evitar el compilador JIT empleando la utilidad
Native Image Generator (Ngen.exe), que crea una imagen nativa a partir de un
ensamblado administrado y la instala en la cach de imagen nativa del sistema
local. La ejecucin de Ngen.exe sobre un ensamblado hace que ste se cargue
ms rpido, ya que restaura cdigo y estructuras de datos desde la cach de
imagen nativa en lugar de generarlas de forma dinmica.

Conmutadores comunes del compilador


Es posible especificar distintos conmutadores para el compilador de C# usando
el comando csc. La siguiente tabla describe los conmutadores ms comunes.
Conmutador

Significado

/?, /help

Muestra las opciones del compilador en la salida estndar.

/out

Especifica el nombre del ejecutable.

/main

Especifica la clase que contiene el mtodo Main (si en la aplicacin


hay ms de una clase que incluya un mtodo Main).

/optimize

Activa y desactiva el optimizador de cdigo.

Introduccin a C#

20
(contina)
Conmutador

Significado

/warn

Fija el nivel de aviso del compilador.

/warnaserror

Trata todos los avisos como errores que interrumpen la compilacin.

/target

Especifica el tipo de aplicacin generada.

/checked

Indica si un desbordamiento aritmtico genera una excepcin en


tiempo de ejecucin.

/doc

Procesa comentarios de documentacin para crear un archivo XML.

/debug

Genera informacin sobre la depuracin.

Compilacin desde la lnea de comandos


Para compilar una aplicacin C# desde la lnea de comandos se emplea el
comando csc. Por ejemplo, para compilar la aplicacin Hola, mundo (Hola.cs)
desde la lnea de comandos, generar informacin sobre la depuracin y crear un
ejecutable llamado Saludo.exe, el comando es:
csc /debug+ /out:Saludo.exe Hola.cs

Importante El archivo de salida que contiene el cdigo compilado debe incluir


el sufijo .exe. Si se omite el sufijo, es necesario cambiar el nombre del archivo
antes de ejecutarlo.

Compilacin desde Visual Studio


Para compilar una aplicacin C# utilizando Visual Studio, abra el proyecto que
contiene la aplicacin C# y seleccione Build Solution (Compilar solucin) en
el men Build.
Nota Por defecto, Visual Studio abre la configuracin de depuracin (Debug)
para el proyecto. Esto significa que lo que se compila es una versin de
depuracin de la aplicacin. Si desea compilar una versin de lanzamiento que
no contenga informacin sobre la depuracin, cambie la configuracin de la
solucin a lanzamiento (Release).
Para cambiar las opciones empleadas por el compilador se puede modificar la
configuracin del proyecto:
1. En Solution Explorer, pulse con el botn derecho del ratn en el icono del
proyecto.
2. Pulse Properties (Propiedades).
3. En el cuadro de dilogo Property Pages (Pginas de propiedades), pulse
Configuration Properties (Propiedades de configuracin) seguido de
Build.
4. Especifique las opciones que desee del compilador y pulse OK.

Introduccin a C#

21

Localizacin de errores
El compilador de C# informar de los errores sintcticos o semnticos que
detecte.
Si la llamada al compilador se hizo desde la lnea de comandos, el compilador
mostrar mensajes en los que indicar los nmeros de lnea y el carcter dentro
de cada lnea donde se encontraran errores.
Si la llamada al compilador se hizo desde Visual Studio, la ventana Task List
(Lista de tareas) mostrar todas las lneas que incluyan errores. Haga doble clic
sobre una lnea de esta ventana para ir al error correspondiente en la aplicacin.
Consejo Es frecuente que un solo error de programacin varios errores de
compilacin. Lo mejor es repasar todos los errores a partir de los que se
encontraron primero, ya que corregir un error al principio del cdigo puede
hacer que desaparezcan automticamente varios errores posteriores.

Introduccin a C#

22

Ejecucin de la aplicacin
Objetivo del tema

Explicar cmo se ejecuta


una aplicacin compilada.

Explicacin previa

Una aplicacin C# se puede


ejecutar desde la lnea de
comandos o desde
Visual Studio.

Ejecucin
z Escribir

el nombre de la aplicacin

Ejecucin
z Pulsar

desde la lnea de comandos

desde Visual Studio

Start Without Debugging en el men Debug

Una aplicacin C# se puede ejecutar desde la lnea de comandos o desde el


entorno Visual Studio.

Ejecucin desde la lnea de comandos


Cuando la aplicacin se compila sin problemas se genera un archivo ejecutable
(un archivo cuyo sufijo es .exe). Para ejecutarlo desde la lnea de comandos,
escriba el nombre de la aplicacin (con o sin el sufijo .exe).

Ejecucin desde Visual Studio


Para ejecutar la aplicacin desde Visual Studio, pulse Start Without
Debugging (Iniciar sin depuracin) en el men Debug (Depurar) o pulse
CTRL+F5. Si se trata de una aplicacin de consola, se abrir inmediatamente
una ventana de consola y la aplicacin se ejecutar. Una vez finalizada la
aplicacin, el sistema le pedir que pulse cualquier tecla para continuar y la
ventana de consola se cerrar.

Introduccin a C#

23

Depuracin
Objetivo del tema

Explicar el uso de
Visual Studio para depurar
una aplicacin.

Explicacin previa

Visual Studio contiene


muchas herramientas
prcticas que le permitirn
depurar y corregir
aplicaciones.

Excepciones y depuracin JIT

El Visual Studio Debugger


z Configuracin
z Seguimiento
z Examen

de puntos de interrupcin e inspecciones

del cdigo paso a paso

y modificacin de variables

Excepciones y depuracin JIT


Si una aplicacin lanza una excepcin y no se ha escrito el cdigo necesario
para ese caso, el runtime de lenguaje comn har que se inicie una depuracin
JIT (no hay que confundir la depuracin JIT con el compilador JIT).
Suponiendo que se ha instalado Visual Studio, se abrir un cuadro de dilogo
que dar a elegir entre depurar la aplicacin con el Visual Studio Debugger
(entorno de desarrollo de Microsoft) o con el depurador del SDK de .NET
Framework.
Si se dispone de Visual Studio, lo ms recomendable es elegir el depurador del
entorno de desarrollo de Microsoft.
Nota El SDK de .NET Framework ofrece otro depurador llamado cordbg.exe,
que es un depurador para lnea de comandos. Incluye la mayor parte de las
funciones ofrecidas por el entorno de desarrollo de Microsoft, salvo la interfaz
grfica de usuario. En este curso no se discutir este depurador.
Recomendacin al
profesor

Abra Visual Studio y


muestre a los estudiantes
las opciones de men y las
barras de herramientas
durante la discusin.
Despus de este tema
encontrar una
demostracin ms
completa.

Configuracin de puntos de interrupcin e inspecciones


en Visual Studio
Se puede utilizar el Visual Studio Debugger para fijar puntos de interrupcin en
el cdigo y examinar los valores de variables.
Al pulsar con el botn derecho del ratn sobre una lnea de cdigo se abre un
men con muchas opciones tiles. Seleccione Insert Breakpoint para insertar
un punto de interrupcin en esa lnea. Tambin puede insertar un punto de
interrupcin pulsando en el margen izquierdo. Vuelva a pulsar para borrar el
punto. Al ejecutar la aplicacin en modo de depuracin, la ejecucin se
detendr en esta lnea y ser posible examinar el contenido de variables.

Introduccin a C#

24

La ventana Watch (Inspeccin) resulta til para supervisar los valores de


variables seleccionadas mientras se ejecuta la aplicacin. Si escribe el nombre
de una variable en la columna Name (Nombre), su valor aparecer en la
columna Value (Valor), por lo que podr ver todos los cambios que se
produzcan durante la ejecucin. Tambin es posible sobrescribir el valor de una
variable inspeccionada para modificarla.
Importante Antes de utilizar el depurador, asegrese de que la configuracin
de la solucin es Debug y no Release.

Seguimiento del cdigo paso a paso


Una vez fijados los puntos de interrupcin necesarios, se puede ejecutar la
aplicacin seleccionando Start (Inicio) en el men Debug o pulsando F5. La
ejecucin se detendr al llegar al primer punto de interrupcin.
La ejecucin se reanudar al seleccionar Continue (Continuar) en el men
Debug, aunque tambin se pueden emplear las opciones de avance paso a paso
del men Debug para avanzar en el cdigo lnea por lnea.
Consejo Las opciones de punto de interrupcin, avance paso a paso e
inspeccin de variables se encuentran tambin en la barra de herramientas
Debug.

Examen y modificacin de variables


Para ver las variables definidas en un mtodo se puede pulsar Locals (Locales)
en la barra de herramientas Debug o bien utilizar la ventana Watch. Tambin es
posible sobrescribir el valor de una variable para modificarla (como en la
ventana Watch).

Introduccin a C#

25

Uso del Visual Studio Debugger


Este programa C#, que convierte temperaturas de Fahrenheit a Celsius, contiene
un error que en algunos casos produce resultados incorrectos en la conversin
de temperaturas. Encuentre y corrija el problema.
Cmo ejecutar el programa C#
1. Abra el proyecto Converter, que se encuentra en la carpeta Converter dentro
del archivo demo02.zip.
2. Ejecute el programa seleccionando Start Without Debugging en el men
Debug o pulsando CTRL+F5.
Explique que el programa pide al usuario una temperatura en grados
Fahrenheit. A continuacin convierte ese valor en un entero y lo almacena
en la variable degreesFahrenheit. Luego calcula la temperatura Celsius
equivalente con la frmula de conversin estndar y almacena el resultado
en la variable degreesCelsius. Finalmente, el programa muestra la
temperatura Fahrenheit original junto con el valor calculado en Celsius.
3. Escriba 32 cuando el sistema le pida una temperatura.
Haga notar a los estudiantes que programa convierte esta temperatura en 0
grados Celsius, que es correcto.
4. Vuelva a ejecutar el programa y escriba 212 cuando el sistema le pida un
valor. Esta temperatura es el punto de ebullicin del agua.
Haga notar a los estudiantes que el programa da un resultado de 100 grados
Celsius, que tambin es correcto.
5. Ejecute el programa por tercera vez y escriba una temperatura de 75 grados
Fahrenheit.
Haga notar a los estudiantes que el resultado mostrado es 23 grados Celsius.
Esto es incorrecto, ya que 75 grados Fahrenheit son 23,8889 grados Celsius.
Explique que, aparentemente, el programa est truncando el resultado a un
entero.
Cmo identificar el error en el programa C# estableciendo un punto de
interrupcin y usando la ventana Watch (Inspeccin)
1. Coloque un punto de interrupcin justo despus de que programa lee la
temperatura Fahrenheit.
2. Ejecute el programa en modo de depuracin seleccionando Start en el men
Debug o pulsando.
Escriba 75 y pulse INTRO. El programa llega hasta el punto de interrupcin
y se detiene.
3. Abra la ventana Watch y aada las variables degreesFahrenheit y
degreesCelsius a la lista de variables inspeccionadas.
Explique que es posible supervisar los valores de variables en la ventana
Watch.

Introduccin a C#

26

4. Seleccione Step Over (Salto) en el men Debug o pulse F10 para ejecutar
el programa lnea por lnea a partir del punto de interrupcin.
En esto consiste el avance paso a paso. Se ejecuta la siguiente lnea de
cdigo y el programa se detiene, lo que permite ver en la ventana Watch los
cambios sufridos por las variables. Por ejemplo, el valor de
degreesFahrenheit es ahora 75. Al saltar a la siguiente lnea, la variable
degreesCelsius cambia cuando se calcula un valor de 23.0.
sta es la lnea que contiene el error. El problema es que se realiza un
clculo entero sobre un dato entero antes de asignarlo a una variable de
punto flotante. As se acumulan errores de redondeo y se obtiene un
resultado incorrecto.
5. Pulse F5 para finalizar la ejecucin del programa.
Cmo corregir el error en el programa C# y comprobar el resultado
1. Cambie una constante a un valor de punto flotante cambiando 32 a 32F, lo
que obliga al compilador a efectuar un clculo de punto flotante.
2. Vuelva a compilar y ejecutar el programa.
3. Seleccione Step Over en el men Debug para ver los resultados del cambio.
Ver que ahora la variable degreesCelsius tiene un valor de 23.8889 en la
ventana Watch.
4. Pulse F10 para continuar ejecutando el programa paso a paso.
5. Seleccione Continue en el men Debug para que el programa se ejecute
hasta el final.

Introduccin a C#

Prctica: Creacin de un programa C# sencillo


Objetivos
Al final de esta prctica, usted ser capaz de:
Crear un programa C#.
Compilar y ejecutar un programa C#.
Usar el Visual Studio Debugger.
Aadir tratamiento de excepciones a un programa C#.
Los archivos solucin de esta prctica se pueden encontrar en la carpeta
Solution del fichero lab02.zip

Ejercicio 1
Creacin de un programa C# sencillo
En este ejercicio utilizar Visual Studio para escribir un programa C#. El
programa le preguntar cmo se llama y luego le saludar por su nombre.
Cmo crear una nueva aplicacin C# de consola
1. Inicie Microsoft Visual Studio .NET.
2. En el men File (Archivo), seale New (Nuevo) y pulse Project (Proyecto).
3. Pulse Visual C# Projects en el cuadro Project Types (Tipos de proyecto).
4. Pulse Console Application (Aplicacin de consola) en el cuadro Templates
(Plantillas).
5. Escriba Saludos en el cuadro Name (Nombre).
6. Escriba la ubicacin deseada para el proyecto en el cuadro Location
(Ubicacin) y pulse OK.
7. Escriba un comentario adecuado para el resumen.
8. Cambie el nombre de la clase a Saludar.
9. Guarde el proyecto seleccionando Save All (Guardar todo) en el men File.
Cmo escribir instrucciones para preguntar y saludar al usuario
1. Inserte la siguiente lnea en el mtodo Main despus de los comentarios
TODO:
string miNombre;

2. Escriba una instruccin que pregunte el nombre a los usuarios.


3. Escriba otra instruccin que lea la respuesta del usuario desde el teclado y la
asigne a la cadena miNombre.
4. Aada una instruccin ms que imprima Hola, miNombre en pantalla
(donde miNombre es el nombre escrito por el usuario).
5. Una vez terminado, el mtodo Main debe contener lo siguiente:

Introduccin a C#

2
static void Main(string[ ] args)
{
string miNombre;
Console.WriteLine("Por favor, escriba su nombre");
miNombre = Console.ReadLine( );
Console.WriteLine("Hola {0}", miNombre);
}

6. Guarde el trabajo realizado.


Cmo compilar y ejecutar el programa
1. En el men Build, seleccione Build Solution (o pulse CTRL+SHIFT+B).
2. Corrija los posibles errores de compilacin y vuelva a compilar si es
necesario.
3. En el men Debug, seleccione Start Without Debugging (o pulse
CTRL+F5).
4. En la ventana de consola que se abrir, escriba su nombre cuando se lo pida
el programa y pulse INTRO.
5. Despus de ver el saludo, pulse una tecla cuando aparezca el mensaje Pulse
cualquier tecla para continuar.

Introduccin a C#

Ejercicio 2
Compilacin y ejecucin del programa C# desde la lnea de
comandos
En este ejercicio compilar y ejecutar su programa desde la lnea de
comandos.
Cmo compilar y ejecutar la aplicacin desde la lnea de comandos
1. Desde el botn de Inicio de Windows, entre en Todos los programas y luego
pulse Visual Studio .NET, seguido de Visual Studio .NET Tools y
finalmente Visual Studio .NET Command Prompt.
2. Vaya a la carpeta Saludos, donde se encuentra el proyecto del apartado
anterior.
3. Compile el programa con el siguiente comando:
4. csc /out:Saludo.exe Class1.cs
5. Ejecute el programa escribiendo:
Saludo
6. Cierre la ventana Command (Comandos).

Introduccin a C#

Ejercicio 3
Uso del depurador
En este ejercicio utilizar el Visual Studio Debugger para ejecutar su programa
paso a paso y examinar el valor de una variable.
Para configurar un punto de interrupcin e iniciar la depuracin con
Visual Studio
7. Inicie Visual Studio .NET si an no se est ejecutando.
8. En el men File, seale Open (Abrir) y pulse Project.
9. Abra el proyecto Saludos.sln en la carpeta Saludos del proyecto del apartado
anterior. Tambin se puede encontrar dentro del fichero lab02.zip.
10. Pulse en el margen derecho sobre la lnea en que aparece por primera vez
Console.WriteLine en la clase Saludar.
En el margen aparecer un punto de interrupcin (u punto grande y rojo).
11. En el men Debug, seleccione Start (o pulse F5).
Al iniciarse la ejecucin del programa, se abrir una ventana de consola y
luego el programa se detendr en el punto de interrupcin.
Cmo inspeccionar el valor de una variable
12. En el men Debug, pulse Windows, luego Watch y finalmente Watch 1.
13. En la ventana Watch, aada la variable miNombre a la lista de variables
inspeccionadas.
14. La variable miNombre aparecer en la ventana Watch con un valor de null.
Cmo ejecutar el cdigo paso a paso
1. En el men Debug, seleccione Step Over (o pulse F10) para ejecutar la
primera instruccin Console.WriteLine.
2. Pulse F10 para saltar a la siguiente lnea que contiene la instruccin
Console.ReadLine.
3. Vuelva a la ventana de consola y escriba su nombre, y a continuacin pulse
la tecla INTRO.
Regrese a Visual Studio. Su nombre ser el valor de la variable miNombre
en la ventana Watch.
4. Pulse F10 para saltar a la siguiente lnea que contiene la instruccin
Console.WriteLine.
5. Ponga en primer plano la ventana de consola.
Aparecer el saludo.
6. Regrese a Visual Studio. En el men Debug, seleccione Continue (o pulse
F5) para ejecutar el programa hasta el final.

Introduccin a C#

Ejercicio 4
Adicin de tratamiento de excepciones a un programa C#
En este ejercicio escribir un programa que utiliza tratamiento de excepciones
para capturar errores inesperados en tiempo de ejecucin. El programa pide al
usuario dos valores enteros, divide el primero por el segundo y muestra el
resultado.
Para crear un programa C# nuevo
1. Inicie Visual Studio .NET si an no se est ejecutando.
2. En el men File, seale New y pulse Project.
3. Pulse Visual C# Projects en el cuadro Project Types.
4. Pulse Console Application en el cuadro Templates.
5. Escriba Divisor en el cuadro Name.
6. Escriba la ubicacin deseada para el proyecto en el cuadro Location
(Ubicacin) y pulse OK.
7. Escriba un comentario adecuado para el resumen.
8. Cambie el nombre de la clase a Dividir.
9. Guarde el proyecto seleccionando Save All en el men File.
Cmo escribir instrucciones para pedir dos enteros al usuario
1. En el mtodo Main, escriba una instruccin que pida al usuario el primer
entero.
2. Escriba otra instruccin que lea la respuesta del usuario desde el teclado y la
asigne a una variable llamada temp de tipo string.
3. Aada la siguiente instruccin para convertir el valor de la cadena de temp
en un entero y almacenar el resultado en i:
int i = Int32.Parse(temp);

4. Aada al cdigo instrucciones para:


a. Pedir al usuario el segundo entero.
b. Leer la respuesta del usuario desde el teclado y asignarla a temp.
c. Convertir el valor de temp en un entero y almacenar el resultado en j.
El cdigo debera ser parecido al siguiente:
Console.WriteLine("Escriba el primer entero");
string temp = Console.ReadLine( );
int i = Int32.Parse(temp);
Console.WriteLine("Escriba el segundo entero");
temp = Console.ReadLine( );
int j = Int32.Parse(temp);

5. Guarde el trabajo realizado.

Introduccin a C#

Cmo dividir el primer entero por el segundo y mostrar el resultado


1. Cree una nueva variable entera k que reciba el valor resultante de dividir i
entre j, e insrtelo al final del procedimiento anterior. El cdigo debera ser
como esto:
int k = i / j;

2. Aada una instruccin para mostrar el valor de k.


3. Guarde el trabajo realizado.
Cmo probar el programa
1. En el men Debug, seleccione Start Without Debugging (o pulse
CTRL+F5).
2. Escriba 10 como valor del primer entero y pulse INTRO.
3. Escriba 5 como valor del segundo entero y pulse INTRO.
4. Compruebe que el valor de k que aparece es 2.
5. Pulse CTRL+F5 para volver a ejecutar el programa.
6. Escriba 10 como valor del primer entero y pulse INTRO.
7. Escriba 0 como valor del segundo entero y pulse INTRO.
8. El programa provoca el lanzamiento de una excepcin (divisin por cero).
9. Pulse No para que desaparezca el cuadro de dilogo de la depuracin Justin-Time.
Cmo aadir tratamiento de excepciones al programa
1. Ponga el cdigo del mtodo Main dentro de un bloque try, como se indica a
continuacin:
try
{

Console.WriteLine (...);
...
int k = i / j;
Console.WriteLine(...);
}

2. Aada a Main una instruccin catch despus del bloque try. La instruccin
catch tiene que imprimir un mensaje corto, como se ve en este cdigo:
catch(Exception e)
{
Console.WriteLine("Excepcin lanzada: {0}" , e);
}
...

3. Guarde el trabajo realizado.

Introduccin a C#

4. El mtodo Main completo ser similar al siguiente:


public static void Main(string[ ] args)
{
try {
Console.WriteLine ("Escriba el primer entero");
string temp = Console.ReadLine( );
int i = Int32.Parse(temp);
Console.WriteLine ("Escriba el segundo entero");
temp = Console.ReadLine( );
int j = Int32.Parse(temp);
int k = i / j;
Console.WriteLine("El resultado de dividir {0} por {1}
es {2}", i, j, k);
}
catch(Exception e) {
Console.WriteLine("Excepcin lanzada: {0}", e);
}
}

Cmo probar el cdigo para tratamiento de excepciones


1. Pulse CTRL+F5 para volver a ejecutar el programa.
2. Escriba 10 como valor del primer entero y pulse INTRO.
3. Escriba 0 como valor del segundo entero y pulse INTRO.
El programa sigue provocando el lanzamiento de una excepcin (divisin
por cero), pero esta vez el error es capturado y aparece su mensaje.

Uso de variables de tipo valor

Prctica : Creacin y uso de tipos


Objetivos
Al final de esta prctica, usted ser capaz de:
Crear nuevos tipos de datos.
Definir y utilizar variables.

Requisitos previos
Antes de realizar la prctica debe estar familiarizado con los siguientes temas:
El sistema de tipos comunes (Common Type System, CTS).
Variables de tipo valor en C#.

Sumario
En el Ejercicio 1 escribir un programa que crea un tipo enum simple y a
continuacin asigna e imprime los valores utilizando la instruccin
Console.WriteLine.
En el Ejercicio 2 escribir un programa que utiliza en una struct el tipo enum
declarado en el Ejercicio 1.
Si le queda tiempo, tambin aadir funcionalidad de entrada/salida al
programa escrito en el Ejercicio 2.

Archivos de inicio y solucin


Existen archivos de inicio y solucin para esta prctica. Los archivos de inicio
estn en la carpeta Starter, mientras que los archivos de solucin se encentran
en Solution. Estas dos carpetas se encuentran dentro del archivo lab03.zip

Uso de variables de tipo valor

Ejercicio 1
Creacin de un tipo enum
En este ejercicio crear un tipo enumerado para representar distintos tipos de
cuentas bancarias (cuentas corrientes y de ahorro). Utilizar este tipo enum
para crear dos variables a las que asignar los valores Corriente y Ahorro.
Finalmente emplear la funcin System.Console.WriteLine para imprimir los
valores de las variables.
Cmo crear un tipo enum
1. Abra el proyecto BankAccount.sln en la carpeta Starter\BankAccount dentro
del fichero lab03.zip.
2. Abra el archivo Enum.cs y aada un enum llamado TipoCuenta antes de la
definicin de clase:
public enum TipoCuenta { Corriente, Ahorro }

Este enum contendr los tipos Corriente y Ahorro.


3. Declare en Main dos variables de tipo TipoCuenta:
TipoCuenta goldCuenta;
TipoCuenta platinumCuenta;

4. Asigne a la primera variable el valor Corriente y a la segunda el valor


Ahorro:
goldCuenta = TipoCuenta.Corriente;
platinumCuenta = TipoCuenta.Ahorro;

5. Aada dos instrucciones Console.WriteLine que impriman el valor de cada


variable:
Console.WriteLine("El tipo de cuenta del cliente es {0}"
, goldCuenta);
Console.WriteLine("El tipo de cuenta del cliente es {0}"
, platinumCuenta);

6. Compile y ejecute el programa.

Uso de variables de tipo valor

Ejercicio 2
Creacin y uso de un tipo struct
En este ejercicio definir una struct que se puede usar para representar una
cuenta bancaria. Emplear variables para el nmero de cuenta (long), el saldo
de la cuenta (decimal) y el tipo de cuenta (el enum creado en el Ejercicio 1).
Crear una variable de tipo struct, le asignar algunos datos de ejemplo e
imprimir el resultado.
Cmo crear un tipo struct
1. Abra el proyecto StructType.sln en la carpeta Starter\StructType dentro del
fichero lab03.zip.
2. Abra el archivo Struct.cs y aada una public struct llamada
CuentaBancaria que contenga los siguientes campos.
Tipo

Variable

public long

cuentaNum

public decimal

cuentaSaldo

public TipoCuenta

cuentaTipo

3. Declare en Main una variable goldCuenta de tipo TipoCuenta.


CuentaBancaria goldCuenta;

4. Asigne valores a los campos cuentaTipo, cuentaSaldo y cuentaNum de la


variable goldCuenta.
goldCuenta.cuentaTipo = TipoCuenta.Corriente;
goldCuenta.CuentaSaldo = (decimal)3200.00;
goldCuenta.cuentaNum = 123;

5. Aada instrucciones Console.WriteLine que impriman el valor de cada


elemento en la variable struct.
Console.WriteLine("Nmero de cuenta {0}",
goldCuenta.cuentaNum);
Console.WriteLine("Tipo de cuenta
{0}",
goldCuenta.cuentaTipo);
Console.WriteLine("Saldo de la cuenta ${0}",
goldCuenta.CuentaSaldo);

6. Compile y ejecute el programa.

Uso de variables de tipo valor

Si el tiempo lo permite
Adicin de funcionalidad de entrada/salida
En este ejercicio tendr que modificar el cdigo escrito en el Ejercicio 2. En
lugar de usar el nmero de cuenta 123, pedir que sea el usuario quien lo
introduzca el nmero y usar ese nmero para imprimir el resumen de la cuenta.
Cmo aadir funcionalidad de entrada/salida
1. Abra el proyecto StructType.sln en la carpeta Starter\Optional dentro del
fichero lab03.zip.
2. Abra el archivo Struct.cs y cambie la lnea siguiente:
goldCuenta.cuentaNum = 123; //borre esta lnea y escriba el
siguiente cdigo

por una instruccin Console.Write que pregunte el nmero de cuenta al


usuario:
Console.Write("Introduzca el nmero de cuenta: ");

3. Utilice una instruccin Console.ReadLine para leer el nmero de cuenta y


asigne este valor a goldCuenta.cuentaNum.
goldCuenta.cuentaNum = long.Parse(Console.ReadLine());

Nota Hay que utilizar el mtodo long.Parse para convertir la cadena leda
por la instruccin Console.ReadLine en un valor decimal antes de asignarlo
a goldCuenta.cuentaNum.
4. Compile y ejecute el programa. Escriba un nmero de cuenta cuando se lo
pida el programa.

Uso de variables de tipo valor

Contenido
Descripcin general

Sistema de tipos comunes (CTS)

Nombres de variables
Uso de tipos de datos predefinidos

8
12

Creacin de tipos de datos definidos por el


usuario
21
Conversin de tipos de datos

25

Uso de variables de tipo valor

Notas para el instructor


Este mdulo ofrece a los estudiantes una introduccin al sistema de tipos
comunes (Common Type System, CTS). Los estudiantes conocern las
variables de tipo valor y tambin crearn y utilizarn tipos de datos definidos
por el usuario.
Al final de este mdulo, los estudiantes sern capaces de:
Describir los tipos de variables que se pueden emplear en aplicaciones C#.
Nombrar variables segn las convenciones de nomenclatura estndar de C#.
Declarar variables utilizando tipos de datos predefinidos.
Asignar valores a variables.
Convertir variables existentes de un tipo de dato a otro.
Crear y utilizar sus propios tipos de datos.

Uso de variables de tipo valor

Descripcin general
Objetivo del tema

Ofrecer una introduccin a


los contenidos y objetivos
del mdulo.

Explicacin previa

En este mdulo aprender a


usar variables de tipo valor
en C#.

Recomendacin al
profesor

Si desea ms informacin
sobre los temas tratados en
este mdulo, consulte la
documentacin de la
biblioteca de clases de .NET
Framework y la
especificacin del lenguaje
C# en los documentos de
ayuda de Visual Studio
.NET.

Sistema de tipos comunes (CTS)

Nombres de variables

Uso de tipos de datos predefinidos

Creacin de tipos de datos definidos por el usuario

Conversin de tipos de datos

Todas las aplicaciones manipulan datos de alguna manera. Como desarrollador


de C#, necesitar aprender a almacenar y procesar datos en sus aplicaciones.
Cada vez que una aplicacin tiene que almacenar datos temporalmente para
usarlos durante la ejecucin, esos datos se almacenan en una variable. Antes de
utilizar una variable hay que definirla, y cuando se define una variable lo que se
hace en realidad es reservar espacio de almacenamiento para ella, identificando
su tipo de datos y dndole un nombre. Una vez definida, ya es posible asignar
valores a esa variable.
En este mdulo aprender a usar variables de tipo valor en C#. Estudiar cmo
especificar el tipo de datos de las variables, cmo nombrar variables segn las
convenciones de nomenclatura estndar y cmo asignar valores a variables.
Aprender tambin a convertir variables existentes de un tipo de dato a otro y a
crear sus propias variables.
Al final de este mdulo, los estudiantes sern capaces de:
Describir los tipos de variables que puede emplear en aplicaciones C#.
Nombrar variables segn las convenciones de nomenclatura estndar de C#.
Declarar una variable utilizando tipos de datos predefinidos.
Asignar valores a variables.
Convertir variables existentes de un tipo de dato a otro.
Crear y utilizar sus propios tipos de datos.

Uso de variables de tipo valor

Sistema de tipos comunes (CTS)


Objetivo del tema

Ofrecer una introduccin a


los temas tratados en esta
seccin.

Explicacin previa

En esta seccin conocer


algunos de los tipos de
datos de C#, as como el
sistema de tipos comunes.

Aspectos generales del CTS

Comparacin de tipos de valor y de referencia

Comparacin de tipos de valor predefinidos y definidos


por el usuario

Tipos simples

Cada variable tiene un tipo de datos que determina los valores que se pueden
almacenar en ella. C# es un lenguaje de especificaciones seguras (type-safe), lo
que significa que el compilador de C# garantiza que los valores almacenados en
variables son siempre del tipo adecuado.
El runtime de lenguaje comn incluye un sistema de tipos comunes (Common
Type System, CTS) que define un conjunto de tipos de datos predefinidos que
se pueden utilizar para definir variables.
Al final de esta leccin, usted ser capaz de:
Explicar cmo funciona el CTS.
Elegir los tipos de datos ms adecuados para sus variables.

Uso de variables de tipo valor

Aspectos generales del CTS


Objetivo del tema
Describir el CTS.

Explicacin previa

El CTS es compatible con


estilos de programacin
procedurales y orientados a
objetos. Adems, el CTS
admite tipos de valor y de
referencia.

El CTS admite tanto tipos de valor como de referencia

Tipo
Tipo

Tipo
Tipo de
de valor
valor

Tipo
Tipo de
de referencia
referencia

Al definir una variable es necesario elegir el tipo de datos correcto para ella. El
tipo de datos determina los valores permitidos para esa variable, los cuales a su
vez determinan las operaciones que se pueden efectuar sobre ella.

CTS
El CTS es una parte integral del runtime de lenguaje comn y es compartido
por los compiladores, las herramientas y el propio runtime. Es el modelo que
define las reglas que sigue el runtime a la hora de declarar, usar y gestionar
tipos. El CTS establece un marco que permite la integracin entre lenguajes, la
seguridad de tipos y la ejecucin de cdigo con altas prestaciones.
En este mdulo estudiar dos tipos de variables:
Variables de tipos de valor.
Variables de tipos de referencia.

Uso de variables de tipo valor

Comparacin de tipos de valor y de referencia


Objetivo del tema

Describir las diferencias


entre tipos de valor y de
referencia.

Explicacin previa

Este mdulo se concentra


en los tipos de valor. Entre
los tipos de valor y los tipos
de referencia existen
considerables diferencias
que los desarrolladores
deben comprender.

Tipos de valor:

Contienen sus datos


directamente

Tipos de referencia:

Cada una tiene su


propia copia de datos

Almacenan referencias a
sus datos (conocidos como
objetos)

Las operaciones
sobre una no afectan
a otra

Dos variables de referencia


pueden apuntar al mismo
objeto

Las operaciones sobre una


pueden afectar a otra

Tipos de valor
Las variables de tipos de valor contienen sus datos directamente. Cada una de
ellas tiene su propia copia de los datos, por lo que las operaciones efectuadas
sobre una variable no pueden afectar a otra.

Tipos de referencia
Las variables de tipos de referencia contienen referencias a sus datos. Los datos
para estas variables se almacenan en un objeto. Es posible que dos variables de
tipos de referencia apunten al mismo objeto, por lo que las operaciones
efectuadas sobre una variable pueden afectar al objeto apuntado por otra
variable de referencia.
Nota Todos los tipos de datos bsicos estn definidos en el espacio de nombres
System y, en ltimo trmino, se derivan de System.Object. Los tipos de valor
se derivan de System.ValueType.

Uso de variables de tipo valor

Comparacin de tipos de valor predefinidos y definidos por el


usuario
Objetivo del tema

Comparar tipos de valor


predefinidos y definidos por
el usuario.

Tipos de valor

Explicacin previa

Los tipos de valor incluyen


tipos predefinidos y
definidos por el usuario. En
este tema veremos algunos
ejemplos de cada tipo.

Predefinido

Ejemplos de tipos de
valor predefinidos:

Del usuario

Ejemplos de tipos de valor


definidos por el usuario:

int

enum

float

struct

Los tipos de valor incluyen tipos de datos predefinidos y definidos por el


usuario. La diferencia entre los dos tipos en C# es mnima, puesto que los tipos
definidos por el usuario se pueden usar de la misma forma que los predefinidos.
La nica diferencia real entre tipos de datos predefinidos y tipos de datos
definidos por el usuario es que para los primeros se pueden escribir valores
literales. Todos los tipos de valor contienen datos directamente y no pueden ser
null.
En este mdulo aprender a crear tipos de datos definidos por el usuario, como
tipos de enumeraciones y tipos de estructuras.

Uso de variables de tipo valor

Tipos simples
Objetivo del tema

Describir los tipos simples.

Explicacin previa

C# ofrece un conjunto de
tipos de estructura
predefinidos llamados tipos
simples.

Se identifican mediante palabras reservadas


z

int // Palabra reservada

-oz

System.Int32

Los tipos de valor predefinidos tambin reciben el nombre de tipos de datos


bsicos o tipos simples. Los tipos simples se identifican por medio de palabras
reservadas que son alias para tipos de estructura predefinidos.
Un tipo simple y el tipo de estructura correspondiente son completamente
indistinguibles. En el cdigo se puede utilizar la palabra reservada o el tipo de
estructura. Los ejemplos que siguen ilustran ambas posibilidades:
byte // Palabra reservada

O
System.Byte // tipo de estructura

int // Palabra reservada

O
System.Int32 // tipo de estructura

Para ms informacin sobre los tamaos e intervalos de tipos de valor


predefinidos, busque tipos de valor en los documentos de ayuda de
Microsoft Visual Studio .NET.

Uso de variables de tipo valor

La siguiente tabla muestra las palabras reservadas y el tipo de estructura


equivalente.
Palabras reservadas

Alias para tipo de estructura

sbyte
byte
short
ushort
int
uint
long
ulong
char
float
double
bool
decimal

System.SByte
System.Byte
System.Int16
System.UInt16
System.Int32
System.UInt32
System.Int64
System.UInt64
System.Char
System.Single
System.Double
System.Boolean
System.Decimal

Uso de variables de tipo valor

Nombres de variables
Objetivo del tema

Ofrecer una introduccin a


los temas tratados en esta
seccin.

Explicacin previa

En esta seccin aprender


a asignar y utilizar nombres
de variables significativos
en una aplicacin C#.

Reglas y recomendaciones para nombrar variables

Palabras clave de C#

Problema: Puede encontrar nombres de variables no


permitidos?

Para usar una variable hay que elegir primero un nombre apropiado y
significativo para ella. Cada variable tiene un nombre al que se conoce tambin
por identificador de variable.
En el momento de nombrar variables se deben seguir las recomendaciones de
nomenclatura estndar recomendadas para C#. Tambin hay que conocer las
palabras reservadas de C# que no se pueden utilizar para nombres de variables.
Al final de esta leccin, usted ser capaz de:
Identificar las palabras reservadas de C#.
Nombrar sus variables segn las convenciones de nomenclatura estndar de C#.

Uso de variables de tipo valor

Reglas y recomendaciones para nombrar variables


Objetivo del tema

Aprender las reglas para


nombrar variables.

Explicacin previa

Reglas
z

Hay reglas y
recomendaciones que se
deben seguir al elegir el
nombre de una variable.

Recomendaciones
z

z
z

Recomendacin al
profesor

Insista en que C# distingue


maysculas y minsculas,
como C y C++.

Use letras, el signo de subrayado


y dgitos
Evite poner todas las letras en
maysculas
Evite empezar con un signo de
subrayado
Evite el uso de abreviaturas
Use PascalCasing para nombres
con varias palabras

9
8

Respuesta42
Respuesta42
42Respuesta
42Respuesta

diferente
diferente
Diferente
Diferente

9
9

Mal
Mal
_regular
_regular
Bien
Bien

8
8
9

Msj
Msj
Mensaje
Mensaje

8
9

Al nombrar variables hay que respetar las siguientes reglas y recomendaciones.

Reglas
Las siguientes son reglas de nomenclatura para variables de C#:
Comience todos los nombres de variables con una letra o un signo de
subrayado.
Despus del primer carcter, use letras, dgitos o el signo de subrayado.
No utilice palabras reservadas.
Si usa un nombre de variable no permitido, se producir un error en tiempo de
compilacin.

Recomendacin al
profesor

Anime a los estudiantes a


seguir estas
recomendaciones.
Explqueles que el uso de
convenciones de
nomenclatura estndar les
ayudar a desarrollar cdigo
coherente y de sencillo
mantenimiento.

Recomendaciones
Es aconsejable seguir estas recomendaciones a la hora de nombrar variables:
Evite poner todas las letras en maysculas.
Evite empezar con un signo de subrayado.
Evite el uso de abreviaturas.
Use PascalCasing para nombres con varias palabras.

Uso de variables de tipo valor

10

Convencin de nomenclatura PascalCasing


La convencin de nomenclatura PascalCasing consiste en poner en mayscula
el primer carcter de todas las palabras. Utilice PascalCasing para clases,
mtodos, propiedades, enumeraciones, interfaces, campos constantes y de slo
lectura, espacios de nombres y propiedades, como se muestra en el siguiente
ejemplo:
void InicializarDatos( );

Convencin de nomenclatura camelCasing


La convencin de nomenclatura camelCasing consiste en poner en mayscula el
primer carcter de todas las palabras excepto la primera. Utilice camelCasing
para variables que definan campos y parmetros, como se muestra en el
siguiente ejemplo:
int bucleNumMax;

Para ms informacin sobre convenciones de nomenclatura, busque


instrucciones de nomenclatura en los documentos de ayuda del kit de
desarrollo de software (SDK) de .NET.

Uso de variables de tipo valor

11

Palabras clave de C#
Objetivo del tema

Dar una lista de algunas de


las palabras reservadas
ms comunes.

Las palabras clave son identificadores reservados

Explicacin previa

Las palabras clave son


identificadores reservados
para el lenguaje y no se
pueden utilizar como
nombres de variables.

abstract,
abstract, base,
base, bool,
bool, default,
default, if,
if, finally
finally

No utilice palabras clave como nombres de variables


z

Produce errores en tiempo de compilacin

Procure no usar palabras clave cambiando maysculas


y minsculas
int
int INT;
INT; //
// Mal
Mal estilo
estilo

Las palabras clave estn reservadas, lo que significa que no se puede utilizar
ninguna de ellas como nombre de variable en C#. El uso de una palabra clave
como nombre de variable produce un error en tiempo de compilacin.

Palabras clave en C#
A continuacin se ofrece una lista de palabras clave en C#. Recuerde que
ninguna de estas palabras se puede emplear como nombre de variable.
abstract
byte
class
delegate
event
fixed
if
internal
new
override
readonly
short
struct
try
unsafe
volatile

as
case
const
do
explicit
float
implicit
is
null
params
ref
sizeof
switch
typeof
ushort
while

base
catch
continue
double
extern
for
in
lock
object
private
return
stackalloc
this
uint
using

bool
char
decimal
else
false
foreach
int
long
operator
protected
sbyte
static
throw
ulong
virtual

break
checked
default
enum
finally
goto
interface
namespace
out
public
sealed
string
true
unchecked
void

Uso de variables de tipo valor

12

Uso de tipos de datos predefinidos


Objetivo del tema

Ofrecer una introduccin a


los temas tratados en esta
seccin.

Explicacin previa

Es importante comprender
qu tipos de valor contienen
datos directamente y no
pueden contener valores
null.

Declaracin de variables locales

Asignacin de valores a variables

Asignacin compuesta

Operadores comunes

Incremento y decremento

Precedencia de operadores

Para crear una variable hay que elegir un nombre, declarar la variable y
asignarle un valor, salvo si C# ya le ha asignado un valor automticamente.
Al final de esta leccin, usted ser capaz de:
Crear una variable local utilizando tipos de datos predefinidos.
Usar operadores para asignar valores a variables.
Definir constantes y variables de slo lectura.

Uso de variables de tipo valor

13

Declaracin de variables locales


Objetivo del tema

Explicar cmo declarar


variables locales.

Explicacin previa

En C# es muy importante
saber usar variables locales.

Se suelen declarar por tipo de dato y nombre de variable:

int
int objetoCuenta;
objetoCuenta;

Es posible declarar mltiples variables en una


declaracin:

int
int objetoCuenta,
objetoCuenta, empleadoNmero;
empleadoNmero;
--o-int
int objetoCuenta,
objetoCuenta,
empleadoNmero;
empleadoNmero;

Recomendacin al
profesor

Es posible que los


estudiantes no estn
familiarizados con mtodos,
propiedades e indizadores.
sta es la primera vez en el
curso en que aparecen
estos trminos. Explique
que un mtodo es como una
funcin. Mencione que
estos temas se tratarn en
otros mdulos del curso.

Las variables declaradas en mtodos, propiedades o indizadores se llaman


variables locales. Una variable local se declara normalmente especificando el
tipo de dato seguido por el nombre de la variable, como se ve en el siguiente
ejemplo:
int objetoCuenta;

Es posible declarar mltiples variables en una sola declaracin separndolas


con una coma, como en este ejemplo:
int objetoCuenta, empleadoNumero;

En C# no se pueden usar variables sin inicializar. Este cdigo producira un


error en tiempo de compilacin porque no se ha asignado un valor inicial a la
variable bucleCuenta:
int bucleCuenta;
Console.WriteLine ("{0}", bucleCuenta);

Uso de variables de tipo valor

14

Asignacin de valores a variables


Objetivo del tema

Aprender a asignar valores


a variables.

Explicacin previa

Antes de poder usar


variables sin inicializar hay
que asignarles valores. En
este tema veremos algunas
instrucciones sencillas de
asignacin.

Asignar valores a variables ya declaradas:

int
int empleadoNumero;
empleadoNumero;
empleadoNumero
empleadoNumero == 23;
23;

Inicializar una variable cuando se declara:

int
int empleadoNumero
empleadoNumero == 23;
23;

Tambin es posible inicializar valores de caracteres:

char
char inicialNombre
inicialNombre == 'J';
'J';

Para asignar un nuevo valor a una variable se utilizan operadores de asignacin.


En el caso de una variable ya declarada se usa el operador de asignacin (=),
como se ve en el siguiente ejemplo:
int empleadoNumero;
empleadoNumero = 23;

Tambin es posible inicializar una variable al declararla, como en este ejemplo:


int empleadoNumero = 23;

Se puede usar el operador de asignacin para asignar valores a variables de tipo


carcter, como en este caso:
char inicialNombre = 'J';

Uso de variables de tipo valor

15

Asignacin compuesta
Objetivo del tema

Describir la unin de
operadores para asignacin
compuesta.

Explicacin previa

Muchas veces se necesita


sumar o restar un valor a
una variable en lugar de
asignarle un valor
totalmente nuevo.

Es muy habitual sumar un valor a una variable

itemCount
itemCount == itemCount
itemCount ++ 40;
40;

Se puede usar una expresin ms prctica

itemCount
itemCount +=
+= 40;
40;

Esta abreviatura es vlida para todos los operadores


aritmticos:

itemCount
itemCount -=
-= 24;
24;

Recomendacin al
profesor

Los programadores de
Microsoft Visual Basic no
estarn familiarizados con la
asignacin compuesta.

Es muy habitual sumar u valor a una variable


El siguiente cdigo declara una variable int llamada objetoCuenta, le asigna el
valor 2 y posteriormente la incrementa en 40:
int objetoCuenta;
objetoCuenta = 2;
objetoCuenta = objetoCuenta + 40;

Se puede usar una expresin ms prctica


Este cdigo funciona para incrementar una variable, pero es un poco farragoso
porque hay que escribir dos veces el identificador que se desea incrementar.
Esto no suele ser un problema para identificadores simples, salvo que haya
muchos identificadores con nombres similares. No obstante, es posible utilizar
expresiones tan complejas como se quiera para designar el valor que se
incrementa, como en este ejemplo:
items[(index + 1) % 32] = items[(index + 1) % 32] + 40;

En estos casos es muy fcil cometer algn pequeo error al escribir dos veces la
expresin. Afortunadamente, existe una forma abreviada que evita la
duplicacin:

Uso de variables de tipo valor

16
objetoCuenta += 40;
items[(index + 1) % 32] += 40;

Esta abreviatura es vlida para todos los operadores


aritmticos
var
var
var
var
var

+=
-=
*=
/=
%=

expresion;
expresion;
expresion;
expresion;
expresion;

//
//
//
//
//

var
var
var
var
var

=
=
=
=
=

var
var
var
var
var

+ expresin
- expresin
* expresin
/ expresin
% expresin

Uso de variables de tipo valor

17

Operadores comunes
Objetivo del tema

Describir operadores
comunes que se pueden
emplear en C#.

Operadores
Operadores comunes
comunes

Explicacin previa

Los operadores de
asignacin se usan para
asignar valores a variables,
descriptores de acceso a
propiedades y descriptotes
de acceso a ndices. Aqu
veremos algunos de los
operadores comunes que se
pueden usar para asignar
un valor a una variable.

Ejemplo

Operadores de igualdad == !=

Operadores relacionales < > <= >= is

Operadores condicionales && || ?:

Operador de incremento ++

Operador de decremento - -

Operadores aritmticos

Operadores de asignacin = *= /= %= += -= <<=


>>= &= ^= |=

+ - * / %

Las expresiones estn formadas por operandos y operadores. Los operadores


de una expresin indican las operaciones que se aplican a los operandos.
Algunos ejemplos de operadores son el operador de concatenacin y suma (+),
el operador de resta (-), el operador de multiplicacin (*) y el operador de
divisin (/). Literales, campos, variables locales y expresiones son ejemplos de
operandos.

Operadores comunes
La siguiente tabla describe algunos de los operadores ms comunes que se
utilizan en C#.
Tipo

Descripcin

Operadores de asignacin

Asignan valores a variables usando una asignacin


simple. Para ello es necesario que el valor en el lado
derecho de la asignacin sea de un tipo que se
pueda convertir implcitamente al tipo de la variable
en el lado izquierdo de la asignacin.

Operadores lgicos relacionales

Comparan dos valores.

Operadores lgicos

Realizan operaciones bit a bit sobre valores.

Operador condicional

Selecciona entre dos expresiones, dependiendo de


una expresin booleana.

Operador de incremento

Aumenta en uno el valor de una variable.

Operador de decremento

Reduce en uno el valor de una variable.

Operadores aritmticos

Realizan operaciones aritmticas estndar.

Para ms informacin sobre los operadores de C#, busque expresiones en los


documentos de ayuda de Visual Studio .NET sobre el lenguaje C#.

Uso de variables de tipo valor

18

Incremento y decremento
Objetivo del tema

Describir los operadores de


incremento y decremento y,
en particular, explicar la
diferencia entre las
versiones de prefijo y sufijo.

objetoCuenta
objetoCuenta +=
+= 1;
1;
objetoCuenta
objetoCuenta -=
-= 1;
1;

Explicacin previa

Muchas veces (cuando se


cuenta algo, por ejemplo) se
necesita sumar o restar uno
a una variable.

Es muy habitual cambiar un valor en una unidad

Se puede usar una expresin ms prctica


objetoCuenta++;
objetoCuenta++;
objetoCuenta--;
objetoCuenta--;

Existen dos formas de esta abreviatura


++objetoCuenta;
++objetoCuenta;
--objetoCuenta;
--objetoCuenta;

Es muy habitual cambiar un valor en una unidad


A menudo hay que escribir instrucciones que incrementan o decrementan
valores en una unidad. Se podra hacer as, por ejemplo:
objetoCuenta = objetoCuenta + 1;
objetoCuenta = objetoCuenta 1;

Pero tambin se puede usar una expresin ms prctica, como acabamos de ver:
objetoCuenta += 1;
objetoCuenta -= 1;

Expresin prctica
Los incrementos y decrementos unitarios de un valor son tan comunes que
existe una expresin an ms abreviada:
objetoCuenta++; // objetoCuenta += 1;
objetoCuenta--; // objetoCuenta -= 1;

El operador ++ recibe el nombre de operador de incremento, mientras que -- es


el operador de decremento. Se puede pensar en ++ como un operador que
cambia un valor por su posterior y en -- como un operador que cambia un valor
por su anterior.
La abreviatura es, tambin en este caso, la forma preferida por los
programadores de C# para incrementar o decrementar un valor en una unidad.
Nota: C++ se llam C++ porque era el sucesor de C!

Uso de variables de tipo valor

19

Existen dos formas de esta abreviatura


Los operadores ++ y -- se pueden usar de dos maneras.
1. Se puede colocar el smbolo del operador antes del identificador, como en
los siguientes ejemplos. A esto se le llama notacin de prefijo.
++objetoCuenta;
--objetoCuenta;

2. Se puede colocar el smbolo del operador despus del identificador, como


en los siguientes ejemplos. A esto se le llama notacin de sufijo.
objetoCuenta++;
objetoCuenta--;

En ambos casos se incrementa (para ++) o decrementa (para --) objetoCuenta


en una unidad. Pero entonces, por qu hay dos notaciones? Para responder a
esta pregunta es necesario saber ms sobre la asignacin:
Una caracterstica importante de C# es que la asignacin es un operador. Esto
quiere decir que, adems de asignar un valor a una variable, una expresin de
asignacin tiene en s misma un valor, o resultado, que es el valor de la variable
despus de que se realice la asignacin. En la mayor parte de las instrucciones
se descarta el valor de la expresin de asignacin, pero es posible usarlo en una
expresin mayor, como en el siguiente ejemplo:
int objetoCuenta = 0;
Console.WriteLine(objetoCuenta = 2); // Imprime 2
Console.WriteLine(objetoCuenta = objetoCuenta + 40); // Imprime 42

Una asignacin compuesta tambin es una asignacin. Esto significa que una
expresin de asignacin compuesta, adems de asignar un valor a una variable,
tiene tambin un valor o resultado. Tambin en este caso se descarta el valor de
la expresin de asignacin compuesta en la mayor parte de las instrucciones,
pero es posible usarlo en una expresin mayor, como en el siguiente ejemplo:
int objetoCuenta = 0;
Console.WriteLine(objetoCuenta += 2); // Imprime 2
Console.WriteLine(objetoCuenta -= 2); // Imprime 0

El incremento y el decremento tambin son asignaciones. Esto significa, por


ejemplo, que una expresin de incremento, adems de incrementar una variable
en uno, tiene tambin un valor o resultado. Tambin en este caso se descarta el
valor de la expresin de incremento en la mayor parte de las instrucciones, pero
es posible usarlo en una expresin mayor, como en el siguiente ejemplo:
int objetoCuenta = 42;
int prefijoValor = ++objetoCuenta; // prefijoValor == 43
int sufijoValor = objetoCuenta++; // sufijoValor = 43

El valor de la expresin de incremento vara dependiendo de que se use la


versin de prefijo o de sufijo. objetoCuenta se incrementa en los dos casos. La
diferencia no est ah, sino en el valor de la expresin de incremento. El valor
de la expresin de incremento/decremento como prefijo es el valor de la
variable despus de realizar el incremento/decremento, mientras que el valor de
un incremento/decremento como sufijo es el valor de la variable antes del
incremento/decremento.

Uso de variables de tipo valor

20

Precedencia de operadores
Objetivo del tema

Explicar la precedencia de
operadores.

Explicacin previa

Para entender cmo


funcionan los programas en
C#, es preciso conocer el
orden en que C# evala los
operadores empleados.

Recomendacin al
profesor

Puede ser conveniente


repasar los distintos tipos de
operadores.
Operadores monarios. Los
operadores monarios se
aplican a un operando y
usan notacin de prefijo
(como --x) o de sufijo (como
x++).
Operadores binarios. Los
operadores monarios se
aplican a dos operandos y
usan notacin de prefijo
(como x + y).
El operador ternario. Existe
slo un operador ternario
(?:). El operador ternario se
aplica a tres operandos y
usan notacin de infijo
(como c? x: y).

Precedencia y asociatividad de operadores


z

Todos los operadores binarios, salvo los de


asignacin, son asociativos por la izquierda
Los operadores de asignacin y el operador
condicional son asociativos por la derecha

Precedencia de operadores
Si una expresin contiene varios operadores, la precedencia de estos controla el
orden en que se evala cada uno de ellos. Por ejemplo, la expresin x + y * z se
evala como x + (y * z) porque el operador de multiplicacin tiene una
precedencia mayor que el de suma. Una expresin aditiva, por ejemplo, consta
de una secuencia de expresiones multiplicativas separadas por operadores + o -,
por lo que los operadores + y tienen una precedencia menor que los
operadores *, /, y %.

Asociatividad
Si un operando est entre dos operadores con la misma precedencia, la
asociatividad de los operadores controla el orden en que se efectan las
operaciones. Por ejemplo, x + y + z se evala como (x + y) + z. Esto tiene
especial importancia para operadores de asignacin. Por ejemplo, x = y = z se
evala como x = (y = z).
Todos los operadores binarios, salvo los de asignacin, son asociativos por la
izquierda, lo que quiere decir que las operaciones se realizan de izquierda a
derecha.
Los operadores de asignacin y el operador condicional (?:)son asociativos por
la derecha, lo que quiere decir que las operaciones se realizan de derecha a
izquierda.
Es posible controlar la precedencia y la asociatividad utilizando parntesis. Por
ejemplo, x + y * z multiplica primero y por z y luego suma el resultado a x,
pero (x + y) * z suma primero x ms y, y luego multiplica el resultado por z.

Uso de variables de tipo valor

21

Creacin de tipos de datos definidos por el usuario


Objetivo del tema

Ofrecer una introduccin a


los temas tratados en esta
seccin.

Explicacin previa

En esta seccin aprender


a crear tipos de datos enum
y struct.

Enumeraciones

Estructuras

En las aplicaciones es necesario saber cmo crear tipos de datos de


enumeracin (enum) y estructura (struct) definidos por el usuario.
Al final de esta leccin, usted ser capaz de:
Crear tipos de datos enum definidos por el usuario.
Crear tipos de datos struct definidos por el usuario.

Uso de variables de tipo valor

22

Enumeraciones
Objetivo del tema

Explicar cmo se crea una


variable del tipo enum en
C#.

Explicacin previa

Una enumeracin crea un


conjunto nico de valores
constantes relacionados.

Definicin de una enumeracin

enum
enum Color
Color {{ Rojo,
Rojo, Verde,
Verde, Azul
Azul }}

Uso de una enumeracin

Color
Color colorPaleta
colorPaleta == Color.Rojo;
Color.Rojo;

Visualizacin de una variable de enumeracin

Console.WriteLine({0},
Console.WriteLine({0}, colorPaletta);
colorPaletta); //
// Muestra
Muestra Rojo
Rojo

Los enumeradores son tiles cuando una variable slo puede tener un conjunto
de valores concreto.

Definicin de enumeraciones
Para declarar una enumeracin se usa la palabra clave enum seguida de un
nombre de variable enum y los valores iniciales. Por ejemplo, esta enumeracin
define tres constantes enteras, llamadas valores del enumerador.
enum Color { Rojo, Verde, Azul }

Por defecto, los valores de enumeradores empiezan en 0. En el ejemplo


anterior, Rojo tiene el valor 0, Verde tiene el valor 1 y Azul tiene el valor 2.
Es posible inicializar una enumeracin especificando literales enteros.

Uso de variables de tipo valor

23

Uso de una enumeracin


Se puede declarar una variable colorPaleta de tipo Color empleando la
siguiente sintaxis:
Color colorPaleta;
// Declara la variable
colorPaleta = Color.Rojo; // Asigna el valor

-OcolorPaleta = (Color)0;

// Tipo int a Color

Visualizacin de un valor de enumeracin


Para ver un valor de enumeracin en un formato legible se puede usar la
siguiente instruccin:
Console.WriteLine("{0}", colorPaleta);

Uso de variables de tipo valor

24

Estructuras
Objetivo del tema

Explicar cmo se crean


estructuras definidas por el
usuario (structs) en C#.

Explicacin previa

Una estructura es una


agrupacin de tipos
arbitrarios.

Definicin de una estructura

public
public struct
struct Empleado
Empleado
{{
public
public string
string pilaNombre;
pilaNombre;
public
int
public int age;
age;
}}

Uso de una estructura

Employee
Employee empresaEmpleado;
empresaEmpleado;
empresaEmpleado.pilaNombre
empresaEmpleado.pilaNombre == "Juan";
"Juan";
empresaEmpleado.age
empresaEmpleado.age == 23;
23;

Las estructuras se pueden emplear para crear objetos que se comportan como
tipos de valor predefinidos. Las estructuras se almacenan en lnea y no se
asignan por montones, por lo que la necesidad de eliminar elementos no
utilizados en el sistema es menor que en el caso de las clases.
Todos los tipos de datos simples, como int, float y double, son estructuras
predefinidas en .NET Framework.

Definicin de una estructura


Recomendacin al
profesor

Nota: Las estructuras no


permiten la herencia.
Presente un ejemplo
sencillo de estructura, como
una estructura de Punto.
Algunos ejemplos de
estructura son punto,
rectngulo y nmero
complejo.

Se puede utilizar una estructura para agrupar varios tipos arbitrarios, como
muestra el siguiente ejemplo:
public struct Empleado
{
public string pilaNombre;
public int
edad;
}

Este cdigo define un nuevo tipo, llamado Empleado, que consta de dos
elementos: el nombre de pila y la edad.

Uso de una estructura


Para acceder a los elementos de una estructura se puede emplear la siguiente
sintaxis:
Empleado empresaEmpleado;
empresaEmpleado.pilaNombre =
empresaEmpleado.edad = 23;

// Declara la variable
"Juan"; // Asigna el valor

Uso de variables de tipo valor

25

Conversin de tipos de datos


Objetivo del tema

Ofrecer una introduccin a


los temas tratados en esta
seccin.

Explicacin previa

En C# hay dos tipos de


conversin de datos:
implcita y explcita.

Conversin implcita de tipos de datos

Conversin explcita de tipos de datos

En C# hay dos tipos de conversin:


Conversin implcita de tipos de datos.
Conversin explcita de tipos de datos.
Al final de esta leccin, usted ser capaz de:
Realizar una conversin implcita de datos.
Realizar una conversin explcita de datos.

Uso de variables de tipo valor

26

Conversin implcita de tipos de datos


Objetivo del tema

Explicar como hacer una


conversin implcita de tipos
de datos.

Explicacin previa

La conversin implcita no
puede fallar para tipos de
datos predefinidos.

Conversin de int a long

using
using System;
System;
class
class Test
Test
{{
static
static void
void Main(
Main( ))
{{
int
int intValor
intValor == 123;
123;
long
long longValor
longValor == intValor;
intValor;
Console.WriteLine("(long)
Console.WriteLine("(long) {0}
{0} == {1}",
{1}", intValor,
intValor,
longValor);
longValor);
}}
}}

Las conversiones implcitas no pueden fallar


z

Se puede perder precisin, pero no magnitud

La conversin de un tipo de datos int a otro long es implcita. Esta conversin


siempre tiene xito y jams produce una prdida de informacin. El siguiente
ejemplo muestra cmo convertir la variable intValor de un int a un long:
using System;
class Test
{
static void Main( )
{
int intValor = 123;
long longValor = intValor;
Console.WriteLine("(long) {0} = {1}", intValor,
longValor);
}
}

Uso de variables de tipo valor

27

Conversin explcita de tipos de datos


Objetivo del tema

Explicar como hacer una


conversin implcita de tipos
de datos.

Explicacin previa

Para hacer una conversin


explcita de datos se emplea
una expresin de cast
(molde).

Para hacer conversiones explcitas se usa una


expresin de cast (molde):

using
using System;
System;
class
class Test
Test
{{
static
static void
void Main(
Main( ))
{{
long
long longValor
longValor == Int64.MaxValor;
Int64.MaxValor;
int
int intValor
intValor == (int)
(int) longValor;
longValor;
Console.WriteLine("(int)
Console.WriteLine("(int) {0}
{0} == {1}",
{1}", longValor,
longValor,
intValor);
intValor);
}}
}}

Para hacer una conversin explcita de tipos de variables se puede emplear una
expresin de cast (molde). El siguiente ejemplo muestra cmo convertir la
variable longValor de un tipo de datos long a otro int utilizando una expresin
de cast:
using System;
class Test
{
static void Main( )
{
long longValor = Int64.MaxValor;
int intValor = (int) longValor;
Console.WriteLine("(int) {0} = {1}", longValor,
intValor);
}
}

En este ejemplo se produce un desbordamiento, por lo que el resultado es el


siguiente:
(int) 9223372036854775807 = -1

Uso de variables de tipo valor

28

Para que esto no ocurra se puede usar la instruccin checked, que lanza una
excepcin en caso de fallo en una conversin:
using System;
class Test
{
static void Main( )
{
checked
{
long longValor = Int64.MaxValor;
int intValor = (int) longValor;
Console.WriteLine("(int) {0} = {1}", longValor,
intValor);
}
}
}

Instrucciones y excepciones

ndice
Notas generales

Introduccin a las instrucciones

Uso de instrucciones condicionales

Uso de instrucciones iterativas

15

Uso de instrucciones de salto

25

Tratamiento de excepciones bsicas

28

Lanzamiento de excepciones

39

Instrucciones y excepciones

Notas para el instructor


Este mdulo explica el uso de algunas instrucciones comunes de C#. Tambin
explica el tratamiento de excepciones en C#. En particular, muestra cmo
lanzar y capturar errores, y cmo emplear bloques try-finally para asegurarse
de que una excepcin no hace que el programa se detenga antes de que se
elimine el error.
Al final de este mdulo, los estudiantes sern capaces de:
Describir los distintos tipos de instrucciones de control.
Usar instrucciones de salto.
Usar instrucciones condicionales.
Usar instrucciones iterativas.
Tratar y lanzar excepciones en una aplicacin C#.

Instrucciones y excepciones

Notas generales
Objetivo del tema

Ofrecer una introduccin a


los contenidos y objetivos
del mdulo.

Explicacin previa

En este mdulo estudiar


las instrucciones comunes y
las instancias de
programacin que se
pueden emplear en C#.

Introduccin a las instrucciones

Uso de instrucciones condicionales

Use instrucciones iterativas

Uso de instrucciones de salto

Tratamiento de excepciones bsicas

Lanzamiento de excepciones

Una de las cosas ms importantes a la hora de utilizar un lenguaje de


programacin es saber escribir las instrucciones que forman la lgica de un
programa en ese lenguaje. Este mdulo explica cmo usar algunas instrucciones
comunes, as como el tratamiento de excepciones en C#.
En particular, este mdulo muestra cmo lanzar y capturar errores, y cmo
emplear bloques try-finally para asegurarse de que una excepcin no hace que
el programa se detenga antes de que se elimine el error.
Al final de este mdulo, usted ser capaz de:
Describir los distintos tipos de instrucciones de control.
Usar instrucciones de salto.
Usar instrucciones condicionales.
Usar instrucciones iterativas.
Tratar y lanzar excepciones.

Instrucciones y excepciones

Introduccin a las instrucciones


Objetivo del tema

Ofrecer una introduccin a


los temas tratados en esta
seccin.

Explicacin previa

Esta seccin ofrece una


introduccin a las
instrucciones y a los
principales tipos de
instrucciones que se
emplean en C#.

Bloques de instrucciones

Tipos de instrucciones

Un programa consiste en una sucesin de instrucciones. En tiempo de


ejecucin, estas instrucciones se ejecutan en el orden en que aparecen en el
programa, de izquierda a derecha y de arriba a abajo.
Al final de esta leccin, usted ser capaz de:
Agrupar un conjunto de instrucciones en C#.

Usar los distintos tipos de instrucciones disponibles en C#.

Instrucciones y excepciones

Bloques de instrucciones
Objetivo del tema

Explicar cmo agrupar


instrucciones en bloques.

Explicacin previa

Los grupos de instrucciones


son necesarios en muchos
lenguajes, incluido C#.

Se usan llaves
para delimitar
bloques
{{
//
// code
code
}}

Un bloque y su
bloque padre o
pueden tener una
variable con el
mismo nombre
{{
int
int i;
i;
...
...
{{
int
int i;
i;
...
...
}}

Bloques
hermanos pueden
tener variables
con el mismo
nombre
{{
int
int i;
i;
...
...
}}
...
...
{{
int
int i;
i;
...
...

}}
}}

Cuando se desarrollan aplicaciones C# es necesario agrupar instrucciones, del


mismo modo que se hace en otros lenguajes de programacin. Para ello se
emplea la sintaxis de lenguajes como C, C++ y Java, lo que significa que los
grupos de instrucciones estn rodeados por llaves: { y }. Para los grupos de
instrucciones no se utilizan delimitadores con combinaciones de palabras, como
If ... End If de Microsoft Visual Basic.

Instrucciones agrupadas en bloques


Un grupo de instrucciones puestas entre llaves recibe el nombre de bloque. Un
bloque puede contener una sola instruccin o bien otro bloque anidado dentro
de l.
Cada bloque define un mbito. Una variable que est declarada en un bloque es
una variable local, y su mbito se extiende desde su declaracin hasta la llave
de cierre con que termina el bloque al que pertenece. Es conveniente declarar
una variable en un bloque lo ms interno posible, ya que la menor visibilidad de
la variable contribuye a hacer ms claro el programa.

Instrucciones y excepciones

Uso de variables en bloques de instrucciones


En C# no es posible declarar una variable en un bloque interno con el mismo
nombre que una variable en un bloque externo. Por ejemplo, el siguiente cdigo
no est permitido:
int i;
{
int i; // Error: i ya declarada en bloque padre
...
}

Sin embargo, es posible declarar variables con el mismo nombre en bloques


hermanos. Los bloques hermanos son bloques que pertenecen al mismo bloque
padre y estn anidados al mismo nivel, como en el siguiente ejemplo:
{
int i;
...
}
...
{
int i;
...
}

Se pueden declarar variables en cualquier punto de un bloque de instrucciones,


lo que hace ms sencillo seguir la recomendacin de inicializar una variable en
el momento de declararla.

Instrucciones y excepciones

Tipos de instrucciones
Objetivo del tema

Describir los tres tipos de


instrucciones comunes que
se pueden utilizar en el
lenguaje C#.

Instrucciones
Instrucciones Condicionales
Condicionales
Las
Las instrucciones
instrucciones ifif yy switch
switch

Explicacin previa

C# ofrece tres tipos distintos


de instrucciones para
controlar el flujo de
ejecucin.

Instrucciones
Instrucciones de
de iteracin
iteracin
Las
Las instrucciones
instrucciones while,
while, do,
do, for,
for, yy foreach
foreach
Instrucciones
Instrucciones de
de salto
salto
Las
instrucciones
Las instrucciones goto,
goto, break,
break, yy continue
continue

La complejidad de la lgica de un programa aumenta a medida que lo hace la


complejidad del problema que se intenta resolver con ese programa. Por ello es
preciso que el programa tenga control estructurado de flujo, lo que se puede
conseguir mediante el uso de instancias o instrucciones de ms alto nivel. Estas
instrucciones se pueden agrupar en las siguientes categoras:

Instrucciones condicionales
Las instrucciones if y switch se conocen como instrucciones
condicionales, ya que toman decisiones en funcin del valor de
expresiones y ejecutan unos comandos u otros en funcin de las
decisiones tomadas.

Instrucciones iterativas
Las instrucciones while, do, for y foreach se ejecutan repetidamente
mientras se cumple una condicin. Tambin se conocen como
instrucciones de bucle. Cada una de estas instrucciones est pensada
para un estilo de iteracin distinto.

Instrucciones de salto
Las instrucciones goto, break y continue se usan para transferir el
control incondicionalmente a otra instruccin.

Instrucciones y excepciones

Uso de instrucciones condicionales


Objetivo del tema

Ofrecer una introduccin a


los temas tratados en esta
seccin.

Explicacin previa

Esta seccin explica el uso


de las instrucciones
condicionales if y switch.

La instruccin if

Instruccin if en cascada

La instruccin switch

Problema: Dnde est el error?

Las instrucciones if y switch se conocen como instrucciones condicionales, ya


que toman decisiones en funcin del valor de expresiones y ejecutan unos
comandos u otros en funcin de las decisiones tomadas.
Al final de esta leccin, usted ser capaz de:

Usar la instruccin if en C#.

Usar la instruccin switch en C#.

Instrucciones y excepciones

La instruccin if
Objetivo del tema

Describir la instruccin if.

Explicacin previa

A menudo los programas


tienen que ejecutar distintas
instrucciones dependiendo
de una condicin.

Sintaxis:

if
if (( expresin-booleana
expresin-booleana ))
primera-instruccin-incrustada
primera-instruccin-incrustada
else
else
segunda-instruccin-incrustada
segunda-instruccin-incrustada

No hay conversin implicita de int a bool

int
int x;
x;
...
...
if
//
if (x)
(x) ...
...
// Debe
Debe ser
ser if
if (x
(x !=
!= 0)
0) en
en C#
C#
if
(x
=
0)
...
//
Debe
ser
if
(x
==
0)
en
if (x = 0) ... // Debe ser if (x == 0) en C#
C#

Recomendacin al
profesor

La sintaxis de la instruccin
if no es ninguna novedad
para los programadores de
C y C++, as que procure no
dedicar demasiado tiempo a
este tema y concntrese en
las diferencias entre C# y
otros lenguajes, y en
particular en la ausencia de
una conversin
predeterminada de un valor
entero en otro booleano.
Muestre un ejemplo de una
instruccin if que tenga un
bloque incrustado, y utilice
este ejemplo para explicar
cmo declarar una variable
dentro de un bloque.

La instruccin if es la ms utilizada para tomar decisiones. Puede estar asociada


con una clusula opcional else, como se muestra aqu:
if ( expresin-booleana )
primera-instruccin-incrustada
else
segunda-instruccin-incrustada

La instruccin if evala una expresin booleana para determinar el curso de


accin a tomar. Si el resultado de la expresin booleana es true, el control pasa
a la primera instruccin; si es false y existe una clusula else, el control se
transfiere a la segunda instruccin.

Instrucciones y excepciones

Ejemplos
Se puede utilizar una instruccin if sencilla, como la siguiente:
if (numero % 2 == 0)
Console.WriteLine("par");

Aunque las instrucciones incrustadas no necesitan llaves, muchas guas de


estilo recomiendan utilizarlas porque previenen errores y hacen que el cdigo
sea ms fcil de mantener. El ejemplo anterior se puede reescribir con llaves,
como vemos:
if (numero % 2 == 0) {
Console.WriteLine("par");
}

Tambin es posible usar un bloque de instrucciones if como en este ejemplo:


if (minuto == 60) {
minuto = 0;
hora++;
}

Conversin de valores enteros en booleanos


La conversin implcita de un valor entero en otro booleano es una fuente de
posibles errores. Para evitar estos errores, C# no permite la conversin de
valores enteros en booleanos. sta es una diferencia importante entre C# y otros
lenguajes similares.
Las instrucciones siguientes, por ejemplo, generan como mucho avisos en C y
C++, mientras que en C# producen errores de compilacin:
int x;
...
if (x) ...
// En C# debe ser x != 0
if (x = 0) ... // En C# debe ser x == 0

Instrucciones y excepciones

Instrucciones if en cascada
Objetivo del tema

Explicar cmo usar


instrucciones condicionales
complejas.

Explicacin previa

En situaciones complejas
puede ser necesario anidar
varias instrucciones if.

Recomendacin al
profesor

El cdigo de ejemplo
mostrado en la
transparencia aparecer
modificado cuando se
estudie la instruccin
switch. Puede ser
conveniente repasar esta
transparencia despus de
ver la instruccin switch.

enum
enum Palo
Palo {{ Treboles,
Treboles, Corazones,
Corazones, Diamantes,
Diamantes, Picas}
Picas}
Palo
cartas
=
Palo.Corazones;
Palo cartas = Palo.Corazones;
if
if (cartas
(cartas ==
== Palo.Treboles)
Palo.Treboles)
color
=
color = Negro;
Negro;
else
else if
if (cartas
(cartas ==
== Palo.Corazones)
Palo.Corazones)
color
=
Rojo";
color = Rojo";
else
else if
if (palo
(palo ==
== Palo.Diamantes)
Palo.Diamantes)
color
=
"Rojo";
color = "Rojo";
else
else
color
color == Negro";
Negro";

Para las instrucciones if en cascada se utiliza else if. C# no incluye la


instruccin else if, sino que forma una instruccin del mismo tipo a partir de
una clusula else y una instruccin if, como en C y C++. En otros lenguajes,
como Visual Basic, se crean cascadas de instrucciones if colocando una
instruccin else if entre la instruccin if y la instruccin final else.
La instancia else if permite tener un nmero arbitrario de ramas. No obstante,
las instrucciones controladas por una instruccin if en cascada son mutuamente
excluyentes, lo que significa que slo se ejecuta una instruccin de entre todas
las instancias else if.

Instrucciones y excepciones

10

Instrucciones if anidadas
El anidamiento de una instruccin if dentro de otra puede crear una ambigedad
llamada dangling else (else pendiente), como se ve en el siguiente ejemplo:
if (porciento >= 0 && porciento <= 100)
if (porciento > 50)
Console.WriteLine("Pasa");
else
Console.WriteLine("Error: fuera del intervalo");

La clusula else aparece indentada en la misma columna que el primer if, por lo
que al leer el cdigo no parece que el else est asociado al segundo if. Esto
puede resultar peligroso, ya que el compilador vincula una clusula else a su
instruccin if ms cercana independientemente del diseo del programa. Esto
significa que el compilador interpretar el cdigo anterior de la siguiente
manera:
if (porciento >= 0 && porciento <= 100) {
if (porciento > 50)
Console.WriteLine("Pasa");
else
Console.WriteLine("Error: fuera del intervalo");
}

Una forma de asociar el else al primer if es utilizar un bloque:


if (porciento >= 0 && porciento <= 100) {
if (porciento > 50)
Console.WriteLine("Pasa");
} else {
Console.WriteLine("Error: fuera del intervalo");
}

Consejo Es recomendable escribir instrucciones if en cascada con la


indentacin adecuada, ya que de lo contrario las decisiones largas se hacen
rpidamente ilegibles y superan el margen derecho de la pgina o pantalla.

Instrucciones y excepciones

11

La instruccin switch
Objetivo del tema

Explicar una forma


alternativa de tomar
decisiones complejas.

Explicacin previa

Las instrucciones if
anidadas pueden resultar
confusas a la hora de
expresar condiciones
complejas. En algunos
casos, pero no en todos, es
posible utilizar la instruccin
switch como alternativa.

Recomendacin al
profesor

Se dice a menudo que en


programas orientados a
objetos se debe evitar la
instruccin switch. Por
supuesto, esto se debe a
que muchas instrucciones
switch utilizan un marcador
de tipo en lugar de un
polimorfismo. La instruccin
switch se puede emplear
para tomar decisiones en
funcin del valor de un dato,
y es especialmente
adecuada para determinar
el valor de una variable
enum.

Las instrucciones switch se usan en bloques de


varios casos

Se usan instrucciones break para evitar cadas en


cascada (fall through)

switch
switch (palo)
(palo) {{
case
Palo.Treboles
case Palo.Treboles ::
case
case Palo.Picas
Palo.Picas ::
color
color == "Negro";
"Negro"; break;
break;
case
Palo.Corazones
case Palo.Corazones ::
case
case Palo.Diamantes
Palo.Diamantes ::
color
color == "Rojo";
"Rojo"; break;
break;
default:
default:
color
color == "ERROR";
"ERROR"; break;
break;
}}

La instruccin switch proporciona un mecanismo elegante para expresar


condiciones complejas que, de lo contrario, requeriran el uso de instrucciones
if anidadas. Consta de bloques de varios casos, cada uno de los cuales
especifica una sola constante y una etiqueta case asociada. No est permitido
agrupar varias constantes en una sola etiqueta case, sino que cada constante
debe tener la suya propia.
Un bloque switch puede contener declaraciones. El mbito de una constante o
variable local declarada en un bloque switch se extiende desde su declaracin
hasta el final del bloque switch, como se ve en el ejemplo de la transparencia.

Ejecucin de instrucciones switch


Una instruccin switch se ejecuta de la siguiente forma:
1. Si una de las constantes especificada es una etiqueta case es igual al valor
de la expresin switch, el control pasa a la lista de instrucciones que sigue a
la correspondiente etiqueta case.
2. Si ninguna constante de las etiquetas case es igual al valor de la expresin
switch, y la instruccin switch contiene una etiqueta default, el control pasa
a la lista de instrucciones que sigue a la etiqueta default.
3. Si ninguna constante de las etiquetas case es igual al valor de la expresin
switch, y la instruccin switch no contiene una etiqueta default, el control
pasa al final de la instruccin switch.

Instrucciones y excepciones

12

Una instruccin switch slo se puede utilizar para evaluar los siguientes tipos
de expresiones: cualquier tipo entero, un char, una enum o una string.
Tambin es posible evaluar otros tipos de expresiones con la instruccin
switch, siempre y cuando haya exactamente una conversin implcita definida
por el usuario del tipo no permitido a uno de los tipos permitidos.
Nota Al contrario de lo que ocurre en Java, C o C++, el tipo que rige una
instruccin switch en C# puede ser una cadena. Con una expresin de cadena,
la constante de una etiqueta case puede tener el valor null.
Para ms informacin sobre operadores de conversin, busque operadores de
conversin en los documentos de ayuda del SDK de Microsoft .NET
Framework.

Grupos de constantes
Para agrupar varias constantes hay que repetir la palabra clave case para cada
una de ellas, como se muestra en el siguiente ejemplo:
enum MesNombre { Enero, Febrero, ..., Diciembre }
MesNombre actual;
int mesDias;
...
switch (actual) {
case MesNombre.Febrero :
mesDias = 28;
break;
case MesNombre.Abril :
case MesNombre.Junio :
case MesNombre.Septiembre :
case MesNombre.Noviembre :
mesDias = 30;
break;
default :
mesDias = 31;
break;
}

Las etiquetas case y default se utilizan nicamente como puntos de entrada


para el flujo de control del programa en funcin del valor de la expresin
switch, pero no modifican el flujo de control.
Los valores de las constantes en las etiquetas case deben ser nicos, lo que
significa que no puede haber dos constantes con el mismo valor. Por ejemplo,
este ejemplo generar un error en tiempo de compilacin:
switch (cartas) {
case Palo.Treboles :
case Palo.Treboles: // Error: etiqueta duplicada
...
default :
default : // Error: etiqueta duplicada de nuevo
...
}

Instrucciones y excepciones

13

Uso de break en instrucciones switch


Al contrario de lo que ocurre en Java, C o C++, las instrucciones de C#
asociadas con una o ms etiquetas case no pueden caer en cascada ni continuar
hasta la siguiente etiqueta case. Una cada silenciosa en cascada (silent fall
through) se produce cuando la ejecucin avanza sin generar un error. En otras
palabras, la ltima instruccin asociada con un grupo de etiquetas case no
puede dejar que el flujo de control llegue hasta el segundo grupo de etiquetas
case.
Esta condicin, conocida como regla de cada en cascada o fall-through rule, se
puede cumplir con las instrucciones break (posiblemente la ms comn), goto
(muy poco habitual), return o throw, as como con un bucle infinito.
El siguiente ejemplo (que forma nmeros ordinales en ingls) generar un error
en tiempo de compilacin porque incumple la regla de cada en cascada:
string sufijo = "th";
switch (dias % 10) {
case 1 :
if (dias / 10 != 1) {
sufijo = "st";
break;
}
// Error: Cada en cascada
case 2 :
if (dias / 10 != 1) {
sufijo = "nd";
break;
}
// Error: Cada en cascada
case 3 :
if (dias / 10 != 1) {
sufijo = "rd";
break;
}
// Error: Cada en cascada
default :
sufijo = "th";
// Error: Cada en cascada
}

Instrucciones y excepciones

14

El error se puede corregir reescribiendo el cdigo de la siguiente manera:


switch (dias
case 1 :
sufijo
break;
case 2 :
sufijo
break;
case 3 :
sufijo
break;
default :
sufijo
break;
}

% 10) {
= (dias / 10 == 1) ? "th" : "st";

= (dias / 10 == 1) ? "th" : "nd";

= (dias / 10 == 1) ? "th" : "rd";

= "th";

Uso de goto en instrucciones switch


Al contrario de lo que ocurre en Java, C o C++, en C# se puede utilizar una
etiqueta case y una etiqueta default como destino de una instruccin goto. De
esta forma se puede lograr el efecto de cada en cascada, si es necesario. Por
ejemplo, este cdigo se compilar sin ningn problema:
switch (dias % 10) {
case 1 :
if (dias / 10 != 1) {
sufijo = "st";
break;
}
goto case 2;
case 2 :
if (dias / 10 != 1) {
sufijo = "nd";
break;
}
goto case 3;
case 3 :
if (dias / 10 != 1) {
sufijo = "rd";
break;
}
goto default;
default :
sufijo = "th";
break;
}

La regla de cada en cascada permite reordenar las secciones de una instruccin


switch sin afectar a su comportamiento general.

Instrucciones y excepciones

15

Uso de instrucciones iterativas


Objetivo del tema

Ofrecer una introduccin a


los temas tratados en esta
seccin.

Explicacin previa

Esta seccin explica el uso


de las instrucciones de
bucle.

La instruccin while

La instruccin do

La instruccin for

La instruccin foreach

Problema: Dnde est el error?

Las instrucciones while, do, for y foreach se conocen como instrucciones


iterativas. Se puede utilizar para realizar operaciones mientras se cumple una
condicin.
Al final de esta leccin, usted ser capaz de:

Usar instrucciones iterativas en C#.

Identificar errores en el uso de instrucciones iterativas en C#.

Instrucciones y excepciones

16

La instruccin while
Objetivo del tema

Describir la instruccin
while.

Explicacin previa

A menudo hay que ejecutar


varias veces el mismo
bloque de instrucciones
hasta que se cumple una
condicin.

Ejecuta instrucciones en funcin de un valor booleano

Evala la expresin booleana al principio del bucle

Ejecuta las instrucciones mientras el valor booleano


sea True

int
int ii == 0;
0;
while
while (i
(i << 10)
10) {{
Console.WriteLine(i);
Console.WriteLine(i);
i++;
i++;
}}

0 1 2 3 4 5 6 7 8 9

Recomendacin al
profesor

Insista en que tampoco en


este caso hay conversin
implcita de un entero en un
valor booleano. La
expresin booleana de
control debe ser
genuinamente booleana.

La instruccin while es la ms sencilla de todas las instrucciones iterativas.


Ejecuta repetidamente una instruccin mientras (while) se cumpla una
expresin booleana. La expresin evaluada por la instruccin while tiene que
ser booleana, ya que C# no permite la conversin implcita de un entero en un
valor booleano.

Flujo de ejecucin
Una instruccin while se ejecuta de la siguiente manera:
1. Se evala la expresin booleana que controla la instruccin while.
2. Si la expresin booleana se cumple (true), el control pasa a la instruccin
incrustada. Al llegar al final de la misma, el control se transfiere
implcitamente al inicio de la instruccin while y se vuelve a evaluar la
expresin booleana.
3. Si la expresin booleana no se cumple (false), el control pasa al final de la
instruccin while. Por lo tanto, el programa ejecuta repetidamente la
instruccin incrustada mientras la expresin booleana de control sea true.
La expresin booleana se prueba al inicio del bucle while, por lo que es posible
que la instruccin incrustada no se llegue a ejecutar.

Instrucciones y excepciones

17

Ejemplos
Se puede utilizar una instruccin incrustada sencilla como en este ejemplo:
while (i < 10)
Console.WriteLine(i++);

No es necesario utilizar llaves para las instrucciones incrustadas, aunque


muchas guas de estilo recomiendan hacerlo ya que facilitan el mantenimiento.
El ejemplo anterior se puede reescribir con llaves, como vemos:
while (i < 10) {
Console.WriteLine(i++);
}

Tambin es posible usar un bloque de instrucciones while como en este


ejemplo:
while (i < 10) {
Console.WriteLine(i);
i++;
}

Consejo A pesar de ser la instruccin iterativa ms simple, while puede crear


problemas a los desarrolladores si no tienen el cuidado necesario. La sintaxis
habitual de una instruccin while es la siguiente:
inicializacin
while ( expresin-booleana ) {
instruccin-incrustada
actualizacin
}

Es muy fcil olvidarse de la parte de actualizacin en el bloque while,


especialmente si se est pensando slo en la expresin booleana.

Instrucciones y excepciones

18

La instruccin do
Objetivo del tema
Explicar el uso de la
instruccin do.

Explicacin previa

En ocasiones puede ser


necesario comprobar la
condicin que controla un
bucle al final de una
iteracin, en lugar de al
principio.

Ejecuta instrucciones en funcin de un valor booleano

Evala la expresin booleana al final del bucle

Ejecuta las instrucciones mientras el valor booleano


sea True

int
int ii == 0;
0;
do
do {{
Console.WriteLine(i);
Console.WriteLine(i);
i++;
i++;
}} while
while (i
(i << 10);
10);

0 1 2 3 4 5 6 7 8 9

Una instruccin do va siempre acompaada de una instruccin while y es


similar a sta, salvo en que la expresin booleana que determina si hay que salir
del bucle o continuar se evala al final del bucle en lugar de al principio. Esto
quiere decir que, al contrario de la instruccin while, que efecta cero o ms
iteraciones, una instruccin do realiza una o ms iteraciones.
Por lo tanto, la instruccin incrustada de una instruccin do se ejecuta siempre
al menos una vez. Esto resulta especialmente til cuando es necesario validar la
entrada antes de permitir que contine la ejecucin del programa.

Flujo de ejecucin
Una instruccin do se ejecuta de la siguiente manera:
1. El control pasa a la instruccin incrustada.
2. Al llegar al final de la instruccin incrustada, se evala la expresin
booleana.
3. Si la expresin booleana se cumple (true), el control pasa al inicio de
la instruccin do.
4. Si la expresin booleana no se cumple (false), el control pasa al final
de la instruccin do.

Instrucciones y excepciones

19

Ejemplos
Se puede utilizar una instruccin incrustada sencilla como en este ejemplo:
do
Console.WriteLine(i++);
while (i < 10);

Como ocurre con las instrucciones if y while, no es necesario, aunque s


conveniente, utilizar llaves para las instrucciones incrustadas.
Tambin es posible usar un bloque de instrucciones do como en este ejemplo:
do {
Console.WriteLine(i);
i++;
} while (i < 10);

Como se ve, una instruccin do tiene que terminar siempre con punto y coma:
do {
Console.WriteLine(i++);
} while (i < 10) // Error: no hay ;

Instrucciones y excepciones

20

La instruccin for
Objetivo del tema
Explicar el uso de la
instruccin for.

Explicacin previa

La mayor parte de los


bucles iterativos siguen un
mismo patrn: Inicializan
una variable de control,
prueban una condicin,
ejecutan un bloque de
instrucciones y actualizan al
variable de control.

La informacin de actualizacin est al principio del bucle

for
for (int
(int ii == 0;
0; ii << 10;
10; i++)
i++) {{
Console.WriteLine(i);
Console.WriteLine(i);
}}

1 for2slo
3 son4vlidas
5 6en el7bloque
8 9
Las variables de un 0
bloque

for
for (int
(int ii == 0;
0; ii << 10;
10; i++)
i++)
Console.WriteLine(i);
Console.WriteLine(i);
Un bucle for puede iterar
varios
valores
Console.WriteLine(i);
//
ii est
Console.WriteLine(i);
// Error:
Error:
est fuera
fuera de
de mbito
mbito

for
for (int
(int ii == 0,
0, jj == 0;
0; ...
... ;; i++,
i++, j++)
j++)

Recomendacin al
profesor

La condicin es en realidad
una expresin booleana. Se
emplea la palabra condicin
porque es la que se utiliza
en la documentacin e
referencia del lenguaje C#.
Destaque el cambio en la
posicin del cdigo de
actualizacin y el distinto
mbito de la variable de
iteracin en la instruccin
for.

Los desarrolladores cometen a menudo el error de olvidarse de actualizar la


variable de control cuando utilizan instrucciones while, como muestra el
siguiente ejemplo:
int i = 0;
while (i < 10)
Console.WriteLine(i); // Error: falta i++

Este error se debe a que los programadores centran su atencin en el cuerpo de


la instruccin while y no en la actualizacin. Adems, el cdigo de
actualizacin puede estar muy alejado de la palabra clave while.
La instruccin for evita el problema y reduce este tipo de errores al mnimo, ya
que pasa el cdigo de actualizacin al principio del bucle, donde es ms difcil
de olvidar. La sintaxis de la instruccin for es la siguiente:
for ( inicializacin ; condicin ; actualizacin )
instruccin-incrustada

Importante El cdigo de actualizacin en una instruccin for est antes que la


instruccin incrustada, pero se ejecuta despus.

Instrucciones y excepciones

21

La sintaxis de la instruccin for es prcticamente idntica a la de la instruccin


while, como muestra el siguiente ejemplo:
inicializacin
while (condicin) {
instruccin-incrustada
actualizacin
}

Como en las dems instrucciones iterativas, la condicin en un bloque for debe


ser una expresin booleana que funciona como condicin para la continuacin,
no para la terminacin.

Ejemplos
Los componentes de inicializacin, condicin y actualizacin de una
instruccin for son opcionales. No obstante, una condicin vaca se considera
un true implcito y puede producir fcilmente un bucle infinito, como se ve en
el siguiente ejemplo:
for (;;) {
Console.WriteLine("Ayuda ");
...
}

Como con las instrucciones while y do, se puede utilizar una instruccin
incrustada sencilla o un bloque de instrucciones, como en estos ejemplos:
for (int i = 0; i < 10; i++)
Console.WriteLine(i);
for (int i = 0; i < 10; i++) {
Console.WriteLine(i);
Console.WriteLine(10 i);
}

Instrucciones y excepciones

22

Declaracin de variables
Una sutil diferencia entre las instrucciones while y for es que una variable
declarada en el cdigo de inicializacin de una instruccin for slo tiene
validez dentro de ese bloque for. Por ejemplo, el siguiente cdigo generar un
error en tiempo de compilacin:
for (int i = 0; i < 10; i++)
Console.WriteLine(i);
Console.WriteLine(i); // Error: i est fuera de mbito

Adems de esto, hay que tener en cuenta que una variable en un bloque for no
se puede declarar con el mismo nombre que una variable en un bloque externo.
Esta regla tambin es vlida para variables declaradas en el cdigo de
inicializacin de una instruccin for. Por ejemplo, el siguiente cdigo generar
un error en tiempo de compilacin:
int i;
for (int i = 0; i < 10; i++) // Error: i ya est en mbito

Por el contrario, el siguiente cdigo s est permitido:


for (int i = 0; i < 10; i++) ...
for (int i = 0; i < 20; i++) ...

Por otra parte, es posible inicializar dos o ms variables en el cdigo de


inicializacin de una instruccin for:
for (int i = 0, j = 0; ... ; ...)

Sin embargo, las variables tienen que ser del mismo tipo. Por lo tanto, el
siguiente cdigo no est permitido:
for (int i = 0, long j = 0; i < 10; i++)
...

Tambin se pueden usar dos o ms expresiones separadas por una o ms comas


en el cdigo de inicializacin de una instruccin for:
for (int i = 0, j = 0; ... ; i++, j++)

La instruccin for resulta muy til cuando no se conoce el nmero de


iteraciones, y especialmente para modificar todos los elementos de una tabla.

Instrucciones y excepciones

23

La instruccin foreach
Objetivo del tema

Describir la instruccin
foreach.

Elige el tipo y el nombre de la variable de iteracin

Explicacin previa

Ejecuta instrucciones incrustadas para cada elemento


de la clase collection

Es habitual hacer
iteraciones para todos los
elementos de una lista o
coleccin.

ArrayList
ArrayList numeros
numeros == new
new ArrayList(
ArrayList( );
);
for
(int
i
=
0;
i
<
10;
i++
for (int i = 0; i < 10; i++ )) {{
numeros.Add(i);
numeros.Add(i);
}}
foreach
foreach (int
(int number
number in
in numeros)
numeros) {{
Console.WriteLine(numero);
Console.WriteLine(numero);
}}

0 1 2 3 4 5 6 7 8 9

Recomendacin al
profesor

Este tema es difcil de


explicar. Recuerde que
todava no se han discutido
ni las matrices ni las clases
de coleccin. La mejor
forma de explicar este tema
es concentrarse en la
cantidad de sintaxis que se
puede eliminar en una
instruccin foreach en
comparacin con una
instruccin for.

Las colecciones son entidades software cuyo propsito es reunir otras entidades
software, del mismo modo que un libro de cuentas se puede considerar una
coleccin de cuentas bancarias o que una casa puede ser una coleccin de
habitaciones.
Microsoft .NET Framework contiene una clase de coleccin sencilla llamada
ArrayList, que se puede emplear para crear una variable de coleccin y aadir
elementos a la coleccin. Por ejemplo, consideremos el siguiente cdigo:
using System.Collections;
...
ArrayList numeros = new ArrayList( );
for (int i = 0; i < 10; i++) {
numeros.Anadir(i);
}

Es posible escribir una instruccin for para acceder por turno a cada elemento
de la coleccin en esta clase de coleccin e imprimirlo:
for (int i = 0; i < numero.Cuenta; i++) {
int numero = (int)numeros[i];
Console.WriteLine(numero);
}

Esta instruccin for contiene muchas instrucciones individuales que,


combinadas, ponen en marcha el mecanismo empleado para iterar cada
elemento de la coleccin de nmeros. No obstante, esta solucin no resulta
sencilla y es propicia al error.

Instrucciones y excepciones

24

Para resolver este problema en C# se puede utilizar la instruccin foreach, que


permite iterar toda una coleccin sin necesidad de instrucciones mltiples. En
lugar de extraer explcitamente cada elemento de una coleccin usando sintaxis
especfica para cada coleccin, la instruccin foreach hace todo lo contrario e
indica a la coleccin que vaya presentando sus elementos de uno en uno; en vez
de llevar la instruccin incrustada a la coleccin, lleva la coleccin a la
instruccin incrustada.
Con la instruccin foreach se puede reescribir la instruccin for anterior de la
siguiente manera:
foreach (int numero in numeros)
Console.WriteLine(numero);

La instruccin foreach ejecuta la instruccin incrustada para cada elemento de


la clase de coleccin numeros. Slo hay que elegir el tipo y el nombre de la
variable de iteracin, que en este caso son int y numero, respectivamente.
No es posible modificar los elementos de una coleccin utilizando una
instruccin foreach porque implcitamente la variable de iteracin es readonly
(slo lectura). Por ejemplo:
foreach (int numero in numeros) {
numero++; // Error en tiempo de compilacin
Console.WriteLine(numero);
}

Consejo Se puede emplear una instruccin foreach para iterar los valores de
un enumerador utilizando el mtodo Enum.GetValues(), que devuelve una
tabla de objetos.
Hay que tomar precauciones cuando se decide el tipo de la variable de iteracin
foreach. En algunos casos es posible que en tiempo de ejecucin no se detecte
un tipo errneo de variable de iteracin.

Instrucciones y excepciones

25

Uso de instrucciones de salto


Objetivo del tema

Ofrecer una introduccin a


los temas tratados en esta
seccin.

Explicacin previa

Esta seccin discute el uso


de las instrucciones goto,
break y continue.

La instruccin goto

Las instrucciones break y continue

Las instrucciones goto, break y continue se conocen como instrucciones de


salto y se utilizan para pasar el control de un punto del programa a otro en
cualquier momento. En esta seccin veremos cmo usar instrucciones de salto
en programas C#.

Instrucciones y excepciones

26

La instruccin goto
Objetivo del tema

Explicar cmo transferir el


control de forma
incondicional a otra parte de
un mtodo.

Transfiere el flujo de control a una instruccin con


etiqueta

Pueden dar lugar fcilmente a cdigo spaghetti de


difcil interpretacin

Explicacin previa

La instruccin goto permite


pasar el control a otra
instruccin dentro del
mismo programa.

Recomendacin al
profesor

La principal razn para


dedicar un tema propio a
goto es que la instruccin
switch interacta con ella
de formas que no son
posibles en Java, C++ o C.
La instruccin goto puede
estar vinculada al
"hiperespacio".

if
if (numero
(numero %% 22 ==
== 0)
0) goto
goto Par;
Par;
Console.WriteLine(impar");
Console.WriteLine(impar");
goto
goto Fin;
Fin;
Par:
Par:
Console.WriteLine(par");
Console.WriteLine(par");
Fin:;
Fin:;

La instruccin goto es la ms primitiva de las instrucciones de salto en C#.


Transfiere el control a una instruccin con etiqueta. Esta etiqueta debe existir y
estar en el mbito de la instruccin goto. Es posible que varias instrucciones
goto pasen el control a una misma etiqueta.
La instruccin goto puede transferir el control fuera de un bloque, pero nunca
dentro de l. El objetivo de esta restriccin, que existe tambin en C++ y otros
lenguajes, es evitar la posibilidad de que se salte una inicializacin.
Dentro del cdigo puede haber mucha distancia entre la instruccin goto y la
instruccin de destino con etiqueta. Esta distancia puede dificultar la
interpretacin de la lgica del flujo de control, por lo que la mayor parte de las
guas de programacin recomiendan no utilizar instrucciones goto.
Nota El uso de instrucciones goto est recomendado nicamente en
instrucciones switch o para pasar el control fuera de un bucle anidado.

Instrucciones y excepciones

27

Las instrucciones break y continue


Objetivo del tema

Describir las instrucciones


break y continue.

Explicacin previa

C# contiene instrucciones
que pueden modificar el
comportamiento de bucles.

La instruccin break salta fuera de una iteracin

La instruccin continue salta a la siguiente iteracin

int
int ii == 0;
0;
while
while (true)
(true) {{
Console.WriteLine(i);
Console.WriteLine(i);
i++;
i++;
if
if (i
(i << 10)
10)
continue;
continue;
else
else
break;
break;
}}

Recomendacin al
profesor

Aunque no resulte obvio (y


eso es lo importante) el
cdigo mostrado en la
transparencia escribe los
valores del cero al nueve.

Una instruccin break abandona la instruccin switch, while, do, for o


foreach ms prxima. Una instruccin continue comienza una nueva iteracin
de la instruccin while, do, for o foreach ms prxima.
Las instrucciones break y continue no se diferencian demasiado de una
instruccin goto, cuyo uso puede dificultar la interpretacin de la lgica del
flujo de control. Por ejemplo, la instruccin while se puede reescribir de la
siguiente manera sin emplear break ni continue:
int i = 0;
while (i < 10) {
Console.WriteLine(i);
i++;
}

Lo mejor es reescribir el cdigo anterior con una instruccin for, como sigue:
for (int i = 0; i < 10; i++) {
Console.WriteLine(i);
}

Instrucciones y excepciones

28

Tratamiento de excepciones bsicas


Objetivo del tema

Ofrecer una introduccin a


los temas tratados en esta
seccin.

Explicacin previa

La capacidad de capturar y
tratar excepciones es una
parte importante de
cualquier programa C#.

Por qu se emplean excepciones?

Objetos excepcin

Uso de bloques try-catch

Bloques catch mltiples

Antes o despus, todos los desarrolladores tienen que dedicar ms tiempo a la


bsqueda y tratamiento de errores que a escribir la lgica del programa. Para
paliar este problema se utilizan las excepciones, que estn pensadas para tratar
errores. En esta seccin aprender a capturar y tratar excepciones en C#.

Instrucciones y excepciones

29

Por qu se emplean excepciones?


Objetivo del tema
Explicar qu es una
excepcin.

Explicacin previa

Hay que estar siempre


preparado para cualquier
imprevisto que pueda surgir
durante la ejecucin de un
programa.

El tradicional tratamiento procedural de errores es


demasiado complicado
Lgica
Lgica del
del programa
programa

int
int errorCodigo
errorCodigo == 0;
0;
FileInfo
FileInfo source
source == new
new FileInfo("code.cs");
FileInfo("code.cs");
if
if (errorCodigo
(errorCodigo ==
== -1)
-1) goto
goto Fallo;
Fallo;
int
int longitud
longitud == (int)source.Length;
(int)source.Length;
if
if (errorCodigo
(errorCodigo ==
== -2)
-2) goto
goto Fallo;
Fallo;
char[]
char[] contenido
contenido == new
new char[longitud];
char[longitud];
if
if (errorCodigo
(errorCodigo ==
== -3)
-3) goto
goto Fallo;
Fallo;
//
// No
No hay
hay problemas
problemas ...
...
Fallo:
Fallo: ...
...
Trat.
Trat. De
De errores
errores

Un buen programa se caracteriza por incluir medidas contra lo inesperado y por


poderse recuperar en caso de que ocurra. Pueden aparecer errores en cualquier
momento durante la compilacin o ejecucin de un programa.
La lgica bsica del programa mostrado en la transparencia es la siguiente:
Recomendacin al
profesor

Estas tres instrucciones


volvern a aparecer en
muchos de los temas
siguientes.
Pida a los estudiantes que
le digan los problemas
asociados con el cdigo y
vea cuntos se les ocurren.

ArchInfo source = new ArchInfo("code.cs");


int longitud = (int)source.Longitud;
char[ ] contenido = new char[longitud];
...

Desgraciadamente, estas instrucciones bsicas se pierden en la confusin del


cdigo para tratamiento de errores. Este cdigo dificulta la interpretacin de la
lgica del programa de distintas maneras:

La lgica del programa se mezcla con el cdigo para tratamiento de


errores.
Las instrucciones bsicas del programa pierden su integridad
conceptual al mezclarse con el cdigo para tratamiento de errores, lo
que hace que sea difcil entender el programa.

Todo el cdigo para errores tiene un aspecto similar.


Todas las instrucciones para tratamiento de errores son similares, ya
que todas utilizan instrucciones if para probar el mismo cdigo de
error. Adems hay mucho cdigo repetido, lo que siempre es una seal
de aviso.

Los cdigos de error no son significativos en s mismos.


En este cdigo, un nmero como 1 no tiene un significado explcito;
podra representar Error de seguridad: no hay permiso de lectura,
pero eso slo se puede saber consultando la documentacin. Por lo

Instrucciones y excepciones

30

tanto, los cdigos enteros de error son muy programticos y no


describen los errores que representan.

Instrucciones y excepciones

31

Los cdigos de error se definen a nivel de mtodo.


Cada mtodo comunica su error asignando al cdigo de error un valor
concreto y exclusivo. No hay dos mtodos que usen el mismo valor.
Esto significa que cada mtodo est vinculado a todos los dems, lo
que se puede ver claramente si se cambian los cdigos enteros de error
por una enumeracin, como en el siguiente cdigo:

enum CodigoError {
ErrorSeguridad = -1,
ErrorIO = -2,
ErrorMemoriaInsuficiente = -3,
...
}

Este cdigo es mejor: Un identificador como ArchivoNoEncontrado es


siempre ms descriptivo que 1. Sin embargo, cada vez que se aada un
nuevo error con nombre a la enum, se vern afectados todos los mtodos
que nombren sus errores en la enum y ser necesario volver a compilar.

Los enteros simples tienen una capacidad de descripcin limitada.


Por ejemplo, la documentacin puede indicar que 1 significa Error
de seguridad: no hay permiso de lectura, pero 1 podra ser tambin el
nombre del archivo que no se puede leer.

Es fcil pasar por alto cdigos de error.


Por ejemplo, los programadores en C casi nunca comprueban el int que
devuelve la funcin printf. Es poco probable que printf falle, pero en
caso de hacerlo devolver un valor entero negativo (normalmente 1).

Como vemos, es necesaria una alternativa al mtodo tradicional de tratamiento


de errores. Las excepciones ofrecen una alternativa que es ms flexible,
requiere menos espacio y produce mensajes de error significativos.

Instrucciones y excepciones

32

Objetos excepcin
Objetivo del tema

Explicar el uso de objetos


de excepciones.

Explicacin previa

Cuando se produce una


excepcin es necesario
saber a qu se debe y qu
informacin est asociada al
error.

Exception
Exception
SystemException
SystemException
OutOfMemoryException
OutOfMemoryException
IOException
IOException
NullReferenceException
NullReferenceException
ApplicationException
ApplicationException

Recomendacin al
profesor

El objetivo de este tema es


ofrecer una introduccin a
los objetos Exception. No
est pensado para que se
explique con detalle cmo
crear nuevos objetos
excepcin.

Los cdigos de error de programacin empleados en el cdigo procedural para


tratamiento de errores son similares al siguiente:
enum CodigoError {
ErrorSeguridad = -1,
ErrorIO = -2,
ErrorMemoriaInsuficiente = -3,
...
}

El uso de estos cdigos de error hace difcil proporcionar informacin que sea
til para recuperarse del error. Por ejemplo, en caso de un ErrorIO no se recibe
informacin sobre de qu tipo de error se trata. Ser un intento de escritura en
un archivo de slo lectura o un archivo inexistente, o se deber a un disco
daado? Y cul es el archivo que se intenta leer o escribir?
Para solucionar este problema de falta de informacin sobre el error generado,
en .NET Framework se ha definido una serie de clases de excepcin.

Instrucciones y excepciones

33

Todas las excepciones se derivan de la clase llamada Exception, que es parte


del runtime de lenguaje comn. La transparencia muestra la jerarqua de estas
excepciones. Las clases de excepcin ofrecen las siguientes ventajas:

Los mensajes de error no estn representados por valores enteros o


enumeraciones.
Los valores enteros de programacin, como -3, desparecen y en su
lugar se utilizan clases de excepcin concretas, como
OutOfMemoryException. Cada clase de excepcin puede residir
dentro de su propio archivo de origen y no est vinculada con las
dems clases de excepcin.

Se generan mensajes de error significativos.


Cada clase de excepcin es descriptiva y representa un error concreto
de forma clara y evidente. En lugar de un 3, se utiliza una clase
llamada OutOfMemoryException. Cada clase de excepcin contiene
tambin informacin especfica. Por ejemplo, una clase
FileNotFoundException podra contener el nombre del archivo no
encontrado.

Consejo Para emplear excepciones de forma eficaz es necesario mantener un


equilibrio entre clases de excepcin demasiado vagas y otras que son demasiado
precisas. Si la clase de excepcin es demasiado vaga, no ser posible escribir un
bloque catch til. Por otra parte, no es conveniente crear una clase de excepcin
demasiado precisa, ya que puede filtrar datos de funcionamiento y rompe la
encapsulacin.

Instrucciones y excepciones

34

Uso de bloques try-catch


Objetivo del tema

Describir las instancias


bsicas de C# para el
tratamiento de excepciones.

Explicacin previa

El uso de controladores de
excepciones hace que el
tratamiento de errores sea
ms elegante.

try
try {{

Solucin orientada a objetos para el tratamiento de


errores
z

Poner el cdigo normal en un bloque try

Tratar las excepciones en un bloque catch aparte

Console.WriteLine("Escriba
Console.WriteLine("Escriba un
un nmero");
nmero");
Lgica
Lgica del
del programa
programa
int
i
=
int.Parse(Console.ReadLine());
int i = int.Parse(Console.ReadLine());

}}
catch
catch (OverflowException
(OverflowException capturada)
capturada)
{{
Console.WriteLine(capturada);
Console.WriteLine(capturada);
}}

Recomendacin al
profesor

El objetivo de esta
transparencia es explicar
cmo try y catch permiten
resolver muchos de los
problemas asociados con el
mtodo procedural de
tratamiento de errores.
Por supuesto, el tema no se
trata en profundidad. El
punto principal que no se
trata es la forma en que la
instruccin throw
desenreda la pila de
llamadas. Esto se explicar
en una transparencia
posterior, as que no hay
que entrar en detalles
ahora.
En la transparencia se usa
un solo bloque catch
general que capturar todas
las excepciones. No
dedique mucho tiempo a
este tema, ya que an no se
ha explicado la herencia.

Tratamiento
Tratamiento de
de errores
errores

Los bloques try-catch son la solucin que ofrece la orientacin a objetos a los
problemas de tratamiento de errores. La idea consiste en separar fsicamente las
instrucciones bsicas del programa para el flujo de control normal de las
instrucciones para tratamiento de errores. As, las partes del cdigo que podran
lanzar excepciones se colocan en un bloque try, mientras que el cdigo para
tratamiento de excepciones en el bloque try se pone en un bloque catch aparte.
La sintaxis de un bloque catch es la siguiente:
catch ( tipo-de-clase identificador ) { ... }

El tipo de clase tiene que ser System.Exception o un tipo derivado de


System.Exception.
El identificador, que es opcional, es una variable local de slo lectura en el
mbito del bloque catch.
catch (Exception capturada) {
...
}
Console.WriteLine(capturada); // Error en tiempo de compilacin:
// capturada est fuera de mbito

Instrucciones y excepciones

35

El ejemplo de la transparencia ilustra el uso de las instrucciones try y catch. El


bloque try contiene una expresin que puede generar la excepcin. En caso de
producirse la excepcin, el runtime detiene la ejecucin normal y empieza a
buscar un bloque catch que pueda capturar la excepcin pendiente (basndose
en su tipo). Si en la funcin inmediata no se encuentra un bloque catch
adecuado, el runtime desenreda la pila de llamadas en busca de la funcin de
llamada. Si tampoco ah encuentra un bloque catch apropiado, busca la funcin
que llam a la funcin de llamada y as sucesivamente hasta encontrar un
bloque catch (o hasta llegar al final de Main, en cuyo caso se cerrar el
programa). Si encuentra un bloque catch, se considera que la excepcin ha sido
capturada y se reanuda la ejecucin normal desde el cuerpo del bloque catch
(que, en el caso de la transparencia, escribe el mensaje contenido en el objeto
excepcin OverflowException).
Por lo tanto, el uso de bloques try-catch hace que las instrucciones para
tratamiento de errores no se mezclen con las instrucciones lgicas bsicas, por
lo que el programa es ms fcil de interpretar.

Instrucciones y excepciones

36

Bloques catch mltiples


Objetivo del tema

Explicar cmo capturar


distintos tipos de
excepciones.

Explicacin previa

Un solo bloque de cdigo


puede lanzar varios tipos de
excepciones diferentes.

try
try
{{

Cada bloque catch captura una clase de excepcion

Un bloque try puede tener un bloque catch general

Un bloque try no puede capturar una clase derivada de


una clase capturada en un bloque catch anterior
Console.WriteLine(Escriba
Console.WriteLine(Escriba el
el primer
primer nmero");
nmero");
int
i
=
int.Parse(Console.ReadLine());
int i = int.Parse(Console.ReadLine());
Console.WriteLine("Escriba
Console.WriteLine("Escriba el
el segundo
segundo nmero");
nmero");
int
j
=
int.Parse(Console.ReadLine());
int j = int.Parse(Console.ReadLine());
int
int kk == ii // j;
j;

}}
catch
catch (OverflowException
(OverflowException capturada)
capturada) {}
{}
catch
(DivideByZeroException
catch (DivideByZeroException capturada)
capturada) {}
{}

Un bloque de cdigo en una instancia try puede contener muchas instrucciones,


cada una de las cuales puede producir una o ms clases diferentes de excepcin.
Al haber muchas clases de excepciones distintas, es posible que haya muchos
bloques catch y que cada uno de ellos capture un tipo especfico de excepcin.
La captura de una excepcin se basa nicamente en su tipo. El runtime captura
automticamente objetos excepcin de un tipo concreto en un bloque catch para
ese tipo.
El siguiente cdigo ayudar a comprender mejor lo que ocurre en un bloque
try-catch mltiple:
1. try {
2.
Console.WriteLine("Escriba el primer nmero");
3.
int i = int.Parse(Console.ReadLine());
4.
Console.WriteLine("Escriba el segundo nmero");
5.
int j = int.Parse(Console.ReadLine());
6.
int k = i / j;
7. }
8. catch (OverflowException capturada)
9. {
10.
Console.WriteLine(capturada);
11. }
12. catch(DivideByZeroException capturada)
13. {
14.
Console.WriteLine(capturada);
15. }
16. ...

Instrucciones y excepciones

37

La lnea 3 inicializa int i con un valor ledo de la consola. Esto puede lanzar un
objeto excepcin de clase OverflowException, en cuyo caso no se ejecutarn
las lneas 4, 5 y 6. Se suspende la secuencia de ejecucin normal y el control
pasa al primer bloque catch que pueda capturar esa excepcin, que en este
ejemplo est en la lnea 8. Una vez transferido el control, se ejecuta la
instruccin hasta la llave de cierre y se devuelve el control a la lnea 16.
Por otra parte, es posible que las lneas 3 a 5 no lancen ninguna excepcin. En
ese caso, la ejecucin continuar normalmente hasta la lnea 6, que puede lanzar
un objeto excepcin de clase DivideByZeroException. Si eso ocurre, el flujo
de control salta al bloque catch de la lnea 12, que se ejecuta normalmente y
devuelve el control a la lnea 16.
Si ninguna de las instrucciones en el bloque try lanza una excepcin, el flujo de
control llega al final del bloque try y pasa a la lnea 16. Hay que tener en cuenta
que el flujo de control slo entra en un bloque catch si se lanza una excepcin.
Las instrucciones de un bloque try se pueden escribir sin preocuparse del
posible fallo de una instruccin anterior en el bloque try. En caso de que una
instruccin anterior produzca una excepcin, el flujo de control no llegar a
alcanzar las instrucciones siguientes en el bloque try.
Si el flujo de control no encuentra ningn bloque catch adecuado, detendr la
llamada al mtodo en que se encuentre y continuar buscando en la instruccin
desde la que se hizo la llamada al mtodo. La bsqueda seguir desenredando la
pila de llamadas hasta llegar a Main, si es necesario. Si esto causa la
finalizacin de Main, el proceso o subproceso que hubiera llamado a Main
terminar de una forma definida previamente.

Bloque catch general


Un bloque catch general, conocido tambin como clusula catch general,
puede capturar cualquier excepcin independientemente de su clase y se utiliza
con frecuencia para capturar cualquier posible excepcin que se pudiera
producir por la falta de un controlador adecuado.
Un bloque catch general se puede escribir de dos maneras. Es posible escribir
una instruccin catch simple:
catch { ... }

Tambin se puede escribir lo siguiente:


catch (System.Exception) { ... }

Un bloque try no puede tener ms que un bloque catch general. Por ejemplo, el
siguiente cdigo generar un error:
try {
...
}
catch { ... }
catch { ... } // Error

Instrucciones y excepciones

38

En caso de existir, un bloque catch general debe ser el ltimo bloque catch en
el programa:
try {
...
}
catch { ... }
catch (OutOfMemoryException capturada) { ... } // Error

Se generar un error en tiempo de compilacin en caso de capturar dos veces la


misma clase, como en el ejemplo siguiente:
catch (OutOfMemoryException capturada) { ... }
catch (OutOfMemoryException capturada) { ... } // Error

Tambin se generar un error en tiempo de compilacin si se intenta capturar


una clase derivada de otra capturada en un bloque catch anterior:
catch (Exception capturada) { ... }
catch (OutOfMemoryException capturada) { ... } // Error

Este cdigo produce un error porque la clase OutOfMemoryException deriva


de la clase SystemException, que a su vez deriva de la clase Exception.

Instrucciones y excepciones

39

Lanzamiento de excepciones
Objetivo del tema

Ofrecer una introduccin a


los temas tratados en esta
seccin.

Explicacin previa

La capacidad de capturar y
tratar excepciones es una
parte importante de
cualquier programa C#.

La instruccin throw

La clusula finally

Comprobacin de desbordamiento aritmtico

Normas para el tratamiento de excepciones

C# incluye la instruccin throw y la clusula finally, que permiten a los


programadores lanzar excepciones cuando sea necesario y controlarlas
convenientemente.
Al final de esta leccin, usted ser capaz de:

Lanzar sus propias excepciones.

Activar la comprobacin de desbordamiento aritmtico.

Instrucciones y excepciones

40

La instruccin throw
Objetivo del tema

Explicar cmo lanzar


excepciones.

Explicacin previa

Como parte del cdigo de


comprobacin de errores,
puede ser necesario lanzar
excepciones propias.

Lanza una excepcin apropiada

Asigna a la excepcin un mensaje significativo

throw
throw expression
expression ;;
if
if (minuto
(minuto << 11 ||
|| minuto
minuto >=
>= 60)
60) {{
throw
throw new
new InvalidTimeException(minuto
InvalidTimeException(minuto ++
"" no
no es
es un
un minuto
minuto vlido");
vlido");
//
// !!
!! Not
Not alcanzado
alcanzado !!
!!
}}

Los bloques try y catch se pueden utilizar para capturar errores lanzados en un
programa C#. Ya hemos visto cmo, en lugar de sealar un error devolviendo
un valor especial o asignndolo a una variable de error global, C# hace que la
ejecucin se transfiera a la clusula catch correspondiente.

Excepciones definidas por el sistema


Cuando necesita lanzar una excepcin, el runtime ejecuta una instruccin throw
y lanza una excepcin definida por el sistema. Esto interrumpe inmediatamente
la secuencia de ejecucin normal del programa y transfiere el control al primer
bloque catch que pueda hacerse cargo de la excepcin en funcin de su clase.

Instrucciones y excepciones

41

Lanzamiento de excepciones propias


Es posible utilizar la instruccin throw para lanzar excepciones propias, como
se ve en el siguiente ejemplo:
if (minuto < 1 || minuto >= 60) {
string fallo = minuta + "no es un minuto vlido";
throw new InvalidTimeException(fallo);
// !!No alcanzado!!
}

En este ejemplo se emplea la instruccin throw para lanzar una excepcin


definida por el usuario, InvalidTimeException, si el tiempo analizado no es
vlido.
En general, las excepciones esperan como parmetro una cadena con un
mensaje significativo que se puede mostrar o quedar registrado cuando se
captura la excepcin. Tambin es conveniente lanzar una clase adecuada de
excepcin.
Precaucin Los programadores en C++ ya estn acostumbrados a crear y
lanzar un objeto excepcin con una sola instruccin, como muestra el siguiente
cdigo:
throw out_of_range("ndice fuera de lmites");

La sintaxis en C# es muy similar, pero requiere la palabra clave new:


throw new FileNotFoundException("...");

Lanzamiento de objetos
Slo es posible lanzar un objeto si el tipo de ese objeto deriva directa o
indirectamente de System.Exception. Esto es diferente a lo que ocurre en C++,
donde se puede lanzar objetos de cualquier tipo, como en el siguiente cdigo:
throw 42; // Permitido en C++, pero no en C#

Se puede utilizar una instruccin throw en un bloque catch para volver a lanzar
el mismo objeto excepcin, como en el siguiente ejemplo:
catch (Exception capturada) {
...
throw capturada;
}

Tambin es posible lanzar un nuevo objeto excepcin de un tipo distinto:


catch (IOException capturada) {
...
throw new FileNotFoundException(nombre_de_archivo);
}

Instrucciones y excepciones

42

En el ejemplo anterior, el objeto IOException y toda la informacin que


contiene se pierde cuando la excepcin se convierte en un objeto
FileNotFoundException. Es ms conveniente ajustar la excepcin, aadiendo
nueva informacin pero conservando la que tiene, como se ve en el siguiente
cdigo:
catch (IOException capturada) {
...
throw new FileNotFoundException(nombre_de_archivo, capturada);
}

La capacidad de asignar un objeto excepcin resulta especialmente til en las


fronteras de un sistema con arquitectura multi-capa.
Es posible usar una instruccin throw sin ninguna expresin, pero slo en un
bloque catch. Vuelve a lanzar la excepcin que se est controlando en ese
momento. En C++ esta accin tambin recibe el nombre de relanzamiento.
Como consecuencia, estas dos lneas de cdigo darn el mismo resultado:
catch (OutOfMemoryException capturada) { throw capturada; }
...
catch (OutOfMemoryException) { throw ; }

Instrucciones y excepciones

43

La clusula finally
Objetivo del tema

Explicar cmo limpiar


recursos tras el lanzamiento
de una excepcin.

Explicacin previa

Las excepciones siempre se


producen en el momento
ms inoportuno. La
instruccin finally de C#
permite liberar los recursos
utilizados y evita la prdida
de informacin.

Las instrucciones de un bloque finally se ejecutan

Monitor.Enter(x);
Monitor.Enter(x);
try
try {{
...
...
}}
finally
finally {{
Monitor.Exit(x);
Monitor.Exit(x);
}}

Bloques
Bloques catch
catch opcionales
opcionales

La clusula finally de C# contiene un conjunto de instrucciones que es


necesario ejecutar sea cual sea el flujo de control. As, las instrucciones del
bloque finally se ejecutarn aunque el control abandone un bucle try como
resultado de la ejecucin normal porque el flujo de control llega al final del
bloque try. Del mismo modo, tambin se ejecutarn las instrucciones del
bloque finally si el control abandona un bucle try como resultado de una
instruccin throw o una instruccin de salto como break, continue o goto.
El bloque finally es til en dos casos: para evitar la repeticin de instrucciones
y para liberar recursos tras el lanzamiento de una excepcin.

Repeticin de instrucciones
Si las instrucciones del final de un bloque try estn repetidas en un bloque
catch general, se puede evitar la duplicacin pasando las instrucciones a un
bloque finally. Consideremos el siguiente ejemplo:
try {
...
instrucciones
}
catch {
...
instrucciones
}

Instrucciones y excepciones

44

Este cdigo se puede reescribir de la siguiente manera para simplificarlo:


try {
...
}
catch {
...
}
finally {
instrucciones
}

Es un error que una instruccin break, continue o goto transfiera el control


fuera de un bloque finally. Estas instrucciones slo se pueden utilizar si el
objetivo del salto est en el mismo bloque finally. Sin embargo, siempre es un
error que haya una instruccin return en un bloque finally, aunque sea la
ltima instruccin del bloque.
Si se lanza una excepcin durante la ejecucin de un bloque finally, se
propagar hasta el siguiente bloque try ::
try {
try {
...
}
catch {
// EjemploExcepcion no se captura aqu
}
finally {
throw new EjemploExcepcion ("quin me capturar?");
}
}
catch {
// EjemploExcepcion se captura aqu
}

Si se lanza una excepcin durante la ejecucin de un bloque finally y ya se


estaba propagando otra excepcin, se perder la excepcin original:
try {
throw new EjemploExcepcion ("Se pierde");
}
finally {
throw new EjemploExcepcion ("Se puede encontrar y capturar");
}

Instrucciones y excepciones

45

Comprobacin de desbordamiento aritmtico


Objetivo del tema

Explicar cmo controlar el


desbordamiento aritmtico.

Explicacin previa

La posibilidad de
desbordamiento o
subdesbordamiento
aritmtico se puede capturar
con algunas instrucciones
adicionales.

Por defecto, el desbordamiento aritmtico no se


comprueba
z

Un comando checked activa la comprobacin de


desbordamiento

checked
checked {{
int
int numero
numero == int.MaxValue;
int.MaxValue;
Console.WriteLine(++numero);
Console.WriteLine(++numero);
}}
unchecked
unchecked {{
int
int numero
numero == int.MaxValue;
int.MaxValue;
Console.WriteLine(++numero);
Console.WriteLine(++numero);
}}

OverflowException
OverflowException
Se lanza un objeto excepcin.
WriteLine no se ejecuta

MaxValue + 1 es negativo?

-2147483648

Por defecto, un programa C# no comprueba la posibilidad de desbordamiento


aritmtico, como se puede ver en este ejemplo:
Recomendacin al
profesor

Los diagramas de la
transparencia representan
deliberadamente el flujo de
control normal con una
flecha que apunta hacia
abajo, y el flujo de control
anormal con una flecha que
apunta hacia arriba.

// ejemplo.cs
class Ejemplo
{
static void Main( )
{
int numero = int.ValorMax;
Console.WriteLine(++numero);
}
}

En este cdigo, numero se inicializa al valor mximo para un int. La expresin


++numero incrementa numero a 2147483648, el mayor valor int negativo,
que se escribe en la consola. No se genera ningn mensaje de error.

Instrucciones y excepciones

46

Control de comprobacin del desbordamiento aritmtico


Cuando se compila un programa C#, es posible activar globalmente la
comprobacin del desbordamiento aritmtico utilizando la opcin de lnea de
comandos /checked+:
c:\ csc /checked+ ejemplo.cs

El programa ejecutable resultante producir una excepcin de clase


System.OverflowException.
Del mismo modo, es posible desactivar globalmente la comprobacin del
desbordamiento aritmtico utilizando la opcin de lnea de comandos
/checked-:
c:\ csc /checked- ejemplo.cs

El programa ejecutable resultante ajustar el valor int a int.ValorMin y no


producir una excepcin de clase System.OverflowException.

Creacin de instrucciones checked y unchecked


Las palabras clave checked y unchecked se pueden utilizar para crear
instrucciones con comprobacin activada o desactivada explcitamente:
checked
{ lista-de-instrucciones }
unchecked { lista-de-instrucciones }

Independientemente del parmetro /checked de tiempo de compilacin, las


instrucciones contenidas en una lista de instrucciones checked activan siempre
la comprobacin del desbordamiento aritmtico. Del mismo modo, las
instrucciones contenidas en una lista de instrucciones unchecked no activan
nunca la comprobacin del desbordamiento aritmtico, independientemente del
parmetro /checked de tiempo de compilacin.

Creacin de expresiones checked y unchecked


Tambin es posible utilizar las palabras clave checked y unchecked para crear
instrucciones con comprobacin activada o desactivada:
checked ( expresin )
unchecked ( expresin )

Una expresin checked se revisa para ver si hay desbordamiento aritmtico,


mientras que una expresin unchecked no se comprueba. Por ejemplo, el
siguiente cdigo generar una System.OverflowException.
// ejemplo.cs
class Ejemplo
{
static void Main( )
{
int numero = int.ValorMax;
Console.WriteLine(checked(++numero));
}
}

Instrucciones y excepciones

47

Normas para el tratamiento de excepciones


Objetivo del tema

Explicar algunas normas


generales recomendadas
para el tratamiento de
excepciones.

Explicacin previa

Hay una serie de prcticas


recomendadas que es
necesario seguir a la hora
de escribir cdigo de
calidad.

Lanzamiento
z

Evitar excepciones para casos normales o esperados

Nunca crear ni lanzar objetos de clase Exception

Incluir una cadena de descripcin en un objeto


Exception
Lanzar objetos de la clase ms especfica posible

Captura
z

Ordenar los bloques catch de lo especfico a lo general

No permitir que salgan excepciones de Main

Siga las siguientes reglas para el tratamiento de excepciones:

Evite excepciones para casos normales o esperados.

Nunca cree ni lance objetos de clase Excepcin.


Cree clases de excepcin derivadas directa o indirectamente de
SystemException (y nunca desde la clase Excepcin raz). El
siguiente cdigo muestra un ejemplo:

class SyntaxException : SystemException


{
...
}

Incluya una cadena de descripcin en un objeto Exception.


Aada siempre una cadena de descripcin til en un objeto excepcin,
como en este caso:

string descripcion =
String.Format("{0}({1}): nueva lnea en constante de
cadena", nombrearchivo, numerolinea);
throw new SyntaxException(descripcion);

Lance objetos de la clase ms especfica posible.


Lance la excepcin ms concreta posible cuando esa informacin
pueda ser til al usuario. Por ejemplo, lance una
FileNotFoundException mejor que una IOException ms general.

Instrucciones y excepciones

48

Ordene los bloques catch desde el ms especfico al ms general.


Ordene los bloques catch desde la excepcin ms concreta a la
excepcin ms general, como en este ejemplo:

catch (SyntaxException capturada) { ... } // Hacer esto


catch (Exception capturada) { ... }

No deje que salgan excepciones de Main.


Ponga una clusula catch general en Main para asegurarse de que
nunca salen excepciones al final del programa.

static void Main( )


{
try {
...
}
catch (Exception capturada) {
...
}
}

Instrucciones y excepciones

Prctica A: Uso de instrucciones


Objetivos
Al final de esta prctica, usted ser capaz de:

Usar instrucciones para controlar el flujo de ejecucin.

Usar instrucciones de bucle.

Requisitos previos
Antes de realizar la prctica debe estar familiarizado con los
siguientes temas:

Creacin de variables en C#

Uso de operadores comunes en C#

Creacin de tipos enum en C#

Ejercicio 1
Conversin de un da del ao en un par de mes y da
En este ejercicio escribir un programa que lee de la consola un
nmero entero de da (entre 1 y 365) y lo almacena en una variable
entera. El programa convertir este nmero en un mes y un da del
mes e imprimir el resultado en la consola. Por ejemplo, el resultado
de introducir 40 debe ser Febrero 9. (En este ejercicio se ignora el
efecto de los aos bisiestos.)
Cmo leer desde la consola el nmero de da
1. Abra el proyecto WhatDay1.sln en la carpeta Starter\WhatDay1 dentro del
fichero lab04.zip. La clase WhatDay contiene una variable con el nmero
de das de cada mes almacenado en una coleccin. Por el momento no es
necesario entender cmo funciona una coleccin.
2. Aada a WhatDay.Main una instruccin System.Console.Write que
escriba un mensaje en la consola para pedir al usuario que introduzca un
nmero de da entre 1 y 365.
3. Aada a Main una instruccin que declare una variable string llamada linea
y la inicialice con una lnea leda desde la consola con el mtodo
System.Console.ReadLine.
4. Aada a Main una instruccin que declare una variable int llamada diaNum
y la inicialice con el entero devuelto por el mtodo int.Parse.
El cdigo completo debera ser como ste:

Instrucciones y excepciones

2
using System;
class WhatDay
{
static void Main( )
{
Console.Write("Por favor, escriba un nmero de da
entre 1 y 365: ");
string linea = Console.ReadLine( );
int diaNum = int.Parse(linea);
//
// Aada cdigo aqu
//
}
...
}

Guarde el trabajo realizado.


Compile el programa WhatDay1.cs y corrija los posibles errores. Ejecute
el programa.

Instrucciones y excepciones

Cmo calcular el par de mes y da a partir del nmero de da


Aada a Main una instruccin que declare una variable int llamada
mesNum y la inicialice a cero.
Hemos preparado diez instrucciones if (una para cada mes entre enero y
octubre) marcadas como comentarios. Elimine las marcas de
comentarios y aada a Main otras dos instrucciones if similares para
los meses de noviembre y diciembre.
Consejo Se pueden borrar a la vez varias marcas de comentarios (conservando
sus contenidos) seleccionando las lneas y eligiendo luego Edit (Edicin),
Advanced (Avanzada) y Uncomment Selection (Borrar marcas de comentarios
en seleccin).
Aada a Main una etiqueta de identificador llamada Fin despus de la
ltima instruccin if.
Despus de la etiqueta End, aada una instruccin que declare una
variable string sin inicializar llamada mesNombre.
Hemos preparado parte de una instruccin switch despus de la etiqueta
End, adems de las diez etiquetas case marcadas como comentarios
para los meses de enero a octubre. Elimine las marcas de
comentarios de las etiquetas case y aada otras dos similares con sus
contenidos para los meses de noviembre y diciembre. Aada una
etiqueta default a la instruccin switch. Aada a la etiqueta default
una instruccin que asigne el literal string sin hacer a la variable
mesNombre.
Despus de la instruccin switch, utilice el mtodo WriteLine para
obtener los valores de diaNum y mesNombre.

Instrucciones y excepciones

El programa completo debera ser como ste:


using System;
class WhatDay
{
static void Main( )
{
Console.Write("Por favor, escriba un nmero de da
entre 1 y 365: ");
string linea = Console.ReadLine( );
int diaNum = int.Parse(linea);
int mesNum = 0;
if (diaNum <= 31) { // Enero
goto Fin;
} else {
diaNum -= 31;
mesNum++;
}
if (diaNum <= 28) { // Febrero
goto Fin;
} else {
diaNum -= 28;
mesNum++;
}
if (diaNum <= 31) { // Marzo
goto Fin;
} else {
diaNum -= 31;
mesNum++;
}
El cdigo contina en la pgina siguiente.

Instrucciones y excepciones

5
if (diaNum <= 30) { // Abril
goto Fin;
} else {
diaNum -= 30;
mesNum++;
}
if (diaNum <= 31) { // Mayo
goto Fin;
} else {
diaNum -= 31;
mesNum++;
}
if (diaNum <= 30) { // Junio
goto Fin;
} else {
diaNum -= 30;
mesNum++;
}
if (diaNum <= 31) { // Julio
goto Fin;
} else {
diaNum -= 31;
mesNum++;
}
if (diaNum <= 31) { // Agosto
goto Fin;
} else {
diaNum -= 31;
mesNum++;
}
if (diaNum <= 30) { // Septiembre
goto Fin;
} else {
diaNum -= 30;
mesNum++;
}
if (diaNum <= 31) { // Octubre
goto Fin;
} else {
diaNum -= 31;
mesNum++;
}
if (diaNum <= 30) { // Noviembre
goto Fin;
} else {
diaNum -= 30;
mesNum++;
}
El cdigo contina en la pgina siguiente.

Instrucciones y excepciones

6
if (diaNum <= 31) { // Diciembre
goto Fin;
} else {
diaNum -= 31;
mesNum++;
}
End:
string mesNombre;
switch (mesNum)
case O :
mesNombre =
case 1 :
mesNombre =
case 2 :
mesNombre =
case 3 :
mesNombre =
case 4 :
mesNombre =
case 5 :
mesNombre =
case 6 :
mesNombre =
case 7 :
mesNombre =
case 8 :
mesNombre =
case 9 :
mesNombre =
case 10 :
mesNombre =
case 11 :
mesNombre =
default:
mesNombre =
}

{
"Enero"; break;
"Febrero"; break;
"Marzo"; break;
"Abril"; break;
"Mayo"; break;
"Junio"; break;
"Julio"; break;
"Agosto"; break;
"Septiembre"; break;
"Octubre"; break;
"Noviembre"; break;
"Diciembre"; break;
"sin hacer"; break;

Console.WriteLine("{0} {1}", diaNum, mesNombre);


}
...
}

Guarde el trabajo realizado.

Instrucciones y excepciones

Compile el programa WhatDay1.cs y corrija los posibles errores. Ejecute


el programa. Utilice los siguientes datos para comprobar que el
programa funciona correctamente:
Nmero de da

Mes y da

32

Febrero 1

60

Marzo 1

91

Abril 1

186

Julio 5

304

Octubre 31

309

Noviembre 5

327

Noviembre 23

359

Diciembre 25

Cmo calcular el nombre del mes utilizando una enum


Ahora sustituir por un mecanismo ms compacto la instruccin switch
que determina el nombre del mes a partir de un nmero de mes.
Declare un tipo enum llamado MesNombre y asgnele los nombres
de los doce meses, empezando con enero y terminando con
diciembre.
Marque como comentario toda la instruccin switch.
Consejo Es posible marcar como comentario varias lneas de cdigo
seleccionando las lneas y eligiendo luego Edit, Advanced y Comment
Selection (Marcar seleccin como comentario).
En lugar de la instruccin switch, aada una instruccin que declare una
variable enum MesNombre llamada temp. Inicialice temp desde la
variable int mesNum. Para ello necesitar la siguiente expresin de
cast:
(MesNombre)mesNum

Sustituya la inicializacin de mesNombre por la expresin


temp.ToString( )

Instrucciones y excepciones

El programa completo debera ser como ste:


using System;
enum MesNombre
{
Enero,
Febrero,
Marzo,
Abril,
Mayo,
Junio,
Julio,
Agosto,
Septiembre,
Octubre,
Noviembre,
Diciembre
}
class WhatDay
{
static void Main( )
{
Console.Write("Por favor, escriba un nmero de da
entre 1 y 365: ");
string linea = Console.ReadLine( );
int diaNum = int.Parse(linea);
int mesNum = 0;
// 12 instrucciones if, como antes
Fin:
MesNombre temp = (MesNombre)mesNum;
string mesNombre = temp.ToString( );
Console.WriteLine("{0} {1}", diaNum, mesNombre);
}
...
}

Guarde el trabajo realizado.


Compile el programa WhatDay1.cs y corrija los posibles errores. Ejecute
el programa. Utilice la tabla de datos anterior para comprobar que el
programa funciona correctamente.

Instrucciones y excepciones

Cmo sustituir las 12 instrucciones if por una instruccin foreach


Ahora sustituir por una instruccin foreach las 12 instrucciones que
calculan los pares de da y mes. Marque como comentarios las 12
instrucciones if que sustituir en los pasos siguientes.
Escriba una instruccin foreach que itere la coleccin DaysInMonths
proporcionada. Para ello, aada la siguiente instruccin:
foreach (int diasEnMes in DaysInMonths) ...

Aada un bloque de instrucciones como cuerpo de la instruccin


foreach. Los contenidos de este bloque sern muy similares a los de
cada una de las instrucciones if marcadas como comentarios,
excepto en que se usa la variable diasEnMes en lugar de los distintos
literales enteros.
Marque como comentario la etiqueta End por encima de la instruccin
switch marcada tambin como comentario. Sustituya la instruccin
goto del foreach por una instruccin break.
El programa completo debera ser como ste:
using System;
enum MesNombre { ... }
class WhatDay
{
static void Main( )
{
Console.Write("Por favor, escriba un nmero de da
entre 1 y 365: ");
string linea = Console.ReadLine( );
int diaNum = int.Parse(linea);
int mesNum = 0;
foreach (int diasEnMes in DaysInMonths) {
if (diaNum <= diasEnMes)
{
break;
}
else
{
diaNum -= diasEnMes;
mesNum++;
}
}
MesNombre temp = (MesNombre)mesNum;
string mesNombre = temp.ToString( );
Console.WriteLine("{0} {1}", diaNum, mesNombre);
}
...
}

Instrucciones y excepciones

10

Guarde el trabajo realizado.


Compile el programa WhatDay1.cs y corrija los posibles errores. Ejecute
el programa. Utilice la tabla de datos anterior para comprobar que el
programa sigue funcionando correctamente.
Ejecute el programa e introduzca nmeros de das menores de 1 y
mayores de 365 para ver qu ocurre.

Instrucciones y excepciones

Prctica B: Uso de excepciones


Objetivos
Al final de esta prctica, usted ser capaz de:

Lanzar y capturar excepciones.

Visualizar mensajes de error.

Requisitos previos
Antes de realizar la prctica debe estar familiarizado con los
siguientes temas:

Creacin de variables en C#

Uso de operadores comunes en C#

Creacin de tipos enum en C#

Ejercicio 1
Validacin del nmero de da
En este ejercicio aadir funcionalidad al programa creado en el
Ejercicio 1. El programa examinar el nmero de da inicial
introducido por el usuario. Si es menor que 1 o mayor que 365, el
programa lanzar una excepcin InvalidArgument (Da fuera de
intervalo), capturar esta excepcin en una clusula catch y mostrar
en la consola un mensaje de diagnstico.
Cmo validar el nmero de da
1. Abra el proyecto WhatDay2.sln en la carpeta Starter\WhatDay2 dentro del
fichero lab04.zip.
2. Incluya todo el contenido de WhatDay.Main en un bloque try.
3. Despus del bloque try, aada una clusula catch que capture excepciones
de tipo System.Exception y las llame capturada. Aada en el bloque
catch una instruccin WriteLine que escriba en la consola la excepcin
capturada.
4. Aada una instruccin if despus de la declaracin de la variable diaNum.
La instruccin if lanzar un objeto excepcin new de tipo
System.ArgumentOutOfRangeException si diaNum es menor que 1 o
mayor que 365. Utilice el literal string Da fuera de intervalo para crear
el objeto excepcin.

Instrucciones y excepciones

El cdigo completo debera ser como ste:


using System;
enum MesNombre { ... }
class WhatDay
{
static void Main( )
{
try {
Console.Write("Por favor, escriba un nmero de
da entre 1 y 365: ");
string linea = Console.ReadLine( );
int diaNum = int.Parse(linea);
if (diaNum < 1 || diaNum > 365) {
throw new ArgumentOutOfRangeException("Da
fuera de intervalo");
}
int mesNum = 0;
foreach (int diasEnMes in DaysInMonths) {
if (diaNum <= diasEnMes) {
break;
} else {
diaNum -= diasEnMes;
mesNum++;
}
}
MesNombre temp = (MesNombre)mesNum;
string mesNombre = temp.ToString( );
Console.WriteLine("{0} {1}", diaNum,
mesNombre);
}
catch (Exception capturada) {
Console.WriteLine(capturada);
}
}
...
}

Guarde el trabajo realizado.


Compile el programa WhatDay2.cs y corrija los posibles errores. Ejecute
el programa. Utilice la tabla de datos de la Prctica 4.1 (Ejercicio 1)
para comprobar que el programa sigue funcionando correctamente.
Ejecute el programa e introduzca nmeros de das menores de 1 y
mayores de 365. Compruebe que la entrada no vlida se captura de
forma segura y que el objeto excepcin es lanzado, capturado y
mostrado.

Instrucciones y excepciones

Ejercicio 2
Tratamiento de aos bisiestos
En este ejercicio aadir funcionalidad al programa realizado en el
Ejercicio 1. Una vez finalizado el ejercicio, el programa pedir al
usuario un ao adems de un nmero de da. El programa detectar si
el ao introducido es bisiesto. Comprobar si el nmero de da est
entre 1 y 366 si el ao es bisiesto, o entre 1 y 365 si no lo es.
Finalmente, utilizar una nueva instruccin foreach para calcular
correctamente el par de mes y da para aos bisiestos.
Cmo introducir el ao desde la consola
1. Abra el proyecto WhatDay3.sln en la carpeta Starter\WhatDay3 dentro del
fichero lab04.zip.
2. Aada al principio de WhatDay.Main una instruccin
System.Console.Write que escriba en la consola un mensaje pidiendo al
usuario que introduzca un ao.
3. Cambie la declaracin y la inicializacin de la string linea a una
asignacin. Cambie string linea = Console.ReadLine( ); por
linea = Console.ReadLine( );.
4. Aada a Main una instruccin que declare una variable string llamada
linea y la inicialice con una lnea leda desde la consola con el mtodo
System.Console.ReadLine.
5. Aada a Main una instruccin que declare una variable int llamada
annoNum y la inicialice con el entero devuelto por el mtodo int.Parse.

Instrucciones y excepciones

El cdigo completo debera ser como ste:


using System;
enum MesNombre { ... }
class WhatDay
{
static void Main( )
{
try {
Console.Write("Por favor, escriba el ao: ");
string linea = Console.ReadLine( );
int annoNum = int.Parse(linea);
Console.Write("Por favor, escriba un nmero de
da entre 1 y 365: ");
linea = Console.ReadLine( );
int diaNum = int.Parse(linea);
// Como antes....
}
catch (Exception capturada) {
Console.WriteLine(capturada);
}
}
...
}

Guarde el trabajo realizado.


Compile el programa WhatDay3.cs y corrija los posibles errores.
Cmo determinar si el ao es bisiesto
Inmediatamente despus de la declaracin de annoNum, aada una
instruccin que declare una variable bool llamada esAnnoBisiesto.
Inicialice esta variable con una expresin booleana que determine si
annoNum es un ao bisiesto. Un ao es bisiesto si se cumplen las
dos condiciones siguientes:
Es divisible por 4.
Es no divisible por 100, o es divisible por 400.
Aada una instruccin if inmediatamente despus de la declaracin de
esAnnoBisiesto. Escriba en la instruccin if la cadena ES un ao
bisiesto o NO es un ao bisiesto para la consola, dependiendo del
valor de esAnnoBisiesto. Emplear esta instruccin if para
comprobar que la determinacin booleana de aos bisiestos es
correcta.

Instrucciones y excepciones

El programa completo debera ser como ste:


using System;
enum MesNombre { ... }
class WhatDay
{
static void Main( )
{
try
{
Console.Write("Por favor, escriba el ao: ");
string linea = Console.ReadLine( );
int annoNum = int.Parse(linea);
bool esAnnoBisiesto = (annoNum % 4 == 0)
&& (annoNum % 100 != 0
|| annoNum % 400 == 0);
if (esAnnoBisiesto)
{
Console.WriteLine(" ES un ao bisiesto");
} else
{
Console.WriteLine("NO es un ao bisiesto ");
}
Console.Write("Por favor, escriba un nmero de
da entre 1 y 365: ");
linea = Console.ReadLine( );
int diaNum = int.Parse(linea);
// Como antes...
}
catch (Exception capturada)
{
Console.WriteLine(capturada);
}
}
...
}

Guarde el trabajo realizado.


Compile el programa WhatDay3.cs y corrija los posibles errores. Utilice
la siguiente tabla para comprobar que la determinacin booleana de
aos bisiestos es correcta.
Ao bisiesto

Ao no bisiesto

1996

1999

2000

1900

2004

2001

Marque como comentario la instruccin if aadida en el paso 2.

Instrucciones y excepciones

Cmo validar el nmero de da frente a 365 o 366


Inmediatamente despus de la declaracin de esAnnoBisiesto, aada una
declaracin de una variable int llamada maxNumDias. Inicialice
maxNumDias con 366 o 365, dependiendo de si esAnnoBisiesto es
true o false, respectivamente.
Modifique la instruccin WriteLine que pregunta al usuario el nmero
de da. Tiene que mostrar el intervalo 1 a 366 si se ha introducido un
ao bisiesto y 1 a 365 si es un ao no bisiesto.
Compile el programa WhatDay3.cs y corrija los posibles errores. Ejecute
el programa y compruebe que el paso anterior funciona
correctamente.
Modifique la instruccin if que valida el valor de diaNum para usar la
variable maxNumDias en lugar del literal 365.
El programa completo debera ser como ste:
using System;
enum MesNombre { ... }
class WhatDay
{
static void Main( )
{
try
{
Console.Write("Por favor, escriba el ao: ");
string linea = Console.ReadLine( );
int annoNum = int.Parse(linea);
bool esAnnoBisiesto = (annoNum % 4 == 0)
&& (annoNum % 100 != 0
|| annoNum % 400 == 0);
int maxNumDias = esAnnoBisiesto ? 366 : 365;
Console.Write("Por favor, escriba un nmero de
da entre 1 y {0}: ", maxNumDias);
linea = Console.ReadLine( );
int diaNum = int.Parse(linea);
if (diaNum < 1 || diaNum > maxNumDias) {
throw new ArgumentOutOfRangeException("Da
fuera de intervalo");
}
// Como antes....
}
catch (Exception capturada)
{
Console.WriteLine(capturada);
}
}
...
}

Instrucciones y excepciones

Guarde el trabajo realizado.


Compile el programa WhatDay3.cs y corrija los posibles errores. Ejecute
el programa y compruebe que el paso anterior funciona
correctamente.
Cmo calcular correctamente el par de mes y da para aos bisiestos
1. Aada una instruccin if-else despus de la instruccin if que valida el
nmero de da y la declaracin del entero mesNum. La expresin
booleana empleada en esta instruccin if-else ser la variable
esAnnoBisiesto.
2. Mueva la instruccin foreach para que quede incrustada en la
instruccin if-else en los casos true y false. Una vez hecho esto, el
cdigo debera ser como ste:
if (esAnnoBisiesto)
{
foreach (int diasEnMes in DaysInMonths) {
...
}
} else
{
foreach (int diasEnMes in DaysInMonths) {
...
}
}

3. Guarde el trabajo realizado.


4. Compile el programa WhatDay3.cs y corrija los posibles errores.
Ejecute el programa y compruebe que el nmero de das en aos no
bisiestos se sigue tratando correctamente.
5. El siguiente paso ser usar la coleccin DaysInLeapMonths
preparada. Es una coleccin de valores int como DaysInMonths, salvo
en que el segundo valor de la coleccin (el nmero de das en febrero)
es 29 en lugar de 28.
6. Use DaysInLeapMonths en lugar de DiasEnMes en la parte true de
la instruccin if-else.

Instrucciones y excepciones

7. El programa completo debera ser como ste:


using System;
enum MesNombre { ... }
class WhatDay
{
static void Main( )
{
try {
Console.Write("Por favor, escriba el ao: ");
string linea = Console.ReadLine( );
int annoNum = int.Parse(linea);
bool esAnnoBisiesto = (annoNum % 4 == 0)
&& (annoNum % 100 != 0
|| annoNum % 400 == 0);
int maxNumDias = esAnnoBisiesto ? 366 : 365;
Console.Write("Por favor, escriba un nmero de
da entre 1 y {0}: ", maxNumDias);
linea = Console.ReadLine( );
int diaNum = int.Parse(linea);
if (diaNum < 1 || diaNum > maxNumDias) {
throw new ArgumentOutOfRangeException("Da
fuera de intervalo");
}
int mesNum = 0;
if (esAnnoBisiesto) {
foreach (int diasEnMes in
DaysInLeapMonths) {
if (diaNum <= diasEnMes) {
break;
} else {
diaNum -= diasEnMes;
mesNum++;
}
}
} else {
foreach (int diasEnMes in DaysInMonths) {
if (diaNum <= diasEnMes) {
break;
} else {
diaNum -= diasEnMes;
mesNum++;
}
}
}
El cdigo contina en la pgina siguiente.

Instrucciones y excepciones

9
MesNombre temp = (MesNombre)mesNum;
string mesNombre = temp.ToString( );
Console.WriteLine("{0} {1}", diaNum,
mesNombre);
}
catch (Exception capturada) {
Console.WriteLine(capturada);
}
}
...
}

Guarde el trabajo realizado.


Compile el programa WhatDay3.cs y corrija los posibles errores. Ejecute
el programa, usando los datos de la siguiente tabla para comprobar
que funciona correctamente.
Ao

Nmero de da

Mes y da

1999

32

Febrero 1

2000

32

Febrero 1

1999

60

Marzo 1

2000

60

Febrero 29

1999

91

Abril 1

2000

91

Marzo 31

1999

186

Julio 5

2000

186

Julio 4

1999

304

Octubre 31

2000

304

Octubre 30

1999

309

Noviembre 5

2000

309

Noviembre 4

1999

327

Noviembre 23

2000

327

Noviembre 22

1999

359

Diciembre 25

2000

359

Diciembre 24

Mtodos y parmetros

Contenido
Notas generales
Uso de mtodos

1
2

Uso de parmetros

16

Uso de mtodos sobrecargados

29

Mtodos y parmetros

Notas para el instructor


Este mdulo explica el uso de mtodos, parmetros y mtodos sobrecargados.
Tambin explica que es recomendable descomponer la lgica del programa en
unidades funcionales, ya que facilita la reutilizacin del cdigo.
El mdulo comienza explicando qu son los mtodos, cmo se crean y cmo se
pueden hacer llamadas a mtodos. A continuacin se discuten brevemente los
modificadores de acceso private y public (que se tratarn con ms detalle en
mdulos posteriores). El mdulo concluye con una explicacin de la sobrecarga
de mtodos y las reglas sobre signaturas de mtodos.
Este mdulo sienta tambin las bases para los temas sobre encapsulacin, que
se tratar en un mdulo posterior.
Al final de este mdulo, los estudiantes sern capaces de:
Crear mtodos estticos que aceptan parmetros y devuelven valores.
Pasar parmetros a mtodos utilizando distintos mecanismos.
Seguir reglas de mbito para variables y mtodos.

Mtodos y parmetros

Notas generales
Objetivo del tema

Ofrecer una introduccin a


los contenidos y objetivos
del mdulo.

Explicacin previa

En este mdulo aprender


cmo usar mtodos en C#,
cmo se pasan parmetros
y cmo se devuelven
valores.

Para su informacin

Este mdulo describe la


sintaxis bsica para el uso
de mtodos en C#, pero no
incluye una discusin
completa de conceptos
orientados a objetos como
la encapsulacin y el
ocultamiento de
informacin. En particular,
este mdulo discute los
mdulos estticos pero no
los mtodos de instancia.
Para parmetros y valores
devueltos se utilizarn
nicamente tipos valor, ya
que todava no se han
tratado los tipos de
referencia.

Uso de mtodos

Uso de parmetros

Uso de mtodos sobrecargados

Uno de los principios bsicos del diseo de aplicaciones es que deben estar
divididas en unidades funcionales, ya que las secciones pequeas de cdigo son
ms fciles de entender, disear, desarrollar y depurar. La divisin de una
aplicacin en unidades funcionales permite tambin la reutilizacin de
componentes funcionales en toda la aplicacin.
Una aplicacin C# est estructurada en clases que contienen bloques de cdigo
con nombre llamados mtodos. Un mtodo es un miembro de una clase que
lleva a cabo una accin o calcula un valor.
Al final de este mdulo, usted ser capaz de:
Crear mtodos estticos que aceptan parmetros y devuelven valores.
Pasar parmetros a mtodos de distintas maneras.
Declarar y usar mtodos sobrecargados.

Mtodos y parmetros

Uso de mtodos
Objetivo del tema

Ofrecer una introduccin a


los temas tratados en esta
seccin.

Explicacin previa

En esta seccin estudiar el


uso de mtodos en C#.

Definicin de mtodos

Llamadas a mtodos

Uso de la instruccin return

Uso de variables locales

Devolucin de valores

En esta seccin estudiar el uso de mtodos en C#. Los mtodos son un


mecanismo importante para estructurar el cdigo de un programa. Aprender
cmo se crean y cmo se pueden hacer llamadas a mtodos desde una sola clase
y desde una clase a otra.
Tambin aprender a usar variables locales, as como a asignarlas y destruirlas.
Finalmente, aprender a devolver un valor desde un mtodo y a utilizar
parmetros para transferir datos a un mtodo o extraerlos de l.

Mtodos y parmetros

Definicin de mtodos
Objetivo del tema

Mostrar la sintaxis para la


definicin de mtodos
simples.

Explicacin previa

Esta transparencia muestra


cmo definir un mtodo
simple.

Main es un mtodo
z

Para definir mtodos propios se usa la misma sintaxis

using
using System;
System;
class
class ExampleClass
ExampleClass
{{
static
static void
void ExampleMethod(
ExampleMethod( ))
{{
Console.WriteLine("ExampleMethod");
Console.WriteLine("ExampleMethod");
}}
static
static void
void Main(
Main( ))
{{
//
// ...
...
}}
}}

Recomendacin al
profesor

No entre por el momento en


explicaciones detalladas
sobre el significado de
static, void o la lista de
parmetros vaca. Lo ms
importante que hay que
recordar es que un mtodo
pertenece a una clase, que
tiene un nombre y que
contiene un bloque de
cdigo.

Un mtodo es una serie de instrucciones C# que han sido agrupadas bajo un


nombre determinado. La mayor parte de los lenguajes de programacin
modernos incluyen un concepto similar; se puede considerar que un mtodo es
equivalente a una funcin, una subrutina, un procedimiento o un subprograma.

Ejemplos de mtodos
El cdigo mostrado en la transparencia contiene tres mtodos:
El mtodo Main
El mtodo WriteLine
El mtodo ExampleMethod
El mtodo Main es el punto de entrada de la aplicacin, mientras que
WriteLine forma parte de Microsoft .NET Framework y se puede llamar
desde un programa. El mtodo WriteLine es un mtodo esttico de la clase
System.Console. El mtodo ExampleMethod pertenece a ExampleMethod y
contiene una llamada al mtodo WriteLine.
Todos los mtodos en C# pertenecen a una clase, al contrario de lo que ocurre
en otros lenguajes de programacin como C, C++ y Microsoft Visual Basic,
que permiten subrutinas y funciones globales.

Mtodos y parmetros

Creacin de mtodos
Cuando se crea un mtodo hay que especificar lo siguiente:
Nombre
Un mtodo no puede tener el mismo nombre que una variable, una constante
o cualquier otro elemento que no sea un cdigo y haya sido declarado en la
clase. El nombre del mtodo puede ser cualquier identificador permitido de
C# y distingue entre maysculas y minsculas.
Lista de parmetros
A continuacin del nombre del mtodo viene una lista de parmetros para el
mtodo. Esta lista aparece entre parntesis que deben estar presentes aunque
no hay ningn parmetro, como se ve en los ejemplos de la transparencia.
Cuerpo del mtodo
Despus de los parntesis viene el cuerpo del mtodo, que debe estar entre
llaves ({ y }) aunque no contenga ms que una instruccin.

Sintaxis para la definicin de mtodos


Para crear un mtodo se utiliza la siguiente sintaxis:
static void MethodName( )
{
cuerpo del mtodo
}

Recomendacin al
profesor

Por el momento, no dedique


demasiado tiempo a hablar
de las palabras clave static
y void. La palabra clave
void se tratar ms
adelante en esta seccin,
mientras que static se
discutir en mdulos
posteriores dedicados a
conceptos orientados a
objetos.

El siguiente ejemplo muestra cmo crear un mtodo llamado ExampleMethod


en la clase ExampleClass:
using System;
class ExampleClass
{
static void ExampleMethod( )
{
Console.WriteLine("Example method");
}
static void Main( )
{
Console.WriteLine("Main method");
}
}

Nota C# distingue entre maysculas y minsculas en los nombres de mtodos,


lo que permite declarar y usar mtodos cuyos nombres slo se diferencian en
letras maysculas o minsculas. Por ejemplo, es posible declarar mtodos
llamados print y PRINT en la misma clase. Sin embargo, el runtime de
lenguaje comn requiere que los nombres de mtodos dentro de una clase se
diferencien tambin en otros aspectos para garantizar la compatibilidad con
otros lenguajes en los que los nombres de los mtodos no distinguen entre
maysculas y minsculas. Esto es importante si se desea que una aplicacin
interacte con otras aplicaciones escritas en lenguajes que no sean C#.

Mtodos y parmetros

Llamadas a mtodos
Objetivo del tema

Explicar cmo hacer una


llamada a un mtodo
simple.

Explicacin previa

Una vez definido un


mtodo, hay que saber
cmo llamarlo.

Una vez definido un mtodo, se puede:


z

Llamar a un mtodo desde dentro de la misma clase


Se usa el nombre del mtodo seguido de una lista de
parmetros entre parntesis
Llamar a un mtodo que est en una clase diferente
Hay que indicar al compilador cul es la clase que
contiene el mtodo que se desea llamar
El mtodo llamado se debe declarar con la palabra clave
public
Usar llamadas anidadas
Unos mtodos pueden hacer llamadas a otros, que a su
vez pueden llamar a otros mtodos, y as sucesivamente

Despus de definir un mtodo, es posible hacer llamadas a ese mtodo desde


dentro de la misma clase y desde otras clases.

Llamadas a mtodos
Recomendacin al
profesor

La sintaxis resultar familiar


para los desarrolladores en
C y C++. A los
desarrolladores en Visual
Basic puede indicarles que
en C# no existe la
instruccin Call y que hay
que usar parntesis en
todas las llamadas a
mtodos.

Para hacer una llamada a un mtodo hay que emplear el nombre del mtodo
seguido de una lista de parmetros entre parntesis. Los parntesis son
obligatorios aunque el mtodo llamado no contenga ningn parmetro, como se
ve en el siguiente ejemplo.
MethodName( );

Nota para los desarrolladores en Visual Basic La instruccin Call no existe.


Los parntesis son obligatorios en todas las llamadas a mtodos.

Mtodos y parmetros

El programa del siguiente ejemplo comienza al principio del mtodo Main de


ExampleClass. La primera instruccin muestra Comienza el programa. La
segunda instruccin en Main es la llamada a ExampleClass. El flujo de control
pasa a la primera instruccin en ExampleClass y aparece Hola, mundo. Al
final del mtodo, el control pasa a la instruccin inmediatamente despus de la
llamada al mtodo, que es la instruccin que muestra Termina el programa.
using System;
class ExampleClass
{
static void ExampleClass( )
{
Console.WriteLine("Hola, mundo");
}
static void Main( )
{
Console.WriteLine("Comienza el programa.");
ExampleMethod( );
Console.WriteLine("Termina el programa.");
}
}

Llamadas a mtodos desde otras clases


Recomendacin al
profesor

Los contenidos de este


tema estn simplificados.
En un mdulo posterior se
explicarn con detalle las
palabras clave public,
private, internal y
protected. Lo nico que
tiene que explicar por el
momento es que los
mtodos llamados desde
una clase diferente tienen
que estar declarados como
public.

Para que los mtodos de una clase puedan hacer llamadas a mtodos en otra
clase hay que:
Especificar la clase que contiene el mtodo que se desea llamar.
Para especificar la clase que contiene el mtodo se utiliza la siguiente
sintaxis:
ClassName.MethodName( );

Declarar el mtodo llamado con la palabra clave public.


El siguiente ejemplo muestra cmo hacer una llamada al mtodo TestMethod,
que est definido en la clase A, desde Main en la clase B:
using System;
class A
{
public static void TestMethod( )
{
Console.WriteLine("Esto es TestMethod en clase A");
}
}
class B
{
static void Main( )
{
A.TestMethod ( );
}
}

Mtodos y parmetros

Si en el ejemplo anterior se eliminara el nombre de la clase, el compilador


buscara un mtodo llamado TestMethod en la clase B. Puesto que en esa clase
no hay ningn mtodo con ese nombre, el compilador mostrar el siguiente
error: El nombre TestMethod no existe en la clase o espacio de nombres
B.
Un mtodo que no se declare como pblico es privado por defecto en la clase.
Por ejemplo, si en la definicin de TestMethod se omite la palabra clave
public, el compilador mostrar el siguiente error: A.TestMethod() no es
accesible debido a su nivel de proteccin.
Tambin se puede emplear la palabra clave private para indicar que slo es
posible hacer llamadas al mtodo desde dentro de la clase. Estas dos lneas de
cdigo tienen exactamente el mismo efecto, ya que los mtodos son privados
por defecto:
private static void MyMethod( );
static void MyMethod( );

Las palabras clave public y private especifican la accesibilidad del mtodo.


Estas palabras clave controlan si es posible hacer llamadas a un mtodo desde
fuera de la clase en la que est definido.

Llamadas anidadas a mtodos


Tambin es posible hacer llamadas a mtodos desde dentro de mtodos. El
siguiente ejemplo muestra cmo anidar llamadas a mtodos:
using System;
class NestExample
{
static void Method1( )
{
Console.WriteLine("Method1");
}
static void Method2( )
{
Method1( );
Console.WriteLine("Method2");
Method1( );
}
static void Main( )
{
Method2( );
Method1( );
}
}

Mtodos y parmetros

La salida de este programa es la siguiente:


Method1
Method2
Method1
Method1

La anidacin permite hacer llamadas a un nmero ilimitado de mtodos. No hay


ningn lmite predefinido para el nivel de anidacin. Sin embargo, el entorno de
tiempo de ejecucin puede imponer lmites, normalmente debido a la cantidad
de RAM disponible para ejecutar el proceso. Cada llamada a un mtodo
necesita memoria para almacenar direcciones de retorno y otra informacin.
Como regla general, si se agota la memoria para llamadas anidadas a mtodos
se debe probablemente a problemas en el diseo de clases.

Mtodos y parmetros

Uso de la instruccin return


Objetivo del tema

Presentar la instruccin
return y explicar cmo
usarla al final de un mtodo.

Explicacin previa

Normalmente, la ejecucin
de un mtodo se devuelve
al llamador cuando se llega
a la ltima instruccin del
mtodo, excepto si se utiliza
la instruccin return.

Return inmediato

Return con una instruccin condicional


static
static void
void ExampleMethod(
ExampleMethod( ))
{{
int
int numBeans;
numBeans;
//...
//...

}}

Recomendacin al
profesor

Esta resultar familiar para


los programadores en C y
C++. Para los
programadores en Visual
Basic, la instruccin return
por s misma es equivalente
a Exit Sub, Exit Function o
Exit Property en Visual
Basic.

Console.WriteLine("Hello");
Console.WriteLine("Hello");
if
if (numBeans
(numBeans << 10)
10)
return;
return;
Console.WriteLine("World");
Console.WriteLine("World");

La instruccin return se puede emplear para hacer que un mtodo se devuelva


inmediatamente al llamador. Sin una instruccin return, lo normal es que la
ejecucin se devuelva al llamador cuando se alcance la ltima instruccin del
mtodo.

Return inmediato
Por defecto, un mtodo es devuelto a su llamador cuando se llega al final de la
ltima instruccin del bloque de cdigo. La instruccin return se utiliza cuando
se quiere que un mtodo sea devuelto inmediatamente al llamador.
El mtodo del siguiente ejemplo muestra Hola, y es inmediatamente devuelto
a su llamador:
static void ExampleMethod( )
{
Console.WriteLine("Hola");
return;
Console.WriteLine("mundo");
}

Este uso de la instruccin return no resulta muy til, ya que la llamada final a
Console.WriteLine no se ejecuta nunca. Si los avisos del compilador de C#
estn activados a nivel 2 o superior, el compilador mostrar el siguiente
mensaje: Detectado cdigo inaccesible.

Mtodos y parmetros

10

Return con una instruccin condicional


Es mucho ms habitual, y mucho ms til, utilizar la instruccin return como
parte de una instruccin condicional como if o switch. Esto permite que un
mtodo sea devuelto al llamador si se cumple cierta condicin.
El mtodo del siguiente ejemplo ser devuelto si la variable numBeans es
menor que 10; en caso contrario, la ejecucin continuar dentro de este mdulo.
static void ExampleMethod( )
{
int numBeans;
//...
Console.WriteLine("Hola");
if (numBeans < 10)
return;
Console.WriteLine("mundo");
}

Consejo En general se considera una buena prctica de programacin que un


mtodo tenga un punto de entrada y otro de salida. El diseo de C# garantiza
que la ejecucin de todos los mtodos comienza por la primera instruccin. Un
mtodo sin ninguna instruccin return tiene un punto de salida al final del
bloque de cdigo. Un mtodo con varias instrucciones return tiene mltiples
puntos de salida, lo que en algunos casos puede hacer que el mtodo sea difcil
de entender y mantener.

Return con un valor


Recomendacin al
profesor

Los valores devueltos se


discutirn ms adelante en
este mdulo. Este prrafo
se ha incluido aqu para
anticiparse a las preguntas
de los estudiantes sobre el
tema.

Si un mtodo est definido con un tipo de datos en lugar de void, return se usa
para asignar un valor a la funcin. Este punto se discutir ms adelante en este
mdulo.

Mtodos y parmetros

11

Uso de variables locales


Objetivo del tema

Describir las variables


locales y explicar cmo se
crean y destruyen.

Explicacin previa

Cada mtodo tiene su


propio conjunto de variables
locales.

Variables locales
z

Se crean cuando comienza el mtodo

Son privadas para el mtodo

Se destruyen a la salida

Variables compartidas
z

Para compartir se utilizan variables de clase

Conflictos de mbito
z

El compilador no avisa si hay conflictos entre nombres


locales y de clase

Cada mtodo tiene su propio conjunto de variables locales, que slo se pueden
utilizar dentro del mtodo en el que estn declaradas. No es posible acceder a
las variables locales desde ninguna otra parte de la aplicacin.

Variables locales
Se pueden incluir variables locales en el cuerpo de un mtodo, como se ve en el
siguiente ejemplo:
static void MethodWithLocals( )
{
int x = 1; // Variable con valor inicial
ulong y;
string z;
...
}

Las variables locales pueden llevar asignado un valor inicial (como la variable x
en el cdigo del ejemplo anterior). La variable no estar inicializada si no se le
asigna un valor o si no tiene una expresin inicial para determinar un valor.

Mtodos y parmetros

Recomendacin al
profesor

Esta aplicacin sobre


asignacin y liberacin de
memoria se refiere
nicamente a tipos de valor.
La administracin de
memoria para tipos de
referencia es ms compleja
y se tratar en un mdulo
posterior.

12

Las variables que se declaran en un mtodo son completamente independientes


de las variables declaradas en otros mtodos, aunque sus nombres sean iguales.
Cada vez que se hace una llamada a un mtodo se asigna memoria para
variables locales, que se libera cuando termina el mtodo. Por lo tanto, los
valores almacenados en estas variables no se conservan desde una llamada a un
mtodo y la siguiente.

Mtodos y parmetros

13

Variables compartidas
El siguiente cdigo intenta contar el nmero de veces que ha sido llamado un
mtodo:
Recomendacin al
profesor

Los desarrolladores
experimentados en Visual
Basic tal vez comenten que,
en Visual Basic, poner
static antes del nombre de
un mtodo hace que todas
las variables locales de ese
mtodo tengan clase de
almacenamiento esttico.
Recuerde este hecho,
aunque normalmente no
ser necesario mencionarlo.

class CallCounter_Bad
{
static void Init( )
{
int nCount = 0;
}
static void CountCalls( )
{
int nCount;
++nCount;
Console.WriteLine("Mtodo llamado {0} veces", nCount);
}
static void Main( )
{
Init( );
CountCalls( );
CountCalls( );
}
}

Este programa no se puede compilar debido a dos problemas importantes. La


variable nCount en Inic no es la misma que la variable nCount en CountCalls.
Independientemente del nmero de veces que se llame al mtodo CountCalls,
el valor nCount se pierde cada vez que termina CountCalls.
Para su informacin

ste es el comportamiento
habitual de las variables
locales en C, C++ y Visual
Basic, por lo que no
deberan surgir demasiados
problemas.

La forma correcta de escribir este cdigo es utilizando una variable de clase,


como se muestra en el siguiente ejemplo:
class CallCounter_Good
{
static int nCount;
static void Init( )
{
nCount = 0;
}
static void CountCalls( )
{
++ nCount;
Console.Write("Mtodo llamado " + nCuenta + " veces.");
}
static void Main( )
{
Init( );
CountCalls( );
CountCalls( );
}
}

En este ejemplo, nCount se declara como clase en vez de mtodo. Por lo tanto,
nCount se comparte entre todos los mtodos de la clase.

Mtodos y parmetros

14

Conflictos de mbito
En C# se puede declarar una variable local con el mismo nombre que una
variable de clase, aunque eso puede producir resultados inesperados. En el
siguiente ejemplo, NumItems est declarada como una variable de clase
ScopeDemo, y tambin como una variable local en Method1. Las dos variables
son completamente distintas. En Method1, NumObjetos se refiere a la variable
local, mientras que en Method2 se refiere a la variable de clase.
class ScopeDemo
{
static int numItems = 0;
static void Method1( )
{
int numItems = 42;
...
}
static void Method2( )
{
numItems = 61;
}
}

Consejo El compilador de C# no indica si hay variables locales y variables de


clase que tienen los mismos nombres, por lo que conviene adoptar una
convencin de nomenclatura para distinguirlas unas variables de otras.

Mtodos y parmetros

15

Devolucin de valores
Objetivo del tema

Explicar cmo utilizar la


instruccin return para
devolver valores.

Explicacin previa

La instruccin return se
puede utilizar para devolver
un valor desde un mtodo.

El mtodo se debe declarar con un tipo que no sea void

Se aade una instruccin return con una expresin

Fija el valor de retorno

Se devuelve al llamador

Los mtodos que no son void deben devolver un valor

static
static int
int DosMasDos(
DosMasDos( )) {{
int
int a,b;
a,b;
aa == 2;
2;
bb == 2;
2;
return
return aa ++ b;
b;
}}

int
int x;
x;
xx == DosMasDos(
DosMasDos( );
);
Console.WriteLine(x);
Console.WriteLine(x);

Ya hemos aprendido a usar la instruccin return para hacer que un mtodo


finalice inmediatamente. Tambin se puede utilizar la instruccin return para
devolver un valor desde un mtodo. Para devolver un valor hay que:
1. Declarar el mtodo con el tipo del valor que se desea devolver.
2. Aadir al mtodo una instruccin return.
3. Incluir el valor que se desea devolver al llamador.

Declaracin de mtodos con un tipo que no sea void


Para declarar un mtodo de forma que devuelva un valor al llamador hay que
cambiar la palabra clave void por el tipo del valor que se desea devolver.

Mtodos y parmetros

16

Uso de instrucciones return


Recomendacin al
profesor

La instruccin return
devuelve un valor al
llamador inmediatamente.
Lo mismo ocurre en C y
C++. En Visual Basic, las
funciones miembro
devuelven un valor por
asignacin al nombre de la
funcin sin causar un return
inmediato.

La palabra clave return seguida de una expresin hace que el mtodo finalice
inmediatamente y devuelve la expresin como valor de retorno del mtodo.
El siguiente ejemplo muestra cmo declarar un mtodo llamado DosMasDos
que devuelve el valor 4 a Main cuando hace una llamada a DosMasDos:
class ExampleReturningValue
{
static int DosMasDos( )
{
int a,b;
a = 2;
b = 2;
return a + b;
}
static void Main( )
{
int x;
x = DosMasDos( );
Console.WriteLine(x);
}
}

El valor devuelto es un int, ya que int es el tipo de retorno del mtodo. Cuando
se hace una llamada al mtodo, ste devuelve el valor 4. En este ejemplo, el
valor se almacena en la variable local x de Main.

Los mtodos que no son void deben devolver valores


Si se declara un mtodo con un tipo distinto de void, es obligatorio aadir al
menos una instruccin return. El compilador intenta comprobar que cada uno
de estos mtodos devuelve siempre un valor al mtodo de llamada. Si detecta
que un mtodo que no es void no incluye ninguna instruccin return, el
compilador mostrar el siguiente mensaje de error: No todas las rutas de
cdigo devuelven un valor. Este mensaje tambin aparecer si el compilador
detecta que es posible ejecutar un mtodo que no es void sin devolver un valor.
Consejo La instruccin return slo se puede utilizar para devolver un valor
desde cada llamada a un mtodo. Si se desea devolver ms de un valor desde
una llamada a un mtodo se pueden utilizar los parmetros out o ref, que se
discutirn ms adelante en este mdulo. Tambin es posible devolver una
referencia a una tabla o clase o estructura, que puede contener varios valores.
La norma general, segn la cual hay que evitar el uso de varias instrucciones
return en un solo mtodo, es vlida tambin para mtodos que no son void.

Mtodos y parmetros

17

Uso de parmetros
Objetivo del tema

Ofrecer una introduccin a


los temas tratados en esta
seccin.

Explicacin previa

En esta seccin aprender


a utilizar parmetros en
mtodos.

Declaracin y llamadas a parmetros

Mecanismos de paso de parmetros

Paso por valor

Paso por referencia

Parmetros de salida

Uso de listas de parmetros de longitud variable

Normas para el paso de parmetros

Uso de mtodos recursivos

En esta seccin aprender a declarar parmetros y a hacer llamadas a mtodos


con parmetros. Estudiar tambin como se pasan parmetros. Finalmente,
aprender el uso de llamadas a mtodos recursivos en C#.
Recomendacin al
profesor

Dependiendo de su
formacin, es posible que
los estudiantes tengan
distintas ideas sobre el paso
de parmetros. C no
permite directamente el
paso de parmetros por
referencia (en su lugar se
pasan punteros). C++
incluye un mecanismo de
paso por referencia,
adems de punteros
similares a los de C. En
Visual Basic, los parmetros
se pasan por referencia de
forma predeterminada,
salvo que se desactive esta
opcin con la palabra clave
ByVal.

En esta seccin aprender a:


Declarar y hacer llamadas a parmetros.
Pasar parmetros utilizando los siguientes mecanismo:
Paso por valor
Paso por referencia
Parmetros de salida
Usar llamadas a mtodos recursivos.

Mtodos y parmetros

18

Declaracin y llamadas a parmetros


Objetivo del tema

Mostrar la sintaxis bsica


para la declaracin y el uso
de parmetros.

Explicacin previa

En la declaracin del
mtodo, los parmetros se
colocan entre los parntesis
que siguen al nombre del
mtodo.

Declaracin de parmetros
z

Se ponen entre parntesis despus del nombre del mtodo

Se definen el tipo y el nombre de cada parmetro

Llamadas a mtodos con parmetros


z

Un valor para cada parmetro

static
static void
void MethodWithParameters(int
MethodWithParameters(int n,
n, string
string y)
y)
{{ ...
}
... }
MethodWithParameters(2,
MethodWithParameters(2, "Hola,
"Hola, mundo");
mundo");

Los parmetros permiten pasar informacin hacia dentro y fuera de un mtodo.


La definicin de un mtodo puede incluir una lista de parmetros entre
parntesis a continuacin del nombre del mtodo. Las listas de parmetros de
todos los ejemplos que hemos visto hasta ahora en este mdulo estaban vacas.

Declaracin de parmetros
Cada parmetro tiene un tipo y un nombre. Se pueden declarar parmetros
poniendo sus declaraciones entre los parntesis que siguen al nombre del
mtodo. La sintaxis que se utiliza es similar a la empleada para declarar
variables locales, salvo que las declaraciones de parmetros se separan con una
coma en lugar de un punto y coma.
El siguiente ejemplo muestra cmo declarar un mtodo con parmetros:
static void MethodWithParameters(int n, string y)
{
// ...
}

Este ejemplo declara el mtodo MethodWithParameters con dos parmetros:


n e y. El primer parmetro es de tipo int, mientras que el segundo es de tipo
string. Los parmetros aparecen en la lista separados por comas.

Mtodos y parmetros

19

Llamadas a mtodos con parmetros


El cdigo de llamada debe indicar los valores de los parmetros en la llamada al
mtodo.
El siguiente cdigo muestra dos ejemplos de llamadas a un mtodo con
parmetros. En ambos casos, los valores de los parmetros son encontrados y
colocados en los parmetros n e y al principio de la ejecucin de
MethodWithParameters.
MethodWithParameters(2, "Hola, mundo");
int p = 7;
string s = "Mensaje de prueba";
MethodWithParameters(p, s);

Mtodos y parmetros

20

Mecanismos de paso de parmetros


Objetivo del tema

Presentar tres formas de


pasar parmetros.

Explicacin previa

Los parmetros se pueden


pasar de tres maneras
distintas.

Tres maneras de pasar parmetros

entrada
Paso por
por valor
valor
entrada Paso
entrada
entrada Paso
Paso por
por referencia
referencia
salida
salida
salida
salida

Para su informacin

Los parmetros se pueden pasar de tres maneras distintas:

En C y C++ se usa por


defecto el mecanismo de
paso por valor.

Por valor

C no incluye ningn
mecanismo de paso por
referencia.

Por referencia

C++ utiliza el modificador &


para indicar paso por
referencia.
Visual Basic utiliza por
defecto paso por referencia.

Parmetros
Parmetros de
de salida
salida

Los parmetros valor se llaman a veces parmetros de entrada, ya que los


datos se pueden transferir a un mtodo pero no fuera de l.
Los parmetros referencia se llaman a veces parmetros de entrada/salida,
ya que los datos se pueden transferir dentro y fuera de un mtodo.
Por salida
Los parmetros de salida se llaman a veces parmetros out, ya que los datos
se pueden transferir fuera de un mtodo pero no dentro de l.

Mtodos y parmetros

21

Paso por valor


Objetivo del tema

Explicar el mecanismo de
paso por valor.

Explicacin previa

El paso por valor es el


mecanismo predeterminado.

Mecanismo predeterminado para el paso de parmetros:


z

Se copia el valor del parmetro

Se puede cambiar la variable dentro del mtodo

No afecta al valor fuera del mtodo

El parmetro debe ser de un tipo igual o compatible

static
static void
void SumaUno(int
SumaUno(int x)
x)
{{
x++;
x++; //
// Incrementar
Incrementar xx
}}
static
static void
void Main(
Main( ))
{{
int
int kk == 6;
6;
SumaUno(k);
SumaUno(k);
}}

Console.WriteLine(k);
Console.WriteLine(k); //
// Muestra
Muestra el
el valor
valor 6,
6, no
no 77

La mayor parte de los parmetros se utilizan en las aplicaciones para pasar


informacin a un mtodo, no fuera de l. Por eso el paso por valor es el
mecanismo predeterminado para pasar parmetros en C#.

Definicin de parmetros valor


La definicin ms sencilla de un parmetro es un nombre de tipo seguido de un
nombre de variable, y se conoce como parmetro valor. Cuando se hace una
llamada a un mtodo, para cada parmetro valor se crea una nueva ubicacin de
almacenamiento donde se copian los valores de las expresiones correspondientes.
La expresin de cada parmetro valor debe ser del mismo tipo que la
declaracin del parmetro valor, o bien de un tipo que pueda ser convertido
implcitamente a ese tipo. Dentro del mtodo se puede escribir cdigo que
cambie el valor del parmetro. Esto no afectar a ninguna variable fuera de la
llamada al mtodo.
En el siguiente ejemplo, la variable x en AddOne (SumaUno) es
completamente independiente de la variable k en Main. Se puede cambiar la
variable x en AddOne, pero esto no afectar al valor de k.

Mtodos y parmetros

22
static void AddOne(int x)
{
x++;
}
static void Main( )
{
int k = 6;
AddOne (k);
Console.WriteLine(k); // Muestra el valor 6, no 7
}

Mtodos y parmetros

23

Paso por referencia


Objetivo del tema

Explicar el mecanismo de
paso por referencia.

Explicacin previa

Un parmetro referencia es
una referencia a una
posicin de memoria.

Qu son los parmetros referencia?


z

Una referencia a una posicin de memoria

Uso de parmetros referencia


z

Se usa la palabra clave ref en la declaracin y las


llamadas al mtodo

Los tipos y valores de variables deben coincidir

Los cambios hechos en el mtodo afectan al llamador

Hay que asignar un valor al parmetro antes de la


llamada al mtodo

Qu son los parmetros referencia?


Un parmetro referencia es una referencia a una posicin de memoria. A
diferencia de un parmetro valor, un parmetro referencia no crea una nueva
ubicacin de almacenamiento. Por el contrario, un parmetro referencia
representa la misma posicin de memoria que la variable indicada en la llamada
al mtodo.
Recomendacin al
profesor

Puede explicar a los


programadores en C y C++
que el operador ref es
similar al operador de
direccin (&) en C y C++,
aunque no son iguales. Las
direcciones de C y C++
permiten modificar
posiciones de memoria
arbitrarias. C# es ms
seguro.

Declaracin de parmetros referencia


Un parmetro referencia se puede declarar poniendo la palabra clave ref antes
del nombre del tipo, como se ve en el siguiente ejemplo:
static void ShowReference(ref int nId, ref long nCount)
{
// ...
}

Uso de distintos tipos de parmetros


La palabra clave ref afecta nicamente al parmetro al que antecede, no a toda
la lista de parmetros. En el siguiente mtodo, nId se pasa por referencia pero
longVar se pasa por valor:
static void OneRefOneVal(ref int nId, long longVar)
{
// ...
}

Mtodos y parmetros

24

Coincidencia de tipos y valores de parmetros


En la llamada a un mtodo, los parmetros referencia se indican utilizando la
palabra clave ref seguida de una variable. El valor indicado en la llamada al
mtodo debe ser exactamente igual al tipo en la definicin del mtodo, y
adems debe ser una variable, no una constante ni una expresin calculada.
int x;
long q;
ShowReference(ref x, ref q);

Si se omite la palabra clave ref o si se emplea una constante o una expresin


calculada, el compilador rechazar la llamada y mostrar un mensaje de error
parecido al siguiente: Imposible convertir de int a ref int.

Cambio de valores de parmetros referencia


Si se cambia el valor de un parmetro referencia cambiar tambin la variable
indicada por el llamador, ya que ambas son referencias a la misma posicin de
memoria. El siguiente ejemplo ilustra cmo el cambio del parmetro referencia
afecta tambin a la variable:
static void AddOne(ref int x)
{
x++;
}
static void Main( )
{
int k = 6;
AddOne(ref k);
Console.WriteLine(k); // Muestra el valor 7
}

Este cdigo funciona porque, cuando se hace la llamada a AddOne, su


parmetro x apunta a la misma posicin de memoria que la variable k en Main.
Por lo tanto, al incrementar x se incrementar tambin k.

Mtodos y parmetros

25

Asignacin de parmetros antes de la llamada al mtodo


Un parmetro ref tiene que estar definitivamente asignado al punto de llamada;
es decir, el compilador debe asegurarse de que se asigna un valor antes de hacer
la llamada. El siguiente ejemplo muestra cmo se pueden inicializar parmetros
referencia antes de la llamada al mtodo:
static void AddOne(ref int x)
{
x++;
}
static void Main( )
{
int k = 6;
AddOne(ref k);
Console.WriteLine(k); // 7
}

El siguiente ejemplo muestra lo que ocurre si no se inicializa un parmetro


referencia k antes de la llamada al mtodo AddOne:
int k;
AddOne(ref k);
Console.WriteLine(k);

El compilador de C# rechazar este cdigo y mostrar el siguiente mensaje de


error: Uso de variable local k no asignada.

Mtodos y parmetros

26

Parmetros de salida
Objetivo del tema

Explicar la palabra clave out


y su relacin con el paso
por referencia.

Explicacin previa

Los parmetros de salida


son similares a los
parmetros referencia, pero
transfieren datos fuera del
mtodo en lugar de al
mtodo.

Qu son los parmetros de salida?


z

Pasan valores hacia fuera, pero no hacia dentro

Uso de parmetros de salida


z
z

Como ref, pero no se pasan valores al mtodo


Se usa la palabra clave out en la declaracin y las
llamadas al mtodo

static
static void
void OutDemo(out
OutDemo(out int
int p)
p)
{{
//
// ...
...
}}
int
int n;
n;
OutDemo(out
OutDemo(out n);
n);

Qu son los parmetros de salida?


Los parmetros de salida son similares a los parmetros referencia, pero
transfieren datos fuera del mtodo en lugar de al mtodo. Al igual que u
parmetro referencia, un parmetro de salida es una referencia a una ubicacin
de almacenamiento indicada por el llamador. Sin embargo, no es necesario
asignar un valor a la variable indicada para el parmetro out antes de hacer la
llamada, y el mtodo asume que el parmetro no ha sido inicializado.
Los parmetros de salida son tiles cuando se quiere devolver valores de un
mtodo por medio de un parmetro sin tener que asignar a ste un valor inicial.

Uso de parmetros de salida


Para declarar un parmetro de salida se utiliza la palabra clave out antes del
tipo y el nombre, como se ve en el siguiente ejemplo:
static void DemoOut(out int p)
{
// ...
}

Como ocurre con la palabra clave ref, out afecta nicamente a un parmetro y
cada parmetro out debe estar separado de los dems.
En la llamada a un mtodo con un parmetro out hay que poner la palabra clave
out antes de la variable que se desea pasar, como en este ejemplo:

Mtodos y parmetros

27
int n;
DemoOut(out n);

En el cuerpo del mtodo al que se hace la llamada no hay ninguna indicacin al


contenido del parmetro de salida, por lo que ste se trata como si fuera una
variable local sin asignar. El valor del parmetro out se tiene que asignar dentro
del mtodo.

Mtodos y parmetros

28

Uso de listas de parmetros de longitud variable


Objetivo del tema

Presentar la palabra clave


params.

Explicacin previa

C# incluye un mecanismo
para pasar listas de
parmetros de longitud
variable.

Se usa la palabra clave params

Se declara como tabla al final de la lista de parmetros

Siempre paso por valor

static
static long
long AddList(params
AddList(params long[
long[ ]] v)
v)
{{
long
long total,
total, i;
i;
for
(i
for (i == 0,
0, total
total == 0;
0; ii << v.Length;
v.Length; i++)
i++)
total
total +=
+= v[i];
v[i];
return
return total;
total;
}}
static
static void
void Main(
Main( ))
{{
long
long xx == AddList(63,21,84);
AddList(63,21,84);
}}

Recomendacin al
profesor

No es necesario que discuta


este tema con mucho
detalle. Recuerde adems
que en este curso todava
no se han tratado las
matrices.

C# incluye un mecanismo para pasar listas de parmetros de longitud variable.

Declaracin de parmetros de longitud variable


En ocasiones resulta til tener un mtodo que pueda aceptar un nmero variable
de parmetros. En C# se puede emplear la palabra clave params para indicar
una lista de parmetros de longitud variable. Cuando se declara un parmetro de
longitud variable hay que:
Declarar slo un parmetro params por mtodo.
Poner el parmetro al final de la lista de parmetros.
Declarar el parmetro como de tipo tabla unidimensional.
Este ejemplo muestra cmo declarar una lista de parmetros de longitud variable:

Mtodos y parmetros

29
static long AddList (params long[ ] v)
{
long total;
long i;
for (i = 0, total = 0; i < v.Length; i++)
total += v[i];
return total;
}

Para su informacin

Visual Basic tiene una


funcin parecida llamada
ParamArray(). C y C++
tienen () y las macros
va_*, que manejan listas de
parmetros variables, como
en printf.

Como un parmetro params es siempre una tabla, todos los valores deben ser
del mismo tipo.

Mtodos y parmetros

30

Paso de valores
Hay dos maneras de pasar valores al parmetro params cuando se hace una
llamada a un mtodo con un parmetro de longitud variable:
Como una lista de elementos separados por comas (la lista puede estar
vaca)
Como una tabla
Ambas tcnicas se muestran en el siguiente cdigo. El compilador trata las dos
tcnicas de la misma forma.
static void Main( )
{
long x;
x = AddList (63, 21, 84); // Lista
x = AddList (new long[ ]{ 63, 21, 84 }); // Tabla
}

Independientemente del mtodo empleado para hacer la llamada al mtodo, el


parmetro params se trata siempre como una tabla. Se puede usar la propiedad
Length de la tabla para determinar el nmero de parmetros pasados a cada
llamada.
Para su informacin

Para conservar los cambios


realizados en el mtodo se
usa una tabla object.

Los datos se copian en el parmetro params y, aunque es posible modificar los


valores dentro del mtodo, los valores fuera del mtodo no cambian.

Mtodos y parmetros

31

Normas para el paso de parmetros


Objetivo del tema

Discutir los distintos


mecanismos para el paso
de parmetros.

Explicacin previa

Mecanismos

Aqu se ofrecen algunas


normas para el paso de
parmetros.

El paso por valor es el ms habitual

El valor de retorno del mtodo es til para un solo valor

ref y/o out son tiles para ms de un valor de retorno

ref slo se usa si los datos se pasan en ambos sentidos

Eficiencia
z

El paso por valor suele ser el ms eficaz

La abundancia de opciones disponibles para pasar parmetros puede hacer que


la eleccin no resulte obvia. Dos de los factores que hay que considerar a la
hora de elegir la forma de pasar parmetros son el mecanismo y su eficiencia.

Mecanismos
Los parmetros valor ofrecen cierta proteccin frente a modificaciones no
deseadas, ya que los cambios realizados dentro del mtodo no tienen efecto
fuera de l. Esto sugiere que los parmetros valor son la mejor opcin, salvo
que sea preciso pasar informacin fuera de un mtodo.
Recomendacin al
profesor

Esto es una ligera


simplificacin. Un mtodo
puede devolver varios
valores utilizando tipos de
referencia (por ejemplo, una
tabla).

Para pasar datos fuera de un mtodo se puede utilizar la instruccin return,


parmetros referencia o parmetros de salida. La instruccin return es fcil de
usar, pero slo puede devolver un resultado. Si se necesita devolver varios
valores hay que usar parmetros referencia y de salida. Utilice ref si desea
transferir datos en las dos direcciones, y out si slo necesita transferir datos
fuera del mtodo.

Eficiencia
En general, los tipos simples como int y long se pasan ms eficazmente por
valor.
Estos aspectos de eficiencia no forman parte del lenguaje, por lo que no hay que
tomrselos al pie de la letra. Aunque la eficiencia puede ser un punto a tener en
cuenta en aplicaciones grandes y que consumen muchos recursos, normalmente
es preferible preocuparse de la correccin, la estabilidad y la potencia del
programa antes que de la eficiencia. El empleo de buenas prcticas de
programacin tiene prioridad sobre la eficiencia.

Mtodos y parmetros

32

Uso de mtodos recursivos


Objetivo del tema

Explicar que C# permite el


uso recursivo de mtodos.

Explicacin previa

Como la mayor parte de los


lenguajes de programacin,
C# permite el uso recursivo
de mtodos.

Recomendacin al
profesor

No todos los estudiantes


estarn familiarizados con la
recursin. En caso de
problemas, explique que por
el momento no es necesario
comprender la recursin en
detalle. Lo nico que tienen
que saber es que pueden
utilizarla cuando sea
necesario.

Un mtodo puede hacer una llamada a s mismo


z

Directamente

Indirectamente

til para resolver ciertos problemas

Un mtodo puede hacer una llamada a s mismo. Esta tcnica se conoce como
recursin y ofrece una solucin para ciertos tipos de problemas. Los mtodos
recursivos suelen ser tiles para manipular estructuras de datos ms complejas,
como listas y rboles.
Los mtodos en C# pueden ser mutuamente recursivos. Por ejemplo, puede
darse una situacin en la que un mtodo A llame a un mtodo B, y el mtodo B
llame al mtodo A.

Ejemplo de mtodo recursivo


La serie de Fibonacci aparece con cierta frecuencia en matemticas y biologa
(por ejemplo, el ndice de reproduccin y la poblacin de conejos). El trmino n
de esta serie tiene el valor 1 si n es 1 2, y en los dems casos es igual a la
suma de los dos nmeros que le preceden en la serie; es decir, el valor del
trmino n para n mayor de 2 se obtiene a partir de dos valores anteriores de la
serie. El hecho de que la definicin del mtodo incluya al propio mtodo
sugiere que puede ser recursivo.
El cdigo para el mtodo Fibonacci podra ser siguiente:

Recomendacin al
profesor

El cdigo del ejemplo usa


ulongs para poder utilizar
valores grandes.

static ulong Fibonacci(ulong n)


{
if (n <= 2)
return 1;
else
return Fibonacci(n-1) + Fibonacci(n-2);
}

Como puede verse, dentro del mtodo se hacen dos llamadas al mismo mtodo.

Mtodos y parmetros

33

Un mtodo recursivo debe tener una condicin de fin para que devuelva un
valor sin hacer ms llamadas. En el caso del mtodo Fibonacci, la condicin de
fin es n <= 2.

Mtodos y parmetros

34

Uso de mtodos sobrecargados


Objetivo del tema

Ofrecer una introduccin a


los temas tratados en esta
seccin.

Explicacin previa

En esta seccin aprender


a usar mtodos
sobrecargados.

Declaracin de mtodos sobrecargados

Signaturas de mtodos

Uso de mtodos sobrecargados

Los mtodos no pueden tener el mismo nombre que otros elementos en una
clase. Sin embargo, dos o ms mtodos en una clase s pueden compartir el
mismo nombre. A esto se le da el nombre de sobrecarga.
En esta seccin aprender a:
Declarar mtodos sobrecargados.
Utilizar signaturas en C# para distinguir mtodos que tienen el mismo
nombre.
Saber cundo usar mtodos sobrecargados.

Mtodos y parmetros

35

Declaracin de mtodos sobrecargados


Objetivo del tema

Explicar cmo sobrecargar


nombres de mtodos.

Explicacin previa

Es posible dar el mismo


nombre a ms de un
mtodo en una clase.

Para su informacin

C++ admite la sobrecarga,


pero C no.
Visual Basic .NET es la
primera versin de Visual
Basic que permite mtodos
sobrecargados.

Mtodos que comparten un nombre en una clase


z

Se distinguen examinando la lista de parmetros

class
class OverloadingExample
OverloadingExample
{{
static
static int
int Suma(int
Suma(int a,
a, int
int b)
b)
{{
return
return aa ++ b;
b;
}}
static
static int
int Suma(int
Suma(int a,
a, int
int b,
b, int
int c)
c)
{{
return
return aa ++ bb ++ c;
c;
}}
static
static void
void Main(
Main( ))
{{
Console.WriteLine(Suma(1,2)
Console.WriteLine(Suma(1,2) ++ Suma(1,2,3));
Suma(1,2,3));
}}
}}

Los mtodos sobrecargados son mtodos que tienen el mismo nombre dentro de
una clase. El compilador de C# distingue mtodos sobrecargados comparando
las listas de parmetros.

Ejemplos de mtodos sobrecargados


El siguiente cdigo muestra cmo se pueden utilizar distintos mtodos con el
mismo nombre en una clase:
class OverloadingExample
{
static int Add(int a, int b)
{
return a + b;
}
static int Add(int a, int b, int c)
{
return a + b + c;
}
static void Main( )
{
Console.WriteLine(Add(1,2) + Add(1,2,3));
}
}

Mtodos y parmetros

Recomendacin al
profesor

Las signaturas se discutirn


con ms detalle en el
siguiente tema.

36

El compilador de C# encuentra en la clase dos mtodos llamados Add, y dos


llamadas a mtodos llamados Add en Main. Aunque los nombres de los
mtodos son iguales, el compilador puede distinguir entre los dos mtodos Add
comparando las listas de parmetros.
El primer mtodo Add acepta dos parmetros, ambos de tipo int. Por su parte,
el segundo mtodo Add lleva tres parmetros que tambin son de tipo int.
Como las listas de parmetros son diferentes, el compilador permite definir
ambos mtodos dentro de la misma clase.
La primera instruccin en Main contiene una llamada a Add con dos
parmetros int, por lo que el compilador la interpreta como una llamada al
primer mtodo Add. La segunda llamada a Add lleva tres parmetros int y el
compilador la interpreta como una llamada al segundo mtodo Add.
No est permitido compartir nombres entre mtodos y variables, constantes o
enumeraciones en la misma clase. El siguiente cdigo no se compilar porque
se ha utilizado el nombre k para un mtodo y una variable:
class BadMethodNames
{
static int k;
static void k( ) {
// ...
}
}

Mtodos y parmetros

37

Signaturas de mtodos
Objetivo del tema

Explicar la funcin de las


signaturas de mtodos.

Explicacin previa

El compilador de C# puede
distinguir entre mtodos en
una clase examinando la
signatura de cada mtodo.

Las signaturas de mtodos deben ser nicas dentro


de una clase

Definicin de signatura

Forman
Forman la
la definicin
definicin
de
la
signatura
de la signatura

No
No afectan
afectan aa la
la
signatura
signatura

Nombre
Nombredel
delmtodo
mtodo

Nombre
Nombrede
de parmetro
parmetro

Tipo
Tipode
deparmetro
parmetro

Tipo
Tipode
deretorno
retornode
de

Modificador
Modificador

mtodo
mtodo

El compilador de C# utiliza signaturas para distinguir entre mtodos en una


clase. Cada mtodo dentro de una clase debe tener una signatura diferente de la
de todos los dems mtodos declarados en esa clase.

Definicin de signatura
La signatura de un mtodo consta del nombre del mtodo, el nmero de
parmetros del mtodo y el tipo y modificador (como out o ref) de cada
parmetro.
Para su informacin

No est permitido definir


mtodos sobrecargados que
se diferencien nicamente
en ref y out.

Los tres mtodos siguientes tienen distintas signaturas, por lo que pueden estar
declarados en la misma clase.
static int LastErrorCode( )
{
}
static int LastErrorCode(int n)
{
}
static int LastErrorCode(int n, int p)
{
}

Mtodos y parmetros

38

Elementos que no afectan a la signatura


La signatura de un mtodo no incluye el tipo retorno. Los dos mtodos
siguientes tienen la misma signatura, por lo que no pueden estar declarados en
la misma clase.
static int LastErrorCode(int n)
{
}
static string LastErrorCode(int n)
{
}

La signatura de un mtodo no incluye los nombres de los parmetros. Los dos


mtodos siguientes tienen la misma signatura, aunque los nombres de los
parmetros sean diferentes.
static int LastErrorCode(int n)
{
}
static int LastErrorCode(int x)
{
}

Mtodos y parmetros

39

Uso de mtodos sobrecargados


Objetivo del tema

Explicar cundo usar


mtodos sobrecargados.

Explicacin previa

Este tema describe algunas


situaciones en las que es
conveniente sobrecargar
mtodos.

Conviene usar mtodos sobrecargados si:


z

Hay mtodos similares que requieren parmetros


diferentes
Se quiere aadir funcionalidad al cdigo existente

No hay que abusar, ya que:


z

Son difciles de depurar

Son difciles de mantener

Los mtodos sobrecargados son tiles si se tienen dos mtodos similares que
requieren distinto nmero o tipo de parmetros.

Mtodos similares que requieren parmetros diferentes


Imaginemos que una clase contiene un mtodo que enva un mensaje de saludo
al usuario. A veces se sabe el nombre del usuario, pero no siempre. Se pueden
definir dos mtodos diferentes llamados Greet y GreetUser, como muestra el
siguiente cdigo:
class GreetDemo
{
static void Greet( )
{
Console.WriteLine("Hola");
}
static void GreetUser(string Name)
{
Console.WriteLine("Hola " + Name);
}
static void Main( )
{
Greet( );
GreetUser("Alex");
}
}

Mtodos y parmetros

40

El programa funciona, pero en la clase hay dos mtodos que realizan una tarea
prcticamente idntica aunque tengan nombres diferentes. Esta clase se puede
reescribir con sobrecarga de mtodos como se muestra a continuacin:
class GreetDemo
{
static void Greet( )
{
Console.WriteLine("Hola");
}
static void Greet(string Name)
{
Console.WriteLine("Hola " + Name);
}
static void Main( )
{
Greet( );
Greet("Alex");
}
}

Mtodos y parmetros

41

Adicin de funcionalidad al cdigo existente


La sobrecarga de mtodos tambin es til si se desea aadir nuevas funciones a
una aplicacin sin tener que hacer demasiados cambios al cdigo existente. Por
ejemplo, se podra ampliar el cdigo anterior aadiendo otro mtodo que salude
a un usuario de forma diferente segn la hora del da, como se muestra a
continuacin:
class GreetDemo
{
enum TimeOfDay { Manana, Tarde, Noche }
static void Greet( )
{
Console.WriteLine("Hola");
}
static void Greet(string Name)
{
Console.WriteLine("Hola " + Name);
}
static void Greet(string Name, TimeOfDay td)
{
string Message = "";
switch(td)
{
case TimeOfDay.Manana:
Message="Buenos das";
break;
case HoraDelDia.Tarde:
Message="Buenas tardes";
break;
case HoraDelDia.Noche:
Message="Buenas noches";
break;
}
Console.WriteLine(Mensaje + " " + Name);
}
static void Main( )
{
Greet( );
Greet("Alex");
Greet("Sandra", HoraDelDia.Manana);
}
}

Cundo utilizar sobrecarga


El uso excesivo de la sobrecarga de mtodos puede hacer que las clases resulten
difciles de depurar y mantener. En general, slo se debe sobrecargar mtodos
que tengan funciones muy estrechamente relacionadas pero que difieran en la
cantidad o el tipo de datos que necesitan.

Mtodos y Parmetros

Prctica : Creacin y uso de mtodos


Objetivos
Al final de esta prctica, usted ser capaz de:
Crear y hacer llamadas a mtodos con y sin parmetros.
Utilizar distintos mecanismos para pasar parmetros.

Requisitos previos
Antes de realizar la prctica debe estar familiarizado con los siguientes temas:
Creacin y uso de variables
Instrucciones de C#

Ejercicio 1
Uso de parmetros en mtodos que devuelven valores
En este ejercicio definir y usar parmetros de entrada en un mtodo que
devuelve un valor. Tambin escribir un sistema de prueba que lea dos valores
de la consola y muestre los resultados.
Crear una clase llamada Utils. En esa clase crear un mtodo llamado Greater
que aceptar como entrada dos parmetros enteros y devolver el valor del que
sea mayor.
Para probar la clase crear otra clase llamada Test que pedir dos nmeros al
usuario, llamar a Utils.Greater para determinar cul de los dos es mayor e
imprimir el resultado.
Cmo crear el mtodo Mayor
1. Abra el proyecto Utils.sln en la carpeta Starter\Utility dentro del fichero
lab05.zip.
Encontrar un espacio de nombres llamado Utils que contiene una clase del
mismo nombre en la que escribir el mtodo Greater.
2. Cree el mtodo Greater como se indica a continuacin:
a. Abra la clase Utils.
b. Aada a la clase Utils un mtodo public static llamado Greater.
c. El mtodo aceptar dos parmetros int llamados a y b que se pasarn por
valor, y devolver un valor int que represente el mayor de los dos
nmeros.
El cdigo para la clase Utils debera ser como ste:

Mtodos y Parmetros
namespace Utils
{
using System;
class Utils
{
//
// Devuelve el mayor de dos valores enteros
//
public static int Mayor(int a, int b)
{
if (a > b)
return a;
else
return b;
}
}
}

Mtodos y Parmetros

Cmo probar el mtodo Mayor


1. Abra la clase Test.
2. Escriba el siguiente cdigo en el mtodo Main.
a. Defina dos variables enteras llamadas x e y.
b. Aada instrucciones que lean dos enteros desde la entrada por teclado y
los asignen a x e y. Use los mtodos Console.ReadLine e int.Parse de
mdulos anteriores.
c. Defina otro entero llamado greater.
d. Haga una llamada al mtodo Greater para probarlo, y asigne el valor
devuelto a la variable mayor.
3. Escriba el cdigo necesario para mostrar el mayor de los dos enteros
empleando Console.WriteLine.
El cdigo para la clase Test debera ser como ste:
namespace Utils
{
using System;
/// <resumen>
///
Sistema de prueba
/// </resumen>
public class Test
{
public static void Main( )
{
int x;
// Valor de entrada 1
int y;
// Valor de entrada 2
int mayor;
// Resultado de Mayor( )
// Obtener nmeros de entrada
Console.WriteLine("Escriba el primer nmero:");
x = int.Parse(Console.ReadLine( ));
Console.WriteLine("Escriba el segundo nmero:");
y = int.Parse(Console.ReadLine( ));
// Probar el mtodo Mayor( )
mayor = Utils.Mayor(x,y);
Console.WriteLine("El valor mayor es "+
mayor);
}
}
}

4. Guarde el trabajo realizado.


5. Compile el proyecto y corrija los posibles errores. Ejecute y pruebe el
programa.

Mtodos y Parmetros

Ejercicio 2
Uso de mtodos con parmetros referencia
En este ejercicio escribir un mtodo llamado Swap que intercambiar los
valores de sus parmetros. Utilizar parmetros que se pasan por referencia.
Cmo crear el mtodo Intercambio
1. Abra el proyecto Utils.sln en la carpeta Utility del ejercicio anterior, si no
est ya abierto.
2. Aada el mtodo Swap a la clase Utils como se indica a continuacin:
a. Aada un mtodo public static void llamado Swap.
b. Swap aceptar dos parmetros int llamados a y b, que se pasarn por
referencia.
c. Escriba instrucciones en el cuerpo de Swap para intercambiar los
valores de a y b. Tendr que crear una variable int local en Swap para
guardar temporalmente uno de los valores durante el intercambio. Llame
a esta variable temp.
El cdigo para la clase Utils debera ser como ste:
namespace Utils
{
using System;
public class Utils
{
... cdigo anterior omitido para mayor claridad ...
//
// Intercambiar dos enteros, pasados por referencia
//
public static void Intercambio(ref int a, ref int b)
{
int temp = a;
a = b;
b = temp;
}
}
}

Mtodos y Parmetros

Cmo probar el mtodo Intercambio


1. Edite el mtodo Main en la clase Test ejecutando los siguientes pasos:
a. Asigne valores a las variables enteras x e y.
b. Haga una llamada al mtodo Swap, pasando estos valores como
parmetros.
Visualice los nuevos valores de los dos enteros antes y despus de
intercambiarlos. El cdigo para la clase Test debera ser como ste:
namespace Utils
{
using System;
public class Test
{
public static void Main( )
{
... cdigo anterior omitido para mayor claridad ...
// Probar el mtodo Intercambio
Console.WriteLine("Antes: " + x + "," + y);
Utils.Swap(ref x,ref y);
Console.WriteLine("Despus: " + x + "," + y);
}
}
}

2. Guarde el trabajo realizado.


3. Compile el proyecto y corrija los posibles errores. Ejecute y pruebe el
programa.
Consejo Si los parmetros no se intercambiaran como esperaba, compruebe
que no los ha pasado como parmetros ref.

Mtodos y Parmetros

Ejercicio 3
Uso de mtodos con parmetros de salida
En este ejercicio definir y usar un mtodo static con un parmetro de salida.
Escribir un nuevo mtodo llamado Factorial que recibir un valor int y
calcular su factorial. El factorial de un nmero es el producto de todos los
nmeros entre 1 y ese nmero; el factorial de cero es 1 por definicin. A
continuacin se dan algunos ejemplos de factoriales:
Factorial(0) = 1
Factorial(1) = 1
Factorial(2) = 1 * 2 = 2
Factorial(3) = 1 * 2 * 3 = 6
Factorial(4) = 1 * 2 * 3 * 4 = 24
Cmo crear el mtodo Factorial
1. Abra el proyecto Utils.sln en la carpeta Utility del ejercicio anterior, si no
est ya abierto.
2. Aada el mtodo Factorial a la clase Utils como se indica a continuacin:
a. Aada un mtodo public static llamado Factorial.
b. Este mtodo recibir dos parmetros llamados n y respuesta. El primero
se pasa por valor y es el int cuyo factorial se va a calcular. El segundo es
un parmetro out int que se utilizar para devolver el resultado.
c. El mtodo Factorial debe devolver un valor bool que indique si ha
funcionado (podra desbordarse y producir una excepcin).
3. Aada funcionalidad al mtodo Factorial.
La forma ms sencilla de calcular un factorial e por medio de un bucle.
Ejecute los siguientes pasos para aadir funcionalidad al mtodo:
a. Cree una variable int llamada k en el mtodo Factorial para utilizarla
como contador del bucle.
b. Cree otra variable int llamada f, que se usar como valor de trabajo
dentro del bucle. Inicialice la variable de trabajo f con el valor 1.
c. Use un bucle for para realizar la iteracin. Comience con un valor de 2
para k, y termine cuando k llegue al valor del parmetro n. Incremente k
cada vez que se ejecute el bucle.
d. En el cuerpo del bucle, multiplique f sucesivamente por cada valor de k
y almacene el resultado en f.
e. El resultado de un factorial puede ser muy grande aunque el valor de
entrada sea pequea. Asegrese de que todos los clculos de enteros
estn en un bloque de comprobacin (checked) y de que se capturan
excepciones como el desbordamiento aritmtico.
f. Asigne el valor del resultado en f al parmetro de salida respuesta.
g. Devuelva true desde el mtodo si el clculo se realiza sin problemas, y
false en caso contrario (es decir, si se produce una excepcin).

Mtodos y Parmetros

El cdigo para la clase Utils debera ser como ste:


namespace Utils
{
using System;
public class Utils
{
... cdigo anterior omitido para mayor claridad ...
//
// Calcular factorial
// y devolver el resultado como un parmetro out
//
public static bool Factorial(int n, out int respuesta)
{
int k;
// Contador del bucle
int f;
// Valor de trabajo
bool ok=true; // True si est bien, false si no
// Comprobar el valor de entrada
if (n<0)
ok = false;
// Calcular el valor del factorial como el
// producto de todos los nmeros de 2 a n
try
{
checked
{
f = 1;
for (k=2; k<=n; ++k)
{
f = f * k;
}
}
}
catch(Exception)
{
// Si hay algn problema en el clculo, se
// capturar aqu. Todas las excepciones se
// tratan de la misma manera: poner el
// resultado a cero y devolver false.
El cdigo contina en la pgina siguiente.

Mtodos y Parmetros
f = 0;
ok = false;
}

// Asignar el valor del resultado


respuesta = f;
// Devolver al llamador
return ok;
}

}
}

Cmo probar el mtodo Factorial


1. Edite la clase Test como se indica a continuacin:
a. Declare una variable bool llamada ok para el resultado true o false.
b. Declare una variable int llamada f para el resultado del factorial.
c. Pida un entero al usuario. Asigne el valor de entrada a la variable int x.
d. Haga una llamada al mtodo Factorial, pasando x como primer
parmetro y f como segundo parmetro. Devuelva el resultado en ok.
e. Si ok es true, muestre los valores de x y f; en caso contrario, muestre un
mensaje para indicar que se ha producido un error.

Mtodos y Parmetros

El cdigo para la clase Test debera ser como ste:


namespace Utils
{
public class Test
{
static void Main( )
{
int f;
// Resultado del factorial
bool ok;
// Factorial correcto o fallido
... cdigo anterior omitido para mayor claridad ...
// Obtener entrada para factorial
Console.WriteLine("Nmero para factorial:");
x = int.Parse(Console.ReadLine( ));
//
ok
//
if

Probar la funcin factorial


= Utils.Factorial(x, out f);
Enviar los resultados del factorial a la salida
(ok)
Console.WriteLine("Factorial(" + x + ") = " +

f);
else
Console.WriteLine("No se puede calcular este
factorial");
}
}
}

2. Guarde el trabajo realizado.


3. Compile el proyecto y corrija los posibles errores. Ejecute y pruebe el
programa.

10

Mtodos y Parmetros

Si el tiempo lo permite
Mtodo con recursin
En este ejercicio reescribir el mtodo Factorial creado en el Ejercicio 3
utilizando recursin en lugar de un bucle.
El factorial de un nmero se puede definir recursivamente de la siguiente
manera: el factorial de cero es 1, y el factorial de cualquier otro entero ms
grande se puede calcular multiplicando ese entero por el factorial del nmero
anterior. En resumen:
Si n = 0, entonces Factorial(n) = 1; en los dems casos, Factorial(n) = n *
Factorial(n-1)
Cmo modificar el mtodo Factorial anterior
1. Edite la clase Utils y modifique el mtodo Factorial para que emplee
recursin en lugar de iteracin.
Los parmetros y tipos de retorno sern los mismos, pero cambiar el
funcionamiento interno del mtodo. Si desea conservar la solucin del
Ejercicio 3, tendr que utilizar otro nombre para este mtodo.
2. Utilice el pseudocdigo mostrado ms arriba para escribir el cuerpo del
mtodo Factorial (tendr que convertirlo a la sintaxis de C#).
3. Aada cdigo a la clase Test para probar el nuevo mtodo.
4. Guarde el trabajo realizado.

Mtodos y Parmetros

11

5. Compile el proyecto y corrija los posibles errores. Ejecute y pruebe el


programa.
La versin recursiva del mtodo Factorial (RecursiveFactorial) se muestra
a continuacin:
//
// Otra forma de resolver el problema del factorial,
// esta vez como una funcin recursiva
//
public static bool FactorialRecursivo(int n, out int f)
{
bool ok=true;
// Capturar entradas negativas
if (n<0)
{
f=0;
ok = false;
}
if (n<=1)
f=1;
else
{
try
{
int pf;
checked
{
ok = FactorialRecursivo(n-1,out pf);
f = n * pf;
}
}
catch(Exception)
{
// Algo ha ido mal. Poner indicador
// de error y devolver cero.
f=0;
ok=false;
}
}
return ok;
}

Tablas

Prctica: Creacin y uso de tablas


Objetivos
Al final de esta prctica, usted ser capaz de:
Crear y utilizar tablas de tipos valor.
Pasar argumentos a Main.
Crear y utilizar tablas de tamao calculado.
Utilizar tablas de distintos rangos.

Requisitos previos
Antes de realizar la prctica debe estar familiarizado con los siguientes temas:
Uso de instrucciones de programacin en C#.
Creacin y uso de mtodos en C#.

Ejercicio 1
Uso de una tabla de tipos valor
En este ejercicio escribir un programa que espera el nombre de un archivo de
texto como argumento para Main y resume sus contenidos. El programa lee los
contenidos del archivo de texto en una tabla de caracteres. A continuacin
recorre toda la tabla, contando el nmero de vocales y consonantes. Finalmente,
el programa imprime en la consola el nmero total de caracteres, vocales,
consonantes y nuevas lneas.
Cmo capturar el nombre del archivo como parmetro del mtodo Main
1. Abra el proyecto FileDetails.sln. Este proyecto est en la carpeta
Starter\FileDetails dentro del fichero lab06.zip.
2. Aada una tabla de cadenas de caracteres llamada args como parmetro del
mtodo Main de la clase FileDetails. Esta tabla contendr todos los
argumentos de lnea de comandos cuando se ejecute el programa. As es
como el runtime pasa esos argumentos a Main. En este ejercicio, el
argumento de lnea de comandos que se pase a Main ser el nombre de un
archivo de texto.
3. Aada a Main una instruccin que escriba la longitud de args en la consola.
Esta instruccin comprobar que la longitud de args es cero si el runtime no
pasa ningn argumento de lnea de comandos a Main.
4. Aada a Main una instruccin foreach que escriba en la consola cada
cadena de caracteres de args. Esta instruccin comprobar que Main recibe
del runtime los argumentos de lnea de comandos.
El cdigo completo debera ser como ste:

Tablas

2
static void Main(string[ ] args)
{
Console.WriteLine(args.Length);
foreach (string arg in args) {
Console.WriteLine(arg);
}
}

5. Compile el programa FileDetails.cs y corrija los posibles errores. Ejecute el


programa desde la lnea de comandos sin utilizar ningn argumento.
Compruebe que la longitud de args es cero.
Consejo Para ejecutar el programa desde la lnea de comandos, abra la
ventana Command y vaya a la carpeta bin\Debug dentro de la carpeta el
proyecto, donde estar el archivo ejecutable.
6. Ejecute el programa desde la lnea de comandos con el nombre del archivo
Solution\FileDetails\FileDetails.cs dentro del fichero lab06.zip. Compruebe
que el runtime pasa el nombre del archivo a Main.
7. Pruebe el programa con distintos argumentos de lnea de comandos y
compruebe que todos los argumentos se escriben en la consola. Marque
como comentarios las instrucciones que escriben en la consola.
8. Aada a Main una instruccin que declare una variable string llamada
(fileName) nombreArchivo e inicialcela con args[0].

Tablas

Cmo leer del archivo de texto a una tabla


9. Quite las marcas de comentarios del cdigo de declaracin e inicializacin
de FileStream y StreamReader.
10. Determine la longitud del archivo de texto.
Consejo Para encontrar una propiedad adecuada de la clase Stream,
busque clase Stream en los documentos de ayuda del SDK de Microsoft
.NET Framework.
11. Aada a Main una instruccin que declare una variable de cadena de
caracteres llamada contenidos (contents). Inicialice contenidos con una
nueva tabla cuya longitud sea igual a la longitud del archivo de texto, que
acaba de calcular.
12. Aada a Main una instruccin for. El cuerpo de la instruccin for leer un
solo carcter de reader y lo aadir a contenidos.
Consejo Use el mtodo Read, que no recibe ningn parmetro y devuelve
un int. Convierta el resultado en char antes de almacenarlo en la tabla.
13. Aada a Main una instruccin foreach que escriba carcter por carcter
toda la cadena de caracteres en la consola. Esta instruccin comprobar que
el archivo de texto se ha ledo correctamente en la tabla contenidos.
El cdigo completo debera ser como ste:
static void Main(string[ ] args)
{
string fileName = args[0];
FileStream stream = new FileStream(fileName,

FileMode.Open);
StreamReader reader = new StreamReader(stream);
int size = (int)stream.Length;
char[ ] contents = new char[size];
for (int i = 0; i < size; i++) {
contents [i] = (char)reader.Read( );
}
foreach(char ch in contents) {
Console.Write(ch);
}
}

14. Compile el programa y corrija los posibles errores. Ejecute el programa con
el nombre del archivo Solution\FileDetails\FileDetails.cs dentro del fichero
lab06.zip como argumento de lnea de comandos. Compruebe que los
contenidos del archivo se escriben correctamente en la consola.
15. Marque como comentario la instruccin foreach.
16. Cierre el objeto Reader con una llamada al mtodo StreamReader
correspondiente.

Tablas

Cmo clasificar y resumir los contenidos del archivo


17. Declare un nuevo mtodo static llamado Summarize en la clase
FileDetails. Este mtodo no devolver nada y esperar un parmetro de
cadena de caracteres. Aada a Main una instruccin que haga una llamada
al mtodo Summarize, pasando contenidos como argumento.
18. Aada a Summarize una instruccin foreach que inspeccione cada carcter
en el argumento de tabla. Cuente el nmero de caracteres de vocal,
consonante y nueva lnea, y almacene los resultados en variables distintas.
Consejo Para determinar si un carcter es una vocal, cree una cadena de
caracteres con todas las vocales posibles y use sobre ella el mtodo IndexOf
para ver si el carcter existe en esa cadena de caracteres:
if ("AEIOUaeiou".IndexOf(myCharacter) != -1) {
// myCharacter es una vocal
} else {
// myCharacter no es una vocal
}

19. Escriba en la consola cuatro lneas que indiquen:


El nmero total de caracteres en el archivo.
El nmero total de vocales en el archivo.
El nmero total de consonantes en el archivo.
El nmero total de lneas en el archivo.
El cdigo completo debera ser como ste:
static void Summarize (char[ ] contents)
{
int vocales = 0, consonantes = 0, lines = 0;
foreach (char actual in contents) {
if (Char.IsLetter(current)) {
if ("AEIOUaeiou".IndexOf(current) !=
vowels ++;
} else {
consonants++;
}
}
else if (actual == '\n') {
lines++;
}
}
Console.WriteLine("Nm total de caracteres :
contenidos.Length);
Console.WriteLine("Nm total de vocales
:
vocales);
Console.WriteLine("Nm total de consonantes:
consonantes);
Console.WriteLine("Nm total de lneas
:
lineas);
}

-1) {

{0}",
{0}",
{0}",
{0}",

Tablas

20. Compile el programa y corrija los posibles errores. Ejecute el programa


desde la lnea de comandos para resumir los contenidos del archivo
Solution\FileDetails\FileDetails.cs dentro del fichero lab06.zip. El resultado
correcto es el siguiente:
1.353 caracteres
247 vocales
394 consonantes
41 lneas

Tablas

Ejercicio 2
Multiplicacin de matrices
En este ejercicio escribir un programa que usa tablas para multiplicar matrices.
El programa leer cuatro valores enteros de la consola y los pondr en una
matriz entera 2 x 2. A continuacin leer otros cuatro valores enteros de la
consola y los pondr en una segunda matriz entera 2 x 2. Luego multiplicar las
dos matrices, almacenando el resultado en una tercera matriz entera 2 x 2.
Finalmente, imprimir la matriz resultante en la consola.
La frmula para multiplicar dos matrices A y B es la siguiente:
A1

A2

B1

B2

A1.B1 + A2.B3

A1.B2 + A2.B4

A3

A4

B3

B4

A3.B1 + A4.B3

A3.B2 + A4.B4

Cmo multiplicar dos matrices


Abra el proyecto MatrixMultiply.sln en la carpeta
Starter\MatrixMultiply dentro del fichero lab06.zip.
En la clase MatrixMultiply, aada a Main una instruccin que
declare una tabla 2 x 2 de ints y la llame a. La solucin final
para el programa leer los valores de a desde la consola. Por el
momento, inicialice a con los valores enteros de la siguiente
tabla (esto permitir comprobar que la multiplicacin se realiza
correctamente y que los cambios subsiguientes no hacen variar
el comportamiento del programa):
1

3. Aada a Main una instruccin que declare una tabla 2 x 2 de ints y la llame
b. La solucin final para el programa leer los valores de b desde la consola.
Por el momento, inicialice b con los valores enteros de la siguiente tabla:
5

o Aada a Main una instruccin que declare una tabla 2 x 2 de ints y la llame
result. Inicialice result utilizando las siguientes frmulas:
a[0,0] * b[0,0] + a[0,1] * b[1,0]

a[0,0] * b[0,1] + a[0,1] * b[1,1]

a[1,0] * b[0,0] + a[1,1] * b[1,0]

a[1,0] * b[0,1] + a[1,1] * b[1,1]

Tablas

o Aada a Main cuatro instrucciones que escriban en la consola los cuatro


valores int de result. Estas instrucciones le ayudarn a comprobar que ha
copiado las frmulas correctamente.
El cdigo completo debera ser como ste:
static void Main( )
{
int[,] a = new int[2,2];
a[0,0] = 1; a[0,1] = 2;
a[1,0] = 3; a[1,1] = 4;
int[,] b = new int[2,2];
b[0,0] = 5; b[0,1] = 6;
b[1,0] = 7; b[1,1] = 8;
int[,]
result
result
result
result

result = new int[2,2];


[0,0]=a[0,0]*b[0,0] + a[0,1]*b[1,0];
[0,1]=a[0,0]*b[0,1] + a[0,1]*b[1,1];
[1,0]=a[1,0]*b[0,0] + a[1,1]*b[1,0];
[1,1]=a[1,0]*b[0,1] + a[1,1]*b[1,1];

Console.WriteLine(result
Console.WriteLine(result
Console.WriteLine(result
Console.WriteLine(result

[0,0]);
[0,1]);
[1,0]);
[1,1]);

6. Compile el programa y corrija los posibles errores. Ejecute el programa y


compruebe que los cuatro valores de result son los siguientes:
19

22

43

50

Cmo mostrar el resultado usando un mtodo con un parmetro de tabla


1. Declare un nuevo mtodo static llamado Output (Salida) en la clase
MatrixMultiply. Este mtodo no devolver nada y esperar como
parmetro una tabla int de rango 2 llamada result.
2. Corte de Main las cuatro instrucciones que escriben en la consola los
cuatro valores de result y pguelas en Output.
3. Aada a Main una instruccin que llame al mtodo Output, pasando
result como argumento (este cdigo debe ir en el lugar que ocupaban
las cuatro instrucciones cortadas en el paso anterior).
El cdigo completo debera ser como ste:
static void Output(int[,] result)
{
Console.WriteLine(result [0,0]);
Console.WriteLine(result [0,1]);
Console.WriteLine(result [1,0]);
Console.WriteLine(result [1,1]);
}

Tablas

4. Compile el programa y corrija los posibles errores. Ejecute el programa y


compruebe que los cuatro valores escritos en la consola siguen siendo:
19

22

43

50

5. Cambie el mtodo Salida para que utilice dos instrucciones for anidadas en
lugar de cuatro instrucciones WriteLine. Use el valor literal 2 en las
comprobaciones de lmites de las tablas.
El cdigo completo debera ser como ste:
static void Output(int[,] result)
{
for (int r = 0; r < 2; r++) {
for (int c = 0; c < 2; c++) {
Console.Write("{0} ", result[r,c]);
}
Console.WriteLine( );
}
}

6. Compile el programa y corrija los posibles errores. Ejecute el programa y


compruebe que los cuatro valores escritos en la consola siguen siendo:

7.

19

22

43

50

Vuelva a modificar el mtodo Output para hacerlo ms genrico. Sustituya


el valor literal 2 en las comprobaciones de lmites de las tablas por llamadas al
mtodo GetLength.
El cdigo completo debera ser como ste:
static void Output(int[,] result)
{
for (int r = 0; r < result.GetLength(0); r++) {
for (int c = 0; c < result.GetLength(1); c++) {
Console.Write("{0} ", result [r,c]);
}
Console.WriteLine( );
}
}

8. Compile el programa y corrija los posibles errores. Ejecute el programa


y compruebe que los cuatro valores escritos en la consola siguen
siendo:
19

22

43

50

Tablas

Cmo calcular el resultado en un mtodo y devolverlo


21. Declare un nuevo mtodo static llamado Multiply en la clase
MatrixMultiply. Este mtodo devolver una tabla int de rango 2 y esperar
como parmetros dos tablas int de rango 2 llamadas a y b.
22. Copie (sin cortar) de Main a Multiply la declaracin e inicializacin de
result.
23. Aada a Multiply una instruccin return que devuelva result
24. Sustituya la inicializacin de result en Main por una llamada a Multiply,
pasando a y b como argumentos.
El cdigo completo debera ser como ste:
static int[,] Multiply(int[,] a, int [,] b)
{
int[,] result = new int[2,2];
result [0,0]=a[0,0]*b[0,0] + a[0,1]*b[1,0];
result [0,1]=a[0,0]*b[0,1] + a[0,1]*b[1,1];
result [1,0]=a[1,0]*b[0,0] + a[1,1]*b[1,0];
result [1,1]=a[1,0]*b[0,1] + a[1,1]*b[1,1];
return result;
}

5. Compile el programa y corrija los posibles errores. Ejecute el programa y


compruebe que los cuatro valores escritos en la consola siguen siendo:
19

22

43

50

Tablas

10

Cmo calcular el resultado en un mtodo usando instrucciones for


1. Sustituya la inicializacin de result en Multiply por una tabla 2 x 2 de
ints de nueva creacin.
2. Aada a Multiply dos instrucciones for anidadas. Utilice un entero
llamado r en la instruccin for ms externa para recorrer todos los
ndices de la primera dimensin de result, y un entero llamado c en la
instruccin for ms interna para recorrer todos los ndices de la
segunda dimensin de result. Use el valor literal 2 para los lmites de
las tablas. El cuerpo de la instruccin for ms interna tendr que
calcular el valor de result [r,c] con la siguiente frmula:
result [r,c] = a[r,0] * b[0,c]
+ a[r,1] * b[1,c]

El cdigo completo debera ser como ste:


static int[,] Multiply int[,] a, int [,] b)
{
int[,] result = new int[2,2];
for (int r = 0; r < 2; r++) {
for (int c = 0; c < 2; c++) {
result[r,c] += a[r,0] * b[0,c] + a[r,1] * b[1,c];
}
}
return result;
}

3. Compile el programa y corrija los posibles errores. Ejecute el programa


y compruebe que los cuatro valores escritos en la consola siguen
siendo:
19

22

43

50

Cmo introducir la primera matriz desde la consola


1. Sustituya la inicializacin de a en Main por una nueva tabla 2 x 2 de
ints.
2. Aada a Main instrucciones que pidan al usuario cuatro valores y los
lean en a desde la consola. Tienen que ir antes de la llamada al mtodo
Multiply. Las instrucciones para leer un valor desde la consola son:
string s = Console.ReadLine( );
a[0,0] = int.Parse(s);

3. Compile el programa y corrija los posibles errores. Ejecute el


programa, escribiendo en la consola los mismos cuatro valores para a
(es decir, 1, 2, 3 y 4). Compruebe que los cuatro valores escritos en la
consola siguen siendo:
19

22

43

50

4. Declare un nuevo mtodo static llamado Input (Entrada) en la clase


MatrixMultiply. Este mtodo no devolver nada y esperar como
parmetro una tabla int de rango 2 llamada dst.

Tablas

11

5. Corte de Main las instrucciones que leen los cuatro valores en a y


pguelas en Input. Aada a Main (antes de la llamada a Multiply) una
instruccin que llame al mtodo Input, pasando a como parmetro.
6. Compile el programa y corrija los posibles errores. Ejecute el
programa, escribiendo en la consola los mismos cuatro valores para a
(es decir, 1, 2, 3 y 4). Compruebe que los cuatro valores escritos en la
consola siguen siendo:
19

22

43

50

7. Cambie el mtodo Input para que utilice dos instrucciones for


anidadas. Use el valor literal 2 para los lmites de las tablas. Incluya en
el mtodo Input una instruccin Write que pida los valores al usuario.
El cdigo completo debera ser como ste:
static void Input (int[,] dst)
{
for (int r = 0; r < 2; r++) {
for (int c = 0; c < 2; c++) {
Console.Write(
"Escriba el valor de [{0},{1}] : ", r, c);
string s = Console.ReadLine( );
dst[r,c] = int.Parse(s);
}
}
Console.WriteLine( );
}

8. Compile el programa y corrija los posibles errores. Ejecute el


programa, escribiendo en la consola los mismos cuatro valores para a
(es decir, 1, 2, 3 y 4). Compruebe que los cuatro valores escritos en la
consola siguen siendo:
19

22

43

50

Cmo introducir la segunda matriz desde la consola


1. Sustituya la inicializacin de b en Main por una tabla 2 x 2 de ints de
nueva creacin cuyos cuatro valores tengan por defecto el valor cero.
2. Aada a Main una instruccin que lea valores en b desde la consola
llamando al mtodo Input y pasando b como argumento.
3. Compile el programa y corrija los posibles errores. Ejecute el
programa, escribiendo los mismos cuatro valores para a (1, 2, 3 y 4) y
los mismos cuatro valores para b (5, 6, 7 y 8). Compruebe que los
cuatro valores escritos en la consola siguen siendo:
19

22

43

50

4. Ejecute el programa con datos diferentes. Colabore con otro estudiante


para ver si obtienen la misma respuesta para los mismos datos.

Tablas

Contenido
Descripcin general
Introduccin a las tablas

1
2

Creacin de tablas

10

Uso de tablas

18

Tablas

Notas para el instructor


Este mdulo explica cmo declarar y usar tablas (arrays) de distintos rangos en
C#. El mdulo se limita intencionadamente a tablas rectangulares y no incluye
tablas dentadas.
int[ ] fila;
int[,] cuadrcula;
int[,,] cubo;

// Incluida
// Incluida
// Incluida

int[ ][ ] cuadrcula; // No se incluyen porque no considera


// que cumplan las normas del CLS
int[ ][ ][ ] cubo1; // No se incluyen porque no considera
// que cumplan las normas del CLS
int[ ][,] cubo2;
// No se incluyen porque no considera
// que cumplan las normas del CLS

El mdulo comienza explicando los conceptos bsicos de tablas, incluyendo


notacin, variables y rango. Muestra la sintaxis para declarar una variable de
tabla, para acceder a un elemento de una tabla y para comprobar lmites de
tablas. La sintaxis para crear una tabla se tratar en la siguiente seccin.
La segunda seccin describe la creacin e inicializacin de tablas. En la tercera
seccin se explica cmo usar propiedades y mtodos de tabla, cmo pasar
tablas como parmetros, cmo devolver tablas desde mtodos, cmo usar
argumentos de lnea de comandos para Main y cmo usar instrucciones
foreach en tablas.
En el Ejercicio 1, los estudiantes escribirn un programa que espera el nombre
de un archivo de texto como argumento para Main y luego lee los contenidos
de ese archivo en una tabla de caracteres. A continuacin recorre la tabla de
caracteres, clasificando cada carcter como vocal o consonante. Finalmente, el
programa resume los contenidos de la tabla, imprimiendo un breve informe en
la consola.
En el Ejercicio 2, los estudiantes crearn y emplearn tablas de rango 2 y usarn
el mtodo Array.GetLength(int dimension).
Al final de este mdulo, los estudiantes sern capaces de:

Crear, inicializar y usar tablas de distintos rangos.

Usar argumentos de lnea de comandos en un programa C#.

Entender la relacin entre una variable de tabla y una tabla.

Usar tablas como parmetros de mtodos.

Devolver tablas desde mtodos.

Tablas

Descripcin general
Objetivo del tema

Ofrecer una introduccin a


los contenidos y objetivos
del mdulo.

Explicacin previa

En este mdulo repasar el


concepto bsico de tabla y
aprender cmo crear,
inicializar y usar tablas.

Introduccin a las tablas

Creacin de tablas

Uso de tablas

Las tablas proporcionan una forma importante de agrupar datos. Para sacar el
mximo partido a C# es fundamental entender como crear y usar tablas
eficazmente.
Al final de este mdulo, usted ser capaz de:

Crear, inicializar y usar tablas de distintos rangos.

Usar argumentos de lnea de comandos en un programa C#.

Entender la relacin entre una variable de tabla y una tabla.

Usar tablas como parmetros de mtodos.

Devolver tablas desde mtodos.

Tablas

Introduccin a las tablas


Objetivo del tema

Ofrecer una introduccin a


los temas tratados en esta
seccin.

Explicacin previa

Esta seccin ofrece una


introduccin a los
conceptos, caractersticas y
sintaxis bsica de las tablas.

Qu es una tabla?

Notacin para tablas en C#

Rango de una tabla

Acceso a los elementos de una tabla

Comprobacin de los lmites de una tabla

Comparacin de tablas y colecciones

Esta seccin ofrece una introduccin a los conceptos generales de tablas,


presenta la sintaxis que se utiliza in C# para declarar tablas y describe
caractersticas bsicas de tablas como rango y elementos. En la siguiente
seccin veremos cmo definir y usar tablas.

Tablas

Qu es una tabla?
Objetivo del tema

Explicar el concepto de
tabla.

Explicacin previa

Los datos casi nunca estn


aislados, sino que suelen
presentarse en grandes
cantidades.

Una tabla es una secuencia de elementos


z

Todos los elementos de una tabla son del mismo tipo

Las estructuras pueden tener elementos de distintos tipos

Se accede a elementos individuales usando ndices enteros

ndice entero 0
(cero)

ndice entero 4
(cuatro)

Bsicamente hay dos formas de agrupar datos relacionados: estructuras


(structs) y tablas (arrays).
Recomendacin al
profesor

Explique las diferencias


entre una tabla y una
estructura. Las estructuras
pueden contener tipos
diferentes y se accede a sus
miembros por su nombre.
Las tablas contienen el
mismo tipo y se accede a
sus elementos por un ndice
entero.
Destaque que el concepto
de tabla es algo natural, ya
que en cualquier situacin
suele ser necesario
considerar muchos tipos de
informacin. Por ejemplo,
una tabla de casas forma
una calle.

Las estructuras son grupos de datos relacionados que tienen tipos diferentes.
Por ejemplo, un nombre (string), una edad (int), y un gnero (enum)
se agrupan de forma natural en una struct que describe una persona. Se
puede acceder a miembros individuales de una estructura utilizando sus
nombres de campo.
Las tablas son secuencias de datos del mismo tipo.
Por ejemplo, una serie de casas se agrupa de forma natural para formar
una calle. Se puede acceder a un elemento individual de una tabla
utilizando su posicin entera, que recibe el nombre de ndice.
Las tablas permiten el acceso aleatorio. Los elementos de una tabla ocupan
posiciones de memoria contiguas, lo que significa que un programa puede
acceder con la misma rapidez a todos los elementos de una tabla.

Tablas

Notacin para tablas en C#


Objetivo del tema

Terminar la sintaxis y
terminologa que se utilizan
en C# para declarar una
tabla.

Explicacin previa

La mayor parte de los


lenguajes de programacin
tienen una notacin propia
que permite declarar una
entidad como tabla.

Una variable de tabla se declara especificando:


z

El tipo de elementos de la tabla

El rango de la tabla

El nombre de la variable
tipo[
tipo[ ]] nombre;
nombre;
Especifica el nombre de la variable de tabla
Especifica el rango de la tabla
Especifica el tipo de elementos de la tabla

Recomendacin al
profesor

El rango se discute en la
siguiente transparencia.
Esta transparencia muestra
nicamente la sintaxis para
una tabla de rango 1. La
sintaxis se ampliar en la
siguiente transparencia a
tablas de rango 2.

Para declarar una tabla se utiliza la misma notacin que para declarar una
variable simple. Primero se especifica el tipo y a continuacin el nombre de la
variable seguido de un punto y coma. Para declarar el tipo de la variable como
tabla se emplean corchetes. Muchos lenguajes de programacin, como C y C++,
tambin utilizan corchetes para declarar una tabla, mientras que otros, como
Microsoft Visual Basic, usan parntesis.
La notacin para tablas en C# es muy similar a la empleada en C y C++, aunque
con dos diferencias sutiles pero importantes:
No se pueden poner corchetes a la derecha del nombre de la variable.
Al declarar una variable de tabla no se especifica el tamao de la tabla.
A continuacin se ofrecen ejemplos de notaciones permitidas y no permitidas
en C#:
tipo[ ]nombre;
tipo nombre[ ];
tipo[4] nombre;

// Permitida
// No permitida en C#
// Tampoco permitida en C#

Tablas

Rango de una tabla


Objetivo del tema

Introducir el concepto de
rango de tabla en C# y
explicar cmo declarar
tablas de rango 2.

Explicacin previa

Distintos tipos de tablas


requieren distintos nmeros
de ndices para acceder a
sus elementos. Por ejemplo,
las celdas en una hoja de
clculo de Microsoft Excel
requieren un ndice de fila y
un ndice de columna.

Recomendacin al
profesor

Explique el trmino rango


con respecto a tablas. La
transparencia muestra la
sintaxis para tablas de
rango 1 y 2. D un ejemplo
de rango 3 en una pizarra.
Nota: Los grficos que
ilustran las tablas de rango
1 y 2 no muestran
longitudes de tablas porque
todava no se ha discutido
su sintaxis.

El rango se conoce tambin como dimensin de la tabla

El nmero de ndices asociados con cada elemento


long[
long[ ]] fila;
fila;
Rango 1: Unidimensional
Un solo ndice asociado con
cada elemento long

int[,]
int[,] cuadrcula;
cuadrcula;
Rango 2: Bidimensional
Dos ndices asociados con
cada elemento int

Para declarar a una variable de tabla unidimensional se utilizan corchetes


vacos, como se ve en la transparencia. Esta tabla se llama tambin tabla de
rango 1 porque hay un ndice entero asociado con cada elemento de la tabla.
Para declarar a una tabla bidimensional se utiliza una sola coma dentro de los
corchetes, como se ve en la transparencia. Esta tabla se llama tambin tabla de
rango 2 porque hay dos ndices enteros asociados con cada elemento de la
tabla. La extensin de esta notacin es obvia: cada coma adicional dentro de los
corchetes aumenta el rango de la tabla en uno.
En la declaracin de una variable de tabla no se incluye la longitud de las
dimensiones.

Tablas

Acceso a los elementos de una tabla


Objetivo del tema

Describir la sintaxis para


acceder a un elemento de
una tabla y destacas que los
ndices de tablas se
empiezan a contar desde
cero.

Se indica un ndice entero para cada rango


z

Explicacin previa

Los ndices se cuentan a partir de cero

long[
long[ ]] fila;
fila;
...
...
fila[3];
fila[3];

Una vez declarada una


variable de tabla, hay que
saber cmo acceder a los
elementos de la tabla.

int[,]
int[,] cuadrcula;
cuadrcula;
...
...
cuadrcula[1,2];
cuadrcula[1,2];

22
33
11

Recomendacin al
profesor

Esta transparencia es
similar a la anterior, pero en
este caso se accede a un
solo elemento en cada
ejemplo. El punto ms
importante es que los
ndices se cuentan a partir
de cero. Aqu se muestra
nicamente el acceso a
elementos vlidos, ya que
las excepciones por fuera
de lmites se tratarn en la
siguiente transparencia.
Tcnicamente es posible
crear una tabla con lmites
inferiores definidos por el
usuario, como en
Array.CreateInstance
(Tipo, int[ ], int[ ]), pero
probablemente sea mejor
no mencionarlo.

La sintaxis que se utiliza para acceder a los elementos de una tabla es similar a
la empleada para declarar variables de tabla, ya que en ambas se utilizan
corchetes. Este parecido visual (que es deliberado y sigue la tendencia marcada
por C y C++) puede resultar confuso si no se est familiarizado con l. Por eso
es importante ser capaz de distinguir entre la declaracin de una variable de
tabla y la expresin para acceder a los elementos de una tabla.
Para acceder a un elemento de una tabla de rango 1 se utiliza un ndice entero.
Para acceder a un elemento de una tabla de rango 2 se utilizan dos ndices
enteros separados por una coma. La extensin de esta notacin es igual que en
la declaracin de variables: Para acceder a un elemento de una tabla de rango n
se utilizan n ndices enteros separados por comas. Como puede verse, la sintaxis
usada en una expresin para acceder a los elementos de una tabla es igual a la
empleada para declarar variables.
Los ndices de una tabla (de cualquier rango) se cuentan desde cero. As, para
acceder al primer elemento de una fila se usa la expresin:
fila[0]

en lugar de:
fila[1]

Tablas

Algunos programadores prefieren decir elemento inicial en lugar de primer


elemento para evitar la posibilidad de confusin. Contar los ndices desde 0
significa que el ltimo elemento de una tabla con tamao elementos se
encuentra en [tamao -1] y no en [tamao]. Es muy habitual cometer el error de
usar [tamao], especialmente para programadores acostumbrados a lenguajes
que cuentan los ndices a partir de uno, como Visual Basic.
Nota Aunque es una tcnica que apenas se utiliza, es posible crear tablas con
lmites inferiores de ndice entero definido por el usuario. Para ms
informacin, busque Array.CreateInstance en los documentos de ayuda del
SDK de Microsoft .NET Framework.

Tablas

Comprobacin de los lmites de una tabla


Objetivo del tema

Describir el comportamiento
del ndice de una tabla
cuando est fuera de lmites
y explicar cmo encontrar la
longitud de cada rango de
tabla.

Explicacin previa

Qu ocurre si un ndice
est fuera de lmites?
Cmo se puede saber la
longitud de cada rango de
tabla?

Se comprueban los lmites cada vez que se intenta


acceder a una tabla
z

Un ndice errneo lanza la excepcin


IndexOutOfRangeException
Se usan la propiedad Length y el mtodo GetLength

fila
fila

fila.GetLength(0)==6
fila.GetLength(0)==6
fila.Length==6
fila.Length==6

Recomendacin al
profesor

Esta transparencia muestra


nicamente ejemplos de
longitud fija para poder
discutir tanto la propiedad
Length como el mtodo
GetLength. Es importante
estudiar GetLength porque
se utilizar en el Ejercicio 2
de la prctica.
No dedique demasiado
tiempo a la excepcin
IndexOutOfRangeExceptio.

Las excepciones no son


importantes en este mdulo
y no se emplean en los
ejercicios.

cuadr
cuadr

cuadr.GetLength(0)==2
cuadr.GetLength(0)==2
cuadr.GetLength(1)==4
cuadr.GetLength(1)==4
cuadr.Length==2*4
cuadr.Length==2*4

La expresin para acceder a un elemento de una tabla en C# se analiza


automticamente para comprobar que el ndice es vlido. Esta comprobacin
implcita de lmites est siempre activada. Comprobar los lmites es una manera
de garantizar que C# es un lenguaje de especificaciones seguras.
Aunque se comprueben automticamente, hay que asegurarse de que los ndices
de una tabla estn dentro de los lmites. Para ello es preciso comprobar
manualmente los lmites de los ndices, para lo cual se suele emplear la
condicin de fin de una expresin for, como en este ejemplo:
for (int i = 0; i < fila.Length; i++) {
Console.WriteLine(fila[i]);
}

La propiedad Length es la longitud total de la tabla, independientemente de su


rango. Para determinar la longitud de una dimensin concreta se puede utilizar
el mtodo GetLength como se muestra a continuacin:
for (int r = 0; r < cuadr.GetLength(0); r++) {
for (int c = 0; c < cuadr.GetLength(1); c++) {
Console.WriteLine(cuadr[r,c]);
}
}

Tablas

Comparacin de tablas y colecciones


Objetivo del tema

Describir las ventajas e


inconvenientes de tablas y
colecciones.

Una tabla no puede cambiar su tamao cuando est llena


z Una clase de coleccin, como ArrayList, puede cambiar su
tamao

Una tabla contiene elementos de un solo tipo


z Una coleccin est diseada para contener elementos de
distintos tipos

Los elementos de una tabla no pueden ser de slo lectura


z Una coleccin puede tener acceso de slo lectura

En general, las tablas son ms rpidas pero menos


flexibles
z Las colecciones son algo ms lentas pero ms flexibles

Explicacin previa

Cules son las ventajas e


inconvenientes de tablas y
colecciones? Cundo se
debe usar una tabla?
Cundo hay que emplear
una coleccin?

El tamao de una tabla y el tipo de sus elementos se fijan permanentemente en


el momento de crearla. Para crear una tabla que siempre contenga exactamente
42 elementos de tipo int se usa la siguiente sintaxis:
int[ ] rigid = new int [ 42 ];

Una tabla no aumenta ni disminuye de tamao y nunca puede contener nada que
no sean ints. Las colecciones son ms flexibles, ya que se pueden expandir o
contraer a medida que se eliminan o aaden elementos. Las tablas contienen
elementos de un solo tipo, mientras que las colecciones estn diseadas para
albergar elementos de muchos tipos diferentes. Esta flexibilidad se puede
conseguir utilizando boxing, como se muestra a continuacin:
ArrayList flexible = new ArrayList( );
flexible.Add("one"); // Aadir string
...
flexible.Add(99);
// Aadir int

No es posible crear una tabla con elementos de slo lectura. Este cdigo, por
ejemplo, no se compilar:
const int[ ] array = {0, 1, 2, 3};
readonly int[ ] array = {4,2};

Por el contrario, se puede crear una coleccin de slo lectura:


ArrayList flexible = new ArrayList( );
...
ArrayList noWrite = ArrayList.ReadOnly(flexible);
noWrite [0] = 42;
// Excepcin en tiempo de ejecucin

Tablas

10

Creacin de tablas
Objetivo del tema

Ofrecer una introduccin a


los temas tratados en esta
seccin.

Explicacin previa

Una vez explicados los


conceptos bsicos de las
tablas, vamos a ver la
sintaxis que se utiliza para
crear tablas en C#. Casi
toda la sintaxis explicada en
esta seccin se emplear
despus en las prcticas.

Creacin de una tabla

Inicializacin de los elementos de una tabla

Inicializacin de los elementos de una tabla


multidimensional

Creacin de una tabla de tamao calculado

Copia de variables de tabla

En esta seccin veremos cmo crear tablas, cmo inicializar explcitamente los
elementos de una tabla y cmo copiar variables de tabla.

Tablas

11

Creacin de una tabla


Objetivo del tema

Presentar tablas y explicar


la relacin entre tablas y
variables de tabla.

Explicacin previa

Una variable de tabla es


distinta a todas las variables
vistas hasta ahora.

Declarar una variable de tabla no es lo mismo que crear


una tabla!
z Para crear la tabla explcitamente hay que usar new
z El valor implcito por defecto de los elementos de una
tabla es cero
fila

long[
long[ ]] fila
fila == new
new long[4];
long[4];
Variable

int[,]
int[,] cuad
cuad == new
new int[2,3];
int[2,3];
cuadrcula

Recomendacin al
profesor

Recuerde que an no se ha
discutido la palabra
reservada new. Mencione
que un elemento de punto
flotante se inicializa a 0.0 y
que un elemento booleano
se inicializa a false. Escriba
en la pizarra un ejemplo que
muestre cmo crear una
tabla de estructuras.

0 0 0 0
Tabla

0 0 0
0 0 0

La declaracin de una variable de tabla no implica la creacin de una tabla, ya


que las tablas no son tipos de valor sino tipos de referencia. En la expresin
para crear una tabla se emplea la palabra reservada new y en ella hay que
especificar el tamao de todas las longitudes del rango. El siguiente cdigo
producir un error en tiempo de compilacin:
long[ ] fila = new long[ ];
int[,] cuadr = new int[,];

// No permitido
// No permitido

El compilador de C# inicializa implcitamente todos los elementos de una tabla


a un valor que depende de su tipo: los elementos enteros se inicializan
implcitamente a 0, los elementos de punto flotante a 0.0 y los elementos
booleanos a false. En otras palabras, el cdigo C#:
long[ ] fila = new long[4];

ejecutar el siguiente cdigo en tiempo de ejecucin:


long[ ]
fila[0]
fila[1]
fila[2]
fila[3]

fila = new long[4];


= 0L;
= 0L;
= 0L;
= 0L;

Tablas

12

El compilador siempre asigna a una tabla posiciones de memoria contiguas,


independientemente de cul sea su tipo y nmero de dimensiones. Si se crea
una tabla con una expresin como new int[2,3,4], conceptualmente es 2 x 3
x 4, pero la asignacin de memoria subyacente es un solo bloque de memoria lo
suficientemente grande para contener 2*3*4 elementos.

Tablas

13

Inicializacin de los elementos de una tabla


Objetivo del tema

Describir la sintaxis que se


emplea para inicializar los
elementos de una tabla
unidimensional.

Explicacin previa

En muchos casos puede ser


necesario inicializar los
elementos de una tabla a
valores distintos de cero.

Es posible inicializar explcitamente los elementos de


una tabla
z

Se puede utilizar una expresin abreviada


long[
long[ ]] fila
fila == new
new long[4]
long[4] {0,
{0, 1,
1, 2,
2, 3};
3};
long[
long[ ]] fila
fila == {0,
{0, 1,
1, 2,
2, 3};
3};

Equivalentes

0 1 2 3
fila

Recomendacin al
profesor

La expresin abreviada se
utiliza muy a menudo, pero
los estudiantes deben ser
conscientes de que la
expresin de creacin de
una tabla sigue siendo
implcita. Las notas para los
estudiantes incluyen ms
informacin sobre sintaxis
que debe explicar en la
pizarra.
En el Ejercicio 1 de la
prctica se emplear la
sintaxis para inicializar una
tabla de rango 1.

Se puede utilizar un inicializador de tabla para inicializar los valores de los


elementos de una tabla. Un inicializador de tabla es una secuencia de
expresiones puestas entre llaves y separadas por comas. Los inicializadores de
tablas se ejecutan de izquierda a derecha y pueden incluir llamadas a mtodos y
expresiones complejas, como en el siguiente ejemplo:
int[ ] data = new int[4]{a, b( ), c*d, e( )+f( )};

Los inicializadores de tablas tambin se pueden utilizar para inicializar tablas de


estructuras:
struct Date { ... }
Date [ ] dates = new Date[2];

Esta notacin abreviada slo se puede emplear cuando se inicializa una tabla
como parte de la declaracin de una variable de tabla, y no como parte de una
instruccin de asignacin normal.
int[ ] data1 = new int[4]{0, 1, 2, 3};
int[ ] data2 =
{0, 1, 2, 3};
data2 = new int[4]{0, 1, 2, 3};
data2 =
{0, 1, 2, 4};

//
//
//
//

Permitido
Permitido
Permitido
No permitido

Cuando se inicializan tablas hay que inicializar explcitamente todos los


elementos de la tabla. No es posible dejar que slo algunos elementos adopten
su valor cero predeterminado:
int[ ] data3 = new int[2]{};
// No permitido
int[ ] data4 = new int[2]{42};
// Tampoco permitido
int[ ] data5 = new int[2]{42,42}; // Permitido

Tablas

14

Inicializacin de los elementos de una tabla multidimensional


Objetivo del tema

Explicar cmo inicializar los


elementos de una tabla
unidimensional.

Explicacin previa

En muchos casos puede ser


necesario inicializar los
elementos de una tabla
multidimensional a valores
distintos de cero.

Tambin se pueden inicializar los elementos de una


tabla multidimensional
z

Hay que especificar todos los elementos

int[,]
int[,] cuadr
cuadr == {{
{5,
{5, 4,
4, 3},
3},
{2,
{2, 1,
1, 0}
0}
};
};
int[,]
int[,] cuadr
cuadr == {{
{5,
{5, 4,
4, 3},
3},
{2,
1
{2, 1 }}
};
};

Recomendacin al
profesor

Este tema es importante, ya


que muestra la sintaxis para
inicializar tablas de rango
mayor que uno. Los
estudiantes necesitarn
saber cmo inicializar tablas
de rango 2 para hacer el
Ejercicio 2 de la prctica.

Nueva tabla int[2,3] implcita

9
cuadrcula

5 4 3
2 1 0

Todos los elementos de una tabla deben estar inicializados explcitamente,


independientemente de la dimensin de la tabla:
int[,] data = new int[2,3] {
{42, 42, 42},
{42, 42, 42},
};

// Permitido

int[,] data = new int[2,3] {


{42, 42},
{42, 42, 42},
};

// No permitido

int[,] data = new int[2,3] {


{42},
{42, 42, 42},
};

// No permitido

Tablas

15

Creacin de una tabla de tamao calculado


Objetivo del tema

Explicar que no es
necesario que el tamao de
una tabla sea una constante
de tiempo de compilacin y
que se accede a los
elementos de una tabla con
la misma rapidez
independientemente de
cmo se especifique el
tamao de la tabla.

Explicacin previa

Es posible especificar el
tamao de una tabla usando
una expresin entera de
tiempo de ejecucin?
Hara eso que el acceso a
los elementos fuera ms
lento?

Recomendacin al
profesor

El cdigo de la
transparencia supone la
existencia de una
instruccin using. Explique
que una tabla de rango
mayor o igual que 2 sigue
siendo una sola tabla y por
tanto es muy eficiente.

No es necesario que el tamao de una tabla sea una


constante de tiempo de compilacin
z Se puede usar cualquier expresin entera vlida
z El acceso a los elementos es igualmente rpido en todos
los casos
Tamao de tabla especificado por constante entera de
tiempo de compilacin:

long[
long[ ]] fila
fila == new
new long[4];
long[4];

Tamao de tabla especificado por valor entero de


tiempo de ejecucin:
string
string ss == Console.ReadLine();
Console.ReadLine();
int
int tamano
tamano == int.Parse(s);
int.Parse(s);
long[
long[ ]] fila
fila == new
new long[tamano];
long[tamano];

Es posible crear tablas multidimensionales utilizando expresiones de tiempo de


ejecucin para la longitud de cada dimensin, como en el siguiente cdigo:
System.Console.WriteLine("Escriba el nmero de filas: ");
string s1 = System.Console.ReadLine( );
int filas = int.Parse(s1);
System.Console.WriteLine("Escriba el nmero de columnas: ");
string s2 = System.Console.ReadLine( );
int columnas = int.Parse(s2);
...
int[,] matriz = new int[filas,columnas];

En el Ejercicio 1 de la
prctica se emplear la
sintaxis para crear una tabla
de tamao calculado.

Tambin se puede emplear una mezcla de constantes de tiempo de compilacin


y expresiones de tiempo de ejecucin:

Las instrucciones para leer


un valor desde la consola se
utilizan en los dos ejercicios.

System.Console.WriteLine("Escriba el nmero de filas: ");


string s1 = System.Console.ReadLine( );
int filas = int.Parse(s1);
...
int[,] matriz = new int[filas,4];

Hay una pequea restriccin, ya que no est permitido usar una expresin de
tiempo de ejecucin para especificar el tamao de una tabla en combinacin
con inicializadotes de tablas:
string s = System.Console.ReadLine( );
int tamano = int.Parse(s);
int[ ] data = new int[tamano]{0,1,2,3}; // No permitido

Tablas

16

Copia de variables de tablas


Objetivo del tema

Explicar qu ocurre (y qu
no ocurre) cuando se copia
una variable de tabla.

Explicacin previa

Qu se copia cuando se
copia una variable de tabla?
Es la variable de tabla o es
la tabla?

Recomendacin al
profesor

Este tema es importante.


Compare la copia de una
variable struct con la copia
de una variable de tabla.
Compare el siguiente
fragmento de cdigo con el
de la transparencia:
struct Value {
public long
a,b,c,d;
}
Value fila;
fila.a = 0L;
fila.b = 0L;
fila.c = 0L;
fila.d = 0L;
Valor copia =
fila;
fila.a++;
long valor =
copia.a;
Console.WriteLine(
value);

Al copiar una variable de tabla se copia slo la variable


de tabla
z

No se copia la tabla

Dos variables de tabla pueden apuntar a la misma tabla

long[
long[ ]] fila
fila == new
new long[4];
long[4];
long[
long[ ]] copia
copia == fila;
fila;
fila
...
...
fila[0]++;
fila[0]++;
copia
long
long valor
valor == copia[0];
copia[0];
Console.WriteLine(valor);
Console.WriteLine(valor); Variable

0 0 0 0

Tabla

Cuando se copia una variable de tabla lo que se obtiene no es una copia


completa de la tabla. Un anlisis del cdigo de la transparencia revela qu es lo
que ocurre al copiar una variable de tabla.
Las instrucciones siguientes dos declaran variables de tabla llamadas copia y
fila que apuntan a la misma tabla (de cuatro enteros long).
long[ ] fila = new long[4];
long[ ] copia = fila;

Esta instruccin incrementa de 0 a 1 el elemento inicial de esta tabla. Ambas


variables de tabla siguen apuntando a la misma tabla, cuyo elemento inicial es
ahora 1.
fila[0]++;

La siguiente instruccin inicializa un entero long llamado valor a copia[0],


que es el elemento inicial de la tabla a la que apunta copia.
long valor = copia[0];

Puesto que copia y fila apuntan ambos a la misma tabla, inicializar a fila[0]
tiene exactamente el mismo efecto.
La instruccin final escribe valor (que es 1) en la consola:
Console.WriteLine(value);

Tablas

17

Uso de tablas
Objetivo del tema

Ofrecer una introduccin a


los temas tratados en esta
seccin.

Explicacin previa

Ahora que ya sabemos


cmo crear e inicializar
tablas, vamos a explicar la
sintaxis del uso de tablas.
Casi toda la sintaxis
explicada en esta seccin
se emplear despus en las
prcticas.

Propiedades de tablas

Mtodos de tablas

Devolucin de tablas desde mtodos

Paso de tablas como parmetros

Argumentos de lnea de comandos

Demostracin: Argumentos para Main

Uso de tablas con foreach

Problema: Dnde est el error?

En esta seccin estudiaremos cmo usar tablas y cmo pasar tablas como
parmetros a mtodos.
Veremos las reglas que rigen los valores predeterminados de los elementos de
una tabla. Las tablas heredan implcitamente de la clase System.Array, que
contiene muchas propiedades y mtodos de los cuales discutiremos los
empleados ms frecuentemente. Tambin estudiaremos cmo utilizar la
instruccin foreach para recorrer tablas. Finalmente, discutiremos cmo evitar
algunos errores comunes.

Tablas

18

Propiedades de tablas
Objetivo del tema

Presentar algunas
propiedades tiles que las
tablas heredan de
System.Array.

Explicacin previa

La clase System.Array
contiene varias propiedades
tiles que utilizan todas las
tablas.

long[
long[ ]] fila
fila == new
new long[4];
long[4];

0 0 0 0

cuadrcula

Recuerde que la propiedad


Length da la longitud total
de todas las dimensiones
multiplicadas entre s. La
propiedad Length se
emplear en el Ejercicio 1
de la prctica. Trate la
sintaxis de las propiedades
como si fueran una caja
negra, ya que no se vern
en detalle hasta un mdulo
posterior.

11

fila.Length
fila.Length

44

fila

int[,]
int[,] cuad
cuad == new
new int[2,3];
int[2,3];

Recomendacin al
profesor

fila.Rank
fila.Rank

0 0 0
0 0 0

cuad.Rank
cuad.Rank

22

cuad.Length
cuad.Length

66

La propiedad Rank es un valor entero de slo lectura que indica la dimensin


de una tabla. Por ejemplo, en el cdigo
int[ ] uno = new int[a];
int[,] dos = new int[a,b];
int[,,] tres = new int[a,b,c];

los valores resultantes del rango son los siguientes:


uno.Rank == 1
dos.Rank == 2
tres.Rank == 3

La propiedad Length es un valor entero de slo lectura que indica la longitud


total de una tabla. Por ejemplo, dadas las tres declaraciones anteriores de tablas,
los valores resultantes de la longitud son:
uno.Length == a
dos.Length == a * b
tres.Length == a * b * c

Tablas

19

Mtodos de tablas
Objetivo del tema

Presentar algunos mtodos


tiles que las tablas
heredan de System.Array.

Explicacin previa

La clase System.Array
contiene varios mtodos
tiles que utilizan todas las
tablas.

Mtodos utilizados frecuentemente


z

Sort: Ordena los elementos en una tabla de rango 1

Clear: Asigna el valor cero o null a un rango de elementos

Clone: Crea una copia de la tabla

GetLength: Devuelve la longitud de una dimensin dada

Recomendacin al
profesor

Estos mtodos no se usan


en ninguno de los ejercicios.
Es posible ordenar una
tabla de una estructura o
clase definida por el
usuario, siempre y cuando
la estructura o clases
admita la interfaz
IComparable. Sort, Clear e
IndexOf son mtodos static.

IndexOf: Devuelve el ndice de la primera vez que aparece


un valor

La clase System.Array (que utilizan implcitamente todas las tablas) contiene


muchos mtodos que se pueden utilizar para trabajar con tablas. Este tema
describe los mtodos empleados ms frecuentemente
Mtodo Sort
Este mtodo efecta una ordenacin en contexto de la tabla pasada como
argumento. Se puede utilizar para ordenar tablas de estructuras y clases que
admitan la interfaz IComparable.
int[ ] data = {4,6,3,8,9,3};
System.Array.Sort(data);

// Sin ordenar
// Ordenada

Mtodo Clear
Este mtodo cambia el valor de un rango de elementos de la tabla a cero
(para tipos de valor) o null (para tipos de referencia), como en este ejemplo:
int[ ] data = {4,6,3,8,9,3};
System.Array.Clear(data, 0, data.Length);

Mtodo Clone
Este mtodo crea una nueva tabla cuyos elementos son copias de los
elementos de la tabla original. Se puede utilizar para clonar tablas de
estructuras y clases definidas por el usuario. El siguiente es un ejemplo:
int[ ] data = {4,6,3,8,9,3};
int[ ] clone = (int [ ])data.Clone( );

Tablas

20

Precaucin El mtodo Clone realiza una copia superficial. Si la tabla


copiada contiene referencias a objetos, se copiarn las referencias pero no lo
objetos; las dos tablas apuntarn a los mismos objetos.
Mtodo GetLength
Este mtodo devuelve la longitud de una dimensin pasada como un
argumento entero. Se puede utilizar para comprobar los lmites de tablas
multidimensionales. El siguiente es un ejemplo:
int[,] data = { {0, 1, 2, 3}, {4, 5, 6, 7} };
int dim0 = data.GetLength(0); // == 2
int dim1 = data.GetLength(1); // == 4

Mtodo IndexOf
Este mtodo devuelve el ndice entero de la primera vez que aparece un
valor pasado como argumento, o 1 si el valor no est presente. Slo se
puede utilizar en tablas unidimensionales. El siguiente es un ejemplo:
int[ ] data = {4,6,3,8,9,3};
int donde = System.Array.IndexOf(data, 9); // == 4

Nota Dependiendo del tipo de los elementos en la tabla, el mtodo


IndexOf puede obligar a omitir el mtodo Equals para el tipo de los
elementos. Esto se estudiar en un mdulo posterior.

Tablas

21

Devolucin de tablas desde mtodos


Objetivo del tema

Describir la sintaxis que se


utiliza para declarar un
mtodo que devuelve una
tabla, y mostrar un ejemplo
de devolucin de una tabla
usando una instruccin
return.

class
class Example
Example {{
static
static void
void Main(
Main( )) {{
int[
int[ ]] array
array == CreateArray(42);
CreateArray(42);
...
...
}}
static
static int[
int[ ]] CreateArray(int
CreateArray(int tamano)
tamano) {{
int[
]
creada
=
new
int[tamano];
int[ ] creada = new int[tamano];
return
return creada;
creada;
}}
}}

Explicacin previa

Cmo se declara un
mtodo que devuelve una
tabla?

Recomendacin al
profesor

Comente para declarar una


variable de tabla es similar a
la que se usa para declarar
un mtodo que devuelve
una tabla.
En el Ejercicio 2 de la
prctica, los estudiantes
tendrn que devolver una
tabla de rango 2 desde un
mtodo.

Es posible declarar mtodos para que devuelvan tablas

El mtodo CreateArray en la transparencia contiene dos instrucciones. Es


posible combinar estas dos instrucciones en una sola instruccin return como
se indica a continuacin:
static int[ ] CreateArray(int tamano) {
return new int[tamano];
}

Los programadores en C++ notarn que en ninguno de los dos casos se


especifica el tamao de la tabla que se devuelve. Si se indica el tamao de la
tabla se obtendr un error en tiempo de ejecucin, como en este ejemplo:
static int[4] CreateArray( ) // Error de compilacin
{
return new int[4];
}

Tambin es posible devolver tablas de rango mayor que uno, como se ve en el


siguiente ejemplo:
static int[,] CreateArray( ) {
string s1 = System.Console.ReadLine( );
int filas = int.Parse(s1);
string s2 = System.Console.ReadLine( );
int columnas = int.Parse(s2);
return new int[filas,columnas];
}

Tablas

22

Paso de tablas como parmetros


Objetivo del tema

Explicar cmo se puede


pasar una tabla como
parmetro y qu ocurre
cuando se hace.

Explicacin previa

Ya hemos visto cmo


devolver una tabla desde un
mtodo. Veamos ahora
cmo pasar una tabla a un
mtodo como parmetro.

Un parmetro de tabla es una copia de la variable de tabla


z

No es una copia de la tabla

class
class Example2
Example2 {{
static
static void
void Main(
Main( )) {{
int[
int[ ]] arg
arg == {10,
{10, 9,
9, 8,
8, 7};
7};
Method(arg);
Method(arg);
System.Console.WriteLine(arg[0]);
System.Console.WriteLine(arg[0]);
}}
static
static void
void Metodo(int[
Metodo(int[ ]] parametro)
parametro) {{
parametro[0]++;
parametro[0]++;
Este
Este mtodo
mtodo modificar
modificar
}}
la
la tabla
tabla original
original
}}
creada
creada en
en Main
Main

Tablas

Recomendacin al
profesor

Es importante que los


estudiantes sepan pasar
tablas como parmetros, ya
que tendrn que hacerlo en
los dos ejercicios de la
prctica. Puede empezar
con el siguiente cdigo para
ver hasta qu punto los
estudiantes entienden este
proceso:
static void Main(
) {
int arg = 42;
m(arg);
}
void m(int param)
{
param++;
}

23

Cuando se pasa una variable de tabla como argumento para un mtodo, el


parmetro del mtodo pasa a ser una copia del argumento de la variable de
tabla. En otras palabras, el parmetro de tabla se inicializa desde el argumento.
Para inicializar el parmetro de tabla se usa la misma sintaxis que para
inicializar una variable de tabla, como se explic anteriormente en el tema
Copia de variables de tablas. Tanto el argumento de tabla como el parmetro
de tabla apuntan a la misma tabla.
En el cdigo mostrado en la transparencia, arg se inicializa con una tabla de
longitud 4 que contiene los enteros 10, 9, 8 y 7. A continuacin se pasa arg
como argumento para Method. Method acepta arg como parmetro, lo que
quiere decir que tanto arg como el parmetro apuntan a la misma tabla (la
empleada para inicializar arg). La expresin parametro[0]++ en Method hace
que se incremente el elemento inicial de la misma tabla de 10 a 11 (el elemento
inicial de una tabla tambin recibe el nombre de elemento cero, ya que se
accede a l con el valor de ndice 0, no 1). Method devuelve el valor de arg[0]
y Main lo escribe en la consola. El parmetro arg contina apuntando a la
misma tabla cuyo elemento cero ha sido incrementado, por lo que en la consola
se escribe 11.
Cuando se pasa una variable de tabla no se crea una copia profunda de la tabla,
lo que hace que pasar una tabla como parmetro sea muy rpido. Esta copia
superficial es ms que suficiente si se quiere que un mtodo tenga acceso de
escritura a la tabla del argumento.

Luego se convierte
arg en una tabla
que contiene un
solo int:

El mtodo Array.Copy resulta til para asegurarse de que el mtodo llamado


no puede modificar la tabla, aunque esta seguridad se paga con un tiempo de
ejecucin ms largo. Tambin es posible pasar como parmetro de tabla una
tabla de nueva creacin de la siguiente manera:

static void Main(


) {
int[ ] arg = {
42 };
m(arg);
}
void m(int[ ]
param) {
param[0]++;
}

Method(new int[4]{10, 9, 8, 7});

Tablas

24

Argumentos de lnea deg comandos


Objetivo del tema

Explicar cmo acceder a


argumentos de lnea de
comandos en Main.

Explicacin previa

Cuando se ejecutan
programas de consola es
frecuente aadir informacin
en la lnea de comandos.
Cmo accede el programa
a esa informacin?

Recomendacin al
profesor

En el Ejercicio 1 de la
Prctica se emplea el paso
de argumentos a Main en la
lnea de comandos. El
cdigo mostrado en la
transparencia utiliza una
instruccin for; en la
siguiente transparencia se
mostrar la instruccin
foreach equivalente.

El runtime pasa argumentos de lnea de comandos a Main


z

Main puede aceptar como parmetro una tabla de


cadenas de caracteres
El nombre del programa no es un miembro de la tabla

class
class Example3
Example3 {{
static
static void
void Main(string[
Main(string[ ]] args)
args) {{
for
for (int
(int ii == 0;
0; ii << args.Length;
args.Length; i++)
i++) {{
System.Console.WriteLine(args[i]);
System.Console.WriteLine(args[i]);
}}
}}
}}

Cuando se ejecutan programas de consola es muy frecuente pasar nuevos


argumentos en la lnea de comandos. Por ejemplo, al aadir el programa pkzip
desde el smbolo del sistema es posible aadir argumentos para controlar la
creacin de archivos .zip. El siguiente comando aade recursivamente a
code.zip todos los archivos de cdigo *.cs:
C:\> pkzip add rec path=relative c:\code *.cs

Si el programa pkzip estuviera escrito en C#, estos argumentos de lnea de


comandos se capturaran como una tabla de cadenas de caracteres que el
runtime pasara a Main:
class PKZip {
static void Main(string[ ] args) {
...
}
}

Cuando se ejecuta el programa pkzip con este ejemplo, el runtime ejecuta


realmente el siguiente cdigo:

Tablas

25
string[ ] args = {
"-add",
"-rec",
"-path=relative",
"c:\\code",
"*.cs"
};
PKZip.Main(args);

Nota Al contrario de lo que ocurre en C y C++, in C# no se pasa el nombre del


programa como args[0].

Tablas

26

Uso de tablas con foreach


Objetivo del tema

Explicar cmo usar una


tabla en una instruccin
foreach.

Explicacin previa

Es muy habitual escribir


cdigo que recorre una
tabla y ejecuta las mismas
instrucciones para cada
elemento. El uso de
foreach simplifica este
proceso.

Recomendacin al
profesor

La instruccin foreach se
emplear en los dos
ejercicios de la prctica, ya
que puede recorrer tablas
multidimensionales.

La instruccin foreach simplifica enormemente la


manipulacin de tablas

class
class Example4
Example4 {{
static
static void
void Main(string[
Main(string[ ]] args)
args) {{
foreach
(string
arg
in
args)
foreach (string arg in args) {{
System.Console.WriteLine(arg);
System.Console.WriteLine(arg);
}}
}}
}}

Cuando se puede emplear, la instruccin foreach resulta til porque simplifica


el proceso de recorrer de uno en uno todos los elementos de una tabla. Sin
foreach se podra escribir:
for (int i = 0; i < args.Length; i++) {
System.Console.WriteLine(args[i]);
}

Con foreach se convertira en:


foreach (string arg in args) {
System.Console.WriteLine(arg);
}

Con la instruccin foreach no se necesita ni se utiliza:


Un ndice entero (int i)
Una comprobacin de los lmites de la tabla (i < args.Length)
Una expresin de acceso a la tabla (args[i])
Tambin se puede usar la instruccin foreach para recorrer de uno en uno todos
los elementos de una tabla de rango 2 o superior. Por ejemplo, la siguiente
instruccin foreach escribir los valores 0, 1, 2, 3, 4 y 5:

Tablas

27
int[,] numbers = { {0,1,2}, {3,4,5} };
foreach (int number in numbers) {
System.Console.WriteLine(number);
}

Fundamentos de la
programacin orientada a
objetos

Contenido
Descripcin general
Clases y objetos

1
2

Uso de la encapsulacin

10

El lenguaje C# y la orientacin a objetos

23

Definicin de sistemas orientados a


objetos

36

Fundamentos de la programacin orientada a objetos

Notas para el instructor


Este mdulo proporciona a los estudiantes la teora, los conceptos y la
terminologa bsica de la programacin orientada a objetos. Tambin incluye
una porcin mnima de sintaxis de C#, concretamente la necesaria para la
encapsulacin.
Al final de este mdulo, los estudiantes sern capaces de:
Definir los trminos objeto y clase en el contexto de la programacin
orientada a objetos.
Definir los tres aspectos bsicos de un objeto: identidad, estado y
comportamiento.
Describir la abstraccin y cmo ayuda a crear clases reutilizables que son
fciles de mantener.
Usar la encapsulacin para combinar mtodos y datos en una sola clase y
forzar la abstraccin.
Explicar los conceptos de herencia y polimorfismo.
Crear y utilizar clases en C#.

Fundamentos de la programacin orientada a objetos

Descripcin general
Objetivo del tema

Ofrecer una introduccin a


los contenidos y objetivos
del mdulo.

Explicacin previa

En este mdulo estudiar


clases y objetos con ms
detalle.

Clases y objetos

Uso de la encapsulacin

El lenguaje C# y la orientacin a objetos

Definicin de sistemas orientados a objetos

C# es un lenguaje de programacin orientado a objetos. En esta seccin


veremos la terminologa y los conceptos necesarios para crear y utilizar clases
en C#.
Al final de este mdulo, usted ser capaz de:
Definir los trminos objeto y clase en el contexto de la programacin
orientada a objetos.
Definir los tres aspectos bsicos de un objeto: identidad, estado y
comportamiento.
Describir la abstraccin y cmo ayuda a crear clases reutilizables que son
fciles de mantener.
Usar la encapsulacin para combinar mtodos y datos en una sola clase y
forzar la abstraccin.
Explicar los conceptos de herencia y polimorfismo.
Crear y utilizar clases en C#.

Fundamentos de la programacin orientada a objetos

Clases y objetos
Objetivo del tema

Ofrecer una introduccin a


los temas tratados en esta
seccin.

Explicacin previa

Los trminos clase y objeto


aparecen muy a menudo.
En esta seccin
aprenderemos qu es lo
que significan exactamente.

Qu es una clase?

Qu es un objeto?

Comparacin de clases y estructuras

Abstraccin

Toda la estructura de C# est basada en el modelo de programacin orientada a


objetos. Para sacar el mximo partido a C# como lenguaje es necesario
comprender la naturaleza de la programacin orientada a objetos.
Al final de esta leccin, usted ser capaz de:
Definir los trminos objeto y clase en el contexto de la programacin
orientada a objetos.
Aplicar el concepto de abstraccin.

Fundamentos de la programacin orientada a objetos

Qu es una clase?
Objetivo del tema

Explicar el concepto de
clase.

Explicacin previa

COCHE?
COCHE?

El objetivo principal del


lenguaje C# es definir
clases y especificar su
comportamiento.

Para el filsofo
z

Un artefacto de clasificacin humana

Clasificamos segn un comportamiento o atributos comunes

Acordamos descripciones y nombres de clases tiles

Creamos vocabulario; nos comunicamos; pensamos!

Para el programador orientado a objetos


z

Una construccin sintctica con nombre que describe un


comportamiento y atributos comunes
Una estructura de datos que incluye datos y funciones

La palabra clase proviene de clasificacin. Formar clases es el acto de


clasificar, algo que hacen todos los seres humanos (y no slo los
programadores). Por ejemplo, todos los coches comparten un mismo
comportamiento (se pueden dirigir, detener,) y atributos comunes (tienen
cuatro ruedas, un motor,). Usamos la palabra coche para referirnos a todos
estos comportamientos y propiedades comunes. Imaginemos qu ocurrira si no
fusemos capaces de clasificarlos en un concepto al que damos un nombre. En
lugar de coche, tendramos que decir todas las cosas que coche significa. Las
frases se haran largas y complicadas, y de hecho es muy probable que la
comunicacin fuera imposible. En la medida en que todos estemos de acuerdo
en lo que significa una palabra (es decir, en la medida en que todos hablemos el
mismo idioma), podremos comunicarnos y expresar ideas complejas, pero
precisas, de una forma compacta. Estos conceptos con nombre nos sirven a su
vez para crear conceptos de un nivel ms alto y para aumentar la capacidad
expresiva de la comunicacin.
Todos los lenguajes de programacin describen datos y funciones comunes.
Esta capacidad de describir caractersticas comunes ayuda a evitar la
duplicacin. Uno de los lemas bsicos de la programacin es No te repitas.
Un cdigo duplicado crea problemas porque es ms difcil de mantener. Por el
contrario, un cdigo que no se repite es ms fcil de mantener, es parte porque
es ms corto. Los lenguajes orientados a objetos llevan este concepto al
siguiente nivel, ya que permiten descripciones de clases (conjuntos de objetos)
que comparten estructura y comportamiento. Si se hace bien, este principio
funciona extremadamente bien y se adapta de forma natural a la forma de hablar
y comunicarse que tienen las personas.
Las clases no se limitan a clasificar objetos concretos (como coches), sino que
tambin se pueden usar para clasificar objetos abstractos (como tiempo). No
obstante, a la hora de clasificar objetos abstractos los lmites se hacen ms
imprecisos y el diseo se convierte en algo importante.

Fundamentos de la programacin orientada a objetos

El nico requisito real que debe cumplir una clase es estimular la comunicacin.

Fundamentos de la programacin orientada a objetos

Qu es un objeto?
Objetivo del tema

Definir el trmino objeto.

Explicacin previa

A menudo se comete el
error de usar los trminos
clase y objeto como si
significaran lo mismo,
cuando en realidad son dos
conceptos muy diferentes.

Un objeto es una instancia de una clase

Los objetos se caracterizan por:


z

Identidad: Los objetos se distinguen unos de otros

Comportamiento: Los objetos pueden realizar tareas

Estado: Los objetos contienen informacin

Fundamentos de la programacin orientada a objetos

Recomendacin al
profesor

Puede emplear la analoga


del coche a lo largo de toda
la explicacin de identidad,
comportamiento y estado.
Por ejemplo, puede
preguntar a los estudiantes
si esta frase se refiere a los
coches como objetos o
como una clase: "El carril de
lentos, que es el derecho,
es para coches con ms de
tres ocupantes." Esta frase
usa "coche" como un objeto
(una instancia de una
clase). Los objetos pueden
ser annimos, pero no por
ello dejan de ser objetos. El
hecho de que un coche
lleve a tres personas no lo
convierte en un objeto
distinto de un coche que
lleve a dos o cuatro
personas. El nmero de
ocupantes es un ejemplo
del estado del coche.
Explique que estado se
refiere a los valores de los
atributos internos de un
objeto que pueden variar
con el tiempo, como el
nmero de pasajeros.
Compare esto con los
valores que probablemente
estn fijos y no cambien
desde la fabricacin del
coche, como el nmero de
puertas.

La palabra coche significa distintas cosas segn el contexto. A veces usamos la


palabra coche para referirnos al concepto general de coche: hablamos de coche
como una clase, la del conjunto de todos los coches, sin pensar en ningn tipo
de coche concreto. En otras ocasiones empleamos la palabra coche para hablar
de un coche en particular. Los programadores usan el trmino objeto o
instancia para referirse a un coche concreto. Es importante entender esta
diferencia.
Los objetos se pueden comprender mejor con las tres caractersticas de
identidad, comportamiento y estado.

Identidad
La identidad es la caracterstica que distingue un objeto de todos los dems
objetos de la misma clase. Por ejemplo, imaginemos que dos vecinos tienen
coches que son exactamente de la misma marca, modelo y color. A pesar de lo
mucho que se puedan parecer, podemos estar seguros de que sus matrculas
sern diferentes y reflejarn la identidad de cada uno de los coches. La ley dice
que es necesario poder distinguir un objeto coche de otro. (Cmo les ira a los
seguros de automviles si los coches no tuvieran identidad?)

Fundamentos de la programacin orientada a objetos

Comportamiento
El comportamiento es la caracterstica que hace que los objetos sean tiles. Los
objetos existen para que se comporten de una cierta manera. La mayor parte del
tiempo podemos olvidarnos de cmo funciona un coche y pensar slo en su
comportamiento externo o de alto nivel. Los coches nos son tiles porque
podemos conducirlos; tienen un mecanismo interno, pero nos resulta casi
inaccesible. Lo que s es accesible es el comportamiento del objeto, que es
adems el factor determinante para su clasificacin. Los objetos de una misma
clase comparten un comportamiento comn: Un coche es un coche porque
podemos conducirlo, un bolgrafo es un bolgrafo porque podemos usarlo para
escribir.

Estado
El estado se refiere a los mecanismos internos de un objeto que hacen que se
comporte de una determinada manera. Un objeto bien diseado mantiene su
estado inaccesible. Esto guarda una relacin muy estrecha con los conceptos de
abstraccin y encapsulacin. No nos preocupa por qu un objeto hace lo que
hace, slo queremos que lo haga. Es posible que dos objetos tengan el mismo
estado, pero siguen siendo dos objetos diferentes; por ejemplo, dos gemelos
idnticos tienen exactamente el mismo estado (su ADN), pero son dos personas
distintas.

Fundamentos de la programacin orientada a objetos

Comparacin de clases y estructuras


Objetivo del tema

Ofrecer una breve


comparacin entre clases y
estructuras.

Explicacin previa

Tal vez sepa ya que las


estructuras pueden
contener mtodos y datos,
igual que las clases. Cul
es entonces la diferencia
entre una estructura y una
clase?

Recomendacin al
profesor

En programas C++, las


palabras reservadas struct
y class se pueden usar
indistintamente. Haga
hincapi en que, en C#, las
clases no son un tipo de
"sper estructuras."

Una estructura define un valor

Sin identidad, estado accesible, sin comportamiento


aadido

Una clase define un objeto


z

Identidad, estado inaccesible, comportamiento aadido

struct
struct Time
Time
{{
public
public int
int hour;
hour;
public
int
public int minute;
minute;
}}

class
class BankAccount
BankAccount
{{
...
...
...
...
}}

Estructuras
Una estructura, como Reloj en el ejemplo, no tiene identidad. Si dos variables
Reloj representan las 12:30, el programa se comportar exactamente de la
misma manera independientemente de cul de ellas utilicemos. Las entidades de
software sin identidad se llaman valores. Los tipos predefinidos descritos en el
Mdulo 3, Uso de variables de tipo valor, en el Curso 2124C, Programacin
en C#, como int, bool, decimal y todos los tipos struct, se llaman en C# tipos
de valor.
Las variables del tipo struct pueden contener mtodos, aunque es preferible que
no lo hagan. Idealmente, deben contener slo datos. Por otra parte, no hay
ningn problema en definir operadores en estructuras. Los operadores son un
tipo de mtodos que no aaden nada al comportamiento, sino slo una sintaxis
ms concisa para un mismo comportamiento.

Clases
Una clase, como CuentaBancaria en el ejemplo, tiene identidad. Si hay dos
objetos CuentaBancaria, el programa se comportar de distinta forma
dependiendo de cul se utilice. Las entidades de software con identidad se
llaman objetos (en ocasiones, las variables del tipo struct reciben tambin el
nombre de objetos, pero estrictamente hablando son valores). Los tipos
representados por clases se llaman en C# tipos de referencia. A diferencia de
las estructuras, en una clase bien diseada no se debe ver nada que no sea un
mtodo. Estos mtodos aaden comportamiento de alto nivel al
comportamiento primitivo que existe a nivel de los datos inaccesibles.

Fundamentos de la programacin orientada a objetos

Tipos de valor y tipos de referencia


Los tipos de valor son los que se encuentran en el nivel ms bajo de un
programa. Son los elementos que se utilizan para crear entidades de software
ms grandes. Los tipos de valor se pueden copiar libremente y estn en la pila
como variables locales o como atributos dentro de los objetos que describen.
Los tipos de referencia son los que se encuentran en el nivel ms alto de un
programa. Se crean a partir de entidades de software ms pequeas.
Normalmente los tipos de referencia no se pueden copiar y estn en el montn
(heap).

Fundamentos de la programacin orientada a objetos

10

Abstraccin
Objetivo del tema

Definir la abstraccin.

Explicacin previa

Es necesario saber cmo


funciona una cosa para
poder usarla?

La abstraccin es ignorancia selectiva


z

Decidir qu es importante y qu no lo es

Concentrarse en lo importante y depender de ello

Ignorar lo que no es importante y no depender de ello

Usar encapsulacin para forzar una abstraccin

El
El objetivo
objetivo de
de la
la abstraccin
abstraccin es
es no
no perderse
perderse en
en vaguedades
vaguedades yy crear
crear
un
un nuevo
nuevo nivel
nivel semntico
semntico en
en el
el que
que se
se pueda
pueda ser
ser absolutamente
absolutamente preciso.
preciso.
Edsger
Edsger Dijkstra
Dijkstra

Recomendacin al
profesor

Los contenidos de la
transparencia tienen
implicaciones importantes.
Lo primero que se dice es
que hay que decidir qu es
importante y qu no lo es.
En otras palabras, hay que
tomar decisiones de diseo.
Dado el nivel de este curso,
dedique poco o ningn
tiempo a discutir este tema.
Concntrese ms bien en la
dependencia, que guarda
una relacin muy estrecha
con la idea de cambio (que
se discute a continuacin).

La abstraccin es la tctica de despojar una idea u objeto de todo lo innecesario


hasta llegar a su forma mnima y esencial. Una buena abstraccin elimina los
detalles poco importantes y permite concentrarse slo en lo que es importante.
La abstraccin es un importante principio del software. Una clase bien diseada
deja ver una cantidad mnima de mtodos que permiten obtener fcilmente el
comportamiento esencial de la clase. Desgraciadamente, crear buenas
abstracciones de software no es sencillo. Para llegar a una buena abstraccin
suele ser necesario tener un profundo conocimiento del problema y de su
contexto, pensar con gran claridad y tener una enorme experiencia.

Dependencia mnima
Las mejores abstracciones de software hacen que las cosas ms complejas
parezcan sencillas. Para ello ocultan todos los aspectos de una clase que no son
esenciales. Una vez ocultos, estos aspectos ya no pueden ser vistos ni utilizados
y no se depende de ellos de ninguna manera.
Este principio de dependencia mnima es lo que hace que la abstraccin sea tan
importante. Una de las pocas cosas seguras en el desarrollo de software es que
siempre es necesario cambiar el cdigo. La comprensin perfecta slo se
alcanza (si es que se consigue) al final del proceso de desarrollo; las primeras
decisiones se toman a partir de una comprensin incompleta del problema, por
lo que siempre hay que reconsiderarlas ms tarde. Las especificaciones tambin
cambian a medida que se va entendiendo mejor el problema. Las versiones
posteriores incluyen cada vez ms funciones. Los cambios son normales en el
desarrollo de software; lo ms que podemos hacer cuando se producen es
minimizar sus efectos, y cuanto menos dependamos de una cosa, menos nos
afectarn sus cambios.

Fundamentos de la programacin orientada a objetos

11

Citas ilustrativas
He aqu algunas citas para ilustrar el principio de dependencia mnima que hace
que la abstraccin sea tan importante:
Para su informacin

La cita de Dijkstra se puede


usar para intentar
desmontar un mito muy
extendido; no hay nada
vago en una abstraccin de
software.
Tanto usted como sus
estudiantes pueden
encontrar ms informacin
sobre el profesor Edsger
Wybe Dijkstra en
www.cs.utexas.edu/users/
UTCS/report/1994/profiles/
dijkstra.html
Entre sus contribuciones a
la informtica y las
matemticas estn los
semforos informticos; sus
famosos nombres "P y V"
para los semforos
proceden de las palabras
holandesas passeer y
verlaat, o pasar y salir.
Tambin se dio su nombre
al algoritmo de Dijkstra, que
encuentra la ruta ms corta
desde un punto de un
grfico hasta su destino.

Cuanto ms perfecta es una mquina, ms invisible resulta tras su funcin. Es


como si la perfeccin se alcanzara no cuando ya no hay nada ms que aadir,
sino cuando ya no queda nada que eliminar. En la cima de su evolucin, la
mquina queda totalmente oculta.
Antoine de Saint-Exupry, Viento, arena y estrellas
Podramos definir el minimum como la perfeccin que alcanza un objeto cuando
ya resulta imposible mejorarlo por substraccin. sta es la calidad que define a
un objeto cuando todos y cada uno de sus componentes, detalles y conexiones
han sido reducidos o condensados a lo esencial. Es el resultado de la omisin de
lo innecesario.
John Pawson, Minimum
El objetivo bsico de la comunicacin es la claridad y la simplicidad. La
simplicidad es el resultado de un esfuerzo bien enfocado.
Edward de Bono, Simplicidad

Fundamentos de la programacin orientada a objetos

Uso de la encapsulacin
Objetivo del tema

Ofrecer una introduccin a


los temas tratados en esta
seccin.

Explicacin previa

Qu es la encapsulacin?
Cmo se puede emplear la
encapsulacin en una clase,
y por qu?

Combinacin de datos y mtodos

Control de la visibilidad de acceso

Por qu se encapsula?

Datos de objetos

Uso de datos estticos

Uso de mtodos estticos

Al final de esta leccin, usted ser capaz de:


Combinar datos y mtodos en una sola cpsula.
Usar encapsulacin dentro de una clase.
Usar mtodos de datos estticos en una clase.

12

Fundamentos de la programacin orientada a objetos

13

Combinacin de datos y mtodos


Objetivo del tema

Discutir la motivacin que


hay detrs de la
encapsulacin.

Explicacin previa

Despus de decidir qu
partes pueden ser de
acceso pblico y cules
deben quedar ocultas, es
preciso contar con una
forma sencilla de ocultar la
complejidad interna de una
clase.

Combinacin de datos y mtodos en una sola cpsula

La frontera de la cpsula crea un espacio interior y


otro exterior

Retirar( )

Retirar( )

saldo

saldo

Ingresar( )
CuentaBancaria ?

Ingresar( )
CuentaBancaria ?

La encapsulacin incluye dos aspectos importantes:


Combinacin de datos y funciones en una sola entidad (esta transparencia)
Control de la accesibilidad a los miembros de la entidad (siguiente
transparencia)
Recomendacin al
profesor

La transparencia termina
recomendando el uso de la
encapsulacin para forzar la
abstraccin.
sta es la primera de dos
transparencias sobre
encapsulacin. La segunda
transparencia proporciona
informacin adicional. En
esta transparencia se hace
hincapi en la palabra
cpsula porque de ella se
deriva la palabra
encapsulacin.
Observe que la figura de la
izquierda lleva un signo de
interrogacin. Esto se debe
a que no existe ningn
elemento individual e
independiente que
represente la cuenta
bancaria.

Programacin procedural
Los programas procedurales tradicionales, escritos en lenguajes como C,
contienen fundamentalmente una gran cantidad de datos y muchas funciones, y
cada funcin puede acceder a todos los datos. Este mtodo con un nivel tan alto
de asociacin puede funcionar bien en un programa pequeo, pero se hace cada
vez menos conveniente a medida que crece el programa. Un cambio en la
representacin de los datos puede resultar catico, ya que har que fallen todas
las funciones que usan los datos modificados (y que por tanto dependen de
ellos). Los cambios son ms complicados a medida que el programa se hace
ms grande y, por tanto, ms frgil y menos estable. La separacin de datos y
funciones no se mantiene al cambiar la escala del programa. Esto dificulta los
cambios y, como saben todos los desarrolladores de software, el cambio es la
nica constante.
La separacin de datos y funciones plantea otro serio problema. En trminos de
abstraccin de comportamientos a alto nivel, esta tcnica no corresponde a la
forma de pensar de los humanos. Puesto que los programas estn escritos por
personas, es mucho mejor utilizar un modelo de programacin que se aproxime
a la forma en que las personas piensan y no a la forma en que estn fabricados
los sistemas informticos.

Fundamentos de la programacin orientada a objetos

14

Programacin orientada a objetos


La programacin orientada a objetos surgi para resolver estos problemas en la
medida de lo posible. Si se entiende y se utiliza debidamente, la programacin
orientada a objetos puede llegar a ser realmente una programacin orientada a
personas, puesto que los humanos tendemos de forma natural a pensar y
trabajar en trminos del comportamiento de objetos a alto nivel.
El paso primero y ms importante para pasar de la programacin procedural a la
programacin orientada a objetos consiste en combinar los datos y las funciones
en una sola entidad.

Fundamentos de la programacin orientada a objetos

15

Control de la visibilidad de acceso


Objetivo del tema

Explicar cmo se puede


llevar a la prctica la
encapsulacin.

Explicacin previa

Despus de decidir qu
partes van a quedar ocultas
del mundo exterior, cmo
podemos asegurarnos de
que nadie podr ver cmo
funcionan las clases?

Los mtodos son pblicos, accesibles desde el exterior

Los datos son privados, accesibles slo desde el interior

Retirar( )
saldo
Ingresar( )
CuentaBancaria ?

Recomendacin al
profesor

Esta transparencia explica


el segundo aspecto de la
encapsulacin.
Observe que la figura de la
izquierda lleva un signo de
interrogacin. Esto se debe
a que en la vida real uno no
tiene acceso directo a su
saldo bancario. La figura de
la derecha modifica la
frontera de forma que el
saldo queda en la parte
interior. Como esto
corresponde a las cuentas
bancarias reales, no se ha
utilizado signo de
interrogacin.

Retirar( )

saldo
Ingresar( )

CuentaBancaria ?

En la figura de la izquierda, Retirar, Ingresar y saldo han sido agrupadas


dentro de una cpsula. La transparencia sugiere que el nombre de la cpsula
es CuentaBancaria. Sin embargo, hay algo que no funciona en este modelo de
cuenta bancaria: el dato saldo es accesible (si en la realidad se pudiera acceder
directamente al saldo de una cuenta bancaria, sera posible aumentarlo sin hacer
ningn ingreso). Las cuentas bancarias no funcionan de este modo, lo que
quiere decir que hay una mala correspondencia entre el problema y su modelo.
La encapsulacin permite resolver este problema. Una vez se han combinado
datos y funciones en una sola entidad, sta forma una frontera cerrada que crea
de forma natural un espacio interior y otro exterior. Esta frontera se puede
utilizar para controlar de forma selectiva la accesibilidad de las entidades:
algunas sern accesibles desde el interior y el exterior, mientras que a otras slo
ser posible acceder desde el interior. Los miembros que son siempre accesibles
se denominan pblicos, mientras que aquellos a los que slo se puede acceder
desde el interior son privados.
Para que el modelo de una cuenta bancaria se aproxime ms a la realidad, se
puede hacer que saldo sea privado y que los mtodos Retirar e Ingresar sean
pblicos. De esta forma, la nica manera de aumentar el saldo desde el exterior
es ingresar dinero en la cuenta. Como se ve, Ingresar est en el interior y por
tanto puede acceder a saldo.

Fundamentos de la programacin orientada a objetos

16

Como muchos otros lenguajes de programacin orientados a objetos, C# da


completa libertad a la hora de elegir qu miembros deben ser accesibles. Es
posible crear datos pblicos siempre que se desee. No obstante, se recomienda
marcar los datos siempre como privados (esta recomendacin se convierte en
obligatoria en algunos lenguajes de programacin).
Los tipos cuya representacin de datos es completamente privada se llaman
tipos de datos abstractos (ADT). Son abstractos en el sentido de que no es
posible acceder a la representacin de datos privada (ni depender de ella); slo
se pueden usar los mtodos de comportamiento.
En cierto modo, los tipos predefinidos como int tambin son ADT. Para sumar
dos variables enteras no es necesario conocer la representacin binaria interna
de cada valor entero; tan slo hay que saber el nombre del mtodo que hace
sumas: el operador de suma (+).
Cuando se forman miembros accesibles (pblicos), es posible crear distintas
vistas de una misma entidad. La vista desde el exterior es un subconjunto de la
vista desde el interior. Una vista restringida est muy prxima a la idea de
abstraccin: desnudar la idea para quedarse con lo esencial.
La decisin de si algo debe quedar dentro o fuera implica una gran cantidad de
diseo. Cuantas ms caractersticas queden en el interior (y se puedan seguir
utilizando), tanto mejor.

Fundamentos de la programacin orientada a objetos

17

Por qu se encapsula?
Objetivo del tema

Explicar cmo se puede


usar la encapsulacin para
que las aplicaciones sean
ms fciles de modificar y
mantener.

Explicacin previa

Con qu frecuencia
cambian los detalles
internos de una clase? Es
posible cambiar la forma de
almacenamiento o
procesamiento de la
informacin?

Retirar( )

Porque permite el control


El objeto se usa slo
con los mtodos
pblicos

Ingresar( )

Porque permite el cambio


z

El uso del objeto no


vara si cambia el tipo
de los datos privados

saldo 12,56

Retirar( )
Ingresar( )
euros 12
cntimos

Recomendacin al
profesor

Esta transparencia presenta


el concepto de cambio y los
principios fundamentales de
la programacin orientada a
objetos. No es posible evitar
los cambios; lo ms que se
puede hacer es trabajar con
un lenguaje y un proceso de
diseo que minimice sus
efectos.
Observe que el saldo es de
12,56 en los dos ejemplos
de la transparencia (en
distintas representaciones).

56

Hay dos razones para encapsular:


Controlar el uso.
Minimizar los efectos del cambio.

La encapsulacin permite el control


Controlar el uso es el primer motivo para encapsular. Cuando conducimos un
coche pensamos nicamente en el acto de conducir, no en los aspectos internos
del coche. Si retiramos dinero de una cuenta, no nos planteamos cmo estar
representada. La encapsulacin y los mtodos de comportamiento sirven para
disear objetos de software que funcionan slo como queremos que lo hagan.

La encapsulacin permite el cambio


La segunda razn para encapsular es una consecuencia de la primera. Si el
mecanismo de creacin de un objeto es privado, es posible modificarlo de
forma que los cambios no afecten directamente a los usuarios del objeto (que
slo pueden acceder a los mtodos pblicos). Esto puede ser extremadamente
til en la prctica, ya que los nombres de los mtodos se suelen fijar mucho
antes de su realizacin.
La capacidad de realizar cambios internos est muy relacionada con la
abstraccin. Dados dos diseos para una misma clase, por regla general hay que
elegir el que tenga menos mtodos pblicos.
En otras palabras: Si se puede elegir entre hacer un mtodo pblico o privado,
lo mejor es hacerlo privado. Un mtodo privado se puede cambiar libremente y
ms tarde, tal vez, convertirlo en un mtodo pblico. Por el contrario, no es
posible convertir un mtodo pblico en privado sin romper el cdigo cliente.

Fundamentos de la programacin orientada a objetos

18

Datos de objetos
Objetivo del tema

Discutir aspectos
relacionados con datos de
objetos privados.

Explicacin previa

Es necesario que objetos


de la misma clase
compartan sus datos?
Normalmente no lo hacen.

Los datos de objetos describen informacin para


objetos concretos
z

Por ejemplo, cada cuenta bancaria tiene su propio saldo.


Si dos cuentas tienen el mismo saldo, ser slo una
coincidencia .

Retirar( )

Retirar( )

Ingresar( )

Ingresar( )

saldo 12,56

saldo

12,56

prop. Juan"

prop.

Pedro"

La mayor parte de los datos dentro de un objeto describen informacin sobre


ese objeto concreto. Por ejemplo, cada cuenta bancaria tiene su propio saldo.
Por supuesto, es perfectamente posible que haya muchas cuentas bancarias con
el mismo saldo, pero eso ser slo una coincidencia.
Un dato de un objeto es privado y slo los mtodos del objeto pueden acceder a
l. Esta encapsulacin y separacin significa que, en la prctica, un objeto es
una entidad autnoma.

Fundamentos de la programacin orientada a objetos

19

Uso de datos estticos


Objetivo del tema

Explicar cmo los objetos


pueden compartir datos
privados.

Explicacin previa

Ocasionalmente es
necesario que objetos de la
misma clase compartan
datos.

Los datos estticos describen informacin para todos los


objetos de una clase
z

Por ejemplo, supongamos que todas las cuentas


comparten el mismo inters. No sera conveniente
almacenar el inters en todas las cuentas. Por qu?
Retirar( )

Retirar( )

Ingresar( )

Ingresar( )

saldo 12,56
inters 7%

saldo

99,12

inters 7%

Hay veces en que no tiene sentido almacenar informacin dentro de cada


objeto. Si todas las cuentas bancarias comparten siempre el mismo inters, por
ejemplo, almacenar el inters dentro de cada objeto cuenta no sera conveniente
por los siguientes motivos:
Recomendacin al
profesor

El inters se muestra en la
transparencia como dato de
objeto. La "X" roja indica
que no es una buena idea.
El segundo ejercicio de la
prctica pide a los
estudiantes que creen datos
y mtodos estticos.

Es una forma poco eficaz de resolver el problema tal como est planteado:
Todas las cuentas bancarias comparten el mismo inters.
Aumenta innecesariamente el tamao de cada objeto, utilizando ms
memoria cuando se ejecuta el programa y ms espacio en disco cada vez
que se guarda.
Hace difcil cambiar el inters, ya que habra que modificarlo en todos y
cada uno de los objetos cuenta y eso podra hacer imposible acceder a las
cuentas durante el cambio.
Aumenta el tamao de la clase. El dato privado de inters necesitara
mtodos pblicos, por lo que la clase cuenta se hara menos compacta y no
funcionara todo lo bien que debiera.
Para resolver este problema no se debe compartir a nivel de objeto informacin
que sea comn a varios objetos. En lugar de describir el inters muchas veces a
nivel de objeto, es mucho mejor describirlo una sola vez a nivel de clase. El
inters definido a nivel de clase se convierte en la prctica en un dato global.
Pero los datos globales, por definicin, no se almacenan dentro de una clase, y
por lo tanto no pueden ser encapsulados. A causa de esto, muchos lenguajes de
programacin orientados a objetos (incluyendo C#) no permiten los datos
globales. En su lugar permiten describir datos como estticos.

Fundamentos de la programacin orientada a objetos

20

Declaracin de datos estticos


Un dato esttico (static) se define fsicamente dentro de una clase (que es una
entidad esttica de tiempo de compilacin) y se beneficia de la encapsulacin
de sta, pero lgicamente est asociado a la clase y no a un objeto concreto. En
otras palabras, un dato esttico se declara dentro de una clase por conveniencia
sintctica y existe aunque el programa nunca cree objetos de esa clase.

Fundamentos de la programacin orientada a objetos

21

Uso de mtodos estticos


Objetivo del tema

Describir los mtodos


estticos.

Explicacin previa

Si el inters pertenece a la
clase cuenta en lugar de a
un objeto cuenta concreto, y
si se utiliza encapsulacin
para ocultar la
representacin interna del
inters, cmo se puede
acceder al inters o
modificarlo?

Los mtodos estticos acceden slo a datos estticos


z

Un mtodo esttico se llama en la clase, no el objeto

La clase cuenta
Inters( )

9
inters 7%
Las clases contienen datos
y mtodos estticos

Un objeto cuenta

8
8

Retirar( )
Ingresar( )
saldo

99,12

prop.

Pedro"

Los objetos contienen datos


y mtodos de objetos

Para encapsular datos estticos se pueden utilizar mtodos estticos. En el


ejemplo de la transparencia, el inters pertenece a la clase cuenta y no a un
objeto cuenta concreto. Por lo tanto, tiene sentido que a nivel de clase haya
mtodos que se puedan emplear para acceder al inters o modificarlo.
Es posible declarar mtodos como estticos de la misma forma que se declara
un dato esttico. Los mtodos estticos existen a nivel de clase. La accesibilidad
de mtodos y datos estticos se puede controlar con modificadores como public
(pblico) y private (privado). Mtodos estticos pblicos con datos estticos
privados permiten encapsular datos estticos del mismo modo que se
encapsulan datos de objetos.
Un mtodo esttico existe a nivel de clase y las llamadas a ese mtodo se hacen
con referencia a la clase, no a un objeto. Esto significa que un mtodo esttico
no puede utilizar el operador this, que implcitamente apunta al objeto que hace
una llamada a un mtodo de objeto. En otras palabras, un mtodo esttico no
puede acceder a datos o mtodos que no sean estticos. Los nicos miembros de
una clase a los que puede acceder un mtodo esttico son datos estticos y otros
mtodos estticos.

Fundamentos de la programacin orientada a objetos

22

Los mtodos estticos siguen teniendo acceso a todos los miembros privados de
una clase y pueden acceder a datos privados no estticos por medio de una
referencia a objeto. El siguiente cdigo muestra un ejemplo:
class Reloj
{
...
public static void Reset(Reloj t)
{
t.hora = 0;
// Okay
t.minuto = 0; // Okay
hora = 0;
// error al compilar
minuto = 0;
// error al compilar
}
private int hora, minuto;
}

Fundamentos de la programacin orientada a objetos

23

El lenguaje C# y la orientacin a objetos


Objetivo del tema

Ofrecer una introduccin a


los temas tratados en esta
seccin.

Explicacin previa

Ahora que hemos visto


parte de la teora que hay
detrs de la orientacin a
objetos, vamos a ver cmo
se utiliza en C#.

Hola, mundo de nuevo

Definicin de clases simples

Instancias de nuevos objetos

Uso del operador this

En esta seccin volveremos a examinar el programa Hola, mundo original y


explicaremos su estructura desde una perspectiva orientada a objetos.
Al final de esta leccin, usted ser capaz de:
Usar los mecanismos que hacen que un objeto pueda crear otro en C#.
Definir clases anidadas.

Fundamentos de la programacin orientada a objetos

24

Hola, mundo de nuevo


Objetivo del tema

Explicar cmo se invoca


Main cuando se ejecuta una
aplicacin.

Explicacin previa

Un programa C# es una
clase que tiene un mtodo
esttico llamado Main. Por
qu?

using
using System;
System;
class
class Hello
Hello
{{
public
public static
static int
int Main(
Main( ))
{{
Console.WriteLine(Hello,
Console.WriteLine(Hello, World);
World);
return
return 0;
0;
}}
}}

La transparencia muestra el cdigo para Hola, mundo. Podemos hacer y


contestar varias preguntas:
Cmo invoca una clase el runtime?
Por qu Main es esttico?

Cmo invoca una clase el runtime?


Si slo hay un mtodo Main, el compilador lo interpretar automticamente
como el punto de entrada al programa. El siguiente cdigo muestra un ejemplo:
// UnaEntrada.cs
class UnaEntrada
{
static void Main( )
{
...
}
}
// fin del archivo
c:\> csc UnaEntrada.cs

Aviso El punto de entrada a un programa C# debe ser Main con una M


mayscula. La signatura de Main tambin es importante.

Fundamentos de la programacin orientada a objetos

25

Si, por el contrario, existen varios mtodos llamados Main, es necesario que
uno de ellos est designado explcitamente como punto de entrada al programa
(y que ese Main tambin sea pblico explcitamente). El siguiente cdigo
muestra un ejemplo:
// DosEntradas.cs
using System;
class EntradaUno
{
public static void Main( )
{
Console.Write("EntradaUno.Main( )");
}
}
class EntradaDos
{
public static void Main( )
{
Console.Write("EntradaDos.Main( )");
}
}
// Fin del archivo
c:\> csc /main:EntradaUno DosEntradas.cs
c:\> dosentradas.exe
EntradaUno.Main( )
c:\> csc /main:EntradaDos DosEntradas.cs
c:\> dosentradas.exe
EntradaDos.Main( )
c:\>

La opcin de lnea de comandos distingue maysculas y minsculas. Si el


nombre de la clase que contiene Main es EntradaUno (con E y O maysculas),
el siguiente comando no funcionar:
c:\> csc /main:entradauno DosEntradas.cs

Fundamentos de la programacin orientada a objetos

26

No se puede crear un programa ejecutable si el proyecto no contiene ningn


mtodo Main. Sin embargo, es posible crear una biblioteca de vnculos
dinmicos (DLL) de la siguiente manera:
// SinEntrada.cs
using System;
class SinEntrada
{
public static void NoMain( )
{
Console.Write("SinEntrada.NoMain( )");
}
}
// Fin del archivo
c:\> csc /target:library SinEntrada.cs
c:\> dir
...
SinEntrada.dll
...

Por qu Main es esttico?


El hecho de que Main sea esttico hace que sea posible invocarlo sin que el
runtime tenga que crear una instancia de la clase.
Las llamadas a mtodos no estticos slo pueden estar en un objeto, como se ve
en el siguiente cdigo:
class Ejemplo
{
void NonStatic( ) { ... }
static void Main( )
{
Ejemplo eg = new Example( );
eg.NonStatic( ); // Compila
NonStatic( );
// error al compilar
}
...
}

Esto significa que si Main no es esttico, como en el siguiente cdigo, el


runtime necesita crear un objeto para hacer una llamada a Main.
class Ejemplo
{
void Main( )
{
...
}

}
En otras palabras, en la prctica el runtime tendra que ejecutar el siguiente
cdigo:
Ejemplo ejecuta = new Example( );
ejecuta.Main( );

Fundamentos de la programacin orientada a objetos

27

Definicin de clases simples


Objetivo del tema

Describir la sintaxis bsica


para la definicin de clases.

Explicacin previa

Ya sabemos qu son las


clases. Ahora tenemos que
saber cmo se definen.

Datos y mtodos juntos dentro de una clase

Los mtodos son pblicos, los datos son privados

class
class BankAccount
BankAccount
Mtodos
Mtodos pblicos
pblicos
{{
describen
describen un
un
public
void
Withdraw(decimal
cantidad)
public void Withdraw(decimal cantidad) comportamiento
comportamiento
{{ ...
accesible
accesible
... }}
public
public void
void Deposit(decimal
Deposit(decimal cantidad)
cantidad)
Campos
{{ ...
Campos privados
privados
... }}
describen
describen un
un
private
decimal
balance;
private decimal balance;
estado
estado
private
string
name;
private string name;
inaccesible
inaccesible
}}

A pesar de ser distintas semnticamente, las clases y estructuras tienen algunos


parecidos sintcticos. Para definir una clase en vez de una estructura:
Se usa la palabra reservada class en lugar de struct.
Los datos se declaran dentro de la clase exactamente igual que para una
estructura.
Los mtodos se declaran dentro de la clase.
Se aaden modificadores de acceso a las declaraciones de los datos y
mtodos. Los dos modificadores de acceso ms sencillos son public y
private (los otros tres se discutirn ms adelante en este curso).
Nota El uso de public y private para forzar la encapsulacin es
responsabilidad del programador. C# no impide la creacin de datos pblicos.
El significado de public es acceso sin limitaciones, mientras que private
quiere decir acceso limitado al tipo que lo contiene. El siguiente ejemplo
aclara este punto:
class CuentaBancaria
{
public void Ingresar(decimal cantidad)
{
saldo += cantidad;
}
private decimal saldo;
}

Fundamentos de la programacin orientada a objetos

28

En este ejemplo, el mtodo Ingresar puede acceder al saldo privado porque


Ingresar es un mtodo de CuentaBancaria (el tipo que contiene saldo). En
otras palabras, Ingresar est en la parte de dentro. Desde el exterior nunca es
posible acceder a miembros privados. En el siguiente ejemplo no se compilar
la expresin cuentaAtacada.saldo.
class LadronDeBancos
{
public void RobarDe(CuentaBancaria cuentaAtacada)
{
cuentaAtacada.saldo -= 999999M;
}
}

La expresin cuentaAtacada.saldo no se compilar porque est dentro del


mtodo RobarDe de la clase LadronDeBancos. Slo los mtodos de la clase
CuentaBancaria pueden acceder a miembros privados de objetos de
CuentaBancaria.
Para declarar datos estticos se sigue el mismo patrn que para mtodos
estticos (como Main), poniendo la palabra reservada static antes de la
declaracin del campo. El siguiente cdigo muestra un ejemplo:
class CuentaBancaria
{
public void Ingresar(decimal cantidad) { ... }
public static void Main( ) { ... }
...
private decimal saldo;
private static decimal inters;
}

Fundamentos de la programacin orientada a objetos

29

Un miembro de una clase para el que no especifique ningn modificador de


acceso ser privado por defecto. En otras palabras, los dos mtodos siguientes
son idnticos semnticamente:
class CuentaBancaria
{
...
decimal saldo;
}
class CuentaBancaria
{
...
private decimal saldo;
}

Consejos Aunque no sea estrictamente necesario, se considera una buena


prctica de programacin escribir private explcitamente.
El orden en que se declaran los miembros de una clase no tiene importancia
para el compilador de C#. Sin embargo, se considera una buena prctica de
programacin declarar los miembros pblicos (mtodos) antes que los privados
(datos). Esto se debe a que el usuario de una clase slo tiene acceso a los
miembros pblicos, por lo que declarar estos antes que los privados refleja esa
prioridad.

Fundamentos de la programacin orientada a objetos

30

Instancias de nuevos objetos


Objetivo del tema

Presentar el operador new.

Explicacin previa

Antes de crear un objeto, es


preciso crear una instancia
de l.

Al declarar una variable de clase no se crea un objeto


z

Para crear un objeto se usa el operador new

class
class Program
Program
ahora hora
{{
minuto
static
static void
void Main(
Main( ))
nuevo
suya
{{
... objeto
... CuentaBancaria
Reloj
Reloj ahora;
ahora;
ahora.hora
ahora.hora == 11;
11;
Cuenta
Cuenta Bancaria
Bancaria suya
suya == new
new CuentaBancaria(
CuentaBancaria( );
);
suya.Ingresar(999999M);
suya.Ingresar(999999M);
}}
}}

Consideremos los siguientes cdigos de ejemplo:

Recomendacin al
profesor

El primer ejercicio de la
prctica hace hincapi en la
diferencia entre estructuras
y clases y utiliza el operador
new para crear objetos.

struct Reloj
{
public int hora, minuto;
}
class Programa
{
static void Main( )
{
Reloj ahora;
ahora.hora = 11;
ahora.minuto = 59;
...
}
}

Las variables del tipo struct son tipos de valor. Esto quiere decir que, cuando se
declara una variable de estructura (como ahora en Main), se crea un valor en la
pila. En este caso, la estructura Reloj contiene dos ints, por lo que la declaracin
de ahora crea dos ints en la pila, una llamada ahora.hora y otra ahora.minuto.
Estos dos ints NO se inicializan a cero por defecto. Por eso no es posible leer el
valor de ahora.hora ni de ahora.minuto hasta que se les asigna un valor. Los
valores slo tienen validez en el bloque en el que se declaran. En este ejemplo,
el mbito de ahora es Main. Esto significa que cuando el flujo de control
abandona Main (por un return normal o porque se ha lanzado una excepcin),
ahora quedar fuera de mbito y dejar de existir.

Fundamentos de la programacin orientada a objetos

31

Las clases son totalmente distintas, como muestra el siguiente cdigo:


class Reloj // NOTA: Reloj es ahora una clase
{
public int hora, minuto;
}
class Programa
{
static void Main( )
{
Reloj ahora;
ahora.hora = 11;
ahora.minuto = 59;
...
}
}

Cuando se declara una variable de clase, no se crea una instancia u objeto de


esa clase. En este caso, la declaracin de ahora no crea un objeto de la clase
Reloj. Al declarar una variable de clase se crea una referencia que puede
apuntar a un objeto de esa clase. Por esta razn las clases se llaman tipos de
referencia. Esto significa que, si el runtime ejecutara el cdigo anterior,
intentara acceder a los enteros dentro de un objeto Reloj que no existe.
Afortunadamente, el compilador avisara de este error con el siguiente mensaje:
error CS0165: Uso de variable local no asignada 'ahora'

Para corregir este error es necesario crear un objeto Reloj (usando la palabra
reservada new) y hacer que la variable de referencia ahora apunte al objeto
recin creado, como en el siguiente cdigo:
class Programa
{
static void Main( )
{
Reloj ahora = new Reloj( );
ahora.hora = 11;
ahora.minuto = 59;
...
}
}

Fundamentos de la programacin orientada a objetos

32

Recordemos que, cuando se crea un valor de estructura local en la pila, los


campos NO se inicializan a cero por defecto. Las clases son diferentes: cuando
se crea un objeto como una instancia de una clase, como anteriormente, los
campos del objeto se inicializan a cero por defecto. El siguiente cdigo se
compilar sin errores:
class Programa
{
static void Main( )
{
Reloj ahora = new Reloj( );
Console.WriteLine(ahora.hora);
// escribe 0
Console.WriteLine(ahora.minuto); // escribe 0
...
}
}

Fundamentos de la programacin orientada a objetos

33

Uso de la palabra reservada this


Objetivo del tema

Describir el operador this.

Explicacin previa

Los mtodos dentro de una


clase tienen que poder
apuntar a la instancia actual
de la clase.

La palabra reservada this apunta al objeto usado para la


llamada al mtodo
z

Es til en caso de conflicto entre identificadores de


distintos mbitos

class
class CuentaBancaria
CuentaBancaria
{{
...
...
public
public void
void PoneNombre(string
PoneNombre(string nombre)
nombre)
Si esta instruccin fuera
{{
nombre = nombre;
this.nombre
this.nombre == nombre;
nombre;
qu ocurrira?
}}
private
private string
string nombre;
nombre;
}}

La palabra reservada this apunta implcitamente al objeto que est haciendo una
llamada a un mtodo de objeto.
En el siguiente cdigo, la instruccin nombre = nombre no tendra ningn
efecto, ya que el identificador nombre en el lado izquierdo de la asignacin no
se corresponde al campo privado de CuentaBancaria llamado nombre. Los dos
identificadores se refieren al parmetro del mtodo, que tambin se llama
nombre.
class CuentaBancaria
{
public void PoneNombre(string nombre)
{
nombre = nombre;
}
private string nombre;
}

Aviso El compilador de C# no emite un aviso para alertar de este error.

Uso de la palabra reservada this


Este problema de referencia se puede resolver con la palabra reservada this,
como se ve en la transparencia. La palabra reservada this apunta al objeto
actual para el que se hace la llamada al mtodo.
Nota Los mtodos estticos no pueden usar this, puesto que no se les llama
empleando un objeto.

Fundamentos de la programacin orientada a objetos

34

Cambio del nombre del parmetro


Tambin es posible resolver el problema de referencia cambiando el nombre del
parmetro, como en el siguiente ejemplo:
class CuentaBancaria
{
public void PoneNombre(string nuevoNombre)
{
nombre = nuevoNombre;
}
private string nombre;
}

Consejo En C# es muy habitual usar this para escribir constructores. El


siguiente cdigo muestra un ejemplo:
struct Reloj
{
public Reloj(int hora, int minuto)
{
this.hora = hora;
this.minuto = minuto;
}
private int hora, minuto;
}

Fundamentos de la programacin orientada a objetos

35

Consejo La palabra clave this se usa tambin para encadenar llamadas. En la


siguiente clase, los dos mtodos devuelven el objeto que ha hecho la llamada:
class Libro
{
public Libro PoneAutor(string autor)
{
this.autor = autor;
return this;
}
public Libro PoneTitulo(string titulo)
{
this.titulo = titulo;
return this;
}
private string autor, titulo;
}

La devolucin de this permite encadenar llamadas a mtodos, como se muestra


a continuacin:
class Uso
{
static void Cadena(Libro bueno)
{
bueno.PoneAutor(" Fowler").PoneTitulo(" Refactoring");
}
static void NoCadena(Libro bueno)
{
bueno.PoneAutor("Fowler");
bueno.PoneTitulo (" Refactoring");
}
}

Nota Un mtodo esttico existe a nivel de clase y las llamadas a l se hacen en


referencia a la clase y no a un objeto. Esto significa que un mtodo esttico no
puede usar el operador this.

Fundamentos de la programacin orientada a objetos

36

Definicin de sistemas orientados a objetos


Objetivo del tema

Ofrecer una introduccin a


los temas tratados en esta
seccin.

Explicacin previa

En esta leccin discutiremos


los conceptos de herencia y
polimorfismo.

Herencia

Jerarquas de clases

Herencia sencilla y mltiple

Polimorfismo

Clases base abstractas

Interfaces

En esta leccin discutiremos los conceptos de herencia y polimorfismo. En


mdulos posteriores estudiaremos cmo se utilizan en C# estos conceptos.

Fundamentos de la programacin orientada a objetos

37

Herencia
Objetivo del tema

Explicar el concepto de
herencia.

Explicacin previa

La herencia permite definir


nuevas clases a partir de
otras ya existentes.

Recomendacin al
profesor

La transparencia incluye
una figura de un hombre,
una mujer y una nia
pequea en un triciclo.
Utilice esta figura como
ejemplo de cmo no usar la
herencia, tal como se
explica en las notas.

La herencia indica una relacin es un tipo de"


z

La herencia es una relacin entre clases

Las nuevas clases aaden especializacin a las existentes

Generalizacin

Msico
Msico

Especializacin

Violinista
Violinista

Clase base

Clase derivada

Es ste un buen
ejemplo de
herencia ?

La herencia es una relacin especificada a nivel de clase para reflejar el hecho


de que una clase nueva puede derivar de otra ya existente. En la transparencia,
la clase Violinista deriva de la clase Msico. La clase Msico se denomina
clase base (o, con menos frecuencia, la clase padre o superclase), mientras que
la clase Violinista recibe el nombre de clase derivada (o tambin la clase hija o
subclase). La herencia se indica en notacin de lenguaje unificado de modelado
(UML). En transparencias posteriores veremos ms notacin UML.
La herencia es una relacin muy poderosa, ya que una clase derivada lo hereda
todo de su clase base. Por ejemplo, si la clase base Msico contiene un mtodo
llamado AfinaTuInstrumento, este mtodo se convierte automticamente en
miembro de la clase derivada Violinista.
Una clase base puede tener un nmero arbitrario de clases derivadas. Por
ejemplo, de la clase Msico podran derivar otras clases nuevas (como
Flautista o Pianista) que tambin heredaran automticamente el mtodo
AfinaTuInstrumento de la clase base Msico.
Nota Un cambio en la clase base se convierte automticamente en un cambio
para todas las clases derivadas. Por ejemplo, si se aadiera un campo o tipo
IntrumentoMusical a la clase base Msico, todas las clases derivadas
(Violinista, Flautista, Pianista, etc.) adquiriran automticamente un campo o
tipo IntrumentoMusical. Un error que aparezca en una clase base se extiende
automticamente a todas las clases derivadas (lo que se conoce como problema
de clase base frgil).

Fundamentos de la programacin orientada a objetos

38

La herencia en la programacin orientada a objetos


La figura de la transparencia muestra a un hombre, una mujer y una nia
pequea montada en un triciclo. Si el hombre y la mujer son los padres
biolgicos de la nia, sta heredar la mitad de sus genes del hombre y la otra
mitad de la mujer.
Sin embargo, ste no es un buen ejemplo de herencia de clase. Las clases en
este caso son Hombre y Mujer. Hay dos representantes de la clase Mujer (uno
de ellas con el atributo edad menor que 16) y uno de la clase Hombre, pero no
hay herencia de clase. La nica posibilidad de que en este ejemplo hubiera
herencia de clase pasara por considerar que las clases Hombre y Mujer
comparten una clase base Persona.

Fundamentos de la programacin orientada a objetos

39

Jerarquas de clases
Objetivo del tema

Explicar las jerarquas de


clases.

Explicacin previa

Las clases que derivan de


clases base pueden a su
vez convertirse en clases
base para otras clases.

Las clases con relaciones de herencia forman


jerarquas de clases
Msico
Msico

Msico
Msico de
de
cuerda
cuerda

???
???

Violinista
Violinista

toca

Instrumento
Instrumento
musical
musical

toca

Instrumento
Instrumento de
de
cuerda
cuerda

toca

Violn
Violn

???
???

Las clases que derivan de clases base pueden a su vez convertirse en clases base
para otras clases. En la transparencia, por ejemplo, la clase MsicoDeCuerda
deriva de la clase Msico, pero a su vez en una clase base para la clase derivada
Violinista. Un grupo de clases con relaciones de herencia forma una estructura
conocida como jerarqua de clases. Estas clases representan conceptos ms
generales (generalizacin) a medida que ascendemos en la jerarqua, y ms
especializados (especializacin) a medida que nos movemos hacia abajo.
La profundidad de una jerarqua de clases es el nmero de niveles de herencia
que hay en la jerarqua. Las jerarquas de clases ms profundas son ms
difciles de usar que las jerarquas de clases poco profundas. La mayor parte de
las normas de programacin recomiendan limitar la profundidad a entre cinco y
siete clases.
La transparencia muestra dos jerarquas de clases paralelas, una para msicos y
otra para instrumentos musicales. Crear jerarquas de clases no es fcil, ya que
las clases se tienen que disear como clases base desde el principio. Las
jerarquas de herencia son tambin la caracterstica principal de los marcos de
trabajo o frameworks, que son modelos ampliables sobre los que se crean
entidades ms complejas.

Fundamentos de la programacin orientada a objetos

40

Herencia sencilla y mltiple


Objetivo del tema

Comparar la herencia
sencilla y la herencia
mltiple.

Explicacin previa

En teora, el
comportamiento de una
clase puede derivar de ms
de un antecesor.

Herencia sencilla: derivadas de una clase base

Herencia mltiple: derivadas de dos o ms clases base


Instrumento
Instrumento de
de
cuerda
cuerda

Instrumento
Instrumento
musical
musical

Con
Con teclas
teclas

Violn
Violn

Instrumento
Instrumento de
de
cuerda
cuerda

Violn tiene una sola


clase base directa

Instrumento de cuerda tiene


dos clases base directas

La herencia se denomina sencilla cuando una clase tiene una sola clase base
directa. En el ejemplo de la transparencia, la clase Violn hereda de una clase,
InstrumentoDeCuerda, y es un ejemplo de herencia sencilla.
InstrumentoDeCuerda deriva de dos clases, pero esto no afecta a la clase
Violn. La herencia sencilla tambin puede ser difcil de utilizar. Es bien
conocido que la herencia es una de las herramientas ms potentes de modelado
de software, pero al mismo tiempo una de las peor entendidas y empleadas.
Recomendacin al
profesor

Puede utilizar un acorden


como ejemplo de herencia
mltiple.

La herencia se denomina mltiple una clase tiene dos o ms clases base


directas. En el ejemplo de la transparencia, la clase InstrumentoDeCuerda
deriva directamente de dos clases, InstrumentoMusical y ConTeclas, y
proporciona un ejemplo de herencia mltiple. La herencia mltiple se utiliza
mal en un gran porcentaje de casos. C#, como la mayor parte de los lenguajes
de programacin modernos (excluido C++), limita el uso de la herencia
mltiple: est permitida la herencia de un nmero ilimitado de interfaces, pero
slo se puede heredar de una no interfaz (es decir, una clase abstracto o
concreta como mucho). Los trminos interfaz, clase abstracta y clase concreta
se discutirn ms adelante en este mdulo.
Todas las formas de herencia, pero especialmente la herencia mltiple, ofrecen
muchas vistas del mismo objeto. Por ejemplo, un objeto Violn se podra usar a
nivel de la clase Violn, pero tambin a nivel de la clase InstrumentoMusical.

Fundamentos de la programacin orientada a objetos

41

Polimorfismo
Objetivo del tema

Explicar el concepto de
polimorfismo.

Explicacin previa

A veces puede ser


necesario utilizar un mtodo
de diferentes maneras en
distintas clases hijas.

El nombre del mtodo reside en la clase base

Los distintos cuerpos del mtodo residen en


las clases derivadas
Msico
Msico de
de cuerda
cuerda
AfinaTuInstrumento(
AfinaTuInstrumento( ))

Un
Un mtodo
mtodo sin
sin
cuerpo
cuerpo se
se llama
llama
operacin
operacin

Guitarrista
Guitarrista

Violinista
Violinista

AfinaTuInstrumento(
AfinaTuInstrumento( ))

AfinaTuInstrumento(
AfinaTuInstrumento( ))

Polimorfismo significa literalmente muchas formas. Es el concepto segn el


cual un mtodo declarado en una clase base se puede utilizar de muchas formas
diferentes en las distintas clases derivadas.
Supongamos que todos los msicos de una orquesta estn afinando sus
instrumentos antes de un concierto. Sin polimorfismo, el director tiene que ir de
msico en msico para ver qu tipo de instrumento toca y darle instrucciones
sobre cmo afinarlo. Con polimorfismo, el director slo tiene que decirle a cada
msico afina tu instrumento. El instrumento que toque cada msico le es
indiferente; slo necesita saber que todos ellos respondern con el
comportamiento solicitado y de una forma adecuada al instrumento que tocan.
De esta forma el director no tiene la responsabilidad de saber cmo se afinan
todos los distintos tipos de instrumentos, sino que este conocimiento se divide
entre los distintos tipos de msicos: un guitarrista sabe cmo afinar una
guitarra, un violinista sabe cmo afinar un violn, etc. De hecho, el director no
sabe cmo afinar ninguno de los instrumentos. Esta asignacin descentralizada
de responsabilidades significa tambin que se pueden aadir a la jerarqua
nuevas clases derivadas (como Tambor) sin que necesariamente se modifiquen
el resto de las clases (como el director).
Slo hay un problema. Cmo es el cuerpo del mtodo al nivel de la clase base?
Si no se sabe qu tipo de instrumento es el que toca un msico, es imposible
saber cmo afinar ese instrumento. Para hacer frente a este problema, en la
clase base slo se puede declarar el nombre del mtodo, pero no el cuerpo. Un
nombre de mtodo que no tenga cuerpo se llama operacin. Una de las formas
de denotar una operacin en UML es ponindola en cursiva, como se muestra
en la transparencia.

Fundamentos de la programacin orientada a objetos

42

Clases base abstractas


Objetivo del tema

Presentar el concepto de
clase abstracta.

Explicacin previa

Tendra sentido crear un


objeto Msico de cuerda
en tiempo de ejecucin?

Algunas clases existen slo para ser clases base


z

No tiene sentido crear instancias de estas clases

Estas clases son abstractas


Msico
Msico de
de cuerda
cuerda
{{ abstract
abstract }}

No
No se
se pueden
pueden crear
crear instancias
instancias
de
de clases
clases abstractas
abstractas
Se
Se pueden
pueden crear
crear instancias
instancias
de
de clases
clases concretas
concretas

Guitarrista
Guitarrista
concrete
concrete

Recomendacin al
profesor

El ejemplo de la
transparencia es el mismo
que el empleado en la
transparencia anterior y el
mismo que se usar en la
siguiente.

Violinista
Violinista
concrete
concrete

En una jerarqua de clases tpica, la operacin (el nombre de un mtodo) se


declara en la clase base y el cuerpo del mtodo se escribe de diferentes maneras
en las distintas clases derivadas. La clase base existe nicamente para introducir
el nombre del mtodo en la jerarqua. En particular, no es necesario que la
operacin de la clase base tenga cuerpo. Por ello es fundamental que la clase
base no se utilice como una clase normal y, lo que es ms importante, que no
sea posible crear instancias de la clase base, ya que de lo contrario se correra el
riesgo de hacer una llamada a una operacin sin cuerpo. Se necesita un
mecanismo que haga imposible la creacin de instancias de estas clases base:
marcar la clase base como abstracta.
En un diseo UML se puede marcar una clase como abstracta escribiendo su
nombre en cursiva o poniendo la palabra abstract entre llaves ({ y }). Por otra
parte, es posible poner la palabra concrete o class entre dobles parntesis
angulares (<< y >>) para denotar en UML una clase que no es abstracta y que
se puede usar para creara instancias. La transparencia ilustra esta notacin.
Todos los lenguajes de programacin orientados a objetos tienen estructuras
gramaticales para clases abstractas (incluso C++ puede usar constructores
protegidos).
A veces la creacin de una clase base abstracta es ms retrospectiva y se
combinan en una nueva clase base caractersticas comunes duplicadas en las
clases derivadas. Sin embargo, tambin en este caso es necesario marcar la
clase como abstracta, ya que su propsito no es la creacin de instancias, sino
servir nicamente de clase base.

Fundamentos de la programacin orientada a objetos

43

Interfaces
Objetivo del tema

Describir el propsito de las


interfaces.

Explicacin previa

Cmo es posible
garantizar que todos los
msicos (sea cual sea su
tipo) derivados de Msico
de cuerda saben realmente
cmo afinar o tocar sus
instrumentos?

Las interfaces contienen slo operaciones, no


implementacin
Msico
Msico
interface
interface

Msico
Msico de
de cuerda
cuerda
{{ abstract
abstract }}

Violinista
Violinista
concrete
concrete

Recomendacin al
profesor

Hay dos puntos que vale la


pena discutir en la pizarra.
El primero es la importancia
de que haya una interfaz
por encima de una clase
abstracta. El segundo se
refiere al hecho de que en
realidad hay dos especies
diferentes de clases
abstractas: La primera, que
es pblica, participa en la
jerarqua y tiene una interfaz
por encima, mientras que la
segunda, que es privada, no
tiene participacin lgica en
la jerarqua y normalmente
se utiliza slo para modificar
el cdigo y evitar
repeticiones.

Nada
Nada ms
ms que
que operaciones.
operaciones.
No
No se
se pueden
pueden crear
crear instancias
instancias
de
de una
una interfaz.
interfaz.

Puede
Puede contener
contener implementacin.
implementacin.
No
No se
se pueden
pueden crear
crear instancias
instancias de
de
una
una interfaz.
interfaz.

Implementa
Implementa las
las operaciones
operaciones heredadas.
heredadas.
Se
Se pueden
pueden crear
crear instancias
instancias de
de una
una clase
clase
concreta.
concreta.

Las clases abstractas y las interfaces se parecen en que ninguna de ellas se


puede usar para crear instancias de objetos. Sin embargo, se diferencian en que
una clase abstracta puede contener mtodos con cuerpo mientras que una
interfaz no contiene ninguno, sino slo operaciones (nombres de mtodos).
Podramos decir que una interfaz es todava ms abstracta que una clase
abstracta.
En UML se puede definir una interfaz poniendo la palabra interface entre
dobles parntesis angulares (<< y >>). Todos los lenguajes de programacin
orientados a objetos tienen estructuras gramaticales para interfaces.
Las interfaces son importantes en los programas orientados a objetos y UML
tiene una notacin y una terminologa especficas para ellas. Se dice que se
implementa una interfaz cuando se hace una derivacin desde ella; en UML,
esto se indica con una lnea discontinua llamada realizacin. Se dice que se
extiende una clase cuando se hace una derivacin desde una no interfaz (una
clase abstracta o una clase concreta); en UML, esto se indica con una lnea
continua llamada generalizacin/especializacin.
Las interfaces deben estar en lo ms alto de una jerarqua de clases. La idea es
sencilla: Si se puede programar para una interfaz (es decir, si slo se usan
aquellas caractersticas de un objeto que estn declaradas en su interfaz), el
programa pierde totalmente la dependencia de ese objeto especfico y su clase
concreta. En otras palabras, cuando se programa para una interfaz se pueden
usar indistintamente muchos objetos diferentes de muchas clases distintas. En la
programacin orientada a objetos, esta capacidad de hacer cambios sin que
causen efectos secundarios est en el origen de la mxima Programa para una
interfaz y no para un cdigo.

Fundamentos de la programacin orientada a objetos

Prctica A: Creacin y uso de clases


Objetivos
Al final de esta prctica, usted ser capaz de:
Crear clases y hacer instancias de objetos.
Usar datos y mtodos no estticos.
Usar datos y mtodos estticos.

Requisitos previos
Antes de realizar la prctica debe estar familiarizado con los siguientes temas:
Creacin de mtodos en C#
Paso de argumentos como parmetros de mtodos en C#

Ejercicio 1
Creacin y uso de una clase
En este ejercicio retomar la estructura de cuenta bancaria desarrollada a lo
largo del mdulo y la convertir en una clase. Declarar sus datos como
privados, pero incluir mtodos pblicos no estticos para acceder a los datos.
Escribir un sistema de prueba que cree un objeto cuenta y le asigne un nmero
de cuenta y un saldo indicados por el usuario. Finalmente, imprimir los datos
en la cuenta.
Cmo convertir la estructura CuentaBancaria en una clase
1. Abra el proyecto CreateAccount.sln en la carpeta Starter\CreateAccount
dentro del fichero lab07.zip.
2. Estudie el cdigo del archivo BankAccount.cs. Observe que BankAccount
(CuentaBancaria) es un tipo struct.
3. Compile y ejecute el programa. Tendr que introducir un nmero de cuenta
y un saldo inicial. Repita este proceso para crear otra cuenta.
4. Modifique BankAccount en BankAccount.cs para que sea una clase en lugar
de una estructura.
5. Compile el programa. No se compilar. Abra el archivo CreateAccount.cs y
vea la clase CreateAccount. La clase tendr este aspecto:

Fundamentos de la programacin orientada a objetos


class CreateAccount
{
...
static BankAccount NewBankAccount( )
{
BankAccount created;
...
created.accNo = number; // Error aqu
...
}
...
}

6. La asignacin a created.accNo no daba error de compilacin cuando


BankAccount era una estructura, pero no se compila ahora que es una
clase. Esto se debe a que, cuando BankAccount era una estructura, la
declaracin de la variable created creaba un valor BankAccount (en la
pila). Ahora que BankAccount es una clase, la declaracin de la variable
created no crea un valor BankAccount; sino una referencia BankAccount
que todava no apunta a un objeto BankAccount.

Fundamentos de la programacin orientada a objetos

7. Cambie la declaracin de created para que se inicialice con un objeto


BankAccount de nueva creacin, como se indica:
class CreateAccount
{
...
static BankAccount NewBankAccount( )
{
BankAccount created = new BankAccount( );
...
created.accNo = number;
...
}
...
}

8. Guarde el trabajo realizado.


9. Compile y ejecute el programa. Compruebe que los datos introducidos en la
consola se leen correctamente y se muestran en el mtodo
CreateAccount.Write.
Cmo encapsular la clase BankAccount
1. Todos los datos de la clase BankAccount son an pblicos. Modifquelos
para que sean privados, como se indica:
class BankAccount
{
private long accNo;
private decimal accBal;
private AccountType accType;
}

2. Compile el programa. No se compilar. El error se produce en la clase


CreateAccount, como se muestra a continuacin:
class CreateAccount
{
...
static BankAccount NewBankAccount( )
{
BankAccount created = new BankAccount( );
...
created.accNo = number; // Error aqu de nuevo
...
}
...
}

Fundamentos de la programacin orientada a objetos

3. Ahora las asignaciones de datos de BankAccount no se compilan porque


los datos son privados y slo los mtodos de BankAccount pueden acceder
a datos privados de BankAccount. Tiene que escribir un mtodo pblico de
BankAccount para que haga las asignaciones. Ejecute los siguientes pasos:
Aada a BankAccount un mtodo pblico no esttico llamado Populate.
Este mtodo devolver void y recibir dos parmetros: un entero largo (el
nmero de la cuenta bancaria) y un decimal (el saldo de la cuenta bancaria).
El cuerpo de este mtodo asignar el parmetro entero largo al campo
accNo y el parmetro decimal al campo accBal. Tambin dirigir el campo
accType a AccountType.Checking, como se muestra a continuacin:
class BankAccount
{
public void Populate(long number, decimal balance)
{
accNo = number;
accBal = balance;
accType = AccountType.Checking;
}
private long accNo;
private decimal accBal;
private AccountType accType;
}

4. Marque como comentarios las tres asignaciones a la variable created en el


mtodo CreateAccount.NewbankAccount y aada en su lugar una
instruccin que llame al mtodo Populate sobre la variable created,
pasando como argumentos number y balance. El cdigo ser el siguiente:
class CreateAccount
{
...
static BankAccount NewBankAccount( )
{
BankAccount created = new BankAccount( );
...
// created.accNo = number;
// created.accBal = balance;
// created.accType = AccountType.Checking;
created.Populate(number, balance);
...
}
...
}

5. Guarde el trabajo realizado.

Fundamentos de la programacin orientada a objetos

6. Compile el programa. No se compilar. En el mtodo


CreateAccount.Write quedan todava tres instrucciones que intentan
acceder directamente a los campos privados de BankAccount. Tiene que
escribir tres mtodos pblicos de BankAccount que devuelvan los valores
de estos tres campos. Ejecute los siguientes pasos:
a. Aada a BankAccount un mtodo pblico no esttico llamado Number.
Este mtodo devolver un entero largo y no recibir ningn parmetro.
Devolver el valor del campo accNo, como se muestra a continuacin:
class BankAccount
{
public void Populate(...) ...
public long Number( )
{
return accNo;
}
...
}

b. Aada a BankAccount un mtodo pblico no esttico llamado Balance,


como muestra el siguiente cdigo. Este mtodo devolver un decimal y
no recibir ningn parmetro. Devolver el valor del campo accBal.
class BankAccount
{
public void Populate(...) ...
...
public decimal Balance( )
{
return accBal;
}
...
}

c. Aada a BankAccount un mtodo pblico no esttico llamado Type,


como muestra el siguiente cdigo. Este mtodo devolver un
AccountType y no recibir ningn parmetro. Devolver el valor del
campo accType.
class BankAccount
{
public void Populate(...) ...
...
public AccountType Type( )
{
return accType;
}
...
}

Fundamentos de la programacin orientada a objetos

d. Finalmente, sustituya las tres instrucciones del mtodo


CreateAccount.Write que intentan acceder directamente a los campos
privados de BankAccount por llamadas a los tres mtodos pblicos que
acaba de crear, como se muestra a continuacin:
class CreateAccount
{
...
static void Write(BankAccount toWrite)
{
Console.WriteLine("Account number is {0}",
toWrite.Number( ));
Console.WriteLine("Account balance is {0}",
toWrite.Balance( ));
Console.WriteLine("Account type is {0}",
toWrite.Type( ));
}
}

7. Guarde el trabajo realizado.


8. Compile el programa y corrija los posibles errores. Ejecute el programa.
Compruebe que los datos introducidos en la consola y pasados al mtodo
BankAccount.Populate se leen correctamente y se muestran en el mtodo
CreateAccount.Write.
Cmo encapsular an ms la clase BankAccount
1. Cambie el mtodo BankAccount.Type para que devuelva el tipo de la
cuenta como una cadena de caracteres en lugar de cmo una enumeracin
AccountType, como se muestra a continuacin:
class BankAccount
{
...
public string Type( )
{
return accType.ToString( );
}
...
private AccountType accType;
}

2. Guarde el trabajo realizado.


3. Compile el programa y corrija los posibles errores. Ejecute el programa.
Compruebe que los datos introducidos en la consola y pasados al mtodo
BankAccount.Populate se leen correctamente y se muestran en el mtodo
CreateAccount.Write.

Fundamentos de la programacin orientada a objetos

Ejercicio 2
Generacin de nmeros de cuenta
En este ejercicio modificar la clase BankAccount del Ejercicio 1 para que
genere nmeros de cuenta exclusivos. Para ello usar una variable esttica en la
clase BankAccount y un mtodo que incrementa y devuelve el valor de esta
variable. Cuando cree una nueva cuenta, el sistema de prueba llamar a este
mtodo para generar el nmero de cuenta. Luego llamar al mtodo de la clase
BankAccount que fija el nmero para la cuenta, pasando este valor como
parmetro.
Cmo comprobar que cada nmero de BankAccount es nico
1. Abra el proyecto UniqueNumbers.sln en la carpeta Starter\UniqueNumbers
dentro del fichero lab07.zip.
Nota Este proyecto es el mismo que el proyecto CreateAccount finalizado
en el Ejercicio 1.
2. Aada un entero largo privado esttico llamado nextAccNo a la clase
BankAccount, como se muestra a continuacin:
class BankAccount
{
...
private long accNo;
private decimal accBal;
private AccountType accType;
private static long nextAccNo;
}

3. Aada a la clase BankAccount un mtodo pblico esttico llamado


NextNumber, como se ve en el siguiente cdigo. Este mtodo devolver un
entero largo y no recibir ningn parmetro. Devolver el valor del campo
nextAccNo e incrementar ese campo.
class BankAccount
{
...
public static long NextNumber( )
{
return nextAccNo++;
}
private long accNo;
private decimal accBal;
private AccountType accType;
private static long nextAccNo;
}

Fundamentos de la programacin orientada a objetos

4. Marque como comentarios la instruccin del mtodo


CreateAccount.NewBankAccount que escribe en la consola un mensaje
para pedir el nmero de la cuenta bancaria, como se indica:
//Console.Write("Enter the account number: ");

5. Sustituya la inicializacin de number en el mtodo


CreateAccount.NewBankAccount por una llamada al mtodo
BankAccount.NextNumber que acaba de crear:
//long number = long.Parse(Console.ReadLine( ));
long number = BankAccount.NextNumber( );

6. Guarde el trabajo realizado.


7. Compile el programa y corrija los posibles errores. Ejecute el programa.
Compruebe que los dos nmeros de cuenta son 0 y 1.
8. El valor de inicializacin por defecto del campo esttico
BankAccount.nextAccNo es cero en estos momentos. Inicialice este campo
de forma explcita a 123.
9. Compile y ejecute el programa. Compruebe que los nmeros de las dos
cuentas creadas son 123 y 124.
Cmo encapsular an ms la clase BankAccount
1. Cambie el mtodo BankAccount.Populate para que slo reciba como
parmetro el balance decimal. Dentro del mtodo, asigne el campo accNo
utilizando el mtodo esttico BankAccount.NextNumber, como se muestra
a continuacin:
class BankAccount
{
public void Populate(decimal balance)
{
accNo = NextNumber( );
accBal = balance;
accType = AccountType.Checking;
}
...
}

2. Convierta BankAccount.NextNumber en un mtodo privado:


class BankAccount
{
...
private static long NextNumber( ) ...
}

Fundamentos de la programacin orientada a objetos

3. Marque como comentarios la declaracin e inicializacin de number en el


mtodo CreateAccount.NewBankAccount. Cambie la llamada al mtodo
created.Populate para que pase un solo parmetro, como se indica:
class CreateAccount
{
...
static BankAccount NewBankAccount( )
{
BankAccount created = new BankAccount( );
//long number = BankAccount.NextNumber( );
...
created.Populate(balance);
...
}
...
}

4. Guarde el trabajo realizado.


5. Compile el programa y corrija los posibles errores. Ejecute el programa.
Compruebe que los dos nmeros de cuenta siguen siendo 123 y 124.

Fundamentos de la programacin orientada a objetos

10

Ejercicio 3
Inclusin de ms mtodos pblicos
En este ejercicio aadir dos mtodos a la clase Account: Withdraw (Retirar)
y Deposit (Ingresar).
Withdraw recibir un parmetro decimal y deducir del saldo la cantidad
indicada. Sin embargo, antes comprobar que se dispone de suficientes fondos,
ya que las cuentas no pueden quedar en nmeros rojos. Devolver un valor
booleano que indique si la retirada de fondos ha sido correcta.
Deposit recibir tambin un parmetro decimal cuyo valor sumar al saldo de la
cuenta. Devolver el nuevo valor del saldo.
Cmo aadir un mtodo Deposit a la clase BankAccount
1. Abra el proyecto MoreMethods.sln en la carpeta Starter\MoreMethods
dentro del fichero lab07.zip.
Nota Este proyecto es el mismo que el proyecto UniqueNumbers finalizado
en el Ejercicio 2.
2. Aada a la clase BankAccount un mtodo pblico no esttico llamado
Deposit, como se ve en el siguiente cdigo. Este mtodo recibir un
parmetro decimal cuyo valor sumar al saldo de la cuenta. Devolver el
nuevo valor del saldo.
class BankAccount
{
...
public decimal Deposit(decimal amount)
{
accBal += amount;
return accBal;
}
...
}

Fundamentos de la programacin orientada a objetos

11

3. Aada a la clase CreateAccount un mtodo pblico esttico llamado


TestDeposit, como se ve en el siguiente cdigo. Este mtodo devolver
void y recibir un parmetro de BankAccount. El mtodo escribir en la
consola un mensaje que pregunte al usuario la cantidad del depsito,
capturar como decimal la cantidad introducida y llamar al mtodo
Deposit sobre el parmetro BankAccount, pasando la cantidad como
argumento.
class CreateAccount
{
...
public static void TestDeposit(BankAccount acc)
{
Console.Write("Enter amount to deposit: ");
decimal amount = decimal.Parse(Console.ReadLine());
acc.Deposit(amount);
}
...
}

4. Aada a CreateAccount.Main instrucciones que llamen al mtodo


TestDeposit que acaba de crear, como muestra el siguiente cdigo.
Compruebe que la llamada a TestDeposit se hace para los dos objetos de
cuenta. Use el mtodo CreateAccount.Write para mostrar la cuenta una
vez hecho el depsito.
class CreateAccount
{
static void Main( )
{
BankAccount berts = NewBankAccount( );
Write(berts);
TestDeposit(berts);
Write(berts);
BankAccount freds = NewBankAccount( );
Write(freds);
TestDeposit(freds);
Write(freds);
}
}

5. Guarde el trabajo realizado.


6. Compile el programa y corrija los posibles errores. Ejecute el programa.
Compruebe que los depsitos funcionan correctamente.
Nota Si le queda tiempo, puede aadir a Deposit una comprobacin ms para
asegurarse de que el parmetro decimal que se pasa no es negativo.

Fundamentos de la programacin orientada a objetos

12

Cmo aadir un mtodo Withdraw a la clase BankAccount


7. Aada a la clase BankAccount un mtodo pblico no esttico llamado
Withdraw, como se ve en el siguiente cdigo. Este mtodo recibir un
parmetro decimal con la cantidad que se desea retirar, y la deducir del
saldo slo si se dispone de suficientes fondos, ya que las cuentas no pueden
quedar en nmeros rojos. Devolver un valor booleano que indique si la
retirada de fondos ha sido correcta.
class BankAccount
{
...
public bool Withdraw(decimal amount)
{
bool sufficientFunds = accBal >= amount;
if (sufficientFunds) {
accBal -= amount;
}
return sufficientFunds;
}
...
}

8. Aada a la clase CreateAccount un mtodo pblico esttico llamado


TestWithdraw, como se ve en el siguiente cdigo. Este mtodo devolver
void y recibir un parmetro de BankAccount. El mtodo escribir en la
consola un mensaje que pregunte al usuario la cantidad que desea retirar,
capturar como decimal la cantidad introducida y llamar al mtodo
Withdraw sobre el parmetro BankAccount, pasando la cantidad como
argumento. Capturar el resultado booleano devuelto por Withdraw y
escribir un mensaje en la consola si no ha sido posible retirar la cantidad.
class CreateAccount
{
...
public static void TestWithdraw(BankAccount acc)
{
Console.Write("Enter amount to withdraw: ");
decimal amount = decimal.Parse(Console.ReadLine());
if (!acc.Withdraw(amount)) {
Console.WriteLine("Insufficient funds.");
}
}
...
}

Fundamentos de la programacin orientada a objetos

13

9. Aada a CreateAccount.Main instrucciones que llamen al mtodo


TestWithdraw que acaba de crear, como muestra el siguiente cdigo.
Compruebe que la llamada a TestWithdraw se hace para los dos objetos de
cuenta. Use el mtodo CreateAccount.Write para mostrar la cuenta una
vez retirada la cantidad.
class CreateAccount
{
static void Main( )
{
BankAccount berts = NewBankAccount( );
Write(berts);
TestDeposit(berts);
Write(berts);
TestWithdraw(berts);
Write(berts);
BankAccount freds = NewBankAccount( );
Write(freds);
TestDeposit(freds);
Write(freds);
TestWithdraw(freds);
Write(freds);
}
}

10. Guarde el trabajo realizado.


11. Compile el programa y corrija los posibles errores. Ejecute el programa.
Compruebe que las cantidades se retiran correctamente. Haga pruebas con
cantidades que den resultados correctos e incorrectos.

Uso de variables de tipo referencia

Prctica A: Definicin y uso de variables de tipo


referencia
Objetivos
Al final de esta prctica, usted ser capaz de:
Crear variables referencia y pasarlas como parmetros de mtodos.
Usar el marco de trabajo del sistema.

Requisitos previos
Antes de realizar la prctica debe estar familiarizado con los siguientes temas:
Creacin y uso de clases
Llamadas a mtodos y paso de parmetros
Uso de tablas

Ejercicio 1
Inclusin de un mtodo de instancia con dos parmetros
En la Prctica 7 desarrollamos una clase BankAccount. En este ejercicio
volver a utilizar esa clase y aadir un nuevo mtodo de instancia, llamado
TransferFrom, que transfiere dinero de una cuenta especificada a la actual. Si
no termin la Prctica 7, puede conseguir una copia de la clase BankAccount
en la carpeta Starter\Bank dentro del fichero lab08.zip.
Cmo crear el mtodo TransferFrom
1. Abra el proyecto Bank.sln en la carpeta Starter\Bank dentro del fichero
lab08.zip.
2. Edite la clase BankAccount como se indica a continuacin:
a. Cree un mtodo de instancia pblico llamado TransferFrom en la clase
BankAccount.
b. El primer parmetro es una referencia a otro objeto BankAccount
llamado accFrom, desde donde se va a transferir el dinero.
c. El segundo parmetro es un valor decimal llamado amount, que se pasa
por valor e indica la cantidad que se va a transferir.
d. El mtodo no tiene valor de devolucin.
3. Aada al cuerpo de TransferFrom dos instrucciones que realicen las
siguientes tareas:
a. Deducir amount del saldo de accFrom (usando Withdraw).
b. Comprobar que el dinero se ha podido retirar sin problemas. Si es as,
sumar amount al saldo de la cuenta actual (usando Deposit).
El cdigo para la clase BankAccount debera ser como ste:

Uso de variables de tipo referencia


class BankAccount
{
... dems cdigo omitido para mayor claridad ...
public void TransferFrom(BankAccount accFrom, decimal
amount)
{
if (accFrom.Withdraw(amount))
this.Deposit(amount);
}
}

Uso de variables de tipo referencia

Cmo probar el mtodo TransferFrom


1. Aada al proyecto el archivo Test.cs.
2. Aada a este archivo la clase siguiente, que ser el sistema de prueba.
using System;
public class Test
{
public static void Main()
{
}
}

3. En el mtodo Main, aada cdigo para crear dos objetos BankAccount,


ambos con un saldo inicial de 100 $ (use el mtodo Populate).
4. Aada cdigo para mostrar el tipo, nmero de cuenta y saldo actual de cada
cuenta.
5. Aada cdigo para llamar a TransferFrom y transferir 10 de una cuenta a
otra.
6. Aada cdigo para mostrar los saldos despus de la transferencia.
El cdigo para la clase Test debera ser como ste:
public static void Main( )
{
BankAccount b1 = new BankAccount( );
b1.Populate(100);
BankAccount b2 = new BankAccount( );
b2.Populate(100);
Console.WriteLine("Before transfer");
Console.WriteLine("{0} {1} {2}",
b1.Type( ), b1.Number( ), b1.Balance( ));
Console.WriteLine("{0} {1} {2}",
b2.Type( ), b2.Number( ), b2.Balance( ));
b1.TransferFrom(b2, 10);
Console.WriteLine("After transfer");
Console.WriteLine("{0} {1} {2}",
b1.Type( ), b1.Number( ), b1.Balance( ));
Console.WriteLine("{0} {1} {2}",
b2.Type( ), b2.Number( ), b2.Balance( ));
}

7. Guarde el trabajo realizado.


8. Compile el proyecto y corrija los posibles errores. Ejecute y pruebe el
programa.

Uso de variables de tipo referencia

Ejercicio 2
Inversin de una cadena de caracteres
En el Mdulo 5 desarrollamos una clase Utils que contena distintos mtodos.
En este ejercicio aadir un nuevo mtodo esttico llamado Reverse (Invertir) a
la clase Utils. Este mtodo recibe una cadena de caracteres y devuelve otra
nueva con los caracteres en orden inverso.
Cmo crear el mtodo Reverse
1. Abra el proyecto Utils.sln en la carpeta Starter\Utils dentro del fichero
lab08.zip.
2. Aada un mtodo public static llamado Reverse a la clase Utils:
a. Tiene un solo parmetros, llamado s, que es una referencia a una string.
b. El mtodo tiene un tipo de devolucin void.
3. En el mtodo Reverse, cree una variable string llamada sInv que contendr
la cadena devuelta como resultado. Inicialice esta variable a "".

Uso de variables de tipo referencia

4. Para crear una cadena de caracteres invertida:


a. Escriba un bucle que extraiga caracteres uno a uno desde s. Comience
por el final (use la propiedad Length) y retroceda hasta llegar al
principio de la cadena. Puede emplear notacin de tablas ([ ]) para
examinar un carcter concreto en una cadena.
Consejo El ltimo carcter en una cadena est en la posicin Length 1, y
el primero en la posicin 0.
b. Aada este carcter al final de sInv.
La clase Utils podra contener lo siguiente:
class Utils
{
... dems mtodos omitidos para mayor claridad ...
//
// Inversin de una cadena
//
public static void Reverse(ref string s)
{
string sRev = "";
for (int k = s.Length 1; k >= 0 ; k--)
sInv = sInv + s[k];
// Devolver resultado a llamador
s = sInv;
}
}

Cmo probar el mtodo Invertir


1. Aada al proyecto el archivo Test.cs.
2. Aada a este archivo la clase siguiente, que ser el sistema de prueba.
namespace Utils
{
using System;
public class Test
{
public static void Main()
{
}
}
}

3. En el mtodo Main, cree una variable string.


4. Utilice Console.ReadLine para leer un valor en la variable string.

Uso de variables de tipo referencia

5. Pase la cadena de caracteres a Reverse. No olvide la palabra reservada ref.


6. Muestre el valor devuelto por Reverse.
La clase Test podra contener lo siguiente:
static void Main( )
{
string message;
// Obtener una cadena de entrada
Console.WriteLine("Escriba una cadena para invertirla:");
mensaje = Console.ReadLine( );
// Reverse
Utils. Reverse (ref message);
// Mostrar el resultado
Console.WriteLine(message);
}

7. Guarde el trabajo realizado.


8. Compile el proyecto y corrija los posibles errores. Ejecute y pruebe el
programa.

Uso de variables de tipo referencia

Ejercicio 3
Copia en maysculas de un archivo
En este ejercicio escribir un programa que pida al usuario el nombre de un
archivo de texto. El programa comprobar que el archivo existe, y en caso
contrario mostrar un mensaje y se cerrar. Abrir el archivo y lo copiar a otro
(cuyo nombre preguntar al usuario), pero con todos los caracteres en
maysculas.
Antes de empezar, tal vez sea conveniente que revise brevemente la
documentacin para System.IO en los documentos de ayuda del SDK de .NET
Framework. En particular, consulte la documentacin para las clases
StreamReader y StreamWriter.
Cmo crear la aplicacin de copia de archivos
1. Abra el proyecto CopyFileUpper.sln en la carpeta Starter\CopyFileUpper
dentro del fichero lab08.zip.
2. Edite la clase CopyFileUpper y aada una instruccin using para el espacio
de nombres System.IO.
3. En el mtodo Main, declare dos variables string llamadas sFrom y sTo que
contendrn los nombres de los archivos de entrada y salida.
4. Declare una variable de tipo StreamReader llamada srFrom. Esta variable
contendr la referencia al archivo de entrada.
5. Declare una variable de tipo StreamWriter llamada swTo. Esta variable
contendr la referencia a la secuencia de salida.
6. Pregunte el nombre del archivo de entrada, lea el nombre y almacnelo en la
variable string sFrom.
7. Pregunte el nombre del archivo de salida, lea el nombre y almacnelo en la
variable string sTo.
8. Las operaciones de entrada/salida que va a utilizar pueden producir
excepciones. Comience un bloque try-catch que pueda capturar
FileNotFoundException (para archivos que no existen) y Exception (para
cualquier otra excepcin). Imprima un mensaje adecuado para cada
excepcin.
9. En el bloque try, cree un nuevo objeto StreamReader usando el nombre
del archivo de entrada en sFrom, y almacnelo en la variable referencia
StreamReader srFrom.
10. Del mismo modo, cree un nuevo objeto StreamWriter usando el nombre
del archivo de salida en sTo, y almacnelo en la variable referencia
StreamWriter swTo.
11. Aada un bucle while que se ejecute si el mtodo Peek de la secuencia de
entrada no devuelve -1. Dentro del bucle:
a. Use el mtodo ReadLine sobre la secuencia de entrada para leer la lnea
siguiente en una variable string llamada sBuffer.
b. Aplique el mtodo ToUpper a sBuffer.
c. Use el mtodo WriteLine para enviar sBuffer a la secuencia de salida.
12. Una vez finalizado el bucle, cierre las secuencias de entrada y de salida.

Uso de variables de tipo referencia

13. El archivo CopyFileUpper.cs debera ser como ste:


using System;
using System.IO;
class CopyFileUpper
{
static void Main( )
{
string
sFrom, sTo;
StreamReader srFrom;
StreamWriter swTo;
// Pedir el nombre del archivo de entrada
Console.Write("Copiar de:");
sFrom = Console.ReadLine( );
// Pedir el nombre del archivo de salida
Console.Write("Copiar a:");
sTo = Console.ReadLine( );
Console.WriteLine("Copiar de {0} a {1}", sFrom,
sTo);
try
{
srFrom = new StreamReader(sFrom);
swTo
= new StreamWriter(sTo);
while (srFrom.Peek( )!=-1)
{
string sBuffer = srFrom.ReadLine( );
sBuffer = sBuffer.ToUpper( );
swTo.WriteLine(sBuffer);
}
swTo.Close( );
srFrom.Close( );
}
catch (FileNotFoundException)
{
Console.WriteLine("Archivo de entrada no
encontrado");
}
catch (Exception e)
{
Console.WriteLine("Excepcin inesperada");
Console.WriteLine(e.ToString( ));
}
}
}

14. Guarde el trabajo realizado. Compile el proyecto y corrija los posibles


errores.

Uso de variables de tipo referencia

Cmo probar el programa


1. Abra una ventana Command y vaya a la carpeta bin\debug dentro del
proyecto CopyFileUpper.
2. Ejecute CopyFileUpper.
3. Cuando lo pida el programa, indique como nombre de archivo de origen
drive:\path\CopyFileUpper.cs
(es el archivo que acaba de crear).
4. Indique Test.cs como archivo de destino.
5. Cuando el programa finalice, utilice un editor de texto para examinar el
archivo Test.cs, que debera contener una copia del cdigo fuente en letras
maysculas.

Uso de variables de tipo referencia

Prctica.B: Conversin de datos


Objetivos
Al final de esta prctica, usted ser capaz de:

Convertir valores de un tipo referencia a otro.

Probar si una variable referencia es compatible con una interfaz


determinada.

Requisitos previos
Antes de realizar la prctica debe estar familiarizado con los siguientes temas:

Conceptos de programacin orientada a objetos

Creacin de clases

Definicin de mtodos

Ejercicio 1
Prueba de la implementacin de una interfaz
En este ejercicio aadir un mtodo esttico llamado IsItFormattable a la clase
Utils creada en la Prctica 5. Si no termin esa prctica, puede conseguir una
copia de la clase en la carpeta Starter dentro del fichero lab08.zip.
El mtodo IsItFormattable recibe un parmetro de tipo object y prueba si ese
parmetro implementa la interfaz System.IFormattable. El mtodo devuelve
true si el objeto tiene esta interfaz y false en caso contrario.
Una clase implementa la interfaz System.IFormattable para devolver una
representacin en cadena de caracteres de una instancia de esa clase. Los tipos
bsicos, como int y ulong, implementan esta interfaz (despus de que se
aplique boxing al valor), pero no as muchos tipos referencia, como por ejemplo
string. Los tipos definidos por el usuario pueden implementar la interfaz si as
lo quiere el desarrollador. Para ms informacin sobre esta interfaz, consulte la
documentacin de ayuda del SDK de .NET Framework.
Escribir cdigo de prueba que llame al mtodo Utils. IsItFormattable con
argumentos de distintos tipos y muestre los resultados en la pantalla.
Cmo crear el mtodo IsItFormattable
1. Abra el proyecto InterfaceTest.sln en la carpeta Starter\InterfaceTest dentro
del fichero lab08.zip.
2. Edite la clase Utils de la siguiente manera:
a. Cree un mtodo pblico esttico llamado IsItFormattable en la clase
Utils.
b. Este mtodo recibe un parmetro llamado x de tipo object, que se pasa
por valor. El mtodo devuelve un bool.
c. Use el operador is para determinar si el objeto pasado es compatible con
la interfaz System.IFormattable. Devolver true si es as, y false en
caso contrario.

Uso de variables de tipo referencia

El mtodo finalizado debera ser como ste:


using System;
...
class Utils
{
public static bool IsItFormattable(object x)
{
// Usa el operador is para probar si el
// objeto tiene la interfaz IFormattable
if (x is IFormattable)
return true;
else
return false;
}
}

Uso de variables de tipo referencia

Cmo probar el mtodo IsItFormattable


1. Edite la clase Test del archivo.
2. En el mtodo Main, declare e inicialice variables de tipos int, ulong y
string.
3. Pase cada variable a Utils. IsItFormattable() e imprima el resultado de
cada llamada.
4. La clase Test podra ser as:
using System;
public class Test
{
static void Main( )
{
int
i = 0;
ulong ul = 0;
string s = "Test";

Console.WriteLine("int: {0}",
Utils.IsItFormattable(i));
Console.WriteLine("ulong: {0}",
Utils.IsItFormattable(ul));
Console.WriteLine("String: {0}",
Utils.IsItFormattable(s));

5. Compile y pruebe el cdigo. Debera obtener true para los valores int y
ulong, y false para el valor string.

Uso de variables de tipo referencia

Ejercicio 2
Uso de interfaces
En este ejercicio escribir un mtodo Display que usar el operador as para
determinar si el objeto pasado como parmetro es compatible con una interfaz
definida por el usuario llamada IPrintable, y en caso afirmativo llamar a un
mtodo de esa interfaz.
Cmo crear el mtodo Display
1. Abra el proyecto TestDisplay.sln en la carpeta Starter\TestDisplay dentro
del fichero lab08.zip.
El cdigo de inicio incluye la definicin de una interfaz llamada IPrintable,
que contiene un mtodo llamado Print. Una clase que implemente esta
interfaz podr usar el mtodo Print para mostrar en la consola los valores
contenidos en el objeto. En los archivos del cdigo de inicio tambin est
definida una clase llamada Coordinate, que implementa la interfaz
IPrintable.
Un objeto Coordinate contiene un par de nmeros que pueden definir una
posicin en dos dimensiones. No es necesario que sepa cmo funciona la
clase Coordinate (aunque puede examinarla), sino slo que implementa la
interfaz IPrintable y que puede usar el mtodo Print para mostrar sus
contenidos.
2. Edite la clase Utils de la siguiente manera:
a. Aada un mtodo void pblico esttico llamado Display en la clase
Utils. Este mtodo recibir un parmetro (un object pasado por valor)
llamado item.
b. En Display, declare una variable de interfaz llamada ip de tipo
IPrintable.
c. Convierta la referencia en el parmetro item en una referencia a la
interfaz IPrintable que utilice el operador as. Asigne el resultado a ip.
d. Si el valor de ip es distinto de null, use la interfaz IPrintable para
llamar a Print. Si es null, el objeto no es compatible con la interfaz. En
este ltimo caso, utilice Console.WriteLine para mostrar los resultados
del mtodo ToString en el parmetro.
El mtodo finalizado debera ser como ste:
public static void Display(object item)
{
IPrintable ip;
ip = (item as IPrintable);
if (ip != null)
ip.Print( );
else
Console.WriteLine(item.ToString( ));
}

Uso de variables de tipo referencia

Cmo probar el mtodo Display


1. Dentro del mtodo Main de la clase Test, cree una variable de tipo int, otra
de tipo string y otra de tipo Coordinate. Para inicializar la variable
Coordinate puede usar el siguiente constructor de dos parmetros:
Coordinate c = new Coordinate(21.0, 68.0);

2. Pase cada una de estas res variables a Utils.Display para ver el resultado.
3. El cdigo debera ser el siguiente:
public class Test
{
static void Main( )
{
int
num = 65;
string msg = "A String";
Coordinate c = new Coordinate(21.0,68.0);
Utils.Display(num);
Utils.Display(msg);
Utils.Display(c);
}
}

4. Compile y pruebe la aplicacin.

Uso de variables de tipo


referencia

Contenido
Notas generales
Uso de variables de tipo referencia

1
2

Uso de tipos referencia comunes

15

La jerarqua de objetos

23

Espacios de nombres en .NET Framework

30

Conversiones de datos

36

Uso de variables de tipo referencia

Notas para el instructor


Este mdulo ofrece a los estudiantes informacin detallada sobre tipos
referencia. Define los tipos referencia y su relacin con las clases. Explica las
diferencias entre variables de tipo referencia y de tipo valor. Tambin explica
con detalle el tipo string como ejemplo de tipo referencia predefinido.
En este mdulo se habla tambin de la jerarqua de clases System.Object y el
tipo object en C#, mostrando las relaciones entre los distintos tipos. Igualmente
se discuten espacios de nombres comunes en Microsoft .NET Framework.
El mdulo concluye explicando cmo convertir datos. Describe las
conversiones explcitas para tratar datos de un tipo referencia como de otro.
Tambin explica cmo usar conversiones boxing y unboxing para convertir
datos entre tipos referencia y tipos valor.
Al final de este mdulo, los estudiantes sern capaces de:
Describir las diferencias ms importantes entre tipos referencia y tipos
valor.
Usar tipos referencia comunes, como string.
Explicar cmo funciona el tipo object y familiarizarse con los mtodos que
proporciona.
Describir espacios de nombres comunes en .NET Framework.
Determinar si distintos tipos y objetos son compatibles.
Hacer conversiones explcitas e implcitas de tipos de datos entre tipos
referencia.
Realizar conversiones boxing y unboxing entre datos de referencia y de
valor.

Uso de variables de tipo referencia

Notas generales
Objetivo del tema

Ofrecer una introduccin a


los contenidos y objetivos
del mdulo.

Explicacin previa

En este mdulo
discutiremos el uso de tipos
referencia y estudiaremos la
jerarqua de objetos en C#.

Uso de variables de tipo referencia

Uso de tipos referencia comunes

La jerarqua de objetos

Espacios de nombres en .NET Framework

Conversiones de datos

En este mdulo aprenderemos a usar tipos referencia en C#. Discutiremos


varios tipos referencia, como string, que estn incluidos en el lenguaje C# y el
entorno de tiempo de ejecucin y que utilizaremos como ejemplos.
Tambin hablaremos de la jerarqua de clases System.Object y en particular
del tipo object, lo que nos permitir comprender la relacin de los tipos
referencia entre s y con los tipos valor. Estudiaremos cmo convertir datos
entre tipos referencia usando conversiones explcitas e implcitas, y veremos
cmo las conversiones boxing y unboxing convierten datos entre tipos
referencia y tipos valor.
Al final de este mdulo, usted ser capaz de:
Describir las diferencias ms importantes entre tipos referencia y tipos
valor.
Usar tipos referencia comunes, como string.
Explicar cmo funciona el tipo object y familiarizarse con los mtodos que
proporciona.
Describir espacios de nombres comunes en .NET Framework.
Determinar si distintos tipos y objetos son compatibles.
Hacer conversiones explcitas e implcitas de tipos de datos entre tipos
referencia.
Realizar conversiones boxing y unboxing entre datos de referencia y de
valor.

Uso de variables de tipo referencia

Uso de variables de tipo referencia


Objetivo del tema

Ofrecer una introduccin a


los temas tratados en esta
seccin.

Explicacin previa

En esta leccin
aprenderemos a usar tipos
referencia en C#.

Recomendacin al
profesor

Aunque se da una breve


explicacin de cmo se
libera memoria desde
variables referencia, en este
mdulo no se discute en
detalle la eliminacin de
elementos no utilizados
(Garbage Collection o
recoleccin de basura).

Comparacin de tipos valor y tipos referencia

Declaracin y liberacin de variables referencia

Referencias no vlidas

Comparacin de valores y comparacin de referencias

Referencias mltiples a un mismo objeto

Uso de referencias como parmetros de mtodos

Los tipos referencia son muy importantes en el lenguaje C#, ya que permiten
escribir aplicaciones complejas de altas prestaciones y hacer un uso eficaz del
marco de trabajo en tiempo de ejecucin.
Al final de esta leccin, usted ser capaz de:
Describir las diferencias ms importantes entre tipos referencia y tipos
valor.
Usar y descartar variables referencia.
Pasar tipos referencia como parmetros de mtodos.

Uso de variables de tipo referencia

Comparacin de tipos valor y tipos referencia


Objetivo del tema

Comparar tipos valor y tipos


referencia.

Explicacin previa

La mayor parte de los


valores y variables que
hemos visto hasta ahora en
este curso son tipos valor.
Vamos a hacer ahora una
comparacin entre tipos
valor y tipos referencia.

Tipos valor
z

La variable
contiene el valor
directamente
Ejemplos:
char, int

int
int mol;
mol;
mol
mol == 42;
42;

Tipos referencia
z

La variable contiene una


referencia al dato
El dato se almacena en un
rea de memoria aparte
string
string mol;
mol;
mol
mol == Hola";
Hola";

Hola
Hola

42
42

Recomendacin al
profesor

Puede ser conveniente


explicar que los tipos
referencia no son lo mismo
que los parmetros
referencia, a pesar de la
similitud de los nombres.
Probablemente tambin
valga la pena discutir que
C# tiene tipos valor porque
son eficientes y se asignan
en la pila, por lo que no es
necesario hacer recoleccin
de basura.

Recomendacin al
profesor

A los desarrolladores en C y
C++ les puede ser til
comparar las variables
referencia con punteros a
objetos, pero insista en que
las variables referencia en
C# se especifican de forma
totalmente segura y no
pueden apuntar a objetos
no vlidos. Adems, C y
C++ no tienen recoleccin
de basura automtica.

C# admite tipos de datos bsicos como int, long y bool, a los que tambin se
llama tipos valor. Pero C# permite adems otros datos ms complejos y
verstiles que se conocen como tipos referencia.

Tipos valor
Las variables de tipo valor son los tipos de datos bsicos predeterminados,
como char o int. Los tipos valor en C# son los ms sencillos. Las variables de
tipo valor contienen sus datos directamente.

Tipos referencia
Las variables de tipo referencia no contienen datos, sino una referencia a los
datos. Los datos se almacenan en reas de memoria aparte.
En este curso ya hemos utilizado varios tipos referencia, tal vez sin ser
conscientes de ello. Las tablas, las cadenas de caracteres y las excepciones son
tipos referencia incluidas en el compilador de C# y en .NET Framework.
Tambin las clases, tanto predefinidas como definidas por el usuario, son en
cierto modo un tipo referencia.

Uso de variables de tipo referencia

Declaracin y liberacin de variables referencia


Objetivo del tema

Explicar cmo se declaran e


inicializan las variables
referencia.

Explicacin previa

Para usar variables de tipo


referencia hay que saber
cmo se declaran e
inicializan y cmo se
pueden liberar.

Declaracin de variables referencia

coordenada
coordenadac1;
c1;
c1
c1==new
newcoordinate();
coordinate();
c1.x
c1.x==6.12;
6.12;
c1.y
c1.y==4.2;
4.2;

6.12
6.12

4.2
4.2

Liberacin de variables referencia


c1
c1 == null;
null;

6.12
6.12

4.2
4.2

Para usar variables de tipo referencia hay que saber cmo se declaran e
inicializan y cmo se pueden liberar.

Declaracin de variables referencia


Para declarar variables de tipo referencia se utiliza la misma sintaxis que para
variables de tipo valor:
coordinate c1;

En este ejemplo se declara una variable c1 que puede tener una referencia a un
objeto de tipo coordinate. Sin embargo, la variable no est inicializada hacia
ningn objeto coordinate.
Para inicializar un objeto coordinate se emplea el operador new, que crea un
objeto nuevo y devuelve una referencia al objeto que se puede almacenar en la
variable de referencia.
Para su informacin

En C y C++, hay que usar


un operador especial ->
para eliminar una referencia
a un puntero y acceder a un
miembro. Esto no es
necesario en C#.

coordinate c1;
c1 = new coordinate( );

Tambin se puede declarar e inicializar la variable en una sola instruccin si se


combina el operador new con la declaracin de la variable, como vemos:
coordinate c1 = new coordinate( );

Una vez se ha creado en memoria un objeto al que apunta c1, es posible


inicializar variables referencia de ese objeto mediante el operador dot, como en
el siguiente ejemplo:
c1.x = 6.12;
c1.y = 4.2;

Uso de variables de tipo referencia

Ejemplo de declaracin de variables referencia


Las clases son tipos referencia. El siguiente ejemplo ilustra cmo declarar una
clase definida por el usuario llamada coordinate. Para simplificar, esta clase
tiene slo dos variables pblicas: x e y.
class coordinate
{
public double x = 0.0;
public double y = 0.0;
}

Recomendacin al
profesor

Esta clase tiene datos


pblicos que no estn bien
encapsulados, pero eso
simplifica el ejemplo.

Esta clase sencilla se usar en ejemplos posteriores para explicar cmo se crean,
utilizan y destruyen variables referencia.

Liberacin de variables referencia


Una vez asignada una referencia a un objeto nuevo, la variable de referencia
continuar apuntando al objeto hasta que sea asignada para apuntar a un objeto
diferente.
C# define un valor especial llamado null, que es el que contiene una variable de
referencia cuando no apunta a ningn objeto vlido. Se puede liberar una
referencia asignando explcitamente el valor null a una variable de referencia (o
simplemente dejando que la referencia quede fuera de mbito).

Uso de variables de tipo referencia

Referencias no vlidas
Objetivo del tema

Explicar cmo el compilador


y el sistema de tiempo de
ejecucin tratan las
referencias no vlidas.

Explicacin previa

No es posible acceder a
variables o mtodos si la
referencia no es vlida.

Si hay referencias no vlidas


z

Referencias no vlidas en tiempo de compilacin


z

No es posible acceder a miembros o variables


El compilador detecta el uso de referencias no inicializadas

Referencias no vlidas en tiempo de ejecucin


z

El sistema generar un error de excepcin

Slo se puede acceder a los miembros de un objeto a travs de una variable de


referencia si sta ha sido inicializada par que apunte a una referencia vlida. Si
la referencia no es vlida, no es posible acceder a variables o mtodos.
El compilador puede detectar este problema en algunos casos. En otras
ocasiones es necesario detectarlo y corregirlo en tiempo de ejecucin.

Referencias no vlidas en tiempo de compilacin


El compilador puede detectar situaciones en las que no se inicializa una variable
de referencia antes de utilizarla.
Por ejemplo, si una variable coordinate se declara pero no se inicializa, se
recibir un mensaje de error parecido al siguiente: Uso de variable local no
asignada c1. El siguiente cdigo muestra un ejemplo:
coordinate c1;
c1.x = 6.12; // Will fail: variable not assigned

Referencias no vlidas en tiempo de ejecucin


En general no es posible determinar en tiempo de compilacin si la referencia
de una variable es vlida o no. Como consecuencia, C# comprueba el valor de
una variable de referencia antes de su uso para asegurarse de que no es null.
Si se intenta utilizar una variable de referencia cuyo valor es null, el sistema de
tiempo de ejecucin lanza una excepcin NullReferenceException. Esta
situacin se puede prevenir utilizando try y catch, como muestra el siguiente
ejemplo:

Uso de variables de tipo referencia

try {
c1.x = 45;
}
catch (NullReferenceException) {
Console.WriteLine("c1 tiene valor null");
}

Esta comprobacin tambin se puede efectuar de forma explcita para evitar


excepciones. El siguiente ejemplo muestra cmo comprobar que una variable
de referencia contiene una referencia distinta de null antes de intentar acceder a
sus miembros:
if (c1 != null)
c1.x = 45;
else
Console.WriteLine("c1 tiene valor null");

Uso de variables de tipo referencia

Comparacin de valores y comparacin de referencias


Objetivo del tema

Explicar el uso
predeterminado de los
operadores == and != para
variables referencia.

Explicacin previa

Los operadores == and !=


pueden no funcionar del
modo esperado con
variables referencia.

Comparacin de tipos valor


z

== and != comparan valores

Comparacin de tipos referencia


z

== and != comparan las referencias, no los valores

1.0
1.0

2.0
2.0

1.0
1.0

2.0
2.0

Diferente

Los operadores de igualdad (==) y desigualdad (!=)pueden no funcionar del


modo esperado con variables referencia.

Comparacin de tipos valor


Para tipos valor, los operadores == and != se pueden usar para comparar
valores.

Comparacin de tipos referencia


Para tipos referencia que no sean string, los operadores == and != determinan
si las dos variables referencia estn apuntando al mismo objeto, pero no
comparan los contenidos de los objetos a los que apuntan las variables. En el
caso del tipo string, == compara el valor de las cadenas de caracteres.

Uso de variables de tipo referencia

Para su informacin

C y C++ usan una


semntica similar para la
comparacin de punteros.
Visual Basic emplea el
operador Is para comparar
dos referencias.

Consideremos el siguiente ejemplo, en el que dos variables de coordenada se


crean e inicializan con los mismos valores:
coordenada c1= new coordinate( );
coordenada c2= new coordinate ( );
c1.x = 1.0;
c1.y = 2.0;
c2.x = 1.0;
c2.y = 2.0;
if (c1 == c2)
Console.WriteLine("Same ");
else
Console.WriteLine("Different ");

La salida de este cdigo es Diferentes. Aunque los objetos a los que apuntan
tienen los mismos valores, c1 y c2 son referencias a distintos objetos y por tanto
== devuelve false.
Recomendacin al
profesor

Los desarrolladores en C y
C++ pueden sorprenderse
de que no se puedan usar
los operadores <, >, <= and
>= con referencias. Esto se
debe a que las referencias
en C# no son direcciones.

Los otros operadores relacionales (<, >, <= y >=) no se pueden utilizar para
comparar si dos variables referencia estn apuntando a un objeto.

Uso de variables de tipo referencia

10

Referencias mltiples a un mismo objeto


Objetivo del tema

Explicar que dos variables


referencia pueden apuntar a
un mismo objeto.

Explicacin previa

Dos referencias pueden apuntar a un mismo objeto


z

El hecho de que las


variables de tipo referencia
contengan una referencia a
los datos permite que dos
de ellas puedan apuntar al
mismo objeto.

Dos formas de acceder a un mismo objeto para


lectura/escritura
c1

c2

2.3
2.3

7.6
7.6

coordinate
coordinate c1=
c1= new
new coordinate
coordinate (( );
);
coordinate
c2;
coordinate c2;
c1.x
c1.x == 2.3;
2.3; c1.y
c1.y == 7.6;
7.6;
c2
=
c1;
c2 = c1;
Console.WriteLine(c1.x
Console.WriteLine(c1.x ++ "" ,, "" ++ c1.y);
c1.y);
Console.WriteLine(c2.x
Console.WriteLine(c2.x ++ "" ,, "" ++ c2.y);
c2.y);

Dos variables referencia pueden apuntar al mismo objeto porque lo que


contienen es una referencia a los datos. Esto significa que es posible utilizar una
referencia para escribir datos y otra para leer datos.

Referencias mltiples a un mismo objeto


En el siguiente ejemplo, la variable c1 se inicializa para que apunte a una
instancia nueva de la clase y se inicializan sus variables x e y. A continuacin se
copia c1 a c2. Finalmente se muestran los valores de los objetos a los que
apuntan c1 y c2.
coordenada c1 = new coordinate( );
coordenada c2;
c1.x = 2.3;
c1.y = 7.6;
c2 = c1;
Console.WriteLine(c1.x + " , " + c1.y);
Console.WriteLine(c2.x + " , " + c2.y);

La salida de este programa es la siguiente:


2.3 , 7.6
2.3 , 7.6

La asignacin de c2 a c1 copia la referencia, por lo que ambas variables


apuntan al mismo objeto. Como consecuencia, los valores que se imprimen para
las variables de c1 y c2 son iguales.

Uso de variables de tipo referencia

11

Escritura y lectura de los mismos datos con distintas


referencias
En el siguiente ejemplo se ha aadido una asignacin inmediatamente antes de
las llamadas a Console.WriteLine.
coordenada c1 = new coordinate( );
coordenada c2;
c1.x = 2.3;
c1.y = 7.6;
c2 = c1;
c1.x = 99; // sta es la nueva instruccin
Console.WriteLine(c1.x + " , " + c1.y);
Console.WriteLine(c2.x + " , " + c2.y);

La salida de este programa es la siguiente:


99 , 7.6
99 , 7.6

Como se ve, la asignacin de 99 a c1.x cambia tambin c2.x. Como la


referencia en c1 se haba asignado previamente a c2, un programa puede
escribir datos por una referencia y leer los mismos datos por otra referencia.

Uso de variables de tipo referencia

12

Uso de referencias como parmetros de mtodos


Objetivo del tema

Explicar que se puede pasar


referencias a y desde
mtodos de distintas
maneras.

Las referencias se pueden usar como parmetros


z

Si se pasan por valor, es posible cambiar el dato


referenciado

22 33

Explicacin previa

Es posible pasar variables


referencia a mtodos o
fuera de ellos.

33 44

static
static void
void PassCoordinateByValue(coordinate
PassCoordinateByValue(coordinate c)
c)
{{
c.x++;
c.x++; c.y++;
c.y++;
}}
loc.x
loc.x == 2;
2; loc.y
loc.y == 3;
3;

PassCoordinateByValue(loc);
PassCoordinateByValue(loc);
Console.WriteLine(loc.x
Console.WriteLine(loc.x ++ "" ,, "" ++ loc.y);
loc.y);

Es posible pasar variables referencia a mtodos o fuera de ellos.

Referencias y mtodos
Para pasar variables referencia como parmetros a mtodos se puede emplear
cualquiera de los tres mecanismos de llamada:
Por valor
Por referencia
Parmetros de salida
El siguiente ejemplo muestra un mtodo que pasa tres referencias de
coordenada. La primera se pasa por valor, la segunda por referencia y la tercera
es un parmetro de salida. El valor de devolucin del mtodo es una referencia
de coordenada.
static coordinate Example(
coordinate ca,
ref coordinate cb,
out coordinate cc)
{
// ...
}

Uso de variables de tipo referencia

13

Paso de referencias por valor


Si se utiliza una variable de referencia como parmetro valor, el mtodo recibe
una copia de la referencia. Esto significa que, mientras dure la llamada, hay dos
referencias que apuntan al mismo objeto. Por ejemplo, el siguiente cdigo
muestra los valores 3 y 4:
static void PassCoordinateByValue (coordenada c)
{
c.x++; c.y++; //c referencing loc
}
coordinate loc = new coordinate( );
loc.x = 2; loc.y = 3;
PassCoordinateByValue (loc);
Console.WriteLine(loc.x + " , " + loc.y);

Tambin significa que los cambios en el parmetro del mtodo no afectan a la


referencia que hace la llamada. Por ejemplo, el siguiente cdigo muestra los
valores 0 y 0:
static void PassCoordinateByValue (coordenada c)
{
c = new coordinate( ); //c no longer referencing loc
c.x = c.y = 22.22;
}
coordinate loc = new coordinate( );
PassCoordinateByValue (loc);
Console.WriteLine(loc.x + " , " + loc.y);

Paso de referencias por referencia


Si se utiliza una variable de referencia como parmetro ref, el mtodo recibe la
variable de referencia. Al contrario de lo que ocurre cuando se pasa por valor,
en este caso hay slo una referencia. El mtodo no hace su propia copia. Esto
significa que los cambios en el parmetro del mtodo afectarn a la referencia
que hace la llamada. Por ejemplo, el siguiente cdigo muestra los valores 33.33
y 33.33:
static void PassCoordinateByRef(ref coordenada c)
{
c = new coordinate ( );
c.x = c.y = 33.33;
}
coordinate loc = new coordinate( );
PassCoordinateByRef(ref loc);
Console.WriteLine(loc.x + " , " + loc.y);

Uso de variables de tipo referencia

14

Paso de referencias por salida


Si se utiliza una variable de referencia como parmetro out, the el mtodo
recibe la variable de referencia. Al contrario de lo que ocurre cuando se pasa
por valor, en este caso hay slo una referencia. El mtodo no hace su propia
copia. El paso por out es similar al paso por ref, salvo que el mtodo debe tener
el parmetro out. Por ejemplo, el siguiente cdigo muestra los valores 44.44 y
44.44:
static void PassCoordinateByOut(out coordenada c)
{
c = new coordinate( );
c.x = c.y = 44.44;
}
coordenada loc = new coordinate( );
PassCoordinateByOut(out loc);
Console.WriteLine(loc.x + " , " + loc.y);

Paso de referencias a mtodos


Las variables de tipos referencia no contienen directamente un valor, sino una
referencia a un valor. Lo mismo ocurre si son parmetros de mtodos, lo que
significa que el mecanismo de paso por valor puede producir resultados
inesperados.
Recomendacin al
profesor

Explique que lo que se pasa


al mtodo es la referencia,
no el objeto al que apunta.
Comente tambin que las
variables referencia no son
lo mismo que el paso por
referencia, a pesar de la
similitud de los nombres.

Consideremos como ejemplo el siguiente mtodo de la clase coordenada:


static void PassCoordinateByValue(coordenada c)
{
c.x++;
c.y++;
}

El parmetro coordinate c se pasa por valor. En el mtodo se incrementan las


dos variables miembro x e y. Veamos ahora el siguiente cdigo, que llama al
mtodo PassCoordinateByValue:
coordinate loc = new coordinate( );
loc.x = 2;
loc.y = 3;
PassCoordinateByValue(loc);
Console.WriteLine(loc.x + " , " + loc.y);

La salida de este cdigo es la siguiente:


3 , 4

Como se ve, el mtodo ha cambiado los valores referenciados por loc. Puede
parecer que esto contradice la explicacin de paso por valor dada anteriormente
en el curso, pero de hecho no es as. La variable referencia loc se copia en el
parmetro c y no puede ser modificada por el mtodo, pero la memoria a la que
apunta no se copia y por tanto no est sujeta a esa limitacin. La variable loc
contina apuntando a la misma rea de memoria, pero ahora sta contiene un
dato distinto.

Uso de variables de tipo referencia

15

Uso de tipos referencia comunes


Objetivo del tema

Ofrecer una introduccin a


los temas tratados en esta
seccin.

Explicacin previa

Algunos tipos referencia


estn predefinidos en el
lenguaje C#.

Clase Exception

Clase String

Mtodos, operadores y propiedades comunes de String

Comparaciones de cadenas de caracteres

Operadores de comparacin en String

Algunos tipos referencia estn predefinidos en el lenguaje C#.


Al final de esta leccin, usted ser capaz de:
Describir el funcionamiento de clases predefinidas.
Usar clases predefinidas como modelos para crear sus propias clases.

Uso de variables de tipo referencia

16

Clase Exception
Objetivo del tema
Describir la clase
Exception.

Explicacin previa

Exception es una clase


cuyos objetos se crean para
lanzarlos en caso de
excepcin.

Exception es una clase

Los objetos Exception se usan para lanzar excepciones

Para crear un objeto Exception se usa new

Para lanzar el objeto se usa throw

Los tipos Exception son subclases de Exception

Los objetos Exception se crean para lanzarlos en caso de excepcin.

Clase Exception
Exception es el nombre de una clase incluida en .NET Framework.

Objetos Exception
Los objetos de tipo Exception son los nicos que se pueden lanzar con throw y
capturar con catch. Por lo dems, la clase Exception es similar a otros tipos
referencia.

Tipos Exception
Exception representa un fallo genrico en una aplicacin. Tambin existen
tipos para excepciones concretas (como InvalidCastException). Cada una de
las clases que heredan de Exception representa una de estas excepciones
concretas.

Uso de variables de tipo referencia

17

Clase String
Objetivo del tema

Describir con ms detalle la


clase String.

Explicacin previa

El tipo string se utiliza para


procesar cadenas de
caracteres.

Cadenas de caracteres Unicode

Abreviatura de System.String

Inmutable

string
string ss == "Hola";
"Hola";
s[0]
s[0] == 'c';
'c'; //
// Error
Error al
al compilar
compilar

Recomendacin al
profesor

El procesamiento de
cadenas de caracteres en
C# se realiza a mucho ms
alto nivel que en C. Por
ejemplo, es posible
sobrescribir caracteres
especiales de terminacin.
La recoleccin de basura
(no discutida en este
mdulo) tambin se hace
automticamente.

En C# se utiliza el tipo string para procesar cadenas de caracteres Unicode (en


contraste, el tipo char es un tipo valor para caracteres individuales).
El nombre del tipo string es una abreviatura de la clase System.String. El
compilador procesa esta forma abreviada, por lo que string y System.String se
pueden usar indistintamente.
La clase String representa una cadena inmutable de caracteres. Una instancia
de String es inmutable, lo que significa que el texto de una cadena no se puede
modificar una vez creado. A primera vista podra parecer que algunos mtodos
modifican un valor string, pero en realidad devuelven una nueva instancia de
string que contiene la modificacin.
Consejo A menudo se usa la clase StringBuilder en combinacin con la clase
String. StringBuilder crea una cadena modificable internamente y que una vez
completa se puede convertir en una String inmutable. StringBuilder elimina la
necesidad de crear repetidamente Strings temporales inmutables y puede
mejorar las prestaciones del cdigo.
La clase System.String tiene muchos mtodos. La informacin sobre
procesamiento de cadenas de caracteres que se incluye en este curso no es
completa, pero s se tratan algunos de los mtodos ms tiles. Para ms
informacin, consulte los documentos de ayuda del kit de desarrollo de
software (SDK) de .NET Framework.

Uso de variables de tipo referencia

18

Mtodos, operadores y propiedades comunes de String


Objetivo del tema

Indicar y describir algunos


mtodos, operadores y
propiedades comunes de la
clase String.

Corchetes

Explicacin previa

Mtodo Insert

Propiedad Length

Mtodo Copy

Mtodo Concat

Mtodo Trim

Mtodos ToUpper y ToLower

Presentamos aqu algunos


ejemplos de mtodos,
operadores y propiedades
de System.String.

Recomendacin al
profesor

Las pginas que siguen no


contienen una lista completa
de todos los mtodos de la
clase String. Puede ser
conveniente que utilice
ahora archivos de referencia
para explicar a los
estudiantes cmo pueden
buscar ms informacin.

Corchetes [ ]
Para extraer un solo carcter en una posicin determinada de una cadena de
caracteres utilizando el nombre de la cadena seguido del ndice entre corchetes
([ and ]). Este proceso es similar al empleado para tablas. El ndice del primer
carcter de una cadena es cero.
El siguiente cdigo muestra un ejemplo:
string s = "Alphabet";
char firstchar = s[2]; // 'p'

No est permitido emplear los corchetes para asignar un carcter, ya que las
cadenas son inmutables. Si se intenta asignar un carcter a una cadena de esta
forma, como en el ejemplo, se producir un error en tiempo de compilacin.
s[2] = '*'; // Not valid

Mtodo Insert
Para insertar caracteres en una variable se puede emplear el mtodo Insert, que
devuelve una nueva string con un valor especificado insertado en la posicin
indicada de la cadena. Este mtodo recibe dos parmetros: la posicin de inicio
de la insercin y la cadena que se desea insertar.
El siguiente cdigo muestra un ejemplo:
string s = "Me encanta C!";
s = s.Insert(2, " Sharp ");
Console.WriteLine(s); // Me encanta C Sharp!

Uso de variables de tipo referencia

19

Propiedad Length
La propiedad Length devuelve un entero que representa la longitud de la
cadena:
string msj = "Hello";
int slen = msj.Length; // 5

Mtodo Copy
El mtodo de clase Copy copia una cadena para crear otra nueva; es decir, hace
un duplicado de una cadena especificada.
El siguiente cdigo muestra un ejemplo:
string s1 = "Hello";
string s2 = String.Copy(s1);

Mtodo Concat
El mtodo de clase Concat crea una nueva cadena de caracteres a partir de una
o ms cadenas o de objetos representados como cadenas.
El siguiente cdigo muestra un ejemplo:
string s3 = String.Concat("a", "b", "c", "d", "e", "f", "g");

El operador + est sobrecargado para cadenas, por lo que el ejemplo anterior se


podra reescribir de la siguiente manera:
string s = "a" + "b" + "c" + "d" + "e" + "f" + "g";
Console.WriteLine(s);

Mtodo Trim
El mtodo Trim elimina todos los caracteres indicados o escribe espacios entre
el principio y el final de una cadena.
El siguiente cdigo muestra un ejemplo:
string s = "
Hello ";
s = s.Trim( );
Console.WriteLine(s); // "Hello"

Mtodos ToUpper y ToLower


Los mtodos ToUpper y ToLower devuelven una cadena con todos los
caracteres cambiados a maysculas y minsculas, respectivamente:
string sText = "El camino al triunfo ";
Console.WriteLine(sText.ToUpper( )); // EL CAMINO AL TRIUNFO
Console.WriteLine(sText.ToLower( )); // el camino al triunfo

Uso de variables de tipo referencia

20

Comparaciones de cadenas de caracteres


Objetivo del tema

Describir los operadores de


comparacin que se
emplean con cadenas de
caracteres.

Explicacin previa

Se pueden utilizar los


operadores == and != sobre
variables string para
comparar sus contenidos.

Mtodo Equals
z

Comparacin de valores

Mtodo Compare
z

Ms comparaciones

Opcin para no distinguir maysculas y minsculas

Ordenacin alfabtica

Opciones locales de Compare

Se pueden utilizar los operadores == and != sobre variables string para


comparar sus contenidos.

Mtodo Equals
La clase System.String contiene un mtodo llamado Equals que se puede
emplear para comparar dos cadenas y ver si son iguales. El mtodo devuelve un
valor bool que es true si las cadenas son iguales y false en caso contrario. Es
un mtodo sobrecargado y se puede usar como mtodo de instancia o como
mtodo esttico. Ambas formas se muestran en el siguiente ejemplo.
string s1 = "Bienvenidos";
string s2 = "Bienvenidos";
if (s1.Equals(s2))
Console.WriteLine("Las cadenas son iguales");
if (String.Equals(s1,s2))
Console.WriteLine("Las cadenas son iguales");

Uso de variables de tipo referencia

21

Mtodo Compare
El mtodo Compare compara dos cadenas desde el punto de vista lxico; es
decir, compara las cadenas segn su ordenacin. Compare puede devolver los
siguientes valores:
Un entero negativo si la primera cadena es anterior a la segunda
0 si las cadenas son iguales
Un entero positivo si la primera cadena es posterior a la segunda
string s1 = "Supercalifragilstico";
string s2 = "Velocpedo";
int comp = String.Compare(s1,s2); // Entero negativo

Por definicin, cualquier cadena (incluyendo una cadena vaca) es siempre


mayor que una referencia null, y dos referencias null se consideran iguales al
compararlas.
Compare es un mtodo sobrecargado. Existe una versin con tres parmetros,
el tercero de los cuales es un valor bool si en la comparacin se deben ignorar
las maysculas. El siguiente ejemplo muestra una comparacin que no
distingue maysculas y minsculas:
s1 = "repollo";
s2 = "Repollo";
comp = String.Compare(s1, s2, true); // Ignorar maysculas

Opciones locales de Compare


Existen versiones sobrecargadas del mtodo Compare que permiten comparar
cadenas a partir de ordenaciones en distintos idiomas. Esto es til cuando se
escriben aplicaciones para un mercado internacional. Este aspecto no est
incluido en el temario de este curso. Para ms informacin, busque espacio de
nombres System.Globalization y clase CultureInfo en los documentos de
ayuda del SDK de .NET Framework.

Uso de variables de tipo referencia

22

Operadores de comparacin en String


Objetivo del tema

Explicar cmo usar los


operadores de comparacin
sobrecargados para
cadenas de caracteres.

Explicacin previa

Los operadores == and !=


estn sobrecargados para la
clase String.

Los operadores == y != estn sobrecargados para cadenas

Son equivalentes a String.Equals y !String.Equals

string
string aa == "Test";
"Test";
string
string bb == "Test";
"Test";
if
if (a
(a ==
== b)
b) ...
... //
// Devuelve
Devuelve true
true

Los operadores == and != estn sobrecargados para la clase String. Estos


operadores sirven para examinar los contenidos de cadenas de caracteres.
string a = "Test";
string b = "Test";
if (a == b) ... // Devuelve true

Los siguientes operadores y mtodos son equivalentes:


El operador == es equivalente al mtodo String.Equals.
El operador!= es equivalente al mtodo!String.Equals.
Los otros operadores relacionales (<, >, <= y >=) no estn sobrecargados para
la clase String.

Uso de variables de tipo referencia

23

La jerarqua de objetos
Objetivo del tema

Ofrecer una introduccin a


los temas tratados en esta
seccin.

Explicacin previa

Las clases base se


organizan en una jerarqua
en cuya cima est la clase
Object.

El tipo object

Mtodos comunes

Reflexin

Todas las clases es .NET son derivadas de la clase System.Object. El tipo


object es un alias de la clase System.Object en lenguaje C#.
Al final de esta leccin, usted ser capaz de:
Describir el funcionamiento de la jerarqua de objetos.
Usar el tipo object.

Uso de variables de tipo referencia

24

El tipo object
Objetivo del tema

Presentar el tipo object.

Explicacin previa

El tipo object es la clase


base pasa todas las dems
clases en C#.

Sinnimo de System.Object

Clase base para todas las dems clases

Object
Object
String
String

Exception
Exception

MyClass
MyClass

SystemException
SystemException

El tipo object es la clase base pasa todas los dems tipos en C#.

System.Object
Recomendacin al
profesor

La herencia se discute en el
Mdulo 10, "Herencia en
C#", del Curso 2124C,
Programacin en C#. Por el
momento no es necesario
que discuta en profundidad
el concepto de herencia.

La palabra reservada object es un sinnimo de la clase System.Object en.NET


Framework. Siempre que aparezca la palabra object se puede poner en su lugar
el nombre de clase System.Object. Normalmente se emplea la forma ms corta.

Clase base
Todas las clases, incluidas las que se escriben para una aplicacin o las que
forman parte del marco de trabajo del sistema, heredan directa o indirectamente
de object. Cuando se declara una clase sin una clase padre explcita, lo que se
est haciendo en realidad es heredar de object.

Uso de variables de tipo referencia

25

Mtodos comunes
Objetivo del tema

Presentar algunos de los


mtodos comunes del tipo
object.

Explicacin previa

El tipo object contiene


varios mtodos comunes
que heredan todos los
dems tipos referencia.

Mtodos comunes para todos los tipos referencia


z

Mtodo ToString

Mtodo Equals

Mtodo GetType

Mtodo Finalize

El tipo object contiene varios mtodos comunes que heredan todos los dems
tipos referencia.

Mtodos comunes para todos los tipos referencia


El tipo object proporciona varios mtodos comunes. Los mtodos derivados
tambin incluyen estos mtodos, ya que todos ellos heredan de object. Entre
estos mtodos comunes estn los siguientes:
ToString
Equals
GetType
Finalize

Mtodo ToString
El mtodo ToString devuelve una cadena de caracteres que representa el objeto
actual.
Su forma predeterminada, que se encuentra en la clase Object, devuelve el
nombre de tipo de la clase. El siguiente ejemplo utiliza la clase coordinate
definida anteriormente:
coordenada c = new coordinate( );
Console.WriteLine(c.ToString( ));

Este ejemplo escribir coordenada en la consola.

Uso de variables de tipo referencia

26

Sin embargo, es posible sobrecargar el mtodo ToString en la clase coordinate


para que devuelva objetos de ese tipo que sean ms representativos, como una
cadena con los valores que contiene el objeto.

Uso de variables de tipo referencia

27

Mtodo Equals
El mtodo Equals determina si el objeto especificado es el mismo que el objeto
actual. Como ya hemos visto, la forma predeterminada de Equals incluye
nicamente la igualdad entre referencias.
Este mtodo puede ser reemplazado por subclases para incluir la igualdad entre
valores.

Mtodo GetType
Este mtodo permite extraer de un objeto informacin sobre su tipo en tiempo
de ejecucin. Se discutir con ms detalle en la seccin sobre conversiones de
datos de este mismo mdulo.

Mtodo Finalize
El sistema de tiempo de ejecucin hace una llamada a este mtodo cuando un
objeto se hace inaccesible.

Uso de variables de tipo referencia

28

Reflexin
Objetivo del tema

Introducir el concepto de
reflexin.

Explicacin previa

En ocasiones es necesario
obtener informacin sobre el
tipo de objeto. Es lo que en
C# se conoce como
reflexin.

Es posible obtener informacin sobre el tipo de un objeto

Espacio de nombres System.Reflection

El operador typeof devuelve el tipo de un objeto


z

Mtodo GetType en System.Object


z

Recomendacin al
profesor

Slo para clases en tiempo de compilacin


Informacin sobre clases en tiempo de ejecucin

Es posible obtener informacin sobre el tipo de un objeto empleado un


mecanismo llamado reflexin.

En otros lenguajes, la
reflexin se conoce como
identificacin de tipos en
tiempo de ejecucin (RTTI).

El mecanismo de reflexin en C# est controlado por el espacio de nombres


System.Reflection en .NET Framework, que contiene clases e interfaces que
proporcionan una vista de tipos, mtodos y campos.

Recomendacin al
profesor

La clase System.Type incluye mtodos que permiten obtener informacin


sobre una declaracin de tipo, como los constructores, mtodos, campos,
propiedades y eventos de una clase. Un objeto Type que representa un tipo es
nico; es decir, dos referencias de objeto Type slo apuntan al mismo objeto si
representan el mismo tipo. Esto hace posible comparar objetos Type utilizando
comparaciones de referencias (los operadores == and !=).

Al contrario de lo que ocurre


en C y C++, typeof slo se
puede aplicar a nombres de
clases, no a variables ni a
expresiones.

Uso de variables de tipo referencia

29

El operador typeof
En tiempo de compilacin se puede utilizar el operador typeof para obtener
informacin de tipo para un nombre de tipo concreto.
Este ejemplo obtiene informacin en tiempo de compilacin para el tipo byte y
muestra el nombre del tipo en la consola.
using System;
using System.Reflection;
Type t = typeof(byte);
Console.WriteLine("Type: {0}", t);

El siguiente ejemplo muestra informacin ms detallada sobre una clase. Ms


concretamente, muestra los mtodos para esa clase.
using System;
using System.Reflection;
Type t = typeof(string); // Obtener informacin sobre tipo
InfoMetodos [ ] mi = t. GetMethods( );
foreach (MethodInfo m in mi) {
Console.WriteLine("Method: {0}", m);
}

Mtodo GetType
El operador typeof slo funciona con clases que existen en tiempo de
compilacin. Cuando se necesita informacin sobre tipo en tiempo de ejecucin
se puede emplear el mtodo GetType de la clase Object.
Para ms informacin sobre reflexin, busque System.Reflection en los
documentos de ayuda del SDK de .NET Framework.

Uso de variables de tipo referencia

30

Espacios de nombres en .NET Framework


Objetivo del tema

Ofrecer una introduccin a


los temas tratados en esta
seccin.

Explicacin previa

En esta leccin veremos


cmo C# utiliza .NET
Framework.

Espacio de nombres System.IO

Espacio de nombres System.Xml

Espacio de nombres System.Data

Otros espacios de nombres tiles

El marco de trabajo .NET Framework incluye servicios de lenguaje comn para


distintas herramientas de desarrollo de aplicaciones. Las clases que contiene
proporcionan una interfaz para el runtime de lenguaje comn, el sistema
operativo y la red.
.NET Framework es demasiado grande y ofrece demasiadas prestaciones como
para poder incluir en este curso todas sus caractersticas. Si desea informacin
ms detallada, consulte los documentos de ayuda de Microsoft Visual Studio
.NET y del SDK de .NET Framework.
Al final de esta leccin, usted ser capaz de:
Identificar espacios de nombres comunes en el marco de trabajo.
Usar algunos de los espacios de nombres comunes en el marco de trabajo.

Uso de variables de tipo referencia

31

Espacio de nombres System.IO


Objetivo del tema

Describir brevemente la
funcionalidad de
System.IO.

Explicacin previa

El espacio de nombres
System.IO proporciona
muchas clases tiles para
trabajar con archivos y
directorios.

Acceso a entrada/salida del sistema de archivos


z

File, Directory

StreamReader, StreamWriter

FileStream

BinaryReader, BinaryWriter

El espacio de nombres System.IO es importante porque contiene muchas clases


que permiten a una aplicacin efectuar distintas operaciones de entrada y salida
(I/O) en el sistema de archivos.
Incluye tambin clases para que una aplicacin pueda realizar operaciones de
entrada y salida sobre archivos y directorios.
El espacio de nombres System.IO es demasiado grande para que podamos
explicarlo aqu con detalle. No obstante, la siguiente lista da una idea de las
posibilidades:
Las clases File y Directory permiten a una aplicacin crear, borrar y
manipular directorios y archivos.
Las clases StreamReader y StreamWriter permiten a un programa
acceder a los contenidos de un archivo como una secuencia de bytes o
caracteres.
La clase FileStream se puede emplear para dar acceso aleatorio a archivos.
Las clases BinaryReader y BinaryWriter ofrecen una forma de leer y
escribir tipos de datos primitivos como valores binarios.

Uso de variables de tipo referencia

32

Ejemplo de System.IO
A continuacin se incluye un breve ejemplo en el que se muestra cmo abrir y
leer un archivo como una secuencia. Este ejemplo no es indicativo de todas las
maneras posibles de emplear el espacio de nombres System.IO, pero ilustra
cmo se puede efectuar una sencilla operacin de copia de archivos.
using System;
using System.IO; // Usar espacio de nombres IO
// ...
StreamReader reader = new StreamReader("archivoentrada.txt");
// Entrada de texto desde archivo
StreamWriter writer = new StreamWriter("archivosalida.txt");
// Salida de texto a archivo
string line;
while ((line = reader.ReadLine( )) != null)
{
writer.WriteLine(line);
}
reader.Close( );
writer.Close( );

Para abrir un archivo para lectura, el cdigo del ejemplo crea un nuevo objeto
StreamReader y pasa el nombre del archivo que se desea abrir en el
constructor. Del mismo modo, el ejemplo crea un nuevo objeto StreamWriter
y pasa el nombre del archivo de salida en su constructor para abrir un archivo
para escritura. En este ejemplo los nombres de los archivos estn incluidos en el
cdigo, pero tambin podran ser variables string.
El programa del ejemplo copia un archivo leyendo lnea a lnea de la secuencia
de entrada y escribiendo esa lnea en la secuencia de salida.
ReadLine y WriteLine nos pueden resultar familiares, ya que a clase Console
incluye dos mtodos estticos del mismo nombre. En el ejemplo, estos mtodos
son mtodos de instancia de las clases StreamReader y StreamWriter,
respectivamente.
Para ms informacin sobre el espacio de nombres System.IO, busque espacio
de nombres System.IO en los documentos de ayuda del SDK de .NET
Framework.

Uso de variables de tipo referencia

33

Espacio de nombres System.Xml


Objetivo del tema

Describir el espacio de
nombres System.Xml.

Explicacin previa

Las aplicaciones que tienen


que interactuar con XML
pueden usar el espacio de
nombres System.Xml.

Compatibilidad con XML

Estndares de XML

Las aplicaciones que tienen que interactuar con XML (lenguaje de marcado
extensible) pueden usar el espacio de nombres System.Xml, que proporciona la
funcionalidad necesaria para procesar XML a partir de estndares del sector.
El espacio de nombres System.Xml es compatible con varios estndares de
XML, incluyendo los siguientes:
XML 1.0 con definicin de tipo de documento (Document Type Definition,
DTD)
Espacios de nombres XML
Esquemas XSD
Expresiones XPath
Transformaciones XSL/T
DOM Level 1 core
DOM Level 2 core
La clase XmlDocument se emplea para representar un documento XML
completo. Los elementos y atributos en un documento XML se representan en
las clases XmlElement y XmlAttribute.
Este curso no incluye una discusin detallada de los espacios de nombres para
XML. Para ms informacin, busque espacio de nombres System.Xml en los
documentos de ayuda del SDK de .NET Framework.

Uso de variables de tipo referencia

34

Espacio de nombres System.Data


Objetivo del tema

Describir los espacios de


nombres
System.Data.SqlClient y
System.Data.ADO.

Explicacin previa

El espacio de nombres
System.Data.SqlClient
permite acceder a SQL
Server. El espacio de
nombres System.Data
consta bsicamente de las
clases que constituyen la
arquitectura ADO.NET.

System.Data.SqlClient
z

SQL Server .NET Data Provider

System.Data
z

Consta bsicamente de las clases que constituyen la


arquitectura ADO.NET

El espacio de nombres System.Data contiene clases que constituyen la


arquitectura ADO.NET, que permite crear componentes que administran de
forma eficaz datos procedentes de distintas fuentes. ADO.NET proporciona las
herramientas necesarias para solicitar, actualizar y reconciliar datos en sistemas
de n niveles.
Dentro de ADO.NET se puede usar la clase DataSet. En cada DataSet hay
objetos DataTable, y cada DataTable contiene a su vez datos procedentes de
una nica fuente, como Microsoft SQL Server.
El espacio de nombres System.Data.SqlClient proporciona acceso directo a
SQL Server. Este espacio de nombres es especfico para SQL Server.
Para acceder a otras bases de datos relacionales y fuentes de datos estructurados
se puede utilizar el espacio de nombres System.Data.OleDb, que proporciona
acceso de alto nivel a los controladores de bases de datos OLEDB.
Este curso no incluye una discusin detallada de los espacios de nombres
System. Para ms informacin, busque espacio de nombres System.Data en
los documentos de ayuda del SDK de .NET Framework.

Uso de variables de tipo referencia

35

Otros espacios de nombres tiles


Objetivo del tema

Ofrecer un breve resumen


de otros componentes tiles
de .NET Framework.

Explicacin previa

.NET Framework contiene


muchos otros componentes
tiles.

Recomendacin al
profesor

No intente explicar el uso de


estos componentes del
marco de trabajo. Limtese
a mencionar que existen y
siga adelante.

Espacio de nombres System

Espacio de nombres System.Net

Espacio de nombres System.Net.Sockets

Espacio de nombres System.Windows.Forms

Hay muchos ms espacios de nombres y clases tiles en .NET Framework.


Aunque en este curso no los vamos a tratar con detalle, la siguiente informacin
puede resultar til para buscar la documentacin y los archivos de referencia:
El espacio de nombres System contiene clases que definen tipos de datos
valor y referencia, eventos e identificadores de eventos, interfaces, atributos
y excepciones de procesamiento que se utilizan con frecuencia. Otras clases
proporcionan servicios para conversin de tipos de datos, manipulacin de
parmetros de mtodos, matemticas, invocacin remota y local a
programas y administracin de aplicaciones.
El espacio de nombres System.Net proporciona una sencilla interfaz de
programacin para muchos de los protocolos que se utilizan hoy en da en
la red. El espacio de nombres System.Net.Sockets contiene una
implementacin de la interfaz Microsoft Windows Sockets para
desarrolladores que requieren acceso de bajo nivel a sistemas de redes
TCP/IP (protocolo de control de transporte/protocolo Internet).

Para su informacin

System.WAO se llamaba
System.WinForms en las
primeras versiones del SDK
de .NET Framework.

System.Windows.Forms es el marco de trabajo de interfaz grfica de


usuario (GUI) para aplicaciones Windows y permite utilizar formularios,
controles e identificadores de eventos.
Para ms informacin sobre espacios de nombres System, busque espacio de
nombres System en los documentos de ayuda del SDK de .NET Framework.

Uso de variables de tipo referencia

36

Conversiones de datos
Objetivo del tema

Ofrecer una introduccin a


los temas tratados en esta
seccin.

Explicacin previa

Esta seccin explica cmo


realizar conversiones de
datos entre tipos referencia
en C#.

Conversin de tipos valor

Conversiones padre/hija

El operador is

El operador as

Conversiones y el tipo object

Conversiones e interfaces

Boxing y unboxing

Esta seccin explica cmo realizar conversiones de datos entre tipos referencia
en C#. Es posible convertir referencias de un tipo a otro, pero debe existir una
relacin entre los tipos referencia.
Al final de esta leccin, usted ser capaz de:
Identificar conversiones permitidas y prohibidas entre tipos referencia.
Usar mecanismos de conversin (casts, is y as).
Identificar aspectos especiales a tener en cuenta para la conversin a y desde
el tipo object.
Usar el mecanismo de reflexin, que permite examinar informacin sobre
tipos en tiempo de ejecucin.
Realizar conversiones automticas (boxing y unboxing) entre tipos valor y
tipos referencia.

Uso de variables de tipo referencia

37

Conversin de tipos valor


Objetivo del tema

Repasar los mecanismos de


conversin de tipo para
tipos valor.

Explicacin previa

Este tema es un repaso de


lo ya aprendido sobre
conversiones de tipo para
tipos valor.

Conversiones implcitas

Conversiones explcitas
z

Operador de cast

Excepciones

Clase System.Convert
z

Control interno de conversiones

C# permite las conversiones de datos implcitas y explcitas.

Conversiones implcitas
Para tipos valor hemos aprendido dos formas de convertir datos: conversin
implcita y conversin explcita utilizando el operador de cast (molde).
Recomendacin al
profesor

Este tema es
fundamentalmente un
repaso de la conversin de
datos tal como se explic en
mdulos anteriores. La
nica novedad se refiere a
la clase System.Convert.

Se dice que una conversin es implcita cuando un valor de un tipo se asigna a


otro tipo. C# nicamente permite la conversin implcita para ciertas
combinaciones de tipos, normalmente cuando el primer valor se puede convertir
al segundo sin prdida de datos. El siguiente ejemplo muestra una conversin
implcita de datos de int a long:
int a = 4;
long b;
b = a; // Conversin implcita de int a long

Conversiones explcitas
Los tipos valor se pueden convertir explcitamente usando el operador de cast,
como en este ejemplo:
int a;
long b = 7;
a = (int) b;

Uso de variables de tipo referencia

38

Excepciones
Al utilizar el operador de cast hay que tener en cuenta que pueden surgir
problemas si la variable de destino no puede contener el valor. Si se detecta un
problema durante una conversin explcita (como tratar de encajar el valor
9.999.999.999 en una variable int), C# puede lanzar una excepcin (en este
caso, OverflowException). Si se desea, se pueden utilizar bloques try-catch
para capturar la excepcin:
try {
a = checked((int) b);
}
catch (Exception) {
Console.WriteLine("Problema en cast");
}

En operaciones con enteros hay que emplear la palabra reservada checked o


bien compilar utilizando la configuracin adecuada del compilador, ya que de
lo contrario no se efectuar la comprobacin.

Clase System.Convert
Las conversiones entre los distintos tipos base (como int, long y bool) se
controlan mediante la clase System.Convert de .NET Framework.
Normalmente no es necesario hacer llamadas a mtodos de System.Convert, ya
que el compilador realiza esas llamadas automticamente.

Uso de variables de tipo referencia

39

Conversiones padre/hija
Objetivo del tema

Explicar las reglas para


conversin de tipo entre
referencias para clases
padres e hijas.

Explicacin previa

Bajo ciertas circunstancias,


es posible convertir una
referencia a un objeto de
una clase hija a un objeto
de su clase padre, y
viceversa.

Conversin a referencia de clase padre


z

Implcita o explcita

Siempre tiene xito

Siempre se puede asignar a un objeto

Conversin a referencia de clase hija


z

Es necesario cast explcito

Comprueba que la referencia es del tipo correcto

Si no lo es, causa una excepcin InvalidCastException

Bajo ciertas circunstancias, es posible convertir una referencia a un objeto de


una clase hija a un objeto de su clase padre, y viceversa.

Conversin a referencia de clase padre


Las referencias a objetos de un tipo de clase se pueden convertir en referencias
a otro tipo si una clase hereda directa o indirectamente de la otra.
Siempre es posible convertir una referencia a un objeto en una referencia a un
objeto de una clase padre. Esta conversin se puede realizar de forma implcita
(por asignacin o como parte de una expresin) o explcita (utilizando el
operador de cast).
En los siguientes ejemplos se usarn dos clases: Animal y Pjaro. Animal es
la clase padre de Pjaro o, por decirlo de otro modo, Pjaro hereda de
Animal.
En este ejemplo se declara una variable de tipo Animal y otra de tipo Pjaro:
Animal a;
Pajaro b = new Pajaro(...);

Supongamos ahora la siguiente asignacin, en la que la referencia en b se copia


a a:
a = b;

La clase Pjaro hereda de la clase Animal y, por lo tanto, un mtodo que est
en Animal estar tambin en Pjaro (es posible que la clase Pjaro haya
sustituido algunos mtodos de Animal para crear su propia versin de ellos,
pero en cualquier caso el mtodo estar presente en alguna forma). Como

Uso de variables de tipo referencia

40

consecuencia, es posible asignar referencias a objetos Pjaro a variables que


contengan referencias a objetos de tipo Animal.
En este caso, C# efecta una conversin de tipo de Pjaro a Animal. Para
hacer una conversin explcita de Pjaro a Animal se puede usar un operador
de cast:
a = (Animal) b;

Este cdigo dar exactamente el mismo resultado.

Conversin a referencia de clase hija


Tambin es posible convertir una referencia a un tipo de clase hija, pero es
necesario hacerlo de forma explcita con un operador de cast. Una conversin
explcita se somete a una comprobacin en tiempo de ejecucin para garantizar
que los tipos son compatibles, como se ve en el siguiente ejemplo:
Pajaro b = (Pajaro) a; // Okay

Este cdigo se compilar sin problemas. El operador de cast efecta una


comprobacin en tiempo de ejecucin para determinar si el objeto al que se
apunta est realmente en la clase Pjaro, y si no lo est lanza la excepcin
InvalidCastException.
Si se intenta hacer una asignacin a un tipo de clase hija sin emplear un
operador de conversin, como en el siguiente cdigo, el compilador mostrar el
mensaje de error Imposible convertir tipo Animal a Pjaro de forma
implcita.
Recomendacin al
profesor

Recuerde que todos los


Pjaros son Animales, pero
no todos los Animales son
Pjaros. Por esta razn es
necesario que el sistema de
tiempo de ejecucin
compruebe el operador de
cast.

b = a; // No se compila

Como con cualquier otra excepcin, se puede utilizar un bloque try-catch para
capturar un error de conversin de tipo, como en el siguiente cdigo:
try {
b = (Pajaro) a;
}
catch (InvalidCastException) {
Console.WriteLine("No es Pjaro");
}

Uso de variables de tipo referencia

41

El operador is
Objetivo del tema

Introducir y explicar el
operador is.

Explicacin previa

El operador is permite
determinar si una referencia
a un objeto se puede
convertir en una referencia
a una clase concreta.

Devuelve true si es posible realizar una conversin

Pajaro
Pajaro b;
b;
if
if (a
(a is
is Pajaro)
Pajaro)
bb == (Pajaro)
(Pajaro) a;
a; //
// No
No hay
hay problema
problema
else
else
Console.WriteLine("No
Console.WriteLine("No es
es Pjaro");
Pjaro");

Es posible controlar los tipos incompatibles capturando la excepcin


InvalidCastException, pero hay otras formas de hacer frente a este problema,
como el operador is.
El operador is se puede utilizar para probar el tipo del objeto sin efectuar una
conversin. Este operador devuelve true si el valor de la izquierda no es null y
es posible realizar un cast a la clase de la derecha sin que se lance una
excepcin; en caso contrario, devuelve false.
if (a is Pajaro)
b = (Pajaro) a; // No hay problema, ya que "a es Pajaro "
devuelve true
else
Console.WriteLine("No es Pjaro");

Podemos pensar en las relaciones entre clases heredadas como si indicaran una
relacin es un tipo de, como en Un pjaro es un tipo de animal. Las
referencias en la variable a deben ser referencias a objetos Animal, y b es un
tipo de animal. Por supuesto, b es tambin un pjaro, pero un pjaro no es ms
que un caso especial de un animal. Lo contrario no es cierto: Un animal no es
un tipo de pjaro; algunos animales son pjaros, pero no es cierto (true) que
todos los animales sean pjaros.
Recomendacin al
profesor

Puede ser conveniente


discutir el significado de a
es Pjaro si a es una
instancia de una nueva
clase Loro, que hereda de
Pjaro.

As, la siguiente expresin se puede leer como Si a es un tipo de pjaro o Si


a es un pjaro o un tipo derivado de pjaro:
if (a is Pajaro)

Uso de variables de tipo referencia

42

El operador as
Objetivo del tema

Introducir y explicar el
operador as.

Explicacin previa

El operador as permite
hacer conversiones entre
tipos referencia sin causar
una excepcin.

Hace conversiones entre tipos referencia, como cast

En caso de error
z

Devuelve null

No causa una excepcin

Pajaro
Pajaro bb == aa as
as Pajaro;
Pajaro; //
// Convertir
Convertir
if
if (b
(b ==
== null)
null)
Console.WriteLine("No
Console.WriteLine("No es
es Pjaro);
Pjaro);

Se puede utilizar el operador as para realizar conversiones entre tipos.

Ejemplo
La siguiente instruccin realiza una conversin de la referencia en a a un valor
que apunta a una clase de tipo Pjaro, y el runtime comprueba
automticamente que la conversin est permitida.
b = a as Pajaro;

Tratamiento de errores
El operador as se diferencia del operador de cast por su forma de controlar los
errores. Si en el ejemplo anterior no fuera posible convertir la referencia en la
variable a en una referencia a un objeto de clase Pjaro, se almacenara en b el
valor null y el programa continuara. El operador as nunca causa una
excepcin.
El cdigo anterior se puede rescribir de la siguiente manera para que muestre un
mensaje de error si no se puede hacer la conversin:
Pajaro b = a as Pajaro;
if (b == null)
Console.WriteLine("No es Pjaro");

Aunque as nunca causa una excepcin, cualquier intento de acceso por el valor
convertido producir una excepcin NullReferenceException si ese valor es
null. Por lo tanto hay que comprobar siempre el valor devuelto por as.

Uso de variables de tipo referencia

43

Conversiones y el tipo object


Objetivo del tema

Explicar cmo convertir el


tipo object a y desde otros
tipos referencia.

Explicacin previa

Todos los tipos referencia


se basan en el tipo object.
Esto significa que es posible
almacenar cualquier
referencia en una variable
de tipo object.

El tipo object es la base para todas las clases

Se puede asignar a object cualquier referencia

Se puede asignar cualquier variable object a cualquier


referencia
z

Con conversin de tipo y comprobaciones

El tipo object y el operador is

object
object buey;
buey;
buey
buey == a;
a;
buey
buey == (object)
(object) a;
a;
buey
=
a
buey = a as
as object;
object;

bb == (Pajaro)
(Pajaro) buey;
buey;
bb == buey
buey as
as Pajaro;
Pajaro;

Todos los tipos referencia se basan en el tipo object. Esto significa que es
posible almacenar cualquier referencia en una variable de tipo object.

El tipo object es la base para todas las clases


El tipo object es la base para todos los tipos referencia.

Se puede asignar a object cualquier referencia


Puesto que todas las clases se basan directa o indirectamente en el tipo object,
es posible asignar cualquier referencia a una variable de tipo object usando una
conversin implcita o un operador de cast. El cdigo siguiente muestra un
ejemplo:

Uso de variables de tipo referencia

Recomendacin al
profesor

Puede comparar con


Variant en Visual Basic,
pero el mecanismo no es
igual. Un Variant de Visual
Basic es una estructura con
un designador de tipo y un
valor, y no se basa en
referencias.
En Visual Basic, Object
representa una interfaz
IDispatch COM latebound. Asegrese de que
los programadores de
Visual Basic comprenden
que object en C# no tiene
relacin con COM.

object
buey =
buey =
buey =

44
buey;
a;
(object) a;
a as object;

Se puede asignar cualquier variable object a cualquier


referencia
Es posible asignar un valor de tipo object a la referencia de cualquier otro
objeto, siempre y cuando se aplique correctamente el operador cast. Hay que
recordar que el sistema de tiempo de ejecucin comprobar que el valor
asignado es del tipo correcto. El cdigo siguiente muestra un ejemplo:
b = (Pajaro) buey;
b = buey as Pajaro;

Uso de variables de tipo referencia

45

Los ejemplos anteriores se pueden escribir con comprobacin completa de


errores de la siguiente manera:
try {
b = (Pajaro) buey;
}
catch (InvalidCastException) {
Console.WriteLine("No es posible convertir a Pjaro");
}
b = buey as Pajaro;
if (b == null)
Console.WriteLine("No es posible convertir a Pjaro");

El tipo object y el operador is


Puesto que en ltimo trmino todos los valores derivan de object, el operador is
siempre devolver true cuando compruebe si un valor es object.
if (a is object) // Siempre devuelve true

Uso de variables de tipo referencia

46

Conversiones e interfaces
Objetivo del tema

Explicar las conversiones de


tipos con interfaces.

Explicacin previa

Los operadores as, is y de


cast tambin se pueden
aplicar a interfaces.

Una interfaz slo se puede usar para acceder a sus


propios miembros

No es posible acceder a otros miembros y variables de


la clase a travs de la interfaz

Cuando se trabaja con interfaces es posible utilizar los operadores as, is y de


cast para hacer conversiones.
Por ejemplo, se puede declarar una variable de un tipo interfaz, como:
IHashCodeProvider hcp;

Conversin de una referencia a una interfaz


El operador de cast se puede usar para convertir la referencia al objeto en una
referencia a una interfaz determinada:
IHashCodeProvider hcp;
hcp = (IHashCodeProvider) x;

Como ocurre en la conversin entre referencias de clase, el operador de cast


producir una excepcin InvalidCastException si el objeto indicado no
implementa la interfaz. Antes de aplicar el cast a un objeto hay que determinar
si ese objeto es compatible con una interfaz, o bien usar un bloque try-catch
para capturar la excepcin.

Implementacin de una interfaz


Se puede usar el operador is para determinar si un objeto es compatible con una
interfaz. La sintaxis es la misma que la que se utiliza para clases:
Recomendacin al
profesor

Podra ser aconsejable leer


esto como "si x implementa
IHashCodeProvider".

if (x is IHashCodeProvider) ...

Uso de variables de tipo referencia

47

Uso del operador as


Tambin se puede utilizar el operador as como alternativa a cast:
IHashCodeProvider hcp;
hcp = x as IHashCodeProvider;

Como ocurre en la conversin entre clases, el operador as devuelve null si la


referencia convertida no es compatible con la interfaz.
Una vez convertida una referencia a una clase en una referencia a una interfaz,
la nueva referencia puede acceder nicamente a miembros de esa interfaz, y no
a los otros miembros pblicos de la clase.

Ejemplo
Consideremos el siguiente ejemplo para cmo funciona la conversin de
referencias en interfaces. Supongamos que hemos creado una interfaz llamada
IVisual que especifica un mtodo llamado Paint:
interface IVisual
{
void Paint( );
}

Supongamos que tenemos tambin una clase Rectangle que implementa la


interfaz IVisual. Implementa por tanto el mtodo Paint, aunque tambin puede
definir sus propios mtodos. En este ejemplo, Rectangle ha definido otro
mtodo llamado Move que no forma parte de IVisual.
Recomendacin al
profesor

No se muestra la sintaxis
para herencia porque se
discutir en un mdulo
posterior.

Como era de esperar, es posible crear un Rectangle, r, y usar sus mtodos


Move y Paint. Incluso podemos referenciarlo a travs de una variable IVisual,
v. Sin embargo, a pesar del hecho de que tanto v como r apuntan al mismo
objeto en la memoria, no es posible usar v para llamar al mtodo Move porque
no forma parte de la interfaz IVisual. El siguiente cdigo ofrece algunos
ejemplos:
Rectangle r = new Rectangle( );
r.Move( );
// Okay
r.Paint( ); // Okay
IVisual v = (IVisual) r;
v.Move( );
// Not valid
v. Paint( );
// Okay

Uso de variables de tipo referencia

48

Boxing y unboxing
Objetivo del tema

Explicar los conceptos de


boxing y unboxing.

Explicacin previa

C# puede convertir
automticamente tipos valor
en referencias a objetos y
referencias a objetos en
tipos valor.

Sistema de tipos unificado

Boxing

Unboxing

Llamadas a mtodos de object en tipos valor


int
int pp == 123;
123;
object
object box;
box;
box
box == p;
p;

123
123

pp == (int)box;
(int)box;

123
123

C# puede convertir tipos valor en referencias a objetos y referencias a objetos


en tipos valor.

Sistema de tipos unificado


C# tiene un sistema unificado de tipos que permite convertir tipos valor en
referencias de tipo object y referencias a objetos en tipos valor. Es posible
convertir tipos valor en referencias de tipo object y viceversa.
De esta forma, los valores de tipos como int y bool se pueden tratar como
valores simples en casi todos los casos. Normalmente sta es la tcnica ms
eficaz, ya que se evitan las complicaciones causadas por las referencias. Sin
embargo, tambin hay un sistema que permite poner estos valores
temporalmente en una caja (box) y utilizarlos como si fueran referencias
cuando sea necesario.

Boxing
Las expresiones de tipos valor tambin se pueden convertir en valores de tipo
object, y viceversa. Si se quiere convertir una variable de tipo valor en un tipo
object, se asigna un objeto box para contener el valor y se copia ste en la caja.
Este proceso se conoce con el nombre de boxing.
int p = 123;
object box;
box = p;
// Boxing (implicit)
box = (object) p; // Boxing (explicit)

La operacin de boxing puede ser implcita o explcita (con un cast a un


objeto). El boxing se usa especialmente cuando se pasa un tipo valor a un
parmetro de tipo object.

Uso de variables de tipo referencia

49

Unboxing
Cuando un valor en un objeto se vuelve a convertir en un tipo valor, el valor se
saca de la caja y se copia en la ubicacin correspondiente. Este proceso se
conoce con el nombre de unboxing.
p = (int) box;

// Unboxing

La operacin de unboxing se tiene que hacer con un operador de cast explcito.


Si el valor en la referencia no es exactamente del mismo tipo que el cast, ste
produce una excepcin InvalidCastException.

Llamadas a mtodos de object en tipos valor


El hecho de que el boxing pueda ser implcito permite hacer llamadas a
mtodos del tipo object type en cualquier variable o expresin, aunque tengan
tipos valor. El cdigo siguiente muestra un ejemplo:
static void Show(object o)
{
Console.WriteLine(o.ToString( ));
}
Show(42);

Este cdigo funciona porque de forma implcita se est aplicando boxing al


valor 42 para convertirlo en un parmetro object, y a continuacin se hace una
llamada al mtodo ToString de este parmetro.
El resultado es el mismo que con el cdigo siguiente:
object o = (object) 42; // Boxing
Console.WriteLine(o.ToString( ));

Nota Cuando se llama a mtodos de Object directamente en un valor no se


produce boxing. Por ejemplo, la expresin 42.ToString( ) no aplica boxing
a 42 para convertirlo en un object. Esto se debe a que el compilador puede
determinar estticamente el tipo y decidir qu mtodo llamar.

Creacin y destruccin de
objetos

Contenido
Descripcin general
Uso de constructores
Objetos y memoria

1
2
13

Creacin y destruccin de objetos

Notas para el instructor


Este mdulo proporciona a los estudiantes la teora y la sintaxis necesarias para
crear y destruir objetos en una aplicacin C#.
Al final de este mdulo, los estudiantes sern capaces de:
Crear objetos usando el operador new.
Usar constructores para inicializar objetos.
Describir el tiempo de vida de un objeto y qu ocurre cuando se destruye.
Crear destructores.
Heredar de la interfaz IDisposable y usar el mtodo Dispose.

Creacin y destruccin de objetos

Descripcin general
Objetivo del tema

Ofrecer una introduccin a


los contenidos y objetivos
del mdulo.

Explicacin previa

En este mdulo
aprenderemos a controlar el
proceso de creacin y
destruccin de objetos.

Uso de constructores

Objetos y memoria

En este mdulo veremos qu ocurre cuando se crea un objeto y cmo se usan


constructores y destructores para inicializar y destruir objetos. Tambin
discutiremos qu ocurre cuando se destruye un objeto y cmo la recoleccin de
basura consume memoria.
Al final de este mdulo, usted ser capaz de:
Usar constructores para inicializar objetos.
Crear constructores sobrecargados que pueden aceptar parmetros variables.
Describir el tiempo de vida de un objeto y qu ocurre cuando se destruye.
Crear destructores.
Utilizar el mtodo Dispose.

Creacin y destruccin de objetos

Uso de constructores
Objetivo del tema

Ofrecer una introduccin a


los temas tratados en esta
seccin.

Explicacin previa

En esta seccin
discutiremos los
constructores y su uso para
inicializar objetos.

Creacin de objetos

Uso del constructor por defecto

Sustitucin del constructor por defecto

Sobrecarga de constructores

Los constructores son mtodos especiales que se utilizan para inicializar objetos
cuando se crean. Aunque no se escriba ningn constructor, existe uno por
defecto que se usa cuando se crea un objeto a partir de un tipo referencia.
Al final de esta leccin, usted ser capaz de:
Usar constructores por defecto.
Usar constructores para controlar lo que ocurre cuando se crea un objeto.

Creacin y destruccin de objetos

Creacin de objetos

Objetivo del tema

Describir el proceso de
creacin de un objeto.

Explicacin previa

En C#, la nica forma de


crear un objeto es mediante
el uso de la palabra
reservada new para asignar
memoria.

Paso 1: Asignacin de memoria


z

Se usa new para asignar memoria desde el montn

Paso 2: Inicializacin del objeto usando un constructor


z

Se usa el nombre de la clase seguido por parntesis

Fecha
Fecha cuando
cuando == new
new Date(
Date( );
);

El proceso de creacin de un objeto en C# se divide en dos pasos:


1. Usar la palabra reservada new para adquirir y asignar memoria para el
objeto.
2. Escribir un constructor para convertir la memoria adquirida por new en un
objeto.
Aunque este proceso consta de dos pasos, ambos deben estar incluidos en una
sola expresin. Por ejemplo, si Fecha es el nombre de una clase, para asignar
memoria e inicializar el objeto cuando se usa la siguiente sintaxis:
Date when = new Date( );

Paso 1: Asignacin de memoria


El primer paso en la creacin de un objeto consiste en asignarle memoria.
Todos los objetos, sin excepcin, se crean con el operador new, ya sea de forma
explcita en el cdigo o dejando que lo haga el compilador.
La siguiente tabla contiene ejemplos de cdigo y lo que representan.
Ejemplo de cdigo

Representa

string s = "Hola";

string s = new string(new char[ ]{'H','o','l','a'});

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

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

Creacin y destruccin de objetos

Paso 2: Inicializacin del objeto usando un constructor


El segundo paso en la creacin de un objeto consiste en llamar a un constructor.
Un constructor convierte en un objeto la memoria asignada por new. Hay dos
tipos de constructores: constructores de instancia, que inicializan objetos, y
constructores estticos, que son los que inicializan clases.

Colaboracin entre new y constructores de instancia


Es importante comprender el papel que juega en la creacin de objetos la
estrecha colaboracin entre new y los constructores de instancia. Lo nico que
new hace es adquirir memoria binaria sin inicializar, mientras que el solo
propsito de un constructor de instancia es inicializar la memoria y convertirla
en un objeto que se pueda utilizar. En particular, new no participa de ninguna
manera en la inicializacin y los constructores de instancia no realizan ninguna
funcin en la adquisicin de memoria.
Aunque new y los constructores de instancia realizan tareas independientes, un
programador no puede emplearlos por separado. De esta forma, C# contribuye a
garantizar que la memoria est siempre configurada para un valor vlido antes
de que se lea (a esto se le llama asignacin definida).
Nota para programadores de C++ En C++ es posible asignar memoria sin
inicializarla (llamando directamente al operador new) e inicializar memoria
asignada previamente (usando new de posicin). Esta separacin no est
permitida en C#.

Creacin y destruccin de objetos

Uso del constructor por defecto


Objetivo del tema

Explicar lo que ocurre si no


se escribe un constructor.

Explicacin previa

Si el programador no
escribe un constructor, el
compilador se encargar de
hacerlo.

Caractersticas de un constructor por defecto


z

Acceso pblico

Mismo nombre que la clase

No tiene tipo de retorno (ni siquiera void)

No recibe ningn argumento

Inicializa todos los campos a cero, false o null

Sintaxis del constructor

class
class Date
Date {{ public
public Date(
Date( )) {{ ...
... }} }}

Si se crea un objeto sin escribir ningn constructor, el compilador de C#


utilizar un constructor por defecto. Consideremos el ejemplo siguiente:
class Fecha
{
private int ssaa, mm, dd;
}
class Test
{
static void Main( )
{
Fecha cuando = new Fecha( );
...
}
}

La instruccin en Test.Main crea un objeto Fecha llamado cuando usando


new (que asigna memoria del montn) y llamando a un mtodo especial que
tiene el mismo nombre que la clase (el constructor de instancia). Sin embargo,
la clase Fecha no declara ningn constructor de instancia (no declara ningn
mtodo). Por defecto, el compilador generar automticamente un constructor
de instancia.

Creacin y destruccin de objetos

Caractersticas de un constructor de instancia


Conceptualmente, el constructor de instancia generado por el compilador para
la clase Fecha ser parecido al siguiente:
class Fecha
{
public Fecha( )
{
ssaa = 0;
mm = 0;
dd = 0;
}
private int ssaa, mm, dd;
}

El constructor presenta las siguientes caractersticas:


Mismo nombre que la clase
Por definicin, un constructor de instancia es un mtodo que tiene el mismo
nombre que la clase a la que pertenece. Esta definicin es natural e intuitiva
y coincide con la sintaxis explicada anteriormente. Por ejemplo:
Fecha cuando = new Fecha( );

No tiene tipo de retorno


sta es la segunda caracterstica que define a un constructor. Un constructor
nunca tiene un tipo de retorno, ni siquiera void.
No necesita argumentos
Es posible declarar constructores que reciben argumentos, pero el
constructor por defecto generado por el compilador no recibe ninguno.
Todos los campos estn inicializados a cero
Esto es importante. El constructor por defecto generado por el compilador
inicializa implcitamente todos los campos no estticos de la siguiente
manera:
Para su informacin

Estas inicializaciones
predeterminadas
contribuyen a que el
constructor por defecto
generado por el compilador
nunca lance una excepcin,
aunque no lo garantizan del
todo. Podra haber una
clase base con su propio
constructor por defecto, que
por supuesto se llamara
implcitamente con la
sintaxis :base( ) (este
aspecto no se discutir en
este mdulo).

Los campos numricos (como int, double y decimal) se inicializan a


cero.
Los campos de tipo bool se inicializan a false.
Los tipos referencia (tratados en un mdulo anterior) se inicializan a
null.
Los campos de tipo struct se inicializan de forma que contengan valores
cero en todos sus elementos.
Acceso pblico
Esto permite crear nuevas instancias del objeto.
Nota En el Mdulo 10, Herencia en C#, del Curso 2124C, Programacin en
C#, se discuten las bases abstractas. El constructor por defecto generado por el
compilador para una clase abstracta tiene acceso protegido.

Creacin y destruccin de objetos

Sustitucin del constructor por defecto


Objetivo del tema

Explicar qu hay que hacer


si el constructor por defecto
no es adecuado.

Explicacin previa

En ocasiones, el constructor
por defecto generado por el
compilador no ser el
adecuado. En ese caso es
mejor no utilizarlo.

El constructor por defecto puede no ser adecuado


z

En ese caso no hay que usarlo, sino escribir otro

Class
Class Date
Date
{{
public
public Date(
Date( ))
{{
ssaa
ssaa == 1970;
1970;
mm
mm == 1;
1;
dd
dd == 1;
1;
}}
private
private int
int ccyy,
ccyy, mm,
mm, dd;
dd;
}}

En ocasiones no es conveniente emplear el constructor por defecto generado por


el compilador. En esos casos se puede escribir otro constructor que contenga
nicamente el cdigo necesario para inicializar campos con valores distintos de
cero. Todos los campos que no estn inicializados en este constructor
conservarn su inicializacin predeterminada a cero.

Qu ocurre si el constructor por defecto no es


adecuado?
Hay varias situaciones en las que el constructor por defecto generado por el
compilador puede no ser apropiado:
No siempre se quiere que el acceso sea pblico.
El patrn Factory Method utiliza un constructor que no es pblico. Este
patrn, que se discute en el libro Design Patterns: Elements of Reusable
Object-Oriented Software, de E. Gamma, R. Helm, R. Johnson y J.
Vlissides, se tratar en un mdulo posterior
Las funciones procedurales (como Cos y Sin) utilizan con frecuencia
constructores privados.
El patrn Singleton usa generalmente un constructor privado. Este patrn
tambin aparece en el libro Design Patterns: Elements of Reusable ObjectOriented Software y se discutir en un tema posterior de esta seccin.
La inicializacin a cero no siempre resulta conveniente.
Consideremos el constructor por defecto generado por el compilador para la
clase Fecha siguiente:

Creacin y destruccin de objetos

8
class Date
{
private int ccyy, mm, dd;
}

El constructor por defecto inicializar el campo de ao (ssaa) a cero, y lo


mismo har cono los campos de mes (mm) y de da (dd), lo que no resulta
conveniente si se desea que el valor por defecto de la fecha sea distinto.
El cdigo invisible s ms difcil de mantener.
El cdigo del constructor por defecto no se puede ver, lo que a veces puede
resultar un problema. Por ejemplo, durante la depuracin no es posible
ejecutar paso a paso el cdigo invisible. Por otra parte, si se utiliza la
inicializacin predeterminada a cero los desarrolladores que deban mantener
el cdigo no podrn saber si ha sido una eleccin deliberada o no.

Cmo escribir nuestro propio constructor


Si el constructor por defecto generado por el compilador no es adecuado, lo
mejor es que escribamos nuestro propio constructor. El lenguaje C# nos ayuda a
hacerlo.
Podemos escribir un constructor que contenga nicamente el cdigo necesario
para inicializar campos con valores distintos de cero. Todos los campos que no
estn inicializados en este constructor conservarn su inicializacin
predeterminada a cero. El siguiente cdigo muestra un ejemplo:
class DefaultInit
{
public int a, b;
public DefaultInit ( )
{
a = 42;
// b conserva la inicializacin predeterminada a cero
}
}
class Test
{
static void Main( )
{
DefaultInit di = new DefaultInit( );
Console.WriteLine(di.a); // Writes 42
Console.WriteLine(di.b); // Writes zero
}
}

Para evitar errores, en los constructores propios es mejor no ir ms all de


inicializaciones sencillas. La nica forma adecuada de sealar un error de
inicializacin en un constructor consiste en lanzar una excepcin.
Nota Esto tambin es vlido para operadores. Los operadores se discuten en el
Mdulo 12, Operadores, delegados y eventos del Curso 2124C,
Programacin en C#.
El objeto se podr usar si la inicializacin tiene xito; de lo contrario, es como
si no existiera.

Creacin y destruccin de objetos

Sobrecarga de constructores
Objetivo del tema

Presentar la idea de que es


posible sobrecargar
constructores para disponer
de ms de una forma de
inicializar objetos de una
clase concreta.

Explicacin previa

Los mtodos pueden estar


sobrecargados y los
constructores tambin,
puesto que los
constructores no son ms
que un tipo especial de
mtodos.

Los constructores son mtodos y pueden estar


sobrecargados
z

Mismo mbito, mismo nombre, distintos parmetros

Permite inicializar objetos de distintas maneras

AVISO
z

Si se escribe un constructor para una clase, el


compilador no crear un constructor por defecto

Class
Class Date
Date
{{
public
public Date(
Date( )) {{ ...
... }}
public
public Date(int
Date(int anno,
anno, int
int mes,
mes, int
int dia)
dia) {{ ...
... }}
...
...
}}

Los constructores son un tipo especial de mtodos y pueden estar sobrecargados


del mismo modo que los mtodos.

Qu es la sobrecarga?
Sobrecarga es el trmino tcnico para la declaracin de dos o ms mtodos en el
mismo mbito y con el mismo nombre. El siguiente cdigo muestra un ejemplo:
class Overload
{
public void Method ( ) { ... }
public void Method (int x) { ... }
}
class Use
{
static void Main( )
{
Sobrecarga o = new Overload( );
o. Method( );
o. Method(42);
}
}

En este ejemplo hay dos mtodos llamados Metodo declarados en el mbito de


la clase Sobrecarga, y se hace una llamada a ambos en Uso.Main. No hay
ninguna ambigedad, puesto que el nmero y los tipos de los argumentos
determinan el mtodo que se est llamando.

Creacin y destruccin de objetos

10

Inicializacin de un objeto de varias maneras


La posibilidad de inicializar un objeto de varias maneras es uno de los motivos
ms importantes para permitir la sobrecarga. Los constructores son un tipo
especial de mtodos y pueden estar sobrecargados exactamente del mismo
modo que los mtodos. Esto significa que es posible definir distintas formas de
inicializar un objeto. El siguiente cdigo muestra un ejemplo:
class Overload
{
public Overload( ) { this.data = -1; }
public Overload(int x) { this.data = x; }
private int data;
}
class Use
{
static void Main( )
{
Overload s1 = new Overload( );
Overload s2 = new Overload(42);
...
}
}

El objeto s1 se crea usando el constructor que no recibe ningn argumento, y se


asigna 1 a la variable de instancia privada dato. Por otra parte, el objeto s2 se
crea usando el constructor que recibe un argumento, y se asigna el valor 42 a la
variable de instancia privada dato.

Inicializacin de campos a valores distintos de los


predeterminados
Hay muchas circunstancias en las que no resulta adecuado inicializar campos a
cero. En esos casos se puede escribir otro constructor que reciba uno o ms
parmetros, que a su vez se emplean para inicializar los campos. Por ejemplo,
consideremos la clase Fecha siguiente:
class Date
{
public Date(int anno, int mes, int dia)
{
ccyy = anno;
mm = mes;
dd = dia;
}
private int ccyy, mm, dd;
}

Este constructor tiene el problema de que es fcil equivocarse en el orden de los


argumentos. Por ejemplo:
Fecha cumpleannos = new Date(23, 11, 1968); // Error

Creacin y destruccin de objetos

11

El cdigo debera ser new Fecha(1968,11,23). Este error no se detectar


durante la compilacin, ya que los tres argumentos son enteros. Una forma de
corregir el problema sera usar el patrn Whole Value y convertir Ao, Mes y
Da en structs en lugar de valores int:
struct Year
{
public readonly int value;
public Anno(int value) { this.value = value; }
}
struct Mes // O como enum
{
public readonly int value;
public Mes(int value) { this.value = value; }
}
struct Dia
{
public readonly int value;
public Dia(int valor) { this.value = value; }
}
class Date
{
public Date (Anno y, Mes m, Dia d)
{
ccyy = y.value;
mm = m.value;
dd = d.value;
}
private int ccyy, mm, dd;
}

Consejo El uso de estructuras o enumeraciones en lugar de clases para Da,


Mes y Ao reduce la sobrecarga cuando se crea un objeto Fecha, como se
explicar ms adelante en este mismo mdulo.
El siguiente cdigo muestra un sencillo cambio que no slo captura errores en
el orden de los argumentos, sino que tambin permite crear constructores
sobrecargados de Fecha con formato europeo, americano e ISO:
class Date
{
public Date
public Date
public Date
...
private int
}

(Anno y, Mes m, Dia d) { ... } // ISO


(Mes m, Dia d, Anno y) { ... } // Americano
(Dia d, Mes m, Anno y) { ... } // Europeo
ccyy, mm, dd;

Creacin y destruccin de objetos

12

La sobrecarga y el constructor por defecto


Si se declara una clase con un constructor, el compilador no genera el
constructor por defecto. En el siguiente ejemplo, la clase Fecha se declara con
un constructor, por lo que la expresin new Fecha( ) no se compilar:
class Date
{
public Date(Anno y, Mes m, Dia d) { ... }
// No hay otros constructores
private int ccyy, mm, dd;
}
class Fallo
{
static void Main( )
{
Fecha predeterminada = new Date( ); // Error de
compilacin
}
}

Esto significa que, si se quiere tener la posibilidad de crear objetos Fecha sin
argumentos para el constructor, es necesario declarar explcitamente un
constructor por defecto sobrecargado, como en el siguiente ejemplo:
class Date
{
public Date( ) { ... }
public Date(Anno y, Mes m, Dia d) { ... }
...
private int ccyy, mm, dd;
}
class Vale
{
static void Main( )
{
Fecha predeterminada = new Date( ); // Okay
}
}

Creacin y destruccin de objetos

13

Objetos y memoria
Objetivo del tema

Ofrecer una introduccin a


los temas tratados en esta
seccin.

Explicacin previa

En la seccin anterior
hemos aprendido qu
ocurre cuando se crea un
objeto. Ahora veremos qu
pasa cuando se destruye un
objeto.

Tiempo de vida de un objeto

Objetos y mbito

Recoleccin de basura

Es necesario saber qu ocurre en una aplicacin cuando un objeto, y no un


valor, est fuera de mbito o se destruye.
Al final de esta leccin, usted ser capaz de:
Identificar el papel jugado por la recoleccin de basura cuando un objeto
est fuera de mbito o se destruye.

Creacin y destruccin de objetos

14

Tiempo de vida de un objeto


Objetivo del tema

Examinar todo el ciclo de


vida de un objeto desde la
creacin hasta su
destruccin, pasando por el
uso.

Explicacin previa

En la primera seccin vimos


que el proceso de creacin
de un objeto tiene dos
pasos, uno de los cuales se
puede controlar. En esta
seccin veremos que la
destruccin de un objeto
tambin es un proceso en
dos pasos de los que
tampoco es posible
controlar ms que uno.

Creacin de objetos

Se usa un constructor para inicializar un objeto en esa


memoria

Uso de objetos
z

Se usa new para asignar memoria

Llamadas a mtodos

Destruccin de objetos
z

Se vuelve a convertir el objeto en memoria

Se libera la memoria

La destruccin de un objeto en C# es un proceso en dos pasos que


corresponden, invirtindolos, a los dos pasos del proceso de creacin del objeto.

Creacin de objetos
En la primera seccin vimos que el proceso de creacin de un objeto en C# para
un tipo referencia consta de los dos pasos siguientes:
1. Uso de la palabra reservada new para adquirir y asignar memoria.
2. Llamada a un constructor para convertir la memoria binaria adquirida por
new en un objeto.

Destruccin de objetos
La destruccin de un objeto en C# tambin es un proceso en dos pasos:
1. Se anula la inicializacin del objeto.
El objeto es convertido de nuevo en memoria binaria. Este paso, que en C#
se realiza con el destructor, es el inverso de la inicializacin efectuada por el
constructor. Es posible controlar lo que sucede en este paso escribiendo un
destructor o mtodo de finalizacin propio.
2. Se libera la memoria binaria; es decir, se devuelve la memoria al montn.
Este paso es el inverso de la asignacin realizada por new y no se puede
controlar de ninguna manera.

Creacin y destruccin de objetos

15

Objetos y mbito
Objetivo del tema

Insistir en que los valores


locales se crean y se
destruyen en momentos
conocidos, y comparar esto
con el caso de los objetos,
cuyo momento de
destruccin no se conoce.

Explicacin previa

Los valores como ints y


structs se asignan en la pila
y se destruyen al final de su
mbito de validez. Por el
contrario, los objetos se
asignan en el montn
administrado (Managed
Heap) y no se destruyen al
final de su mbito de
validez.

El tiempo de vida de un valor a local est vinculado al


mbito en el que est declarado
z

Tiempo de vida corto (en general)

Creacin y destruccin deterministas

El tiempo de vida de un objeto dinmico no est


vinculado a su mbito
z

Tiempo de vida ms largo

Destruccin no determinista

Al contrario de los valores como int y struct, que se asignan en la pila y se


destruyen al final de su mbito de validez, los objetos se asignan en el montn
administrado (Managed Heap) y no se destruyen al final de su mbito.

Valores
El tiempo de vida de un valor local est vinculado al mbito en el que est
declarado. Los valores locales son variables que se asignan en la pila y no en el
montn administrado. Esto significa que, si se declara una variable cuyo tipo es
uno de los primitivos (como int), enum o struct, no es posible usarla fuera del
mbito en el que se declara. Por ejemplo, en el siguiente fragmento de cdigo se
declaran tres valores dentro de una instruccin for, por lo que su mbito
terminar al final de esa instruccin:

Creacin y destruccin de objetos


struct Point { public int x, y; }
enum Season { Primavera, Verano, Otono, Invierno }
class Example
{
void Method(int limite)
{
for (int i = 0; i < limite; i++) {
int x = 42;
Punto p = new Punto( );
Season s = Season.Winter;
...
}
x = 42;
// Compile-time error
p = new Point ( );
// Compile-time error
s = Season.Winter; // Compile-time error
}
}

16

Creacin y destruccin de objetos

17

Nota En el ejemplo anterior da la impresin de que se crea una new Punto.


Pero Punto es una struct y new no asigna memoria del montn administrado.
La nueva Punto est creada en la pila.
De aqu se deducen las siguientes caractersticas de los valores locales:
Creacin y destruccin deterministas
Una variable local se crea en el momento de declararla y se destruye al final
del mbito en el que est declarada. El punto inicial y el punto final de la
vida del valor son deterministas; es decir, tienen lugar en momentos
conocidos y fijos.
Tiempos de vida muy cortos por lo general
Un valor se declara en alguna parte de un mtodo y no puede existir ms
all de una llamada al mtodo. Cuando un mtodo devuelve un valor, lo que
se devuelve es una copia del valor.

Objetos
El tiempo de vida de un objeto no est vinculado al mbito en el que se crea.
Los objetos se inicializan en memoria del montn asignada mediante el
operador new. Por ejemplo, en el siguiente cdigo se declara la variable
referencia ej dentro de una instruccin for, lo que significa que su terminar al
final de esa instruccin y es un a variable local. Sin embargo, ej se inicializa
con un objeto new Example( ), cuyo mbito no se acaba con el de ej.
Recordemos que una variable referencia y el objeto al que apunta son cosas
distintas.
class Example
{
void Method(int limit)
{
for (int i = 0; i < limit; i++) {
Example ej = new Example( );
...
}
// ej est fuera de mbito
// Sigue existiendo ej?
// Sigue existiendo el objeto?
}
}

De aqu se deducen las siguientes caractersticas generales de los objetos:


Destruccin no determinista
Un objeto aparece cuando se crea pero, a diferencia de un valor, no se
destruye al final del mbito en el que se crea. La creacin de un objeto es
determinista, pero no as su destruccin. No es posible controlar
exactamente cundo se destruye un objeto.
Tiempos de vida ms largos
Puesto que el tiempo de vida de un objeto no est vinculado al mtodo que
lo crea, un objeto puede existir mucho ms all de una llamada al mtodo.

Creacin y destruccin de objetos

18

Recoleccin de basura
Objetivo del tema

Presentar la recoleccin de
basura y explicar cmo
funciona.

Explicacin previa

En C# no es posible destruir
objetos de forma explcita.
En lugar de ello se utiliza un
proceso llamado recoleccin
de basura (Garbage
Collection).

No es posible destruir objetos de forma explcita

C# no incluye un inverso de new (como delete)


Ello se debe a que una funcin de eliminacin explcita
es una importante fuente de errores en otros lenguajes

Los objetos se destruyen por recoleccin de basura


z

Busca objetos inalcanzables y los destruye

Los convierte de nuevo en memoria binaria no utilizada

Normalmente lo hace cuando empieza a faltar memoria

Hasta ahora hemos visto que los objetos en C# se crean exactamente de la


misma forma que en otros lenguajes, como C++. Se utiliza la palabra reservada
new para asignar memoria del montn y se hace una llamada a un constructor
para convertir esa memoria en un objeto. Si embargo, no existen parecidos entre
C# y sus predecesores por lo que se refiere al mtodo para destruir objetos.

No es posible destruir objetos de forma explcita


Muchos lenguajes de programacin permiten controlar de forma explcita
cundo se destruye un objeto. Por ejemplo, en C++ se puede usar una expresin
delete para deshacer (o finalizar) la inicializacin del objeto (convertirlo de
nuevo en memoria) y devolver la memoria al montn. En C# no hay ninguna
forma de destruir objetos explcitamente. Esta restriccin es til porque a
menudo los programadores hacen mal uso de la destruccin de objetos. Por
ejemplo:
Se olvidan de destruir objetos.
Si tuviramos la responsabilidad de escribir el cdigo que debe destruir un
objeto, es probable que a veces olvidramos hacerlo. Esto puede ocurrir en
C++ y constituye un problema, ya que el programa usa ms memoria y hace
que el sistema sea ms lento. Es lo que se conoce como prdida de
memoria. A menudo, la nica forma de recuperar la memoria perdida es
cerrar y volver a iniciar el programa en cuestin.
Intentan destruir el mismo objeto ms de una vez.
A veces se puede intentar accidentalmente destruir el mismo objeto ms de
una vez. Esto puede ocurrir en C++ y es un error serio de consecuencias
impredecibles. El problema es que, al destruir el objeto por primera vez, la
memoria se libera y se puede usar para crear un nuevo objeto,

Creacin y destruccin de objetos

19

probablemente de una clase distinta. Si se vuelve a intentar destruir el


mismo objeto, la memoria apunta aun objeto totalmente distinto.
Destruyen un objeto activo.
A veces se puede destruir un objeto que todava estaba siendo utilizado por
otra parte del programa. Se trata de un error grave que se conoce como
problema de puntero colgado y que tambin tiene consecuencias
impredecibles.
Para su informacin

Tcnicamente es posible
finalizar un objeto ms de
una vez si se usa la
resurreccin, pero no vale la
pena mencionar este
aspecto ya que no forma
parte del temario del curso.

Los objetos se destruyen por recoleccin de basura


En C# no es posible destruir un objeto de forma explcita mediante cdigo. En
lugar de ello, C# tiene recoleccin de basura (Garbage Collection), que
destruye objetos automticamente. Esto garantiza que:
Los objetos se destruyen.
Sin embargo, la recoleccin de basura no indica cundo exactamente se
destruir un objeto.
Los objetos se destruyen slo una vez.
Esto significa que nunca se dar el comportamiento impredecible causado
por una doble eliminacin, como puede ocurrir en C++. Esto es importante
porque ayuda a garantizar que un programa C# se comporta siempre de una
forma bien definida.
Slo se destruyen los objetos inalcanzables.
La recoleccin de basura garantiza que un objeto nunca ser destruido si
todava hay algn otro objeto que apunte hacia l. Slo se destruyen los
objetos que ya no son utilizados por ninguna otra parte del programa. La
capacidad de un objeto de acceder a otro a travs de una variable referencia
se llama alcance (reachability). nicamente se destruyen objetos
inalcanzables. La recoleccin de basura se encarga de seguir todas las
referencias de objetos para determinar cules son alcanzables y, por un
proceso de eliminacin, encontrar los objetos inalcanzables. Esta operacin
puede llevar bastante tiempo, por lo que la recoleccin de basura slo se
activa para recuperar memoria no utilizada cuando empieza a faltar
memoria.
Nota La recoleccin de basura se puede forzar de forma explcita en el cdigo,
pero es mejor no hacerlo. Lo ms recomendable es dejar la administracin de
memoria al runtime de .NET.

Creacin y destruccin de objetos

Prctica: Creacin de objetos


Objetivos
En esta prctica modificar la clase BankAccount creada en prcticas
anteriores de forma que utilice constructores. Crear tambin una nueva clase,
BankTransaction, y la utilizar para almacenar informacin sobre las
transacciones (depsitos y retiradas de dinero) que se realicen en una cuenta.
Al final de esta prctica, usted ser capaz de:
Sustituir el constructor por defecto.
Crear constructores sobrecargados.
Inicializar datos readonly.

Requisitos previos
Antes de realizar la prctica debe estar familiarizado con los siguientes temas:
Creacin de clases y de instancias de objetos.
Definicin y llamadas a mtodos.
Es necesario tambin haber realizado la prctica 8.1. Si no la termin, puede
usar el cdigo de la solucin.

Ejercicio 1
Uso de constructores
En este ejercicio modificar la clase BankAccount creada en prcticas
anteriores. Eliminar los mtodos que asignan valores a las variables de
instancia para el nmero y el tipo de cuenta, y los sustituir por una serie de
constructores que se puedan usar al crear una instancia de BankAccount.
Tendr que sustituir el constructor por defecto para generar un nmero de
cuenta (usando la tcnica empleada anteriormente), fijar el tipo de cuenta en
Checking y poner el saldo a cero.
Tambin crear otros tres constructores que recibirn distintas combinaciones
de parmetros:
El primero recibir un AccountType. El constructor generar un nmero de
cuenta, pondr el saldo a cero y asignar al tipo de cuenta el valor recibido.
El segundo recibir un decimal. El constructor generar un nmero de
cuenta, fijar el tipo de cuenta en Checking y asignar al saldo el valor
recibido.
El tercero recibir un AccountType y un decimal. El constructor generar
un nmero de cuenta y asignar al tipo de cuenta el valor del parmetro
AccountType y al saldo el valor el valor del parmetro decimal.
Cmo crear el constructor por defecto

Creacin y destruccin de objetos

1. Abra el proyecto Constructors.sln en la carpeta Lab Files(archivos de


Starter\Constructors dentro del fichero lab09.zip.
2. Borre el mtodo Populate en la clase BankAccount.
3. Cree un constructor por defecto de la siguiente manera:
a. El nombre debe ser BankAccount.
b. Debe ser pblico.
c. No debe recibir ningn parmetro.
d. No debe tener tipo de retorno.
e. El cuerpo del constructor debe generar un nmero de cuenta usando el
mtodo NextNumber, fijar el tipo de cuenta en
AccountType.Checking e inicializar a cero el saldo de la cuenta.
El constructor finalizado debera ser como ste:
public BankAccount( )
{
accNo = NextNumber( );
accType = AccountType.Checking;
accBal = 0;
}

Creacin y destruccin de objetos

Cmo crear los dems constructores


1. Aada otro constructor que reciba un solo parmetro AccountType llamado
aType. Este constructor tendr que:
a. Generar un nmero de cuenta, como antes.
b. Fijar accType en aType.
c. Poner accBal a cero.
2. Defina otro constructor que reciba un solo parmetro decimal llamado aBal.
Este constructor tendr que:
a. Generar un nmero de cuenta.
b. Fijar accType en AccountType.Checking.
c. Poner accBal a aBal.
3. Defina un ltimo constructor que reciba dos parmetros: un AccountType
llamado aType y un decimal llamado aBal. Este constructor tendr que:
a. Generar un nmero de cuenta.
b. Fijar accType en aType.
c. Poner accBal a aBal.
El cdigo finalizado para los tres constructores es el siguiente:
public BankAccount(AccountType aType)
{
accNo = NextNumber( );
accType = aType;
accBal = 0;
}
public BankAccount(decimal aBal)
{
accNo = NextNumber( );
accType = AccountType.Checking;
accBal = aBal;
}
public BankAccount(AccountType aType, decimal aBal)
{
accNo = NextNumber( );
accType = aType;
accBal = aBal;
}

Creacin y destruccin de objetos

Cmo probar los constructores


1. En el mtodo Main de la clase CreateAccount, defina cuatro variables
BankAccount llamadas acc1, acc2, acc3, y acc4.
2. Cree una instancia de acc1 usando el constructor por defecto.
3. Cree una instancia de acc2 usando el constructor que recibe slo un
AccountType. Fije el tipo de acc2 en AccountType.Deposit.
4. Cree una instancia de acc3 usando el constructor que recibe slo un saldo
decimal. Ponga el saldo de acc3 en 100.
5. Cree una instancia de acc4 usando el constructor que recibe un
AccountType y un saldo decimal. Fije el tipo de acc4 en
AccountType.Deposit y ponga el saldo en 500.
6. Use el mtodo Write (incluido en la clase CreateAccount) para mostrar los
contenidos de cada una de las cuentas. El cdigo finalizado es el siguiente:
static void Main( )
{
BankAccount acc1, acc2, acc3, acc4;
acc1
acc2
acc3
acc4

=
=
=
=

new
new
new
new

BankAccount( );
BankAccount(AccountType.Deposit);
BankAccount(100);
BankAccount(AccountType.Deposit, 500);

Write(acc1);
Write(acc2);
Write(acc3);
Write(acc4);
}

7. Compile el proyecto y corrija los posibles errores. Ejectelo y compruebe


que produce los resultados esperados.

También podría gustarte