0 ratings0% found this document useful (0 votes) 36 views47 pagesC Sharp Mod 2
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content,
claim it here.
Available Formats
Download as PDF or read online on Scribd
Introduccién a C#
Modulo 2: Creacion de Métodos,
Manejo de Excepciones y Monitoreo
de AplicacionesAcerca del médulo
Las aplicaciones consisten frecuentemente de unidades logicas de
funcionalidad que realizan funciones especificas, tales como proporcionar
acceso a datos 0 lanzar algiin procesamiento légico. Visual C# es un lenguaje
orientado a objetos y utiliza el concepto de métodos para encapsular unidades
légicas de funcionalidad. Un método puede ser tan simple o complejo como
queramos, por lo tanto, es importante considerar los cambios en el estado de
la aplicaci6n que suceden cuando una excepcion es generada en un método.
En este médulo, aprenderemos a crear y utilizar métodos, asi como la forma
de manejar excepciones. Conoceremos algunas técnicas de seguimiento que
nos permitan registrar el detalle de las excepciones que ocurran.Objetivos
Al finalizar este médulo, los participantes contaran con las habilidades y
conocimientos para:
Crear e invocar métodos.
Crear métodos sobrecargados
Utilizar parametros opcionales y argumentos nombrados.
Manejar excepciones.
Monitorear aplicaciones mediante el uso de las caracteristicas de
logging, tracing y profiling.
Los temas que se cubren en este médulo son:
Lecci6n 1: Creando e invocando Métodos.
Leccién 2: Creando Métodos sobrecargados y utilizando parametros
opcionales y de salida (output).
Leccién 3: Manejo de Excepciones.
Lecci6n 4: Monitoreo de aplicaciones.
Leccion 1:
Creando e invocando Métodos
Una parte clave en el desarrollo de cualquier aplicacion es dividir la solucion
en componentes légicos. En los lenguajes orientados a objetos, tales como
Visual C#, un método es una unidad de cddigo que realiza una pieza discreta
de trabajo.
En esta leccién, aprenderemos a crear e invocar métodos.Objetivos de la leccién
Al finalizar esta leccién, los participantes contaran con los conocimientos y
habilidades para:
Describir el propdsito de los métodos.
Crear métodos.
Invocar métodos.
Depurar métodos.
¢é Qué es un método?
La habilidad de definir e invocar métodos, es un componente fundamental de
la programacién orientada a objetos debido a que los métodos permiten
encapsular operaciones que protegen los datos almacenados dentro de un
tipo.
Normalmente, cualquier aplicacién que desarrollemos utilizando el Microsoft
.NET Framework y Visual C#, tendra varios métodos, cada uno con un
propésito especifico. Algunos métodos son fundamentales para la operacién
de una aplicacion. Por ejemplo, todas las aplicaciones de escritorio de Visual
C#, deben tener un método llamado Main que define el punto de entrada de
la aplicaci6n. Cuando el usuario ejecuta una aplicacion Visual C#, el CLR
ejecuta el método Main de esa aplicacién.
Los métodos pueden ser disefiados para uso interno de un tipo y como tal, se
encuentran ocultos para otros tipos. Los métodos publicos son expuestos
fuera del tipo y pueden ser disefiados para permitir a otros tipos solicitar que
un objeto realice una accion.
El mismo .NET Framework esté compuesto por clases que exponen métodos
que podemos invocar desde nuestras aplicaciones para interactuar con el
usuario y la computadora.Creando Métodos
Un método esta compuesto por dos elementos:
1. La especificacidn del método.
2. El cuerpo del método.
La especificacién del método define el nombre del método, los parametros
que el método puede tomar, el tipo de valor devuelto del método y los
modificadores de acceso del método.
La combinacién del nombre del método y su lista de parametros se conoce
como la firma del método.
La definicidn del valor devuelto de un método no se considera como parte de
la firma. Cada método en una clase debe tener una firma tinica.Nombrando un método
Un nombre de método tiene las mismas restricciones sintacticas que el
nombre de una variable. El nombre del método debe comenzar con una letra
o un guion bajo y solo puede contener letras, guiones y caracteres numéricos.
Visual C# es sensible a maytisculas y mintisculas, por lo que una clase puede
contener dos métodos que tengan el mismo nombre y se diferencien slo en
el uso de maytisculas y mintisculas de una o mas letras, aunque esto no es una
buena practica de codificaci6n.
Dos lineamientos recomendados por Microsoft como una buena practica al
elegir el nombre del método son:
1. Utilizar verbos o frases de verbos para nombrar un método. Esto ayuda
a que otros desarrolladores puedan entender la estructura de nuestro
cédigo.
2. Utilizar la nomenclatura Pascal Casing. No se recomienda iniciar los
nombres de los métodos con un guion o una letra miniscula.Implementando un cuerpo de Método
E] cuerpo de un método es un bloque de cédigo que se implementa mediante
el uso de cualquiera de las sentencias de programacién de Visual Cit. El
cuerpo esté encerrado entre llaves.
Podemos definir variables dentro del cuerpo de un método, en cuyo caso solo
existiran mientras se esté ejecutando el método. Cuando el método finalice,
las variables declaradas ya no seran accesibles.
EI siguiente ejemplo muestra el codigo del método ShowMessage que
contiene una variable llamada Status. La variable Status solo esta disponible
dentro del bloque de codigo ShowMessage. Si tratamos de utilizar la variable
Status fuera del alcance del método, el compilador mostrara un mensaje de
error indicando que ‘Status’ no existe en el contexto actual.
void ShowMessage()
var Status = Service Status;
Wass
}Especificando parametros
Los pardmetros son variables locales que se crean cuando el método se
ejecuta y les son asignados los valores que se especifican cuando el método
es invocado. Los parametros deben ser especificados entre paréntesis después
del nombre del método. Cada parametro esta separado por una coma. Si un
método no requiere algiin parametro, se especifica una lista de parametros
vacia (solo se incluyen los paréntesis después del nombre del método). El
método ShowMessage descrito anteriormente es un ejemplo de un método
que no requiere pardmetros.
Para cada pardmetro, se debe especificar el tipo y el nombre. Por convencién,
los pardmetros utilizan la nomenclatura Camel Casing.
Al definir los pardmetros que el método acepta, podemos utilizar la palabra
clave ref para indicar al CLR que debe pasar una referencia del pardmetro y
no solo el valor del parametro. El cédigo que proporciona el parémetro por
referencia debe inicializarlo previamente. Cualquier cambio al valor del
parametro dentro del cuerpo del método se verd reflejado en la variable
proporcionada como parametro al invocar el método.
EF] siguiente ejemplo muestra como definir un parametro uti
clave ref.
void Saveltems(ref int saveditems)
t
saveditems = Service.ItemsCount;
Ws
}
ando la palabraEspecificando un valor de Retorno
Todos los métodos deben tener un tipo de retorno. Un método que no
devuelve un valor tiene cl tipo de retorno void. Al definir cl método,
especificamos el tipo devuelto antes del nombre del método. Cuando se
declara un método que devuelve datos, debemos incluir la instruccién return
en el cuerpo del método.
El siguiente ejemplo muestra como devolver un tipo string desde un método.
suing GetServiceErorMessage
{
return "El servicio no se encuentra disponible.”";
}
La expresi6n que especifica la sentencia return, debe tener el mismo tipo que
el método declara devolver. Cuando la sentencia return se ejecuta, la
expresién es evaluada y devuelta a la instruccién que invocé al método.
Después de la sentencia return, el método finaliza y las instrucciones que
pudieran estar después de la sentencia return no seran ejecutadas.Invocando Meétodos
Para ejecutar el cédigo de un método, es necesario invocar a ese método. No
es necesario entender como funciona el cédigo en ese método. Incluso,
pudiéramos no tener acceso al cédigo si el método se encuentra en una clase
de un ensamblado del que no tenemos el cédigo fuente, como en el caso de la
biblioteca de clases base del .NET Framework.
Para invocar a un método, especificamos el nombre del método y entre
paréntesis, proporcionamos los argumentos que corresponden a los
parametros del método.
EI siguiente ejemplo muestra como invocar el método RunProcess paséndole
las variables int y bool para satisfacer los requerimientos de parémetros.
void DoJobs()
{
int Process
bool Stop
RunProcess(Process, Stop);
}
void RunProcess(int numProcess, bool stopIfError)
{
W
)
Si el método devuelve un valor, en el cédigo de Hamada debemos especificar
cémo manejar este valor, por lo general asignandolo a una variable del
mismo tipo.
rue;
El siguiente ejemplo muestra como capturar el valor de retorno del método
GetServiceErrorMessage en una variable llamada Message.
void DoJobs0
{
string Message = GetServiceErrorMessage();
}
string GetServiceErrorMessage()
{
return "El servicio no se encuentra disponible.”;
,Para invocar a un método que requiera pardmetros ref, en el cédigo que
invoca debemos declarar una variable ¢ inicializatla antes de pasatla como
argumento.
EI siguiente ejemplo muestra coma invacar el método Saveltems pasdndole
una variable int por referencia para satisfacer los requerimientos de
parametros.
void DoJobs()
{
t
void Saveltems(ref int savedltems)
{
savedltems = Service.ItemsCount;
HW ose
)
En el ejemplo anterior, podemos notar que estamos inicializando la variable
Result antes de pasarla como pardémetro, de no hacerlo, obtendremos un
mensaje de error Use of unassigned local variable ‘Result’.Depurando Métodos
Cuando depuramos una aplicacién, podemos ejecutar el cédigo instruccién
por instrucci6n, una instrucci6n a la vez. Esta es una caracteristica
extremadamente titil debido a que nos permite probar paso a paso la légica
que la aplicacién utiliza.
Visual Studio nos proporciona una serie de herramientas de depuracién que
nos permiten ejecutar cada linea de cddigo en la manera exacta que lo
deseamos. Por ejemplo, podemos avanzar linea por linea de codigo en cada
método que sea ejecutado o podemos ejecutar un bloque de cédigo sin
recorrerlo linea por linea.
Al depurar métodbs, utilizamos 3 principales caracteristicas de depuraci6n:
Step into. La caracteristica Step Into ejecuta la instruccién en la
posicién actual de ejecucion. Si la declaracién es una llamada de
método, la posicién de ejecucién actual se movers al cédigo dentro del
método. Después de haber entrado en un método, se puede continuar la
ejecucién de instrucciones dentro del método, una linea a la vez.
También podemos utilizar la caracteristica Step Into para iniciar una
aplicacién en modo de depuraci6n. Si realizamos esto, la aplicacion
entrard en el modo de interrupcién tan pronto como se inicie.
Step over. La caracterfstica Step Qver ojecuta la instruccién en la
posicién actual de ejecucién. Sin embargo, con esta caracteristica, no
entramos en el cédigo dentro de un método. En vez de eso, el cédigo
dentro del método es ejecutado y Ia posicién de ejecucién se traslada a
la instrucci6n siguiente a la que invoca al método. La excepcién a esto
es cuando el cddigo del método contiene un punto de interrupcion. En
este caso, la ejecucion continuard y en el punto de interrupcién dentro
del método, se detendra.
Step out. La caracteristica Step Out permite ejecutar el resto del
c6digo del método. La ejecucién continuara hasta regresar a la linea
que invoco el método y se detendra en ese punto.Leccién 2:
Creando Métodos sobrecargados y utilizando
parametros opcionales y de salida (output)
Hemos visto que podemos definir un método que acepte un niimero fijo de
pardmetros. Sin embargo, algunas veces podriamos necesitar escribir algtin
método que requiera diferentes conjuntos de pardmetros dependiendo del
contexto en el cual sea utilizado. Podemos crear métodos sobrecargados con
firma tnicas para satisfacer esta necesidad.
En otros escenarios, podriamos querer definir un método que tenga un
ntimero fijo de pardmetros, pero permitir a una aplicacién especificar
argumentos Gnicamente para los pardmetros que necesite. Podemos hacer
esto mediante la definicion de un método que tenga pardmetros opcionales y
entonces utilizar argumentos nombrados para proporcionar el valor de los
pardmetros por su nombre.
En esta lecci6n, aprenderemos a crear métodos sobrecargados, definir y
utilizar parametros opcionales, argumentos nombrados, y parametros de
salida (output).Objetivos de la leccién
Al finalizar esta leccién, los participantes contaran con las habilidades y
conocimientos para:
Crear un método sobrecargado.
Utilizar parémetros opcionales.
Utilizar argumentos nombrados.
Definir parametros de salida (output).Creando métodos sobrecargados
Cuando definimos un método, es posible que nos demos cuenta de que
nuestro método requiere diferentes conjuntos de informaci6n en diferentes
circunstancias. Podemos definir métodos sobrecargados para crear multiples
métodos con la misma funcionalidad que acepten diferentes pardmetros
dependiendo del contexto en el cual sean invocados.
Los métodos sobrecargados tienen el mismo nombre para enfatizar su
intencién comun. Sin embargo, cada método sobrecargado debe tener una
firma tnica para diferenciarlo de otras versiones sobrecargadas del método en
la clase.
Recordemos que la firma de un método incluye su nombre y su lista de
parametros. El tipo devuelto no forma parte de la firma. Por lo tanto, no
podemos definir métodos sobrecargados que difieran tinicamente por el tipo
de valor que devuelven.
El siguiente ejemplo, muestra 3 versiones del método ShowMessage, todos
con firmas tinicas.
void ShowMessage()
{
Mas
)
void ShowMessage(string message)
{
Move
,
void ShowMessage(int messagelD)
{
}
Cuando invocamos al método ShowMessage, tenemos que elegir la versién
sobrecargada que deseamos utilizar. Para hacer esto, simplemente
proporcionamos los argumentos que satisfagan una sobrecarga en particular.
De esta forma, el compilador resolvera la versidn a invocar baséndose en los
argumentos que hemos proporcionado.Creando métodos que utilicen parametros
opcionales
Mediante la definicién de métodos sobrecargados, podemos implementar
diferentes versiones de un método que requiera diferentes parametros.
Cuando creamos una aplicacién que utiliza métodos sobrecargados, el
compilador determina qué instancia especifica de cada método se debe
utilizar para satisfacer cada llamada al método.
Existen otros lenguajes y tecnologias que los desarrolladores pueden utilizar
para crear aplicaciones y componentes que no soportan la sobrecarga de
métodos. Una caracteristica clave de Visual C# es la capacidad de interoperar
con aplicaciones y componentes creados con otras tecnologias. Una de las
principales tecnologias que utiliza Windows es el Component Object Model
(COM). COM no soporta métodos sobrecargados, en vez de eso, utiliza
métodos que pueden tener pardmetros opcionales. Para facilitar la
incorporacién de bibliotecas y componentes COM en una solucién de Visual
C#, Visual C# proporciona soporte a parametros opcionales.
Los pardmetros opcionales también son utiles en otras situaciones.
Proporcionan una solucién compacta y simple cuando no es posible utilizar
sobrecarga debido a que los tipos de pardmetros no varian lo suficiente para
permitir al compilador distinguir entre cada implementacion.
EI siguiente ejemplo, muestra cémo definir un método que acepte un
pardmetro obligatorio y dos parametros opcionales.
void ShowMessage(string message, string title = null, int iconID = 1)
{
uw
)
Cuando definimos un método que acepte parémetros opcionales, debemos
especificar todos los parametros obligatorios antes de cualquier parametro
opcional.
El siguiente ejemplo, muestra la definicién de un método que utiliza
parametros opcionales que generan un error de compilacién.
void ShowMessage(string title = null, string message, int iconID = 1){
u
}
Podemos invocar a un método que acepte parametros opcionales de la misma
manera que invocamos a cualquier otro método. Especificamos el nombre del
método y proporcionamos los argumentos necesarios. La diferencia con los
métodos que aceptan parametros opcionales es que podemos omitir los
argumentos correspondientes y el método utilizara los valores
predeterminados cuando sea ejecutado.
El siguiente ejemplo, muestra como invocar al método ShowMessage
proporcionando tinicamente el argumento obligatorio message.
ShowMessage("hello, World!");
El siguiente ejemplo, muestra como invocar al método ShowMessage,
proporcionando un argumento para el pardmetro obligatorio message y un
argumento para el parametro opcional title.
ShowMessage("hello, World!", "Welcome");Invocando a métodos utilizando argumentos
nombrados
Tradicionalmente, cuando invocamos a un método, el orden y la posicién de
los argumentos en la llamada al método, corresponden al orden de los
parametros en la firma del método. Si los argumentos no estan en la posicién
correcta y los tipos no coinciden, se generar un error de compilacion.
En Visual C #, podemos especificar los parametros por su nombre y, por lo
tanto, proporcionar los argumentos en una secuencia que difiera del definido
en a firma del método. Para utilizar argumentos nombrados, debemos
proporcionar cl nombre del pardmetro y cl valor correspondiente separados
por dos puntos.
EI siguiente ejemplo muestra como invocar el método ShowMessage
utilizando argumentos nombrados para pasar el parametro iconID.
ShowMessage("hello, World!", iconID:19);
Al utilizar argumentos nombrados en conjunto con parametros opcionales,
podemos omitir facilmente los parametros. Cualquier parametro opcional
recibird su valor predeterminado. Sin embargo, si omitimos los parametros
obligatorios, el cédigo no compilard.
Podemos mezclar los argumentos por posicion y los argumentos nombrados.
Sin embargo, debemos especiticar todos los argumentos posicionales antes de
los argumentos nombrados.
El siguiente ejemplo, muestra una forma incorrecta de invocar al método
ShowMessage que hard que el cédigo no compile debido a que los
argumentos por posicion deben ser especificados antes que los argumentos
nombrados.
ShowMessage(iconID:19, "HellCreando métodos que utilicen parametros de salida
out
Mediante la sentencia return, un método puede devolver un valor hacia el
cédigo que lo invoca. Si necesitamos devolver mas de un solo valor al cédigo
que realiza la llamada, podemos utilizar los parémetros de salida para
devolver los datos adicionales requeridos. Cuando agregamos un parametro
de salida a un método, en el cuerpo del método debemos asignar un valor a
ese parametro 0 de lo contrario obtendremos un error de compilacion.
Cuando el método finaliza, el valor del parametro de salida es asignado a la
variable que es especificada como el argumento correspondiente en la
llamada al método.
Para definir un pardmetro de salida, en la firma del método, anteponemos la
palabra reservada out al tipo del parametro. Un método puede tener tantos
pardmetros de salida como sean requeridos.
EI siguiente ejemplo, muestra cémo definir un método que utiliza un
pardmetro de salida.
bool IsStatusError(out string statusMessage)
{
statusMessage =";
1/ Codigo para asignar valores de retorno FoundEsvor y statusMiessage
W
nae FoundError;
Para utilizar un pardmetro de salida, debemos proporcionar una variable para
el argumento correspondiente en el momento de invocar al método. No es
necesario asignarle un valor previamente debido a que el método invocado lo
hard. También debemos anteponer la palabra clave out al argumento en la
Hamada. Si intentamos especificar un argument que no sea una variable o si
omitimos la palabra clave out, el codigo no compilara.
El siguiente ejemplo, muestra cémo invocar un método que acepta un
parametro de salida.string StatusMessage;
bool IsError = IsStatusError(out StatusMessage);
Lecci6n 3:
Manejo de Excepciones
El manejo de excepciones es una estrategia importante para asegurar una
buena experiencia de usuario y para limitar la perdida de datos. Las
aplicaciones deben ser disefiadas con el manejo de excepciones en mente.
En esta leccién, aprenderemos a implementar un manejo de excepciones
efectivo en nuestras aplicaciones. Aprenderemos también, la forma de utilizar
excepciones en nuestros métodos para indicar de forma elegante una
condiciGu de error al c6digu que invoca nuesuus médos.Objetivos de la leccién
Al finalizar esta leccién, los participantes contaran con las habilidades y
conocimientos para:
Describir el propésito de una excepcién.
Manejar excepciones utilizando un bloque try/catch.
Utilizar un bloque finally para ejecutar cédigo después de una
excepcién.
Lanzar una excepcién.éQué es una Excepcion?
Hay muchas cosas que pueden salir mal mientras se ejecuta una aplicacién.
Algunos errores pueden ocurrir debido a fallas en la légica de la aplicacién,
pero otros pueden deberse a condiciones fuera del control de nuestra
aplicacién. Por ejemplo, nuestra aplicacién no puede garantizar que exista un
determinado archivo en el sistema de archivos 0 que una base de datos
requerida se encuentre disponible. Una indicacién de un error o de una
condicién que rara vez ocurre, es conocida como Excepcién.
Cuando disefiemos una aplicacién, debemos considerar la manera de
garantizar que nuestra aplicacién se pueda recuperar de la mejor forma
cuando una excepci6n ocurra. Es una practica comin, comprobar
simplemente el valor devuelto por el método para garantizar que se ha
ejecutado correctamente, sin embargo, esta estrategia no siempre es suficiente
para manejar todos los errores que pueden ocurrir debido a que:
No todos los métodos devuelven un valor.
En la mayoria de los casos, es necesario conocer por qué la llamada al
método ha fallado y no slo el hecho de que ha fallado.
© Los errores inesperados como, por ejemplo, quedarse sin memoria, no
pueden ser manejados de esta manera.
Tradicionalmente, las aplicaciones utilizan la estrategia de un objeto de error
global. En esta estrategia de manejo de errores, cuando una parte del cédigo
causa un error, los datos del error se almacenan en el objeto global para
indicar la causa del mismo y luego se retorna al cdigo que invocé al método
que caus6 el error. Es responsabilidad del cddigo que invoca, examinar el
objeto de error y determinar cémo manejar la situaci6n. Sin embargo, esta
estrategia no es robusta debido a que es muy facil para un programador
olvidar el manejo de errores de forma apropiada.¢Cémo se propagan las excepciones?
Un método puede lanzar una excepcién cuando detecta que algo inesperado
ha sucedido, por ejemplo, cuando la aplicacién intenta abrir un archivo que
no existe.
Cuando en un método se genera una excepcién, el cédigo debe estar
preparado para detectar y manejar esta excepci6n. Si el cddigo no procesa la
excepci6n, la ejecucién es interrumpida y la excepcidn se propaga
automaticamente hacia el cédigo que invocé al método que falld. Este
proceso contintia hasta que una seccién de cédigo toma la responsabilidad
para el manejo de la excepcidn. La ejecucién contintia en esa seccion de
cédigo después de que la légica de manejo de excepciones se haya
completado. Si ningtin cédigo maneja la excepcion, entonces el proceso
finalizara y se mostraré un mensaje al usuario.El tipo Exception
Cuando una excepcién ocurre, es conveniente incluir informaci6n acerca de
la causa original para que cl método que maneja la excepcién pueda tomar la
accién correctiva apropiada. En el .NET Framework, las excepciones se
basan en la clase Exception la cual contiene informacion acerca de la
excepcién. Cuando un método dispara una excepcidn, se crea un objeto
Exception y se puede proporcionar a través de él, informacién acerca de la
causa del error. El objeto Exception es entonces pasado al cédigo que maneja
la excepcion.
La siguiente tabla describe algunas de las clases Exception proporcionadas
por el NET Framework.
forestry Poe ee Pye etn
Exception System Representa
cualquier
excepcion que es
disparada durante
la ejecucién de
una aplicacion.
Esta clase sirve di
base para crear
nuestras propias
clases exception
personalizadas.
SystemException System Representa todas
las excepciones
disparadas por el
CLR. La clase
SystemExceptior
es la clase base de
todas las clases
exception en el
espacio de
nombres System.ApplicationException — System. Representa todas
las excepciones
no fatales
disparadas por las
aplicaciones y no
por el CLR.
NullReferenceException System Representa una
excepcién
causada al
intentar utilizar wi
objeto que es
nulo.
FileNotFoundException System.IO Representa una
excepcién
causada cuando
un archivo no
existe.
SerializationException | System.Runtime.Serialization Representa una
excepcion
causada durante e
proceso de
serializacién 0
deserializacion.
Manejando Excepciones utilizando el bloqueTry/Catch
El bloque try/catch es la sentencia de programacién clave que nos permite
implementar el manejo estructurado de excepciones (Structured Exception
Handling - SEH) en nuestras aplicaciones. Podemos encerrar el cédigo que
podria fallar y provocar una excepcion dentro del bloque try y agregar uno 0
ms bloques catch para controlar las excepciones que se puedan producir.
El siguiente ejemplo, muestra la sintaxis para definir un bloque try/catch.
uy
(
1 Cédigo que puede generar una excepcién
}
catch( {Tipo de excepcién a manejar])
{
1 Cédigo a ejecutar cuando ocurra un tipo de excepcién
)
catch ((Tipo de excepcién a manejar])
{
1 Cédigo a ejecutar cuando ocurra otro tipo de excepcién
}
Las instrucciones que se incluyen entre las Ilaves del bloque try pueden
invocar métodos de otros objetos. Si cualquiera de las instrucciones dentro
del bloque try provoca que una excepcién sea lanzada, la ejecucién pasa al
bloque catch correspondiente. Podemos especificar bloques catch para
diferentes tipos de excepciones. La especificacién catch para cada bloque,
determina la excepcién que atrapara y, opcionalmente, la variable donde se
almacenaré la instancia de la excepcidn. Es una buena practica incluir un
bloque catch para el tipo de excepcin general al final de los bloques catch
para capturar todas las excepciones que no se hayan capturado en algunos de
los bloques catch previos.
En el siguiente ejemplo, si el cédigo en el bloque try causa una excepcién
NullReferenceException, el cddigo en el bloque catch correspondiente serd
ejecutado. Si cualquier otro tipo de excepci6n ocurre, el cédigo en el bloque
catch para el tipo Exception sera ejecutado.
uy
{
1 Cédigo que puede generar una excepcién
}
catch(NullReferenceException ex){
1/ Attapa todas las excepciones NullReferenceException
}
catch (Exception ex)
{
1 Atrapa todas las demas excepciones
}
Cuando definamos més de un bloque catch, debemos asegurarnos de
colocarlos en el orden correcto. Cuando se produce una excepcién, el CLR
intenta encontrar el bloque catch que atrapa la excepcién que coincida con la
excepcién que haya sido generada, Debemos poner bloques catch mas
especificos antes de bloques catch menos especificos, de lo contrario el
cédigo no compilara.Utilizando un bloque Finally
Algunos métodos pueden contener cédigo critico que siempre deba ser
ejecutado, incluso si se produce una excepci6n. Por ejemplo, un método
puede necesitar asegurarse de que un archivo que estaba escribiendo sea
cerrado o bien liberar los recursos utilizados antes de terminar. Un bloque
finally permite manejar esta situaci6n.
Especificamos el bloque finally después de todos los bloques catch. El
bloque finally especitica el codigo que debe ejecutarse cuando el bloque
try/catch finalice independientemente de que se haya generado o no alguna
excepci6n. Si una excepcién es atrapada por un bloque catch, el cédigo en el
bloque catch sera ejecutado antes que el bloque finally.
También podemos agregar un bloque finally a un bloque try que no tenga
bloques catch. En este caso, las excepciones no son manejadas, pero el
bloque finally siempre sera ejecutado.
El siguiente ejemplo, muestra cémo implementar un bloque try/catch/finally.
uy
{
11 Cédigo que puede generar imma excepcién
}
catch(NullReferenceException ex)
{
1 Atwapa todas las excopcionos NullRoforenceException
}
catch (Exception ex)
{
1/ Atrapa todas las demas excepciones
}
finally
{
1 Bl codigo en este bloque si
‘haya 0 no haya excepciones.
}
1 serd ejecutado,Lanzando Excepciones
Podemos crear una instancia de una clase Exception en nuestro codigo y
lanzar la excepci6n para indicar que ha ocurrido una excepcién, Cuando
lanzamos una excepci6n, la ejecucién del bloque de cédigo actual termina y
el CLR pasa el control al primer controlador de excepciones disponibles que
atrape la excepcién.
Para lanzar una excepci6n, utilizamos la palabra clave throw y especificamos
el objeto excepcion a lanzar.
El siguiente ejemplo, muestra cémo crear una instancia de la clase
NullReferenceException para posteriormente lanzar el objeto
NullException.
var NullException =
new NullReferenceException("El valor proporcionado es nulo.");
throw NullException;
Una estrategia comin es atrapar las excepciones en bloques catch y tratar de
manejarlas. Si el bloque catch de una excepcién no puede resolver el error,
este puede volver a lanzar la excepci6n para propagarla al nivel superior del
cédigo que llamo al actual.
El siguiente ejemplo, muestra como volver a lanzar una excepcién que ha
sido atrapada en un bloque catch.
ty
{
11 Cédigo que puede generar una excepcién
catch(NullReferenceException ex)
{
1/ Atrapa todas las excepciones NullReferenceException
}
catch (Exception ex)1 Trata de manejar la excepcién.
W
1/ Si no se puede manejar la excepcién, lanzarla al cédigo
/ que invocé al método que contiene este cédigo.
throw:Leccion 4:
Monitoreo de aplicaciones
Cuando desarrollamos aplicaciones del mundo real, escribir cédigo es
simplemente una parte del proceso. Por lo regular, debemos dedicar una
cantidad considerable de tiempo para resolver bugs, solucionar problemas y
optimizar el rendimiento de nuestro cédigo. Visual Studio y el .NET
Framework, proporcionan varias herramientas que nos pueden ayudar a
realizar estas tareas de forma més eficiente.
En esta leccién, aprenderemos a utilizar diversas herramientas y técnicas para
monitorear y resolver problemas en nuestras aplicaciones.Objetivos de la leccién
Al finalizar esta leccién, los participantes contaran con las habilidades y
conocimientos para:
© Utilizar las caracteristicas de Registro (logging) y Rastreo (tracing) en
el cédigo de una aplicacién.
© Utilizar la caracteristica Profiling en Visual Studio.
© Utilizar los contadores de rendimiento para monitorear el rendimiento
de una aplicacién.Utilizando Registro (Logging) y Seguimiento
(Tracing)
Registro y seguimiento son dos conceptos similares pero distintos. Cuando
implementamos logging en nuestra aplicacién, agregamos cédigo para
escribir informacién hacia un medio de almacenamiento de registro, tal como
un archivo de texto o el registro de eventos de Windows.
Logging nos permite proporcionar ms informacién a los usuarios y
administradores sobre lo que estd haciendo nuestro cédigo. Por ejemplo, si la
aplicacién atrapa una excepcién, podemos escribir los detalles de la
excepcién en cl registro de eventos de Windows para que cl usuario o cl
administrador del sistema puedan resolver cualquier problema relacionado.
Por otro lado, los desarrolladores utilizan Tracing para monitorear la
ejecucién de una aplicacién. Cuando implementamos tracing, agregamos
cédigo para escribir mensajes hacia un agente Trace que se encuentre
escuchando mensajes, el agente a su vez dirige la salida a un destino
especificado. En Visual Studio, de manera predeterminada, los mensajes de
seguimiento aparecen en la ventana de salida (Output). Tipicamente
utilizamos tracing para proporcionar informacion acerca de los valores de las
variables o el resultado de algunas expresiones para ayudarnos a determinar
por qué nuestra aplicacién se comporta de una manera particular.
También podemos utilizar técnicas tracing para interrumpir la ejecucién de
una aplicacion en respuesta a las condiciones que nosotros definamos.Escribiendo al Log de Eventos de Windows
Escribir al log de eventos de Windows es uno de los requerimientos mas
comunes de registro (logging) que podriamos encontrar. La clase
System.Diagnostics.EvenLog proporciona varios métodos estaticos que se
pueden utilizar para escribir en log de eventos de Windows. En particular, el
método EventLog.WriteEntry incluye varias sobrecargas que podemos
utilizar para registrar varias combinaciones de informaci6n. Para escribir al
log de eventos de Windows, necesitamos proporcionar al menos 3 piezas de
informaci6n:
© El log de eventos. Este es el nombre del log de eventos de Windows
hacia el cual queremos escribir. En la mayoria de los casos escribimos
al log Application, sin embargo, podemos crear logs personalizados.
* Elorigen del evento. Esto identifica el origen del evento y tipicamente
suele ser el nombre de la aplicacion. Cuando creamos un origen de
eventos, este se asocia con un log de eventos. Para crear un origen de
evento es necesario contar con permisos de administrador, por lo que es
recomendable que el origen de evento y el log personalizado sean
creados durante la instalacién de la aplicacién ya que durante su
ejecucién es probable que el usuario que ejecuta la aplicacién no tenga
privilegios de administrador. Si la aplicacién no se ejecuta con
suficientes permisos, una excepcién SecurityException sera disparada
cuando la aplicacién intente crear un origen de evento o trate de
escribir al log de eventos.
« El Mensaje. Ese es el texto que deseamos agregar al registro.
También podemos utilizar el método WriteEntry para especificar una
categoria, un ID de evento y de ser necesario, una severidad de evento.
EI siguiente ejemplo, muestra cémo escribir un mensaje al log de eventos
Application de Windows.
string EventLogName = "Applicatio
string EventSource = "Demo logging";
string EventMessage = "Hola mundo desde la aplicacién Demo";
if (!iventl og. SourceExists(EventSource))
{Eventl.og.CreateE ventSource(EventSource, EventLogName);
}
Eventlog,WriteEntry(EventSource, EventMessage);
Depuracion y Seguimiento
(Debugging y Tracing)
El espacio de nombres System.Diagnostic incluye dos clases, Debug y
Trace. Estas clases nos proporcionan informaci6n acerca del rendimiento de
una aplicaci6n durante su desarrollo o después de su implementacion a
produccion. Estas clases son solo una parte de las caracteristicas de
instrumentacién que estén disponibles en el.NET Framework.
Las clases Debug y Trace funcionan de forma similar e incluyen diversos
métodos en comiin. Sin embargo, las instrucciones Debug s6lo estan activas
si se compila la soluci6n en modo de depuracién, mientras que las
instrucciones Trace estan activas en ambos modos de compilacién, Debug y
Realease.
Las clases Debug y Trace incluyen métodos para escribir cadenas
formateadas a la ventana Output en Visual Studio o hacia algtin otro agente
de escucha que hayamos configurado. También podemos escribir a la ventana
Output solo cuando se cumpla cierta condicién y podemos ajustar la
identaci6n de los mensajes trace. Por ejemplo, si estamos escribiendo hacia
la ventana Output el detalle de cada objeto dentro de una enumeracion,
podriamos querer identar ese detalle para distinguirlo de otros mensajes de
salida.
Las clases Debug y Trace también incluyen un método llamado Assert. El
método Assert nos permite especificar una condicién (una expresién que
pueda ser evaluada como falsa o verdadera) junto con una cadena de formato.Si la condici6n se evaltia a false, el método Assert interrumpe la ejecucion
del programa y muestra una caja de didlogo modal con el mensaje que
especifiquemos. Este método es util si necesitamos identificar el punto en un
programa de larga duracién en el cual se ha presentado una condicién
inesperada.
El siguiente ejemplo muestra cémo utilizar la clase Debug para escribir
mensajes a la ventana Output e interrumpir la ejecuci6n si una condicién
inesperada se presenta.
int Option;
Console. Write(""Por favor escribe una opcidn entre 1 y 10 y presiona : ");
string UserOption = Console.ReadLine();
Debuig.Assert(int.TryParse(UserOption, out Option),
string Format(S"imposible convert '{UserOption}' como entero"));
Debug, WriteLine($"El valor proporcionado es {UserOption}");
Debug. WriteLine($"El valor de la opcién es {Option}");
Console. WriteL ine("Presiona para finalizar");
Console.ReadL ine():Perfilamiento
(Profiling)
Cuando desarrollamos aplicaciones, hacer que nuestro cédigo funcione sin
errores es solo parte del desafio. También debemos garantizar que el cédigo
funcione eficientemente. Para ello es necesario revisar el tiempo que toma el
cédigo para realizar tareas y ver si utiliza recursos excesivos de procesador,
memoria, disco o red.
Visual Studio incluye una gama de herramientas, conocidas colectivamente
como Visual Studio Profiling Tools, que nos pueden ayudar a analizar el
rendimiento de nuestras aplicaciones. De manera gencral, ejecutar un andlisis
de rendimiento en Visual Studio consta de tres pasos:
1.
Crear y ejecutar una sesi6n de rendimiento. Todos los anilisis de
rendimiento se llevan a cabo dentro de una sesién de rendimiento. Se
puede crear y ejecutar una sesidn de rendimiento lanzando el Asistente
de Rendimiento desde el ment Debug->Profiler->Performance
Profiler... de Visual Studio. Cuando la sesi6n de rendimiento esta en
ejecuci6n, ejecutamos la aplicacién como lo hacemos normalmente.
Mientras se est ejecutando la aplicaci6n, tipicamente utilizamos la
funcionalidad de nuestra aplicacién que sospechamos pueda estar
causando problemas de rendimiento.
Analizar el informe de perfilamiento. Cuando terminamos de
ejecutar la aplicacion, Visual Studio muestra el informe de
perfilamiento. Esto incluye informacién que puede proporcionar ideas
para mejorar el rendimiento de nuestra aplicacién. Por ejemplo,
podemos:
a. Ver que funcionalidad consume mas tiempo de CPU.
b. Ver la linea de tiempo que muestra lo que la aplicacién estaba
haciendo.
c. Ver las advertencias y sugerencias de cémo mejorar el c6digo.
Revisar el cédigo y repetir el andllisis. Cuando el andlisis haya
concluido, debemos realizar los cambios en el cédigo para arreglar
cualquier problema que hayamos identificado. Después podemosejecutar una nueva sesion de rendimiento y generar un nuevo informe
de generacién de perfilamiento. Las herramientas de Visual Studio
Profiling, nos permiten comparar dos informes para ayudarnos a
identificar y cuantificar como ha cambiado el rendimiento de nuestro
cédigo.
Las sesiones de rendimiento trabajan por muestreo. Cuando creamos una
sesion de rendimiento, podemos elegir si deseamos un muestreo del uso de
CPU, asignacién de memoria, informacién de concurrencia en aplicaciones
de miiltiples hilos o si deseamos utilizar instrumentaci6n para recopilar
informacion detallada sobre cada llamada a funciones durante un lapso de
tiempo. En la mayoria de los casos, se recomienda empezar utilizando el
muestreo de CPU que es la opcién predeterminada. El Muestreo de CPU
utiliza sondeo estadistico para determinar qué funciones utilizan mas tiempo
de CPU. Esto proporciona una visin del rendimiento de la aplicacién, sin
consumir muchos recursos y sin ralentizar nuestra aplicacién.Contadores de rendimiento
Los contadores de rendimiento son herramientas del sistema que recopilan
informacién sobre como son utilizados los recursos. Examinar los contadores
de rendimiento puede proporcionarnos informacién adicional sobre lo que la
aplicacién esta haciendo y puede ayudarnos a resolver problemas de
rendimiento. Los contadores de rendimiento estan organizados en 3
principales grupos:
Contadores que son proporcionados por el sistema operativo y la
plataforma de hardware utilizada. Este grupo incluye a los
contadores que se pueden utilizar para medir el uso del procesador, uso
de memoria fisica, uso de disco, y el uso de la red. El detalle de los
contadores disponibles variard segtin el hardware del equipo.
Contadores que son proporcionados por el .Net Framework. El
-Net Framework incluye contadores que se pueden utilizar para medir
una amplia gama de caracteristicas de una aplicacion. Por ejemplo, se
puede ver el ntimero de excepciones disparadas, ver el detalle bloqueos,
el uso de threads y examinar el comportamiento del recolector de
basura (garbage collector)
Contadores personalizados creados por nosotros mismos. Podemos
crear nuestros propios contadores de rendimiento para examinar
aspectos especificos del comportamiento de la aplicacién. Por ejemplo,
podemos crear un contador de rendimiento para contar el niimero de
llamadas a un método en particular o para contar el ntimero de veces
que una excepcién especifica es lanzada.Navegando y utilizando contadores de rendimiento
Los contadores de rendimiento estan organizados en categorias. Esto nos
ayuda a encontrar los contadores que deseamos cuando capturamos y
examinamos los datos de rendimiento. Por ejemplo, la categoria
PhysicalDisk incluye normalmente contadores para el porcentaje de tiempo
dedicado a leer y escribir a disco, la cantidad de datos leidos y escritos a
disco, y la longitud de la cola para leer y escribir datos al disco.
Normalmente, capturamos y vemos los datos de los contadores de
rendimiento en el Monitor de rendimiento (perform.exe). El monitor de
rendimiento se incluye en el sistema operativo Windows y permite ver 0
capturar los datos de los contadores de rendimiento en tiempo real. Cuando
utilizamos el Monitor de rendimiento, podemos navegar por las categorias de
contadores y agregar varios contadores de rendimiento a una presentacién
grafica. También podemos crear conjuntos de colectores de datos para
capturar datos para reportes 0 anilisis.
Es posible también navegar por los contadores de rendimiento disponibles en
el equipo desde Visual Studio. En el Explorador de Servidores, expandimos
los Servidores, expandimos el nombre del equipo y después expandimos
Contadores de Rendimiento.Crear contadores de rendimiento personalizados
Podemos utilizar las clases PerformanceCounter y
PerformanceCounterCategory para interactuar con los contadores de
rendimiento en diversas formas. Por ejemplo, podemos:
« — Iterar sobre las categorias de contador de rendimiento disponibles en un
equipo especificado.
* — Iterar sobre los contadores de rendimiento dentro de una categoria
especiticada.
* Comprobar si existen categorias de contadores de rendimiento 0
contadores de rendimiento en la computadora local.
* Crear categorias de contadores de rendimiento personalizado 0
contadores de rendimiento.
Por lo general, debemos crear categorias de contadores de rendimiento
personalizados y contadores de rendimiento durante el proceso de instalacion
en lugar de hacerlo durante la ejecuci6n de la aplicacién. Los contadores de
rendimiento no deberian ser utilizados inmediatamente después de haberlos
creado ya que existe un tiempo entre su creacién y su habitaci6n para ser
utilizados.
Después de crear contadores de rendimiento personalizados en un equipo
especifico, estos permanecen ahi. No es necesario tener que volver a crearlos
cada vez que se ejecute la aplicaci6n. Para crear un contador de rendimiento
personalizado, debemos especificar un tipo de contador base mediante la
enumeracién PerformanceCounterType.
El siguiente ejemplo, muestra como crear programaticamente una categoria
de contadores de rendimiento personalizada. Este ejemplo crea una nueva
categoria de contadores de rendimiento llamada NWTraders Ordenes. La
categoria contiene dos contadores de rendimiento. El primer contador registra
el total de pedidos aprobados, y el segundo contador registra el total de
pedidos rechazados.
if (PerformanceCounterCategory.Exists("NWTraders Ordenes"))
{
Console. WriteLine("La categoria NWTraders Ordenes ya existe");
}else
var Contadores = new CounterCreationDataCollectionO;
var Aprobados = new CounterCreationData();
Aprobados.CounterHelp = "Total de pedidos aprobados
Aprobados.CounterName = "# Aprobados";
Aprobados.CounterType = PerformanceCounterType.NumberOfltems32;
Contadores.Add(Aprobados);
var Rechazados = new CounterCreationDataQ;
Rechazados.CounterHelp = "Total de pedidos rechazados";
Rechazados.CounterName = "# Rechazados";
Rechazados.CounterType = PerformanceCounter'Type.NumberOfltems32;
Contadores. Add(Rechazados);
PerformanceCounterCategory.Create("NWTraders Ordenes”,
“Categoria demostrativa",
PerformanceCounterCategoryType.SingleInstance,
Contadores);
}
Ademas de poder crear categorias y contadores de rendimiento
programaticamente, también es posible hacerlo desde el Explorador de
Servidores en Visual Studio.Utilizando Contadores de Rendimiento
Personalizados
Al crear contadores de rendimiento personalizados, nuestras aplicaciones
deben proporcionar datos a los contadores de rendimiento. Los contadores de
rendimiento proporcionan varios métodos que nos permiten actualizar su
valor, tales como los métodos de incremento y decremento, La manera en que
el contador procesard el valor dependerd del tipo base seleccionado al crear el
contador.
El siguiente ejemplo, muestra como modificar contadores de rendimiento de
forma programitica.
1 Obtenemos la referencia a los contadores
var Aprobados = new PerformanceCounter(
"NWTraders Ordenes'", "# Aprobados", false);
var Rechazados = new PerformanceCounter(
"NWTraders Ordenes", "# Rechazados", false);
1 Asignar un valor
Aprobados.RawValue ~ 20;
iH Incrementar su valor
Rechazados.Increment();
// Imprimimos los valores,
Console, WriteL ine
‘$"Aprobados { Aprobados.NextValue()}, Rechazados {Rechazados.NextValue()}");,
Una vez que hayamos creado una categoria de contador de rendimiento
personalizado, podemos ir a la categoria y seleccionar los contadores de
rendimiento individuales en el Monitor de rendimiento. Cuando ejecutemos
la aplicacion, podemos utilizar el Monitor de rendimiento para ver los datos
de los contadores de rendimiento personalizados en tiempo real.Introduccién a C#
Médulo 3: Desarrollando el cédigo
para una aplicacion grafica