Sei sulla pagina 1di 27

Concepto de instruccin

Toda accin que se pueda realizar en el cuerpo de un mtodo, como definir variables locales, llamar a mtodos, asignaciones y muchas cosas ms que veremos a lo largo de este tema, son instrucciones. Las instrucciones se agrupan formando bloques de instrucciones, que son listas de instrucciones encerradas entre llaves que se ejecutan una tras otra. s decir, la sinta!is que se sigue para definir un bloque de instrucciones es" { <listaInstrucciones> } Toda variable que se defina dentro de un bloque de instrucciones slo e!istir dentro de dicho bloque. Tras l ser inaccesible y podr ser destruida por el recolector de basura. #or ejemplo, este cdigo no es vlido" public void f(); { { int b; } b = 1; // ERROR }

b no e!iste fuera del blo"ue donde se declar#$

Los bloques de instrucciones pueden anidarse, aunque si dentro de un bloque interno definimos una variable con el mismo nombre que otra definida en un bloque e!terno se considerar que se ha producido un error, ya que no se podr determinar a cul de las dos se estar haciendo referencia cada vez que se utilice su nombre en el bloque interno.

Instrucciones bsicas Definiciones de variables locales


n el Tema 7:Variables y tipos de datos ya se vi que las variables locales son variables que se definen en el cuerpo de los mtodos y slo son accesibles desde dichos cuerpos. $ecurdese que la sinta!is e!plicada para definirlas era la siguiente" <modificadores> <tipo%ariable> <no&bre%ariable> = <valor>;

Tambin se vi que pod%an definirse varias variables en una misma instruccin separando sus pares nombre&valor mediante comas. #or ejemplo" int a='( b( c=)1;

Asignaciones
'na asignacin es simplemente una instruccin mediante la que se indica un valor a almacenar en un dato. La sinta!is usada para ello es" <destino> = <ori*en>;

n temas previos ya se han dado numerosos ejemplos de cmo hacer esto, por lo que no es necesario hacer ahora mayor hincapi en ello.

Llamadas a mtodos
n el Tema 8: Mtodos ya se e!plic que una llamada a un mtodo consiste en solicitar la ejecucin de sus instrucciones asociadas dando a sus parmetros ciertos valores. (i el mtodo a llamar es una mtodo de objeto, la sinta!is usada para ello es" <ob+eto>.<no&bre,-todo>(<valoresParmetros>); ) si el mtodo a llamar es un mtodo de tipo, entonces la llamada se realiza con" <nombreTipo>.<no&bre,-todo>(<valoresParmetros>); $ecurdese que si la llamada al mtodo de tipo se hace dentro de la misma definicin de tipo donde el mtodo fue definido, la seccin <nombreTipo>. de la sinta!is es opcional.

Instruccin nula
La instruccin nula es una instruccin que no realiza nada en absoluto. (u sinta!is consiste en escribir un simple punto y coma para representarla. * sea, es" ;

(uele usarse cuando se desea indicar e!pl%citamente que no se desea ejecutar nada. 'sarla es +til para facilitar la legibilidad del cdigo o, como veremos ms adelante en el tema, porque otras instrucciones la necesitan para indicar cundo en algunos de sus bloques de instrucciones componentes no se ha de realizar ninguna accin.

Instrucciones condicionales
Las instrucciones condicionales son instrucciones que permiten ejecutar bloques de instrucciones slo si se da una determinada condicin. n los siguientes subapartados de este ep%grafe se describen cules son las instrucciones condicionales disponibles en ,-

Instruccin if
La instruccin if permite ejecutar ciertas instrucciones slo si de da una determinada condicin. (u sinta!is de uso es la sinta!is" if (<condici#n>) <instruccionesIf> else <instruccionesElse> l significado de esta instruccin es el siguiente" se eval+a la e!presin .condicin/, que ha de devolver un valor lgico. (i es cierta 0devuelve true1 se ejecutan las

.instrucciones2f/, y si es falsa 0false1 se ejecutan las .instrucciones lse/ La rama else es opcional, y si se omite y la condicin es falsa se seguir%a ejecutando a partir de la instruccin siguiente al if. n realidad, tanto .instrucciones2f/ como .instrucciones lse/ pueden ser una +nica instruccin o un bloque de instrucciones. 'n ejemplo de aplicacin de esta instruccin es esta variante del 3ola4undo" usin* ./ste&; class 0ola,undoIf { public static void ,ain(.trin*12 ar*s) { if (ar*s$3en*t4 > 5) 6onsole$7rite3ine(890ola {5}:8( ar*s152); else 6onsole$7rite3ine(890ola &undo:8); } } (i ejecutamos este programa sin ning+n argumento veremos que el mensaje que se muestra es 53ola 4undo6, mientras que si lo ejecutamos con alg+n argumento se mostrar un mensaje de bienvenida personalizado con el primer argumento indicado.

Instruccin switch
La instruccin switch permite ejecutar unos u otros bloques de instrucciones seg+n el valor de una cierta e!presin. (u estructura es" switch (<e!presi#n>) { case <valor1>: <bloque1> case <valor2>: default: } l significado de esta instruccin es el siguiente" se eval+a .e!presin/. (i su valor es .valor7/ se ejecuta el .bloque7/, si es .valor8/ se ejecuta .bloque8/, y as% para el resto de valores especificados. (i no es igual a ninguno de esos valores y se incluye la rama default, se ejecuta el .bloque9efault/: pero si no se incluye se pasa directamente a ejecutar la instruccin siguiente al switch . Los valores indicados en cada rama del switch han de ser e!presiones constantes que produzcan valores de alg+n tipo bsico entero, de una enumeracin, de tipo char o de tipo string. ;dems, no puede haber ms de una rama con el mismo valor. n realidad, aunque todas las ramas de un switch son opcionales siempre se ha de incluir al menos una. ;dems, la rama default no tiene porqu aparecer la +ltima si se usa, aunque es recomendable que lo haga para facilitar la legibilidad del cdigo. <bloque2> <siguienteAccin> <siguienteAccin> <siguienteAccin>

... <bloque efault>

l elemento marcado como .siguiente;ccin/ colocado tras cada bloque de instrucciones indica qu es lo que ha de hacerse tras ejecutar las instrucciones del bloque que lo preceden. #uede ser uno de estos tres tipos de instrucciones" goto case <valori>; goto default; break;

(i es un goto case indica que se ha de seguir ejecutando el bloque de instrucciones asociado en el switch a la rama del .valori/ indicado, si es un goto default indica que se ha de seguir ejecutando el bloque de instrucciones de la rama default, y si es un break indica que se ha de seguir ejecutando la instruccin siguiente al s<itch. l siguiente ejemplo muestra cmo se utiliza switch" usin* ./ste&; class 0ola,undo.;itc4 { public static void ,ain(.trin*12 ar*s) { if (ar*s$3en*t4 > 5) s;itc4(ar*s152) { case 8<os-8 6onsole$7rite3ine(80ola <os-$ =uenos d>as8); brea?; case 8@aco8 6onsole$7rite3ine(80ola @aco$ ,e ale*ro de verte8); brea?; default 6onsole$7rite3ine(80ola {5}8( ar*s152); brea?; } else 6onsole$7rite3ine(80ola ,undo8); } } ste programa reconoce ciertos nombres de personas que se le pueden pasar como argumentos al lanzarlo y les saluda de forma especial. La rama default se incluye para dar un saludo por defecto a las personas no reconocidas. #ara los programadores habituados a lenguajes como ,== es importante resaltarles el hecho de que, a diferencia de dichos lenguajes, ,- obliga a incluir una sentencia break o una sentencia goto case al final de cada rama del switch para evitar errores comunes y dif%ciles de detectar causados por olvidar incluir break; al final de alguno de estos bloques y ello provocar que tras ejecutarse ese bloque se ejecute tambin el siguiente.

Instrucciones iterativas
Las instrucciones iterativas son instrucciones que permiten ejecutar repetidas veces una instruccin o un bloque de instrucciones mientras se cumpla una condicin. s

decir, permiten definir bucles donde ciertas instrucciones se ejecuten varias veces. ; continuacin se describen cules son las instrucciones de este tipo incluidas en ,-.

Instruccin while
La instruccin while permite ejecutar un bloque de instrucciones mientras se de una cierta instruccin. (u sinta!is de uso es" while (<condici#n>) <instrucciones> (u significado es el siguiente" (e eval+a la .condicin/ indicada, que ha de producir un valor lgico. (i es cierta 0valor lgico true1 se ejecutan las .instrucciones/ y se repite el proceso de evaluacin de .condicin/ y ejecucin de .instrucciones/ hasta que deje de serlo. ,uando sea falsa 0false1 se pasar a ejecutar la instruccin siguiente al while. n realidad .instrucciones/ puede ser una +nica instruccin o un bloque de instrucciones. 'n ejemplo cmo utilizar esta instruccin es el siguiente" usin* ./ste&; class 0ola,undo74ile { public static void ,ain(.trin*12 ar*s) { int actual = 5; if (ar*s$3en*t4 > 5) ;4ile (actual < ar*s$3en*t4) { 6onsole$7rite3ine(890ola {5}:8( ar*s1actual2); actual = actual A 1; } else 6onsole$7rite3ine(890ola &undo:8); } }

n este caso, si se indica ms de un argumento al llamar al programa se mostrar por pantalla un mensaje de saludo para cada uno de ellos. #ara ello se usa una variable actual que almacena cul es el n+mero de argumento a mostrar en cada ejecucin del while. #ara mantenerla siempre actualizada lo que se hace es aumentar en una unidad su valor tras cada ejecucin de las .instrucciones/ del bucle. #or otro lado, dentro de las .instrucciones/ de un while pueden usarse dos instrucciones especiales"

break;: Indica que se ha de abortar la e ecucin del bucle ! continuarse e ecutando por la instruccin siguiente al while"

continue;: Indica que se ha de abortar la e ecucin de las #instrucciones$ ! reevaluarse la #condicin$ del bucle% volvindose a e ecutar la #instrucciones$ si es cierta o pasndose a e ecutar la instruccin siguiente alwhile si es falsa"

Instruccin do"""while
La instruccin do...while es una variante del while que se usa as%" do <instrucciones> while(<condici#n>);

La +nica diferencia del significado de do...while respecto al de while es que en vez de evaluar primero la condicin y ejecutar .instrucciones/ slo si es cierta, do...while primero ejecuta las .instrucciones/ y luego mira la .condicin/ para ver si se ha de repetir la ejecucin de las mismas. #or lo dems ambas instrucciones son iguales, e incluso tambin puede incluirse break; y continue; entre las .instrucciones/ del do...while. do ... while est especialmente destinado para los casos en los que haya que ejecutar las .instrucciones/ al menos una vez a+n cuando la condicin sea falsa desde el principio., como ocurre en el siguiente ejemplo" usin* ./ste&; class 0ola,undoBo74ile { public static void ,ain() { .trin* le>do; do { 6onsole$7rite3ine(86lave 8); le>do = 6onsole$Read3ine(); } ;4ile (le>do := 8<os-8); 6onsole$7rite3ine(80ola <os-8);

} }

ste programa pregunta al usuario una clave y mientras no introduzca la correcta 0>os1 no continuar ejecutndose. 'na vez que introducida correctamente dar un mensaje de bienvenida al usuario.

Instruccin for
La instruccin for es una variante de while que permite reducir el cdigo necesario para escribir los tipos de bucles ms com+nmente usados en programacin. (u sinta!is es"

for (<inicialiCaci#n>; <condici#n>; <&odificaci#n>) <instrucciones> l significado de esta instruccin es el siguiente" se ejecutan las instrucciones de .inicializacin/, que suelen usarse para definir e inicializar variables que luego se usarn en .instrucciones/. Luego se eval+a .condicin/, y si es falsa se contin+a ejecutando por la instruccin siguiente al for; mientras que si es cierta se ejecutan las .instrucciones/ indicadas, luego se ejecutan las instrucciones de .modificacin/ &que como su nombre indica suelen usarse para modificar los valores de variables que se usen en .instrucciones/& y luego se reeval+a .condicin/ repitindose el proceso hasta que sta +ltima deje de ser cierta. n .inicializacin/ puede en realidad incluirse cualquier n+mero de instrucciones que no tienen porqu ser relativas a inicializar variables o modificarlas, aunque lo anteriro sea su uso ms habitual. n caso de ser varias se han de separar mediante comas 0,1, ya que el carcter de punto y coma 0;1 habitualmente usado para estos menesteres se usa en el for para separar los bloques de .inicializacin/, .condicin/ y .modificacin/. ;dems, la instruccin nula no se puede usar en este caso y tampoco pueden combinarse definiciones de variables con instrucciones de otros tipos. ,on .modificacin/ pasa algo similar, ya que puede incluirse cdigo que nada tenga que ver con modificaciones pero en este caso no se pueden incluir definiciones de variables. ,omo en el resto de instrucciones hasta ahora vistas, en .instrucciones/ puede ser tanto una +nica instruccin como un bloque de instrucciones. ;dems, las variables que se definan en .inicializacin/ sern visibles slo dentro de esas .instrucciones/ La siguiente clase es equivalente a la clase 3ola4undo?hile ya vista solo que hace uso del for para compactar ms su cdigo" usin* ./ste&; class 0ola,undoDor { public static void ,ain(.trin*12 ar*s) { if (ar*s$3en*t4 > 5) for (int actual = 5; actual < ar*s$3en*t4; actualAA) 6onsole$7rite3ine(890ola {5}:8( ar*s1actual2); else 6onsole$7rite3ine(890ola &undo:8); } } ;l igual que con while, dentro de las .instrucciones/ del for tambin pueden incluirse instrucciones continue; y break; que puedan alterar el funcionamiento normal del bucle.

Instruccin foreach
La instruccin foreach es una variante del for pensada especialmente para compactar la escritura de cdigos donde se realice alg+n tratamiento a todos los

elementos de una coleccin, que suele un uso muy habitual de for en los lenguajes de programacin que lo incluyen. La sinta!is que se sigue a la hora de escribir esta instruccin foreach es" foreach (<tipoEle&ento> <ele&ento> in <colecci#n>) <instrucciones> l significado de esta instruccin es muy sencillo" se ejecutan <instrucciones> para cada uno de los elementos de la .coleccin/ indicada. .elemento/ es una variable de slo lectura de tipo .tipo lemento/ que almacenar en cada momento el elemento de la coleccin que se est procesando y que podr ser accedida desde .instrucciones/. s importante se@alar que .coleccin/ no puede valer null porque entonces saltar%a una e!cepcin de tipo (ystem.Aull$eference !ception, y que .tipo lemento/ ha de ser un tipo cuyos objetos puedan almacenar los valores de los elementos de .coleccin/ n tanto que una tabla se considera que es una coleccin, el siguiente cdigo muestra cmo usar for para compactar a+n ms el cdigo de la clase 3ola4undoBor anterior" usin* ./ste&; class 0ola,undoDoeac4 { public static void ,ain(.trin*12 ar*s) { if (ar*s$3en*t4 > 5) foreac4(.trin* ar* in ar*s) 6onsole$7rite3ine(890ola {5}:8( ar*); else 6onsole$7rite3ine(890ola &undo:8); } } n general, se considera que una coleccin es todo aquel objeto que implemente la interfaz System. ollections.!"numerable. sta interfaz est definida en la C,L as%" interface IEnumerable { IEnumerator GetEnumerator(); } l objeto de interfaz System. ollections.!"numerator devuelto ha de ser un enumerador que permita recorrer los elementos de la .coleccin/. 9icha interfaz est as% predefinida" interface IEnumerator { object Current bool o!e"e#t(); !oid $eset(); }

l mtodo #eset$% ha de implementarse de modo que devuelva el enumerador reiniciado a un estado inicial donde a+n no referencie ni siquiera al primer elemento de la coleccin sino que sea necesario llamar a &ove'e(t$% para que lo haga. l mtodo &ove'e(t$% se ha de implementar de modo que haga que el enumerador pase a apuntar al siguiente elemento de la coleccin y devuelva un booleano que indique si tras avanzar se ha alcanzado el final de la coleccin. La propiedad urrent se ha de implementar de modo que devuelva siempre el elemento de la coleccin al que el enumerador est referenciando. (i se intenta leer urrent habindose ya recorrido toda la coleccin o habindose reiniciado la coleccin y no habindose colocado en su primer elemento con &ove'e(t$%, se ha de producir una e!cepcin de tipo System."(ce)tion.System"(ce)tion.!nvalid*)eration"(ce)tion *tra forma de conseguir que foreach considere que un objeto es una coleccin vlida consiste en hacer que dicho objeto siga el )atrn de coleccin. ste patrn consiste en definir el tipo del objeto de modo que sus objetos cuenten con un mtodo p+blico +et"numerator$% que devuelva un objeto no nulo que cuente con una propiedad p+blica llamada urrent que permita leer el elemento actual y con un mtodo p+blico bool &ove'e(t$% que permita cambiar el elemento actual por el siguiente y devuelva false slo cuando se haya llegado al final de la coleccin. l siguiente ejemplo muestra ambos tipos de implementaciones" usin* ./ste&; usin* ./ste&$6ollections; class @atron { private int actual = )1; public @atron EetEnu&erator() { return t4is; } public int 6urrent { *et {return actual;} } public bool ,oveFe!t() { bool resultado = true; actualAA; if (actual==15) resultado = false; return resultado; } }

class InterfaC IEnu&erable(IEnu&erator

{ private int actual = )1; public ob+ect 6urrent { *et {return actual;} } public bool ,oveFe!t() { bool resultado = true; actualAA; if (actual==15) resultado = false; return resultado;

public IEnu&erator EetEnu&erator() { return t4is; } public void Reset() { actual = )1; } } class @rincipal { public static void ,ain() { @atron ob+ = ne; @atron(); InterfaC ob+G = ne; InterfaC(); foreac4 (int ele& in ob+) 6onsole$7rite3ine(ele&); foreac4 (int ele& in ob+G) 6onsole$7rite3ine(ele&);

} }

l tipo System.,rray implementa la interfaz System. ollectiones.!"numerator, por lo que todas las tablas podrn ser usadas recorridas con foreach. (i la tabla a recorrer es multidimensional, sus elementos se recorrern en orden como muestra este ejemplo" int1(2 tabla = { ( };

foreac4 (int ele&ento in tabla) 6onsole$7rite3ine(ele&ento); La salida por pantalla del fragmento de cdigo anterior ser" 1

G H I La utilidad de implementar el patrn coleccin en lugar de la interfaz !"numerable es que as% no es necesario que urrent devuelva siempre un ob-ect, sino que puede devolver objetos de tipos ms concretos y gracias a ello puede detectarse al compilar si el .tipo lemento/ indicado puede o no almacenar los objetos de la coleccin. #or ejemplo, si en el ejemplo anterior sustituimos en el +ltimo foreach el .tipo lemento/ indicado por #atrn, el cdigo seguir compilando pero al ejecutarlo saltar una e!cepcin System.!nvalid ast"(ce)tion. (in embargo, si la sustitucin se hubiese hecho en el pen+ltimo foreach, entonces el cdigo directamente no compilar%a y se nos informar%a de un error debido a que los objetos int no son convertibles en objetos #atrn. Tambin hay que tener en cuenta que la comprobacin de tipos que se realiza en tiempo de ejecucin si el objeto slo implement la interfaz !"numerable es muy estricta, en el sentido de que si en el ejemplo anterior sustituimos el .tipo lemento/ del +ltimo foreach por byte tambin se lanzar la e!cepcin al no ser los objetos de tipo int impl%citamente convertibles en bytes sino slo a travs del operador $% (in embargo, cuando se sigue el patrn de coleccin las comprobaciones de tipo no son tan estrictas y entonces s% que ser%a vlido sustituir int por byte en .tipo lemento/. l problema de slo implementar el patrn coleccin es que este es una caracter%stica propia de ,- y con las instrucciones foreach 0o equivalentes1 de lenguajes que no lo soporten no se podr%a recorrer colecciones que slo siguiesen este patrn. 'na solucin en estos casos puede ser hacer que el tipo del objeto coleccin implemente tanto la interfaz !"numerable como el patrn coleccin. *bviamente esta interfaz deber%a implementarse e!pl%citamente para evitarse conflictos derivados de que sus miembros tengan signaturas coincidentes con las de los miembros propios del patrn coleccin. (i un objeto de un tipo coleccin implementa tanto la interfaz !"numerable como el patrn de coleccin, entonces en ,- foreach usar el patrn coleccin para recorrerlo.

Instrucciones de e&cepciones Concepto de e&cepcin"


Las e(ce)ciones son el mecanismo recomendado en la plataforma .A T para la propagacin de errores que se produzcan durante la ejecucin de las aplicaciones 0divisiones por cero, intentos de lectura de archivos da@ados, etc.1 Csicamente una e!cepcin es un objeto derivado de System."(ce)tion que se genera cuando en tiempo de ejecucin se produce alg+n error y que contiene informacin sobre el mismo. Tradicionalmente, el sistema que en otros lenguajes y plataformas se ha venido usando para informar estos errores consist%a simplemente en hacer que los mtodos en cuya ejecucin pudiesen producirse devolvieran cdigos que informasen sobre si se han ejecutado correctamente o, en caso contrario, sobre cul fue el error producido. (in embargo, las e!cepciones proporcionan las siguientes ventajas frente a dicho sistema"

Claridad: 'l uso de cdigos especiales para informar de error suele dificultar la legibilidad del fuente en tanto que se me(clan las instrucciones propias de la lgica del mismo con las instrucciones propias del tratamiento de los errores que pudiesen producirse durante su e ecucin" )or e emplo:
int resultado = ob+$,-todo(); if (resultado == 5) // .in errores al e+ecutar ob+$,-todo(); else if (resultado == 1) // Jrata&iento de error de c#di*o 1

else if (resultado == G) // Jrata&iento de error de c#di*o G $$$ ,omo se ver, utilizando e!cepciones es posible escribir el cdigo como si nunca se fuesen a producir errores y dejar en una zona aparte todo el cdigo de tratamiento de errores, lo que contribuye a facilitar la legibilidad de los fuentes.

Ms informacin: A partir del valor de un cdigo de error puede ser dif*cil deducir las causas del mismo ! conseguirlo muchas veces implica tenerse que consultar la documentacin que proporcionada sobre el mtodo que lo provoc% que puede incluso que no especifique claramente su causa"
#or el contrario, una e!cepcin es un objeto que cuenta con campos que describen las causas del error y a cuyo tipo suele drsele un nombre que resuma claramente su causa. #or ejemplo, para informar errores de divisin por cero se suele utilizar una e!cepcin predefinida de tipo .ivide/y0ero"(ce)tion en cuyo campo &essage se detallan las causas del error producido

Tratamiento asegurado: Cuando se utili(an cdigos de error nada obliga a tratarlos en cada llamada al mtodo que los pueda producir% e ignorarlos puede provocar ms adelante en el cdigo comportamientos inesperados de causas dif*ciles de descubrir"
,uando se usan e!cepciones siempre se asegura que el programador trate toda e!cepcin que pueda producirse o que, si no lo hace, se aborte la ejecucin de la aplicacin mostrndose un mensaje indicando dnde se ha producido el error.

;hora bien, tradicionalmente en lenguajes como ,== el uso de e!cepciones siempre ha tenido las desventajas respecto al uso de cdigos de error de complicar el compilador y dar lugar a cdigos ms lentos y dif%ciles de optimizar en los que tras cada instruccin que pudiese producir e!cepciones el compilador debe introducir las comprobaciones necesarias para detectarlas y tratarlas as% como para comprobar que los objetos creados sean correctamente destruidos si se producen. (in embargo, en la plataforma .A T desaparacen los problemas de complicar el compilador y dificultar las optimizaciones ya que que es el ,L$ quien se encarga de detectar y tratar las e!cepciones y es su recolector de basura quien se encarga asegurar la correcta destruccin de los objetos. *bviamente el cdigo seguir siendo algo ms lento, pero es un peque@o sacrificio que merece la pena hacer en tanto que

ello asegura que nunca se producirn problemas dif%ciles de detectar derivados de errores ignorados.

La clase +!stem"'&ception
,omo ya se ha dicho, todas las e!cepciones derivan de un tipo predefinido en la C,L llamado System."(ce)tion. Los principales miembros que heredan de ste son"

string Message {virtual get;}: Contiene un mensa e descriptivo de las causas de la e&cepcin" )or defecto este mensa e es una cadena vac*a ,""!ce"tion #nner !ce"tion {virtual get;}: +i una e&cepcin fue causada como consecuencia de otra% esta propiedad contiene el ob eto $%stem& !ce"tion que representa a la e&cepcin que la caus" As* se pueden formar cadenas de e&cepciones de cualquier longitud" +i se desea obtener la .ltima e&cepcin de la cadena es me or usar el mtodo virtual !ce"tion 'et(ase !ce"tion)* string $tackTrace {virtual get;}: Contiene la pila de llamadas a mtodos que se ten*a en el momento en que se produ o la e&cepcin" 'sta pila es una cadena con informacin sobre cul es el mtodo en que se produ o la e&cepcin% cul es el mtodo que llam a este% cul es el que llam a ese otro% etc" string $ource {virtual get; virtual set;}: Almacena informacin sobre cul fue la aplicacin u ob eto que caus la e&cepcin" Method(ase Target$ite {virtual get;}: Almacena cul fue el mtodo donde se produ o la e&cepcin en forma de ob eto $%stem&+eflection&Method(ase" )uede consultar la documentacin del +D/ si desea cmo obtener informacin sobre las caracter*sticas del mtodo a travs del ob eto Method(ase" string ,el"-ink {virtual get;}: Contiene una cadena con informacin sobre cul es la 01I donde se puede encontrar informacin sobre la e&cepcin" 'l valor de esta cadena puede establecerse con virtual !ce"tion $et,el"-ink )string .+#*% que devuelve la e&cepcin sobre la que se aplica pero con la 01I !a actuali(ada"

#ara crear objetos de clase System."(ce)tion se puede usar los constructores" E#ce%tion() E#ce%tion(string msg) E#ce%tion(string msg& E#ce%tion causante)

l primer constructor crea una e!cepcin cuyo valor para 4essage ser 11 y no causada por ninguna otra e!cepcin 0!nner"(ce)tion valdr null1 l segundo la crea con el valor indicado para &essage, y el +ltimo la crea con adems la e!cepcin causante indicada.

n la prctica, cuando se crean nuevos tipos derivados de System."(ce)tion no se suele redefinir sus miembros ni a@adirles nuevos, sino que slo se hace la derivacin para distinguir una e!cepciones de otra por el nombre del tipo al que pertenecen. ;hora bien, es conveniente respetar el convenio de darles un nombre acabado en "(ce)tion y redefinir los tres constructores antes comentados.

'&cepciones predefinidas comunes


n el espacio de nombres System de la C,L hay predefinidas m+ltiples e!cepciones derivadas de System."(ce)tion que se corresponden con los errores ms comunes que pueden surgir durante la ejecucin de una aplicacin. n la 2abla 3 se recogen algunas" 2i)o de la e(ce)cin ,rgument"(ce)tion ,rgument'ull"(ce)tion ,rray2y)e&istmatch"(ce)tion *&"(ce)tion .ivide/y0ero"(ce)tion !nde(*ut*f#ange"(ce)tion !nvalid ast"(ce)tion !nvalid*)eration"(ce)tion !ntero)"(ce)tion 'ull#eference"(ce)tion *verflow"(ce)tion *ut*f&emory"(ce)tion S"5"(ce)tion Stack*verflow"(ce)tion 2y)e!ni4iali4ation"(ce)tion ausa de que se )rodu4ca la e(ce)cin #asado argumento no vlido 0base de e!cepciones de argumentos1 #asado argumento nulo ;signacin a tabla de elemento que no es de su tipo !cepcin de objeto ,*4 9ivisin por cero Dndice de acceso a elemento de tabla fuera del rango vlido 0menor que cero o mayor que el tama@o de la tabla1 ,onversin e!pl%cita entre tipos no vlida *peracin invlida en estado actual del objeto Case de e!cepciones producidas en comunicacin con cdigo inseguro ;cceso a miembro de objeto que vale null 9esbordamiento dentro de conte!to donde se ha de comprobar los desbordamientos 0e!presin constante, instruccin checEed, operancin checEed u opcin del compilador FchecEed1 Balta de memoria para crear un objeto con ne< !cepcin (3 del ;#2 ?inG8 9esbordamiento de la pila, generalmente debido a un e!cesivo n+mero de llamadas recurrentes. 3a ocurrido alguna e!cepcin al inicializar los campos estticos o el constructor esttico de un tipo. n 2nner !ception se indica cul es.

,rgument*ut*f#ange"(ce)tion #asado argumento fuera de rango

Tabla H" !cepciones predefinidas de uso frecuente *bviamente, es conveniente que si las aplicaciones que escribamos necesiten lanzar e!cepciones relativas a errores de los tipos especificados en la 2abla 3, lancen precisamente las e!cepciones indicadas en esa tabla y no cualquier otra & ya sea definida por nosotros mismos o predefinida en la C,L con otro significado.

Lan(amiento de e&cepciones" Instruccin throw


#ara informar de un error no basta con crear un objeto del tipo de e!cepcin apropiado, sino que tambin hay pasrselo al mecanismo de propagacin de e!cepciones del ,L$. ; esto se le llama lan4ar la e(ce)cin, y para hacerlo se usa la siguiente instruccin" throw <ob+etoE!cepci#nK3anCar>;

#or ejemplo, para lanzar una e!cepcin de tipo .ivide/y0ero"(ce)tion se podr%a hacer" t4ro; ne; Bivide=/LeroE!ception(); (i el objeto a lanzar vale null, entonces se producir una 'ull#eference"(ce)tion que ser lanzada en vez de la e!cepcin indicada en la instruccin throw.

Captura de e&cepciones" Instruccin tr!


'na vez lanzada una e!cepcin es posible escribir cdigo que es encarge de tratarla. #or defecto, si este cdigo no se escribe la e!cepcin provoca que la aplicacin aborte mostrando un mensaje de error en el que se describe la e!cepcin producida 0informacin de su propiedad &essage1 y dnde se ha producido 0informacin de su propiedad Stack2race1 ;s%, dado el siguiente cdigo fuente de ejemplo" usin* ./ste&; class @ruebaE!cepciones { static void ,ain() { K ob+1 = ne; K(); ob+1$D(); } } class K { public void D() { E(); } static public void E() { int c = 5; int d = G/c; } } ;l compilarlo no se detectar ning+n error ya que al compilador no le merece la pena calcular el valor de c en tanto que es una variable, por lo que no detectar que dividir

8Fc no es vlido. (in embargo, al ejecutarlo se intentar dividir por cero en esa instruccin y ello provocar que aborte la aplicacin mostrando el siguiente mensaje" Mn4andled E!ception ./ste&$Bivide=/LeroE!ception Cero$ at @ruebaE!cepciones$,ain() Ktte&pted to divide b/

,omo se ve, en este mensaje se indica que no se ha tratado una e!cepcin de divisin por cero 0tipo .ivide/y0ero"(ce)tion1 dentro del cdigo del mtodo 4ain01 del tipo #rueba !cepciones. (i al compilar el fuente hubisemos utilizado la opcin 6debug, el compilador habr%a creado un fichero .)db con informacin e!tra sobre las instrucciones del ejecutable generado que permitir%a que al ejecutarlo se mostrase un mensaje mucho ms detallado con informacin sobre la instruccin e!acta que provoc la e!cepcin, la cadena de llamadas a mtodos que llevaron a su ejecucin y el n+mero de l%nea que cada una ocupa en el fuente" Mn4andled E!ception ./ste&$Bivide=/LeroE!ception Ktte&pted to divide b/ Cero$ at K$E() in E NcONE+Ne+$cs line GG at K$D() in E NcONE+Ne+$cs line 1P at @ruebaE!cepciones$,ain() in E NcONE+Ne+$cs line Q (i se desea tratar la e!cepcin hay que encerrar la divisin dentro de una instruccin try con la siguiente sinta!is" tr' <instrucciones> catch (<e!cepcin1>) <tratamiento1> catch (<e!cepcin2>) <tratamiento2> ... finally <instrucciones"inall#> l significado de try es el siguiente" si durante la ejecucin de las .instrucciones/ se lanza una e!cepcin de tipo .e!cepcin7/ 0o alguna subclase suya1 se ejecutan las instrucciones .tratamiento7/, si fuese de tipo .e!cepcin8/ se ejecutar%a .tratamiento8/, y as% hasta que se encuentre una clusula catch que pueda tratar la e!cepcin producida. (i no se encontrase ninguna y la instruccin try estuviese anidada dentro de otra, se mirar%a en los catch de su try padre y se repetir%a el proceso. (i al final se recorren todos los trys padres y no se encuentra ning+n catch compatible, entonces se buscar%a en el cdigo desde el que se llam al mtodo que produjo la e!cepcin. (i as% se termina llegando al mtodo que inici el hilo donde se produjo la e!cepcin y tampoco all% se encuentra un tratamiento apropiado se aborta dicho hilo: y si ese hilo es el principal 0el que contiene el punto de entrada1 se aborta el programa y se muestra el mensaje de error con informacin sobre la e!cepcin lanzada ya visto. ;s%, para tratar la e!cepcin del ejemplo anterior de modo que una divisin por cero provoque que a d se le asigne el valor I, se podr%a reescribir J01 de esta otra forma" static public void E()

{ tr/ { int c = 5; int d = G/c; } catc4 (Bivide=/LeroE!ception) { d=5; }

#ara simplificar tanto el compilador como el cdigo generado y favorecer la legibilidad del fuente, en los catchs se busca siempre orden de aparacin te!tual, por lo que para evitar catchs absurdos no se permite definir catchs que puedan capturar e!cepciones capturables por catchs posteriores a ellos en su misma instruccin try. Tambin hay que se@alar que cuando en .instrucciones/ se lance una e!cepcin que sea tratada por un catch de alg+n try &ya sea de la que contiene las .instrucciones/, de alg+n try padre suyo o de alguno de los mtodos que provocaron la llamada al que produjo la e!cepcin& se seguir ejecutando a partir de las instrucciones siguientes a ese try. l bloque finally es opcional, y si se incluye ha de hacerlo tras todas los bloques catch. Las .instruccionesBinally/ de este bloque se ejecutarn tanto si se producen e!cepciones en .instrucciones/ como si no. n el segundo caso sus instrucciones se ejecutarn tras las .instrucciones/, mientras que en el primero lo harn despus de tratar la e!cepcin pero antes de seguirse ejecutando por la instruccin siguiente al try que la trat. (i en un try no se encuentra un catch compatible, antes de pasar a buscar en su try padre o en su mtodo llamante padre se ejecutarn las .instruccionesBinally/. (lo si dentro de un bloque finally se lanzase una e!cepcin se aborta la ejecucin del mismo. 9icha e!cepcin ser%a propagada al try padre o al mtodo llamante padre del try que contuviese el finally. ;unque los bloques catch y finally son opcionales, toda instruccin try ha de incluir al menos un bloque catch o un bloque finally. l siguiente ejemplo resume cmo funciona la propagacin de e!cepciones" usin* ./ste&; class ,iE!ception E!ception {} class E!cepciones { public static void ,ain() { tr/ { 6onsole$7rite3ine(8En el tr/ de ,ain()8); ,-todo(); 6onsole$7rite3ine(8Kl final del tr/ de ,ain()8); } catc4 (,iE!ception)

{ 6onsole$7rite3ine(8En el catc4 de ,ain()8); } finall/ { 6onsole$7rite3ine(8finall/ de ,ain()8); } } public static void ,-todo() { tr/ { 6onsole$7rite3ine(8En el tr/ de ,-todo()8); ,-todoG(); 6onsole$7rite3ine(8Kl final del tr/ de ,-todo()8); } catc4 (Overflo;E!ception) { 6onsole$7rite3ine(8En el catc4 de ,-todo()8); } finall/ { 6onsole$7rite3ine(8finall/ de ,-todo()8); } } public static void ,-todoG() { tr/ { 6onsole$7rite3ine(8En el tr/ de ,-todoG()8); t4ro; ne; ,iE!ception(); 6onsole$7rite3ine(8Kl final del tr/ de ,-todoG()8); } catc4 (Bivide=/LeroE!ception) { 6onsole$7rite3ine(8En el catc4 de ,-todoG()8); } finall/ { 6onsole$7rite3ine(8finall/ de ,-todoG()8); } }

Atese que en este cdigo lo +nico que se hace es definir un tipo nuevo de e!cepcin llamado 4i !ception y llamarse en el &ain$% a un mtodo llamado 4todo01 que llama a otro de nombre 4todo801 que lanza una e!cepcin de ese tipo. Kiendo la salida de este cdigo es fcil ver el recorrido seguido durante la propagacin de la e!cepcin" En tr/ de ,ain() En tr/ de ,-todo() En tr/ de ,-todoG() finall/ de ,-todoG finall/ de ,-todo En catc4 de ,ain() finall/ de ,ain()

,omo se puede observar, hay muchos 7rite8ine$% que nunca se ejecutan ya que en cuento se lanza una e!cepcin se sigue ejecutando tras la instruccin siguiente al try que la trat 0aunque ejecutando antes los finally pendientes, como se deduce de la salida del ejemplo1 9e hecho, el compilador se dar cuenta que la instruccin siguiente al throw nunca se ejecutar e informar de ello con un mensaje de aviso. La idea de todo este mecanismo de e!cepciones es evitar mezclar el cdigo normal con el cdigo de tratamiento de errores. ;s%, en .instrucciones/ se escibir%a el cdigo como si no se pudiesen producir errores, en las clusulas catch se tratar%an los posibles errores, y en la clusula finally se incluir%a cdigo a ejecutar tanto si produjesen errores como si no 0suele usarse para liberar recursos ocupados, como fichero o cone!iones de red abiertas1 n realidad, tambin es posible escribir cada clusula catch definiendo una variable que se podr usar dentro del cdigo de tratamiento de la misma para hacer referencia a la e!cepcin capturada. sto se hace con la sinta!is" catch (<tipoE!cepci#n> <no&bre%ariable>) { <trata&iento> } Atese que en tanto que todas las e!cepciones derivan de System."(ce)tion, para definir una clusula catch que pueda capturar cualquier tipo de e!cepcin basta usar" catch(('stem.E#ce%tion <nombre$b%ecto>) { <trata&iento> } n realidad la sinta!is anterior slo permite capturar las e!cepciones propias de la plataforma .A T, que derivan de System."(ce)tion. (in embargo, hay lenguajes como ,== que permiten lanzar e!cepciones no derivadas de dicha clase, y para esos casos se ha incluido en ,- una variante de catch s% que realmente puede capturar e!cepciones de cualquier tipo, tanto si derivan de System."(ce)tion como si no. (u sinta!is es" catch { <trata&iento> } ,omo puede deducirse de su sinta!is, el problema que presenta esta +ltima variante de catch es que no proporciona informacin sobre cul es la e!cepcin capturada, por lo que a veces puede resultar poco +til y si slo se desea capturar cualquier e!cepcin derivada de System."(ce)tion es mejor usar la sinta!is e!plicada previamente a ella. n cualquier casos, ambos tipos de clusulas catch slo pueden ser escritas como la +ltima clusula catch del try, ya que si no las clusulas catch que le siguiesen nunca llegar%an a ejecutarse debido a que las primeras capturar%an antes cualquier e!cepcin derivada de System."(ce)tion.

$especto al uso de throw, hay que se@alar que hay una forma e!tra de usarlo que slo es vlida dentro de cdigos de tratamiento de e!cepciones 0cdigos .tratamientoi/ de las clusulas catch1 sta forma de uso consiste en seguir simplemente esta sinta!is" throw; n este caso lo que se hace es relanzar la misma e!cepcin que se captur en el bloque catch dentro de cuyo de cdigo de tratamiento se usa el throw; 3ay que precisar que la e!cepcin relanzada es precisamente la capturada, y aunque en el bloque catch se la modifique a travs de la variable que la repreesnta, la versin relanzada ser la versin original de la misma y no la modificada. ;dems, cuando se relance una e!cepcin en un try con clusula finally, antes de pasar a reprocesar la e!cepcin en el try padre del que la relanz se ejecutar dicha clusula.

Instrucciones de salto
Las instrucciones de salto permiten ejecutar variar el orden normal en que se ejecutan las instrucciones de un programa, que consiste en ejecutarlas una tras otra en el mismo orden en que se hubiesen escrito en el fuente. n los subapartados de este ep%grafe se describirn cules son las instrucciones de salto incluidas en ,-"

Instruccin brea2
)a se ha visto que la instruccin break slo puede incluirse dentro de bloques de instrucciones asociados a instrucciones iterativas o instrucciones switch e indica que se desea abortar la ejecucin de las mismas y seguir ejecutando a partir de la instruccin siguiente a ellas. (e usa as%" break; ,uando esta sentencia se usa dentro de un try con clusula finally, antes de abortarse la ejecucin de la instruccin iterativa o del switch que la contiene y seguirse ejecutando por la instruccin que le siga, se ejecutarn las instrucciones de la clusula finally del try. sto se hace para asegurar que el bloque finally se ejecute a+n en caso de salto. ;dems, si dentro una clusula finally incluida en de un switch o de una instruccin iterativa se usa break, no se permite que como resultado del break se salga del finally.

Instruccin continue
)a se ha visto que la instruccin continue slo puede usarse dentro del bloque de instrucciones de una instruccin iterativa e indica que se desea pasar a reevaluar directamente la condicin de la misma sin ejecutar el resto de instrucciones que contuviese. La evaluacin de la condicin se har%a de la forma habitual" si es cierta se repite el bucle y si es falsa se contin+a ejecutando por la instruccin que le sigue. (u sinta!is de uso es as% de sencilla"

continue; n cuanto a sus usos dentro de sentencias try, tiene las mismas restricciones que break" antes de salir de un try se ejecutar siempre su bloque finally y no es posible salir de un finally incluido dentro de una instruccin iterativa como consecuencia de un continue.

Instruccin return
sta instruccin se usa para indicar cul es el objeto que ha de devolver un mtodo, y se usa as%" return <ob+etoRetorno>; La ejecucin de esta instruccin provoca que se aborte la ejecucin del mtodo dentro del que aparece y que se devuelva el .objeto$etorno/ al mtodo que lo llam. ,omo es lgico, este objeto ha de ser del tipo de retorno del mtodo en que aparece el return o de alguno compatible con l, por lo que esta instruccin slo podr incluirse en mtodos cuyo tipo de retorno no sea void, o en los bloques get de las propiedades o indizadores. 9e hecho, es obligatorio que todo mtodo con tipo de retorno termine por un return. Los mtodos que devuelvan void pueden tener un return con una sinta!is espacial en la que no se indica ning+n valor a devolver sino que simplemente se usa return para indicar que se desea terminar la ejecucin del mtodo" return; Auevamente, como con el resto de instrucciones de salto hasta ahora vistas, si se incluyese un return dentro de un bloque try con clusula finally, antes de devolverse el objeto especificado se ejecutar%an las instrucciones de la clusula finally. (i hubiesen varios bloques finally anidados, las instrucciones de cada uno es ejecutar%an de manera ordenada 0o sea, del ms interno al ms e!terno1 ;hora bien, lo que no es posible es incluir un return dentro de una clusula finally.

Instruccin goto
La instruccin goto permite pasar a ejecutar el cdigo a partir de una instruccin cuya etiqueta se indica en el goto. La sinta!is de uso de esta instruccin es" goto <eti"ueta>; ,omo en la mayor%a de los lenguajes, goto es una instruccin maldita cuyo uso no se recomienda porque dificulta innecesariamente la legibilidad del cdigo y suele ser fcil simularla usando instrucciones iterativas y selectivas con las condiciones apropiadas. (in embargo, en ,- se incluye porque puede ser eficiente usarla si se anidan muchas instrucciones y para reducir sus efectos negativos se le han impuesto unas restricciones" (lo se pueden etiquetar instrucciones, y no a directivas using, directivas de preprocesado, definiciones de miembros, de tipos o de espacios de nombres.

La etiqueta indicada no pueda pertenecer a un bloque de instrucciones anidado dentro del bloque desde el que se usa el goto ni que etiquete a instrucciones de otro mtodo diferente a aqul en el cual se encuentra el goto que la referencia" )ara etiquetar una instruccin de modo que pueda ser destino de un salto con goto basta precederla del nombre con el que se la quiera etiquetar seguido de dos puntos ,:- )or e emplo% el siguiente cdigo demuestra cmo usar goto ! definir una etiqueta:

usin* ./ste&; class 0ola,undoEoto { public static void ,ain(strin*12 ar*s) { for (int i=5; i<ar*s$3en*t4; iAA) { if (ar*s1i2 := 8salir8) 6onsole$7rite3ine(ar*s1i2); else *oto fin } fin ; } } ste programa de ejemplo lo que hace es mostrar por pantalla todos los argumentos que se le pasen como parmetros, aunque si alguno fuese salir entonces se dejar%a de mostrar argumentos y se aborta la ejecucin de la aplicacin. Kase adems que este ejemplo pone de manifiesto una de las utilidades de la instruccin nula, ya que si no se hubiese escrito tras la etiqueta fin el programa no compilar%a en tanto que toda etiqueta ha de preceder a alguna instruccin 0aunque sea la instruccin nula1 Atese que al fin y al cabo los usos de goto dentro de instrucciones switch que se vieron al estudiar dicha instruccin no son ms que variantes del uso general de goto, ya que default9 no es ms que una etiqueta y case .valor/9 puede verse como una etiqueta un tanto especial cuyo nombre es case seguido de espacios en blanco y un valor. n ambos casos, la etiqueta indicada ha de pertenecer al mismo s<itch que el goto usado y no vale que ste no la contenga pero la contenga alg+n switch que contenga al switch del goto. l uso de goto dentro de sentencias try, tiene las mismas restricciones que break, continue y return" antes de salir con un goto de un try se ejecutar siempre su bloque finally y no es posible forzar a saltar fuera de un finally.

Instruccin throw
La instruccin throw ya se ha visto que se usa para lanzar e!cepciones de este modo" throw <ob%etoE!cepcinA&an'ar>;

n caso de que no se indique ning+n .objeto !cepcin;Lanzar/ se relanzar el que se estuviese tratando en ese moment, aunque esto slo es posible si el throw se ha escrito dentro del cdigo de tratamiento asociado a alguna clusula catch. ,omo ya se ha e!plicado a fondo esta instruccin en este mismo tema, para ms informacin sobre basta remitirse al ep%grafe Excepciones de este tema.

3tras instrucciones
Las instrucciones vistas hasta ahora son comunes a muchos lenguajes de programacin. (in embargo, en ,- tambin se ha incluido un buen n+mero de nuevas instrucciones propias de este lenguaje. stas instrucciones se describen en los siguientes apartados"

Instrucciones chec2ed ! unchec2ed


Las instrucciones checEed y unchecEed permiten controlar la forma en que tratarn los desbordamientos que ocurran durante la realizacin de operaciones aritmticas con tipos bsico enteros. Buncionan de forma similar a los operadores checked y unchecked ya vistos en el Tema 4: Aspectos lxicos, aunque a diferencia de stos son aplicables a bloques enteros de instrucciones y no a una +nica e!presin. ;s%, la instruccin checked se usa de este modo" checked <instrucciones> Todo desbordamiento que se produzca al realizar operaciones aritmticas con enteros en .instrucciones/ provocar que se lance una e!cepcin System.*verflow"(ce)tion. #or su parte, la instruccin unchecked se usa as%" unchecked <instrucciones> n este caso, todo desbordamiento que se produzca al realizar operaciones aritmticas con tipos bsicos enteros en .instrucciones/ ser ignorado y lo que se har ser tomar el valor resultante de quedarse con los bits menos significativos necesarios. #or defecto, en ausencia de estas instrucciones las e!presiones constantes se eval+an como si se incluyesen dentro de una instruccin checked y las que no constantes como si se incluyesen dentro de una instruccin unchecked. (in embargo, a travs de la opcin 6checked del compilador es posible tanto hacer que por defecto se comprueben los desbordamiento en todos los casos para as% siempre poder detectarlos y tratarlos 9esde Kisual (tudio.A T, la forma de controlar el tipo de comprobaciones que por defecto se harn es a travs de :iew ;> <ro)ety <ages ;> onfiguration Settings ;> /uild ;> heck for overflow underflow. l siguiente cdigo muestra un ejemplo de cmo usar ambas instrucciones" usin* ./ste&;

class Mnc4ec?ed { static s4ort ! = HGRPR;

// %alor &a!i&o del tipo s4ort

public static void ,ain() { unc4ec?ed { 6onsole$7rite3ine((s4ort) (!A1)); // (1) 6onsole$7rite3ine((s4ort) HGRPQ); // (G) } } } n un principio este cdigo compilar%a, pero los desbordamientos producidos por el hecho de que G8LMH no es un valor que se pueda representar con un short 07M bits con signo1 provocar%a que apareciese por pantalla dicho valor truncado, mostrndose" )HGRPQ )HGPRQ (in embargo, si sustituysemos la instruccin unchecked por checked, el cdigo anterior ni siquiera compilar%a ya que el compilador detectar%a que se va a producir un desbordamiento en 081 debido a que G8LMH es constante y no representable con un short. (i eliminamos la instruccin 081 el cdigo compilar%a ya que 0!=71 no es una e!presin constante y por tanto el compilador no podr%a detectar desbordamiento al compilar. (in embargo, cuando se ejecutase la aplicacin se lanzar%a una System.*verflow"(ce)tion.

Instruccin loc2
La instruccin lock es +til en aplicaciones concurrentes donde m+ltiples hilos pueden estar accediendo simultneamente a un mismo recurso, ya que lo que hace es garantizar que un hilo no pueda acceder a un recurso mientras otro tambin lo est haciendo. (u sinta!is es la siguiente" lock (<ob+eto>) <instrucciones> (u significado es el siguiente" ning+n hilo puede ejecutar las .instrucciones/ del bloque indicado si otro las est ejecutando, y si alguno lo intenta se quedar esperando hasta que acabe el primero. sto tambin afecta a bloques de .instrucciones/ de cualquier otro lock cuyo .objeto/ sea el mismo. ste .objeto/ ha de ser de alg+n tipo referencia. n realidad, la instruccin anterior es equivalente a hacer" ('stem.)hreading. onitor.Enter(<ob+eto>); tr' <instrucciones>

finall' { ('stem.)hreading. onitor.E#it(<ob+eto>); } (in embargo, usar lock tiene dos ventajas" es ms compacto y eficiente 0<ob-eto> slo se eval+a una vez1 'na buena forma de garantizar la e!clusin mutua durante la ejecucin de un mtodo de un cierto objeto es usando this como .objeto/. n el caso de que se tratase de un mtodo de tipo, en tanto que this no tiene sentido dentro de estos mtodos estticos una buena alternativa ser%a usar el objeto System.2y)e que representase a ese tipo. #or ejemplo" class 6 { public static void D() { loc?(t/peof(6)) { // $$$ 6#di*o al "ue se accede e!clusiva&ente } } }

Instruccin using
La instruccin using facilita el trabajo con objetos que tengan que ejecutar alguna tarea de limpieza o liberacin de recursos una vez que termine de ser +tiles. ;unque para estos menesteres ya estn los destructores, dado su carcter indeterminista puede que en determinadas ocasiones no sea conveniente confiar en ellos para realizar este tipo de tareas. La sinta!is de uso de esta instruccin es la siguiente" using (<tipo> <declaraciones>) <instrucciones> n .declaraciones/ se puede indicar uno o varios objetos de tipo .tipo/ separados por comas. stos objetos sern de slo lectura y slo sern accesibles desde .instrucciones/. ;dems, han de implementar la interfaz System.!.is)osable definida como sigue" interface I*is%osable { !oid *is%ose() } n la implementacin de .is)ose$% se escribir%a el cdigo de limpieza necesario, pues el significado de using consiste en que al acabar la ejecucin de .instrucciones/, se llama automticamente al mtodo .is)ose$% de los objetos definidos en .declaraciones/ 3ay que tener en cuenta que la llamada a 9ispose01 se hace sea cual sea la razn de que se deje de ejecutar las .instrucciones/ s decir, tanto si se ha producido una

e!cepcin como si se ha acabado su ejecucin normalmente o con una instruccin de salto, .is)ose$% es siempre llamado. n realidad una instruccin using como" usin* (R1 r1 = ne; R1()) { r1$D(); } s tratada por el compilador como" {

R1 r1 = ne; R1() tr/ { r1$D(); } finall/ { if (r1:=null) ((IBisposable) r1)$Bispose(); }

(i se declarasen varios objetos en .declaraciones/, a .is)ose$% se le llamar%a en el orden inverso a como fueron declarados. Lo mismo ocurre si se anidasen varias instrucciones using" primero se llamar%a al .is)ose$% de las variables declaradas en los using internos y luego a las de los e!ternos. ;s%, estas dos instrucciones son equivalentes" usin* (Recurso ob+ = ne; Recurso()( ob+G= ne; Recurso()) { r1$D(); rG$D(); } usin* (Recurso ob+ = ne; Recurso()) { usin* (Recurso ob+G= ne; Recurso()) { r1$D(); rG$D(); } } l siguiente ejemplo resume cmo funciona la sentencia using" usin* ./ste&; class K IBisposable { public void Bispose() { 6onsole$7rite3ine(83la&ado a Bispose() de {5}8( Fo&bre); }

public K(strin* no&bre) { Fo&bre = no&bre; } } strin* Fo&bre;

class Msin* { public static void ,ain() { K ob+? = ne; K(8ob+?8); usin* (K ob+1 = ne; K(8ob+18)( ob+G = ne; K(8ob+/8)) { 6onsole$7rite3ine(8Bentro del usin*8); } 6onsole$7rite3ine(8Duera del usin*8); } }

La salida por pantalla resultante de ejecutar este ejemplo ser" Bentro del usin* 3la&ando a Bispose() de ob+/ 3la&ando a Bispose() de ob+1 Duera del usin* ,omo se deduce de los mensajes de salida obtenidos, justo antes de salirse del using se llama a los mtodos .is)ose$% de los objetos declarados en la seccin <declaraciones> de dicha instruccin y en el mismo orden en que fueron declarados.

Instruccin fi&ed
La instruccin fi(ed se utiliza para fijar objetos en memoria de modo que el recolector de basura no pueda moverlos durante la ejecucin de un cierto bloque de instrucciones. sta instruccin slo tiene sentido dentro de regiones de cdigo inseguro, concepto que se trata en el Tema 18: C di!o inse!"ro, por lo que ser all% es donde se e!plique a fondo cmo utilizarla. ;qu% slo diremos que su sinta!is de uso es" fi#ed(<tipo@unteros> <declaraciones@unterosKDi+ar>) <instrucciones >

Potrebbero piacerti anche