Está en la página 1de 538

# C

Especificacin del lenguaje


Versin 3.0

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos. Enve correcciones, co entarios y c!al"!ier otra s!gerencia a sharp# icrosoft.co

$viso
1999-2008 Microsoft Corporation. Reservados todos los derechos. Microsoft, Windows, Vis al !asic, Vis al C" # Vis al C$$ son %arcas re&istradas o %arcas co%erciales de Microsoft Corporation en los ''.((. #)o en otros pa*ses o re&iones. +os de%,s prod ctos # no%-res de co%pa.*as %encionados en esta p -licaci/n p eden ser %arcas co%erciales de s s respectivos propietarios.

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Tabla de contenido

Tabla de contenido
1. Introduccin....................................................................................................................................................1 1.1 Hola a todos.................................................................................................................................................1 1.2 Estructura del programa...............................................................................................................................2 1.3 Tipos y variables.........................................................................................................................................4 1.4 Expresiones.................................................................................................................................................8 1. !nstrucciones..............................................................................................................................................1" 1.# Clases y ob$etos.........................................................................................................................................14 1.#.1 %iembros............................................................................................................................................14 1.#.2 &ccesibilidad......................................................................................................................................1 1.#.3 'ar(metros de tipo...............................................................................................................................1 1.#.4 Clases base..........................................................................................................................................1# 1.#. Campos...............................................................................................................................................1# 1.#.# %)todos..............................................................................................................................................1* 1.#.#.1 'ar(metros.....................................................................................................................................1* 1.#.#.2 Cuerpo del m)todo y variables locales..........................................................................................1+ 1.#.#.3 %)todos est(ticos y de instancia....................................................................................................1+ 1.#.#.4 %)todos virtuales, de invalidaci-n y abstractos............................................................................2" 1.#.#. .obrecarga de m)todos..................................................................................................................22 1.#.* /tros miembros de 0unci-n.................................................................................................................23 1.#.*.1 Constructores.................................................................................................................................2 1.#.*.2 'ropiedades...................................................................................................................................2 1.#.*.3 !ndi1adores....................................................................................................................................2# 1.#.*.4 Eventos..........................................................................................................................................2# 1.#.*. /peradores....................................................................................................................................2* 1.#.*.# 2estructores...................................................................................................................................2* 1.* Estructuras.................................................................................................................................................28 1.8 %atrices.....................................................................................................................................................2+ 1.+ !nter0aces...................................................................................................................................................3" 1.1" Enumeraciones........................................................................................................................................31 1.11 2elegados................................................................................................................................................33 1.12 &tributos..................................................................................................................................................34 2. Estructura lxica...........................................................................................................................................36 2.1 'rogramas..................................................................................................................................................3# 2.2 3ram(ticas.................................................................................................................................................3# 2.2.1 4otaci-n gramatical............................................................................................................................3# 2.2.2 3ram(tica l)xica.................................................................................................................................3* 2.2.3 3ram(tica sint(ctica............................................................................................................................3* 2.3 &n(lisis l)xico...........................................................................................................................................38 2.3.1 Terminadores de l5nea.........................................................................................................................38 2.3.2 Comentarios........................................................................................................................................3+ 2.3.3 Espacio en blanco...............................................................................................................................4" 2.4 To6ens.......................................................................................................................................................4" 2.4.1 .ecuencias de escape de caracteres 7nicode.......................................................................................4" 2.4.2 !denti0icadores....................................................................................................................................41 2.4.3 'alabras clave.....................................................................................................................................43 2.4.4 8iterales..............................................................................................................................................44 2.4.4.1 8iterales booleanos........................................................................................................................44 2.4.4.2 8iterales enteros............................................................................................................................44
Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

iii

Especificacin del lenguaje C#

2.4.4.3 8iterales reales...............................................................................................................................4 2.4.4.4 8iterales de car(cter.......................................................................................................................4# 2.4.4. 8iterales de cadena........................................................................................................................4* 2.4.4.# El literal null..................................................................................................................................4+ 2.4. /peradores y signos de puntuaci-n.....................................................................................................4+ 2. 2irectivas de preprocesamiento.................................................................................................................4+ 2. .1 .5mbolos de compilaci-n condicional................................................................................................. 1 2. .2 Expresiones de preprocesamiento....................................................................................................... 1 2. .3 2irectivas de declaraci-n.................................................................................................................... 2 2. .4 2irectivas de compilaci-n condicional............................................................................................... 3 2. . 2irectivas de diagn-stico.................................................................................................................... 2. .# 2irectivas de regi-n............................................................................................................................ # 2. .* 2irectivas de l5nea............................................................................................................................... # 2. .8 2irectivas pragma............................................................................................................................... * 2. .8.1 'ragma 9arning............................................................................................................................. * 3. Conceptos b sicos..........................................................................................................................................!" 3.1 !nicio de la aplicaci-n................................................................................................................................ + 3.2 :inali1aci-n de la aplicaci-n.....................................................................................................................#" 3.3 2eclaraciones............................................................................................................................................#" 3.4 %iembros..................................................................................................................................................#3 3.4.1 %iembros de espacio de nombres.......................................................................................................#3 3.4.2 %iembros de estructura.......................................................................................................................#3 3.4.3 %iembros de enumeraciones...............................................................................................................#4 3.4.4 %iembros de clase..............................................................................................................................#4 3.4. %iembros de inter0a1..........................................................................................................................#4 3.4.# %iembros de matri1............................................................................................................................#4 3.4.* %iembros de delegados......................................................................................................................#4 3. &cceso a miembros....................................................................................................................................#4 3. .1 &ccesibilidad declarada......................................................................................................................# 3. .2 2ominios de accesibilidad..................................................................................................................# 3. .3 &cceso protegido para miembros de instancia....................................................................................#8 3. .4 ;estricciones de accesibilidad.............................................................................................................#+ 3.# :irmas y sobrecargas.................................................................................................................................*" 3.* <mbitos.....................................................................................................................................................*1 3.*.1 /cultar nombres..................................................................................................................................*4 3.*.1.1 /cultar mediante anidaci-n...........................................................................................................* 3.*.1.2 /cultar mediante =erencia.............................................................................................................* 3.8 Espacios de nombres y nombres de tipos...................................................................................................** 3.8.1 4ombres completos............................................................................................................................*+ 3.+ &dministraci-n autom(tica de la memoria................................................................................................8" 3.1" /rden de e$ecuci-n..................................................................................................................................83 #. Tipos...............................................................................................................................................................$# 4.1 Tipos de valor............................................................................................................................................84 4.1.1 Tipo .ystem.>alueType......................................................................................................................8 4.1.2 Constructores predeterminados...........................................................................................................8 4.1.3 Tipos de estructura..............................................................................................................................8# 4.1.4 Tipos simples......................................................................................................................................8# 4.1. Tipos integrales...................................................................................................................................8* 4.1.# Tipos de punto 0lotante.......................................................................................................................8+

i%

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Tabla de contenido

4.1.* Tipo decimal.......................................................................................................................................+" 4.1.8 Tipo bool.............................................................................................................................................+" 4.1.+ Tipos de enumeraci-n.........................................................................................................................+1 4.1.1" Tipos ?ue aceptan valores 4788......................................................................................................+1 4.2 Tipos de re0erencia....................................................................................................................................+1 4.2.1 Tipos de clase......................................................................................................................................+2 4.2.2 Tipo ob$ect..........................................................................................................................................+3 4.2.3 Tipo string...........................................................................................................................................+3 4.2.4 Tipos de inter0a1.................................................................................................................................+3 4.2. Tipos de matri1...................................................................................................................................+3 4.2.# Tipos de delegados..............................................................................................................................+3 4.3 Conversiones boxing y unboxing..............................................................................................................+3 4.3.1 Conversiones boxing...........................................................................................................................+3 4.3.2 Conversiones 7nboxing......................................................................................................................+ 4.4 Tipos construidos......................................................................................................................................+# 4.4.1 &rgumentos de tipo.............................................................................................................................+* 4.4.2 Tipos cerrados y abiertos....................................................................................................................+* 4.4.3 Tipos enla1ados y sin enla1ar..............................................................................................................+* 4.4.4 Cumplimiento de las restricciones......................................................................................................+8 4. 'ar(metros de tipo.....................................................................................................................................++ 4.# Tipos de (rbol de expresiones..................................................................................................................1"" !. &ariables......................................................................................................................................................1'1 .1 Categor5as de variables............................................................................................................................1"1 .1.1 >ariables est(ticas.............................................................................................................................1"1 .1.2 >ariables de instancia.......................................................................................................................1"1 .1.2.1 >ariables de instancia en clases...................................................................................................1"2 .1.2.2 >ariables de instancia en estructuras...........................................................................................1"2 .1.3 Elementos matriciales.......................................................................................................................1"2 .1.4 'ar(metros de valor...........................................................................................................................1"2 .1. 'ar(metros de re0erencia...................................................................................................................1"2 .1.# 'ar(metros de salida..........................................................................................................................1"3 .1.* >ariables locales...............................................................................................................................1"3 .2 >alores predeterminados.........................................................................................................................1"4 .3 Estado de asignaci-n de0initiva...............................................................................................................1"4 .3.1 >ariables asignadas inicialmente......................................................................................................1" .3.2 >ariables no asignadas inicialmente.................................................................................................1"# .3.3 ;eglas precisas para determinar asignaciones de0initivas.................................................................1"# .3.3.1 ;eglas generales para instrucciones.............................................................................................1"# .3.3.2 !nstrucciones de blo?ues e instrucciones c=ec6ed y unc=ec6ed...................................................1"* .3.3.3 !nstrucciones de expresiones.......................................................................................................1"* .3.3.4 !nstrucciones de declaraci-n........................................................................................................1"* .3.3. !nstrucciones !0............................................................................................................................1"* .3.3.# !nstrucciones .9itc=....................................................................................................................1"8 .3.3.* !nstrucciones @=ile.....................................................................................................................1"8 .3.3.8 !nstrucciones 2o..........................................................................................................................1"8 .3.3.+ !nstrucciones :or.........................................................................................................................1"8 .3.3.1" !nstrucciones Area6, Continue y 3oto.......................................................................................1"+ .3.3.11 !nstrucciones T=ro9..................................................................................................................1"+ .3.3.12 !nstrucciones ;eturn..................................................................................................................1"+ .3.3.13 !nstrucciones TryBcatc=.............................................................................................................1"+

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Especificacin del lenguaje C#

.3.3.14 !nstrucciones TryB0inally...........................................................................................................11" .3.3.1 !nstrucciones TryB0inallyBcatc=..................................................................................................11" .3.3.1# !nstrucciones :oreac=................................................................................................................111 .3.3.1* !nstrucciones 7sing...................................................................................................................111 .3.3.18 !nstrucciones 8oc6.....................................................................................................................111 .3.3.1+ !nstrucciones yield.....................................................................................................................112 .3.3.2" ;eglas generales para expresiones simples................................................................................112 .3.3.21 ;eglas generales para expresiones con expresiones incrustadas................................................112 .3.3.22 Expresiones de invocaci-n y expresiones de creaci-n de ob$etos..............................................112 .3.3.23 Expresiones de asignaci-n simples............................................................................................113 .3.3.24 Expresiones CC........................................................................................................................113 .3.3.2 Expresiones DD.............................................................................................................................114 .3.3.2# Expresiones E.............................................................................................................................11 .3.3.2* Expresiones FF...........................................................................................................................11 .3.3.28 Expresiones FG............................................................................................................................11# .3.3.2+ :unciones an-nimas..................................................................................................................11# .4 ;e0erencias de variables..........................................................................................................................11* . &tomicidad de las re0erencias de variable...............................................................................................11* 6. Con%ersiones................................................................................................................................................11$ #.1 Conversiones impl5citas...........................................................................................................................118 #.1.1 Conversiones de identidad................................................................................................................118 #.1.2 Conversiones num)ricas impl5citas...................................................................................................118 #.1.3 Conversiones de enumeraci-n impl5citas..........................................................................................11+ #.1.4 Conversiones impl5citas ?ue aceptan valores 4788.........................................................................11+ #.1. Conversiones de literal 4788..........................................................................................................12" #.1.# Conversiones de re0erencia impl5citas...............................................................................................12" #.1.* Conversiones boxing.........................................................................................................................12" #.1.8 Conversiones impl5citas de expresi-n constante...............................................................................121 #.1.+ Conversiones impl5citas con par(metros de tipo...............................................................................121 #.1.1" Conversiones de0inidas por el usuario impl5citas............................................................................122 #.1.11 Conversiones de 0unci-n an-nima y conversiones de grupo de m)todos........................................122 #.2 Conversiones expl5citas...........................................................................................................................122 #.2.1 Conversiones expl5citas num)ricas...................................................................................................122 #.2.2 Conversiones de enumeraci-n expl5citas...........................................................................................124 #.2.3 Conversiones expl5citas ?ue aceptan valores 4788.........................................................................124 #.2.4 Conversiones expl5citas de re0erencia...............................................................................................12 #.2. Conversiones 7nboxing....................................................................................................................12# #.2.# Conversiones expl5citas con par(metros de tipo................................................................................12# #.2.* Conversiones expl5citas de0inidas por el usuario...............................................................................12* #.3 Conversiones est(ndar.............................................................................................................................12* #.3.1 Conversiones impl5citas est(ndar......................................................................................................12* #.3.2 Conversiones expl5citas est(ndar.......................................................................................................128 #.4 Conversiones de0inidas por el usuario.....................................................................................................128 #.4.1 Conversiones permitidas de0inidas por el usuario.............................................................................128 #.4.2 /peradores de conversi-n de elevaci-n............................................................................................128 #.4.3 Evaluaci-n de conversiones de0inidas por el usuario........................................................................128 #.4.4 Conversiones expl5citas de0inidas por el usuario...............................................................................12+ #.4. Conversiones expl5citas de0inidas por el usuario...............................................................................13" #. Conversiones de 0unci-n an-nima...........................................................................................................131 #. .1 Evaluaci-n de conversiones de 0unci-n an-nima a tipos delegados..................................................132

%i

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Tabla de contenido

#. .2 Evaluaci-n de conversiones de 0unci-n an-nima a tipos delegados de (rbol de expresiones............133 #. .3 E$emplo de implementaci-n..............................................................................................................133 #.# Conversiones de grupo de m)todos.........................................................................................................13# (. Expresiones..................................................................................................................................................13$ *.1 Clasi0icaciones de expresi-n....................................................................................................................138 *.1.1 >alores de expresiones......................................................................................................................13+ *.2 /peradores..............................................................................................................................................13+ *.2.1 'rioridad y asociatividad de los operadores......................................................................................14" *.2.2 .obrecarga de operadores.................................................................................................................141 *.2.3 ;esoluci-n de sobrecarga de operador unario...................................................................................142 *.2.4 ;esoluci-n de sobrecarga de operador binario..................................................................................142 *.2. /peradores candidatos de0inidos por el usuario................................................................................143 *.2.# 'romociones num)ricas....................................................................................................................143 *.2.#.1 'romociones num)ricas unarias...................................................................................................144 *.2.#.2 'romociones num)ricas binarias.................................................................................................144 *.2.* /peradores de elevaci-n...................................................................................................................14 *.3 AHs?ueda de miembros............................................................................................................................14 *.3.1 Tipos base.........................................................................................................................................14* *.4 %iembros de 0unci-n...............................................................................................................................14* *.4.1 8istas de argumentos.........................................................................................................................1 " *.4.2 !n0erencia de tipos.............................................................................................................................1 2 *.4.2.1 8a primera 0ase............................................................................................................................1 3 *.4.2.2 8a segunda 0ase...........................................................................................................................1 3 *.4.2.3 Tipos de entrada..........................................................................................................................1 4 *.4.2.4 Tipos de resultado......................................................................................................................1 4 *.4.2. 2ependencia................................................................................................................................1 4 *.4.2.# !n0erencias de tipo de resultado...................................................................................................1 4 *.4.2.* !n0erencias expl5citas de tipo de par(metro..................................................................................1 4 *.4.2.8 !n0erencias exactas......................................................................................................................1 *.4.2.+ !n0erencias de l5mite in0erior.......................................................................................................1 *.4.2.1" :i$ar tipos..................................................................................................................................1 *.4.2.11 Tipo de resultado in0erido..........................................................................................................1 *.4.2.12 !n0erencia de tipos para la conversi-n de grupos de m)todos....................................................1 * *.4.2.13 Auscar el me$or tipo comHn de un con$unto de expresiones......................................................1 * *.4.3 ;esoluci-n de sobrecargas................................................................................................................1 * *.4.3.1 %iembro de 0unci-n aplicable.....................................................................................................1 8 *.4.3.2 %e$or miembro de 0unci-n..........................................................................................................1 8 *.4.3.3 %e$or conversi-n de expresiones................................................................................................1 + *.4.3.4 %e$or conversi-n de tipos...........................................................................................................1 + *.4.3. .obrecarga en clases gen)ricas....................................................................................................1#" *.4.4 !nvocaci-n de miembros de 0unci-n..................................................................................................1#" *.4.4.1 !nvocaciones en instancias de conversi-n boxing........................................................................1#2 *. Expresiones primarias..............................................................................................................................1#2 *. .1 8iterales............................................................................................................................................1#3 *. .2 4ombres sencillos.............................................................................................................................1#3 *. .2.1 .igni0icado invariable en blo?ues................................................................................................1# *. .3 Expresiones entre par)ntesis.............................................................................................................1## *. .4 &cceso a miembros...........................................................................................................................1## *. .4.1 4ombres simples y nombres de tipos id)nticos...........................................................................1#8 *. .4.2 &mbigIedades gramaticales........................................................................................................1#8

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

%ii

Especificacin del lenguaje C#

*. . Expresiones de invocaci-n................................................................................................................1#+ *. . .1 !nvocaciones de m)todo..............................................................................................................1*" *. . .2 !nvocaciones del m)todo de extensi-n........................................................................................1*1 *. . .3 !nvocaciones de delegados..........................................................................................................1*3 *. .# &cceso a elementosG..........................................................................................................................1*4 *. .#.1 &cceso a matrices........................................................................................................................1*4 *. .#.2 &cceso al indi1ador.....................................................................................................................1* *. .* &cceso a t=is.....................................................................................................................................1* *. .8 &cceso a bases..................................................................................................................................1*# *. .+ /peradores post0i$os de incremento y decremento............................................................................1** *. .1" El operador ne9..............................................................................................................................1*8 *. .1".1 Expresiones de creaci-n de ob$etos...........................................................................................1*8 *. .1".2 !niciali1adores de ob$eto............................................................................................................18" *. .1".3 !niciali1adores de colecci-n.......................................................................................................182 *. .1".4 Expresiones de creaci-n de matrices.........................................................................................183 *. .1". Expresiones de creaci-n de delegados.......................................................................................18 *. .1".# Expresiones de creaci-n de ob$etos an-nimos...........................................................................18# *. .11 /perador typeo0..............................................................................................................................188 *. .12 8os operadores c=ec6ed y unc=ec6ed.............................................................................................1+" *. .13 Expresiones de valor predeterminadas............................................................................................1+2 *. .14 Expresiones de m)todos an-nimos..................................................................................................1+2 *.# /peradores unarios..................................................................................................................................1+3 *.#.1 /perador unario de signo m(s...........................................................................................................1+3 *.#.2 /perador unario de signo menos.......................................................................................................1+3 *.#.3 /perador de negaci-n l-gica.............................................................................................................1+4 *.#.4 /perador de complemento de bit a bit..............................................................................................1+4 *.#. /peradores pre0i$os de incremento y decremento.............................................................................1+4 *.#.# Expresiones de conversi-n................................................................................................................1+ *.* /peradores aritm)ticos............................................................................................................................1+# *.*.1 /perador de multiplicaci-n...............................................................................................................1+# *.*.2 /perador de divisi-n.........................................................................................................................1+* *.*.3 /perador de resto..............................................................................................................................1+8 *.*.4 /perador de suma.............................................................................................................................1++ *.*. /perador de resta..............................................................................................................................2"1 *.8 /peradores de despla1amiento................................................................................................................2"3 *.+ /peradores de comprobaci-n de tipos y relacionales..............................................................................2"4 *.+.1 /peradores de comparaci-n de enteros.............................................................................................2" *.+.2 /peradores de comparaci-n de punto 0lotante..................................................................................2"# *.+.3 /peradores de comparaci-n decimales.............................................................................................2"# *.+.4 /peradores de igualdad booleanos....................................................................................................2"* *.+. /peradores de comparaci-n de tipo de enumeraci-n........................................................................2"* *.+.# /peradores de igualdad de tipos de re0erencia..................................................................................2"* *.+.* /peradores de igualdad de cadenas...................................................................................................2"+ *.+.8 /peradores de igualdad de delegados...............................................................................................2"+ *.+.+ /peradores de igualdad y 4788......................................................................................................21" *.+.1" /perador !s.....................................................................................................................................21" *.+.11 /perador &s....................................................................................................................................21" *.1" /peradores l-gicos................................................................................................................................211 *.1".1 /peradores l-gicos enteros.............................................................................................................212 *.1".2 /peradores l-gicos de enumeraci-n................................................................................................212 *.1".3 /peradores l-gicos booleanos.........................................................................................................212

%iii

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Tabla de contenido

*.1".4 /peradores l-gicos booleanos ?ue aceptan valores 4788.............................................................213 *.11 /peradores l-gicos condicionales..........................................................................................................213 *.11.1 /peradores l-gicos condicionales booleanos..................................................................................214 *.11.2 /peradores l-gicos condicionales de0inidos por el usuario.............................................................214 *.12 El operador de uso combinado de 4788..............................................................................................21 *.13 /perador condicional............................................................................................................................21 *.14 Expresiones de 0unciones an-nimas......................................................................................................21# *.14.1 :irmas de 0unci-n an-nima.............................................................................................................218 *.14.2 Cuerpos de 0unci-n an-nima...........................................................................................................218 *.14.3 ;esoluci-n de sobrecargas..............................................................................................................21+ *.14.4 >ariables externas...........................................................................................................................22" *.14.4.1 >ariables externas capturadas....................................................................................................22" *.14.4.2 Creaci-n de instancias de variables locales...............................................................................221 *.14. Expresiones de evaluaci-n de 0unciones an-nimas.........................................................................223 *.1 Expresiones de consulta.........................................................................................................................223 *.1 .1 &mbigIedad en expresiones de consulta.........................................................................................224 *.1 .2 Traducci-n de expresiones de consulta...........................................................................................22 *.1 .2.1 Cl(usulas .elect y 3roupby con continuaciones........................................................................22 *.1 .2.2 Tipos de variable de intervalo expl5citos...................................................................................22# *.1 .2.3 Expresiones de consulta degeneradas........................................................................................22# *.1 .2.4 Cl(usulas 0rom, let, 9=ere, $oin y orderby.................................................................................22* *.1 .2. Cl(usulas .elect.........................................................................................................................23" *.1 .2.# Cl(usulas 3roupby....................................................................................................................23" *.1 .2.* !denti0icadores transparentes.....................................................................................................231 *.1 .3 El patr-n de expresiones de consulta...............................................................................................232 *.1# /peradores de asignaci-n......................................................................................................................233 *.1#.1 &signaci-n simple...........................................................................................................................234 *.1#.2 &signaci-n compuesta....................................................................................................................23# *.1#.3 &signaci-n de eventos.....................................................................................................................23* *.1* Expresi-n...............................................................................................................................................23* *.18 Expresiones constantes..........................................................................................................................238 *.1+ Expresiones booleanas...........................................................................................................................23+ $. Instrucciones................................................................................................................................................2#' 8.1 'untos 0inales y alcance...........................................................................................................................24" 8.2 Alo?ues....................................................................................................................................................242 8.2.1 8istas de instrucciones......................................................................................................................242 8.3 !nstrucci-n vac5a......................................................................................................................................243 8.4 !nstrucciones con eti?ueta........................................................................................................................243 8. !nstrucciones de declaraci-n....................................................................................................................244 8. .1 2eclaraciones de variables locales....................................................................................................244 8. .2 2eclaraciones de constantes locales..................................................................................................24# 8.# !nstrucciones de expresiones...................................................................................................................24# 8.* !nstrucciones de selecci-n.......................................................................................................................24* 8.*.1 !nstrucci-n !0.....................................................................................................................................24* 8.*.2 !nstrucci-n .9itc=............................................................................................................................248 8.8 !nstrucciones de iteraci-n........................................................................................................................2 2 8.8.1 !nstrucci-n @=ile..............................................................................................................................2 2 8.8.2 !nstrucci-n 2o...................................................................................................................................2 2 8.8.3 !nstrucci-n :or..................................................................................................................................2 3 8.8.4 !nstrucci-n :oreac=...........................................................................................................................2 4

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

ix

Especificacin del lenguaje C#

8.+ !nstrucciones Jump..................................................................................................................................2 * 8.+.1 !nstrucci-n Area6..............................................................................................................................2 8 8.+.2 !nstrucci-n .tatement........................................................................................................................2 + 8.+.3 !nstrucci-n 3oto................................................................................................................................2 + 8.+.4 !nstrucci-n ;eturn.............................................................................................................................2#" 8.+. !nstrucci-n T=ro9.............................................................................................................................2#1 8.1" !nstrucci-n Try......................................................................................................................................2#2 8.11 !nstrucciones C=ec6ed y 7nc=ec6ed.....................................................................................................2# 8.12 !nstrucci-n 8oc6....................................................................................................................................2# 8.13 !nstrucci-n 7sing...................................................................................................................................2## 8.14 8a instrucci-n yield...............................................................................................................................2#8 ". Espacio de no)bres.....................................................................................................................................2(' +.1 7nidades de compilaci-n.........................................................................................................................2*" +.2 2eclaraciones de espacio de nombres......................................................................................................2*" +.3 &lias extern.............................................................................................................................................2*2 +.4 2irectivas 7sing......................................................................................................................................2*2 +.4.1 2irectivas 7sing alias.......................................................................................................................2*3 +.4.2 2irectivas 7sing espacio de nombres................................................................................................2*# +. %iembros de espacio de nombres............................................................................................................2*8 +.# 2eclaraciones de tipo...............................................................................................................................2*8 +.* Cali0icadores de alias de espacios de nombres.........................................................................................2*+ +.*.1 7nicidad de los alias.........................................................................................................................28" 1'. Clases.........................................................................................................................................................2$1 1".1 2eclaraciones de clases.........................................................................................................................281 1".1.1 %odi0icadores de clase....................................................................................................................281 1".1.1.1 Clases abstractas........................................................................................................................282 1".1.1.2 Clases .ealed.............................................................................................................................282 1".1.1.3 Clases est(ticas..........................................................................................................................283 1".1.2 %odi0icador parcial.........................................................................................................................284 1".1.3 'ar(metros de tipo...........................................................................................................................284 1".1.4 Especi0icaci-n de clase base...........................................................................................................284 1".1.4.1 Clases base................................................................................................................................28 1".1.4.2 !mplementaciones de inter0aces.................................................................................................28# 1".1. ;estricciones de par(metros de tipo................................................................................................28# 1".1.# Cuerpo de clase...............................................................................................................................2+1 1".2 Tipos parciales.......................................................................................................................................2+1 1".2.1 &tributos.........................................................................................................................................2+1 1".2.2 %odi0icadores.................................................................................................................................2+2 1".2.3 'ar(metros de tipo y restricciones...................................................................................................2+2 1".2.4 Clase base.......................................................................................................................................2+3 1".2. !nter0aces base.................................................................................................................................2+3 1".2.# %iembros........................................................................................................................................2+3 1".2.* %)todos parciales...........................................................................................................................2+4 1".2.8 Enlace de nombres..........................................................................................................................2+# 1".3 %iembros de clase.................................................................................................................................2+* 1".3.1 El tipo de instancia .........................................................................................................................2+8 1".3.2 %iembros de tipos construidos........................................................................................................2+8 1".3.3 Herencia..........................................................................................................................................2++ 1".3.4 %odi0icador 4e9............................................................................................................................3"1

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Tabla de contenido

1".3. %odi0icadores de acceso.................................................................................................................3"1 1".3.# Tipos constituyentes........................................................................................................................3"2 1".3.* %iembros est(ticos y de instancia...................................................................................................3"2 1".3.8 Tipos anidados................................................................................................................................3"3 1".3.8.1 4ombre completo......................................................................................................................3"3 1".3.8.2 &ccesibilidad declarada.............................................................................................................3"3 1".3.8.3 /cultar.......................................................................................................................................3"4 1".3.8.4 &cceso t=is................................................................................................................................3" 1".3.8. &cceso a miembros privados y protegidos del tipo contenedor.................................................3" 1".3.8.# Tipos anidados en clases gen)ricas............................................................................................3"# 1".3.+ 4ombres de miembro reservados....................................................................................................3"* 1".3.+.1 4ombres de miembros reservados para propiedades.................................................................3"* 1".3.+.2 4ombres de miembros reservados para eventos........................................................................3"8 1".3.+.3 4ombres de miembros reservados para indi1adores..................................................................3"8 1".3.+.4 4ombres de miembros reservados para destructores.................................................................3"8 1".4 Constantes.............................................................................................................................................3"8 1". Campos..................................................................................................................................................31" 1". .1 Campos est(ticos y de instancia......................................................................................................312 1". .2 Campos de s-lo lectura...................................................................................................................312 1". .2.1 7tili1ar campos de s-lo lectura est(ticos para constantes..........................................................313 1". .2.2 >ersiones de constantes y campos de s-lo lectura est(ticos......................................................313 1". .3 Campos volatile..............................................................................................................................314 1". .4 !niciali1aci-n de campos.................................................................................................................31 1". . !niciali1adores de variables.............................................................................................................31 1". . .1 !niciali1aci-n de campos est(ticos.............................................................................................31# 1". . .2 !niciali1aci-n de campos de instancia........................................................................................318 1".# %)todos.................................................................................................................................................318 1".#.1 'ar(metros de m)todos...................................................................................................................32" 1".#.1.1 'ar(metros de valor...................................................................................................................321 1".#.1.2 'ar(metros de re0erencia...........................................................................................................321 1".#.1.3 'ar(metros de salida..................................................................................................................322 1".#.1.4 %atrices de par(metros.............................................................................................................323 1".#.2 %)todos est(ticos y de instancia.....................................................................................................32# 1".#.3 %)todos virtuales............................................................................................................................32# 1".#.4 %)todos de invalidaci-n.................................................................................................................328 1".#. %)todos sellados.............................................................................................................................33" 1".#.# %)todos abstractos..........................................................................................................................331 1".#.* %)todos externos............................................................................................................................332 1".#.8 %)todos parciales...........................................................................................................................333 1".#.+ %)todos de extensi-n......................................................................................................................333 1".#.1" Cuerpo del m)todo........................................................................................................................334 1".#.11 .obrecarga de m)todos.................................................................................................................334 1".* 'ropiedades...........................................................................................................................................334 1".*.1 'ropiedades est(ticas y de instancia................................................................................................33# 1".*.2 2escriptores de acceso....................................................................................................................33# 1".*.3 'ropiedades autom(ticamente implementadas................................................................................341 1".*.4 &ccesibilidad..................................................................................................................................342 1".*. 2escriptores de acceso virtual, sellado, de invalidaci-n y abstracto................................................343 1".8 Eventos..................................................................................................................................................34 1".8.1 Eventos como campos.....................................................................................................................34* 1".8.2 2escriptores de acceso de evento....................................................................................................34+

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

xi

Especificacin del lenguaje C#

1".8.3 Eventos est(ticos y de instancia......................................................................................................3 " 1".8.4 2escriptores de acceso virtual, sellado, de invalidaci-n y abstracto................................................3 " 1".+ !ndi1adores............................................................................................................................................3 1 1".+.1 .obrecarga de indi1adores...............................................................................................................3 1".1" /peradores...........................................................................................................................................3 1".1".1 /peradores unarios.......................................................................................................................3 # 1".1".2 /peradores binarios......................................................................................................................3 * 1".1".3 /peradores de conversi-n.............................................................................................................3 8 1".11 Constructores de instancia...................................................................................................................3#" 1".11.1 !niciali1adores de constructor........................................................................................................3#1 1".11.2 !niciali1adores de variables de instancia........................................................................................3#2 1".11.3 E$ecuci-n de constructores............................................................................................................3#2 1".11.4 Constructores predeterminados.....................................................................................................3#4 1".11. Constructores 'rivate....................................................................................................................3# 1".11.# 'ar(metros de constructor de instancia opcionales........................................................................3# 1".12 Constructores static..............................................................................................................................3# 1".13 2estructores.........................................................................................................................................3#8 1".14 !teradores.............................................................................................................................................3#+ 1".14.1 !nter0aces del enumerador.............................................................................................................3*" 1".14.2 !nter0aces enumerables..................................................................................................................3*" 1".14.3 Tipo Kield.....................................................................................................................................3*" 1".14.4 /b$etos del enumerador................................................................................................................3*" 1".14.4.1 El m)todo %ove4ext...............................................................................................................3*" 1".14.4.2 8a propiedad Current...............................................................................................................3*2 1".14.4.3 El m)todo 2ispose...................................................................................................................3*2 1".14. /b$etos enumerables.....................................................................................................................3*2 1".14. .1 El m)todo 3etEnumerator.......................................................................................................3*3 1".14.# E$emplo de implementaci-n..........................................................................................................3*3 11. Estructuras................................................................................................................................................3$' 11.1 2eclaraciones de estructuras..................................................................................................................38" 11.1.1 %odi0icadores de estructuras..........................................................................................................38" 11.1.2 %odi0icador parcial.........................................................................................................................381 11.1.3 !nter0aces .truct..............................................................................................................................381 11.1.4 Cuerpo de estructura.......................................................................................................................381 11.2 %iembros de estructura.........................................................................................................................381 11.3 2i0erencias entre clase y estructura.......................................................................................................382 11.3.1 .em(nticas de valor........................................................................................................................382 11.3.2 Herencia..........................................................................................................................................383 11.3.3 &signaci-n......................................................................................................................................383 11.3.4 >alores predeterminados.................................................................................................................383 11.3. Conversiones boxing y unboxing....................................................................................................384 11.3.# .igni0icado de T=is.........................................................................................................................38# 11.3.* !niciali1adores de campo.................................................................................................................38# 11.3.8 Constructores..................................................................................................................................38# 11.3.+ 2estructores....................................................................................................................................38* 11.3.1" Constructores static.......................................................................................................................38* 11.4 E$emplos de estructuras.........................................................................................................................388 11.4.1 Tipo entero de base de datos...........................................................................................................388 11.4.2 Tipo booleano de base de datos.......................................................................................................38+ 12. *atrices.....................................................................................................................................................3"2
xii
Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Tabla de contenido

12.1 Tipos de matri1......................................................................................................................................3+2 12.1.1 Tipo .ystem.&rray..........................................................................................................................3+3 12.1.2 %atrices y la inter0a1 !8ist gen)rica................................................................................................3+3 12.2 Creaci-n de matrices.............................................................................................................................3+4 12.3 &cceso a los elementos de matri1..........................................................................................................3+4 12.4 %iembros de matri1...............................................................................................................................3+4 12. Covarian1a de matrices..........................................................................................................................3+4 12.# !niciali1adores de matrices....................................................................................................................3+ 13. Interfaces...................................................................................................................................................3"( 13.1 2eclaraciones de inter0a1.......................................................................................................................3+* 13.1.1 %odi0icadores de inter0a1................................................................................................................3+* 13.1.2 %odi0icador parcial.........................................................................................................................3+8 13.1.3 !nter0aces base.................................................................................................................................3+8 13.1.4 Cuerpo de inter0a1...........................................................................................................................3+8 13.2 %iembros de inter0a1.............................................................................................................................3++ 13.2.1 %)todos de inter0a1.........................................................................................................................4"" 13.2.2 'ropiedades de inter0a1...................................................................................................................4"" 13.2.3 Eventos de inter0a1..........................................................................................................................4"" 13.2.4 !ndi1adores de inter0a1....................................................................................................................4"1 13.2. &cceso a miembros de inter0a1.......................................................................................................4"1 13.3 4ombres completos de miembros de inter0a1........................................................................................4"3 13.4 !mplementaciones de inter0aces.............................................................................................................4"3 13.4.1 !mplementaciones de miembro de inter0a1 expl5citas......................................................................4"4 13.4.2 Exclusividad de inter0aces implementadas......................................................................................4"# 13.4.3 !mplementaci-n de m)todos gen)ricos............................................................................................4"* 13.4.4 &signaci-n de inter0aces.................................................................................................................4"8 13.4. Herencia de implementaci-n de inter0aces......................................................................................411 13.4.# ;eimplementaci-n de inter0aces.....................................................................................................412 13.4.* !nter0aces y clases abstractas...........................................................................................................413 1#. Enu)eraciones..........................................................................................................................................#1! 14.1 2eclaraciones de enumeraci-n..............................................................................................................41 14.2 %odi0icadores de enumeraci-n..............................................................................................................41 14.3 %iembros de enumeraci-n....................................................................................................................41# 14.4 Tipo .ystem.Enum................................................................................................................................418 14. >alores y operaciones de enumeraci-n..................................................................................................418 1!. 1 1 1 1 +elegados...................................................................................................................................................#1" .1 2eclaraciones de delegados...................................................................................................................41+ .2 Compatibilidad de delegados.................................................................................................................421 .3 Creaci-n de instancias de delegados......................................................................................................422 .4 !nvocaci-n de delegados........................................................................................................................422

16. Excepciones................................................................................................................................................#2! 1#.1 Causas de excepciones...........................................................................................................................42 1#.2 Clase .ystem.Exception........................................................................................................................42 1#.3 C-mo controlar excepciones..................................................................................................................42 1#.4 Clases de excepci-n comunes................................................................................................................42# 1(. ,tributos....................................................................................................................................................#2$ 1*.1 Clases de atributos.................................................................................................................................428

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

xiii

Especificacin del lenguaje C#

1*.1.1 7so de los atributos.........................................................................................................................428 1*.1.2 'ar(metros posicionales y con nombre...........................................................................................42+ 1*.1.3 Tipos de par(metros de atributos.....................................................................................................43" 1*.2 Especi0icaci-n de atributos....................................................................................................................43" 1*.3 !nstancias de atributo.............................................................................................................................43# 1*.3.1 Compilaci-n de un atributo.............................................................................................................43# 1*.3.2 ;ecuperaci-n en tiempo de e$ecuci-n de una instancia de atributo.................................................43# 1*.4 &tributos reservados..............................................................................................................................43* 1*.4.1 &tributo &ttribute7sage..................................................................................................................43* 1*.4.2 &tributo Conditional.......................................................................................................................438 1*.4.2.1 %)todos condicionales..............................................................................................................438 1*.4.2.2 Clases de atributo condicional...................................................................................................44" 1*.4.3 &tributo /bsolete............................................................................................................................441 1*. &tributos para interoperabilidad............................................................................................................442 1*. .1 !nteroperabilidad con componentes C/% y @in32........................................................................442 1*. .2 !nteroperabilidad con otros lengua$es .4ET....................................................................................442 1*. .2.1 &tributo !ndexer4ame...............................................................................................................442 1$. Cdigo no seguro.......................................................................................................................................##3 18.1 Contextos no seguros.............................................................................................................................443 18.2 Tipos de punteros..................................................................................................................................44# 18.3 >ariables 0i$as y m-viles.......................................................................................................................448 18.4 Conversiones de puntero........................................................................................................................44+ 18.4.1 %atrices de punteros.......................................................................................................................4 " 18. 'unteros en expresiones.........................................................................................................................4 1 18. .1 2ireccionamiento indirecto de punteros..........................................................................................4 1 18. .2 &cceso a miembros de puntero.......................................................................................................4 2 18. .3 &cceso a elementos de puntero.......................................................................................................4 2 18. .4 /perador de direcci-n.....................................................................................................................4 3 18. . !ncremento y decremento de punteros.............................................................................................4 4 18. .# &ritm)tica con punteros..................................................................................................................4 4 18. .* Comparaci-n de punteros................................................................................................................4 18. .8 /perador .i1eo0..............................................................................................................................4 # 18.# !nstrucci-n 0ixed....................................................................................................................................4 # 18.* AH0eres 0i$os..........................................................................................................................................4#" 18.*.1 2eclaraciones de bH0eres 0i$os.........................................................................................................4#" 18.*.2 AH0eres 0i$os en expresiones............................................................................................................4#1 18.*.3 Comprobaci-n de asignaci-n de0initiva..........................................................................................4#2 18.8 &signaci-n de pila.................................................................................................................................4#2 18.+ &signaci-n din(mica de memoria..........................................................................................................4#3 ,. Co)entarios de docu)entacin................................................................................................................#66 &.1 !ntroducci-n............................................................................................................................................4## &.2 Eti?uetas recomendadas..........................................................................................................................4#* &.2.1 LcM...................................................................................................................................................4#8 &.2.2 LcodeM.............................................................................................................................................4#8 &.2.3 LexampleM.......................................................................................................................................4#+ &.2.4 LexceptionM.....................................................................................................................................4#+ &.2. LincludeM.........................................................................................................................................4*" &.2.# LlistM................................................................................................................................................4*1 &.2.* LparaM..............................................................................................................................................4*1

xi%

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Tabla de contenido

&.2.8 LparamM...........................................................................................................................................4*2 &.2.+ Lparamre0M.......................................................................................................................................4*2 &.2.1" LpermissionM..................................................................................................................................4*3 &.2.11 Lremar6M........................................................................................................................................4*3 &.2.12 LreturnsM........................................................................................................................................4*3 &.2.13 LseeM..............................................................................................................................................4*4 &.2.14 LseealsoM.......................................................................................................................................4*4 &.2.1 LsummaryM....................................................................................................................................4* &.2.1# LvalueM..........................................................................................................................................4* &.2.1* LtypeparamM..................................................................................................................................4* &.2.18 Ltypeparamre0M..............................................................................................................................4*# &.3 'rocesar el arc=ivo de documentaci-n....................................................................................................4*# &.3.1 :ormato de cadena de !d..................................................................................................................4*# &.3.2 E$emplos de cadena de !d.................................................................................................................4*8 &.4 7n e$emplo.............................................................................................................................................481 &.4.1 C-digo 0uente C#.............................................................................................................................481 &.4.2 N%8 resultante................................................................................................................................484 -. .ra) tica...................................................................................................................................................#$( A.1 3ram(tica l)xica.....................................................................................................................................48* A.1.1 Terminadores de l5nea......................................................................................................................48* A.1.2 Comentarios.....................................................................................................................................48* A.1.3 Espacio en blanco.............................................................................................................................488 A.1.4 To6ens..............................................................................................................................................488 A.1. .ecuencias de escape de caracteres 7nicode....................................................................................488 A.1.# !denti0icadores..................................................................................................................................48+ A.1.* 'alabras clave...................................................................................................................................4+" A.1.8 8iterales............................................................................................................................................4+" A.1.+ /peradores y signos de puntuaci-n..................................................................................................4+2 A.1.1" 2irectivas de preprocesamiento......................................................................................................4+2 A.2 3ram(tica sint(ctica................................................................................................................................4+ A.2.1 Conceptos b(sicos............................................................................................................................4+ A.2.2 Tipos................................................................................................................................................4+ A.2.3 >ariables..........................................................................................................................................4+# A.2.4 Expresiones......................................................................................................................................4+* A.2. !nstrucciones.................................................................................................................................... "3 A.2.# Espacio de nombres.......................................................................................................................... "* A.2.* Clases............................................................................................................................................... "8 A.2.8 Estructuras........................................................................................................................................ 1 A.2.+ %atrices............................................................................................................................................ 1 A.2.1" !nter0aces........................................................................................................................................ 1# A.2.11 Enumeraciones............................................................................................................................... 1* A.2.12 2elegados....................................................................................................................................... 1* A.2.13 &tributos......................................................................................................................................... 18 A.3 Extensiones de la gram(tica para el c-digo no seguro............................................................................ 1+ C. /eferencias..................................................................................................................................................!23

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

x%

Cap0tulo 1' Clases

1. Introduccin
C# OPC s=arpQR es un lengua$e de programaci-n sencillo y moderno, orientado a ob$etos y con seguridad de tipos. C# tiene su ra51 en la 0amilia de lengua$es C y resultar( inmediatamente 0amiliar a programadores de C, CSS y Java. EC%& !nternational estandari1a C# como el est(ndar ECM$-%%&, e !./TCE! como el est(ndar '()*'EC 2%2+0. El compilador de C# de %icroso0t para .4ET :rame9or6 es una implementaci-n compatible de ambos est(ndares. C# es un lengua$e de programaci-n orientado a ob$etos, pero tambi)n es compatible con la programaci-n orientada a co ponentes. El diseUo de so0t9are contempor(neo se basa cada ve1 m(s en componentes de so0t9are en 0orma de pa?uetes de 0uncionalidad autodescriptivos y autosu0icientes. 8a clave de dic=os componentes reside en ?ue presentan un modelo de programaci-n con propiedades, m)todos y eventos, en ?ue tienen atributos ?ue 0acilitan in0ormaci-n declarativa sobre el componente y en ?ue incorporan su propia documentaci-n. C# proporciona construcciones de lengua$e para ?ue se admitan directamente estos conceptos, =aciendo de C# un lengua$e muy natural en el ?ue crear y utili1ar los componentes de so0t9are. &lgunas de las caracter5sticas de C# ayudan en la construcci-n de aplicaciones s-lidas y duraderasG la recolecci,n de ele entos no !tili-ados reclama autom(ticamente la memoria ocupada por ob$etos no utili1adosV el control de e.cepciones proporciona un en0o?ue extensible y estructurado de la detecci-n y recuperaci-n de erroresV y el diseUo con seg!ridad de tipos del lengua$e =ace ?ue sea imposible leer variables no iniciali1adas, indi1ar las matrices m(s all( de sus l5mites o reali1ar conversiones de tipo no comprobado. C# tiene un siste a de tipos !nificado. Todos los tipos de C#, incluidos tipos primitivos como int y double, =eredan de un tipo ra51 object Hnico. 'or lo tanto, todos los tipos comparten un con$unto de operaciones comunes, y se pueden almacenar, transportar y tratar valores de cual?uier tipo de una manera co=erente. &dem(s, C# admite tipos de re0erencia de0inidos por el usuario y tipos de valor, y permite la asignaci-n din(mica de ob$etos as5 como el almacenamiento en l5nea de estructuras ligeras. 'ara asegurarse de ?ue los programas y bibliotecas de C# evolucionan con el tiempo de 0orma compatible, se =a dado muc=a importancia al control de versiones en el diseUo de C#. %uc=os lengua$es de programaci-n apenas prestan atenci-n a este problema y, en consecuencia, los programas escritos en estos lengua$es se interrumpen m(s de lo necesario cuando se incluyen versiones m(s recientes de bibliotecas dependientes. 8os aspectos del diseUo de C# con in0luencia directa de las consideraciones sobre el control de versiones incluyen los modi0icadores virtual y override, las reglas de la resoluci-n de sobrecarga de m)todos y la compatibilidad con declaraciones expl5citas de miembros de inter0a1. En el resto de este cap5tulo se explican las caracter5sticas esenciales del lengua$e C#. %ientras ?ue en cap5tulos posteriores se describen las reglas y las excepciones de una 0orma muy detallada e incluso a veces matem(tica, este cap5tulo se =a redactado dando prioridad a la claridad y la brevedad, a veces incluso a expensas de la integridad. El prop-sito es proporcionar al lector una introducci-n al lengua$e ?ue pueda 0acilitarle la programaci-n de sus primeros programas y la lectura de posteriores cap5tulos.

1.1 Hola a todos


El programa Hola a todos OPHello, @orldQR se utili1a tradicionalmente para presentar un lengua$e de programaci-n. &?u5 est( en C#G
using System;

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Especificacin del lenguaje C# class Hello { static void Main() { Console.WriteLine("Hello ! !

World");

4ormalmente, la extensi-n de los arc=ivos de c-digo 0uente de C# es .cs. .uponiendo ?ue PHello, @orldQ se almacena en el arc=ivo "ello.cs, el programa se puede compilar con el compilador de %icroso0t C#, utili1ando la l5nea de comandos
csc "ello.cs

?ue genera un ensamblado e$ecutable denominado "ello.e#e. El resultado de la e$ecuci-n de esta aplicaci-n es
Hello World

El programa PHello, @orldQ se inicia con una directiva using ?ue =ace re0erencia al espacio de nombres System. 8os espacios de nombres proporcionan una $erar?u5a ?ue permite organi1ar programas y bibliotecas de C#. 8os espacios de nombres contienen tipos y otros espacios de nombres, por e$emplo, el espacio de nombres System contiene varios tipos, como la clase Console, a la ?ue se =ace re0erencia en el programa, y otros espacios de nombres, como $% y Collections. 7na directiva using ?ue =ace re0erencia a un espacio de nombres determinado permite el uso no cali0icado de los tipos ?ue son miembros del espacio de nombres. 2ebido a la directiva using, el programa puede utili1ar Console.WriteLine como 0orma abreviada para System.Console.WriteLine. 8a clase Hello declarada por el programa PHello, @orldQ tiene un Hnico miembro, el m)todo denominado Main. El m)todo Main se declara con el modi0icador static. %ientras ?ue los m)todos de instancia =acen re0erencia a una instancia de ob$eto determinada utili1ando la palabra clave t"is, los m)todos est(ticos 0uncionan sin re0erencia a un ob$eto determinado. 'or convenci-n, un m)todo est(tico denominado Main sirve como punto de entrada de un programa. El m)todo WriteLine genera el resultado del programa en la clase Console del espacio de nombres System. Esta clase es proporcionada por las bibliotecas de clases de .4ET :rame9or6, a las ?ue de 0orma predeterminada =ace re0erencia autom(ticamente el compilador de %icroso0t C#. /bserve ?ue el propio C# no tiene una biblioteca en tiempo de e$ecuci-n independiente. En su lugar, .4ET :rame9or6 es la biblioteca en tiempo de e$ecuci-n de C#.

1.2 Estructura del programa


8os conceptos clave de organi1aci-n en C# son progra as, espacios de no /res, tipos, ie /ros y ensa /lados. 8os programas de C# constan de uno o varios arc=ivos de c-digo 0uente. 8os programas declaran tipos, ?ue contienen los miembros y pueden organi1arse en los espacios de nombres. 8as clases y las inter0aces son e$emplos de tipos. 8os campos, m)todos, propiedades y eventos son e$emplos de miembros. Cuando se compilan programas de C#, se empa?uetan 05sicamente en ensamblados. 4ormalmente la extensi-n de arc=ivo de los ensamblados es .e#e o .dll, dependiendo de si implementan aplicaciones o /i/liotecas. En el e$emplo
using System; names&ace 'cme.Collections { &ublic class Stac( { )ntry to&; &ublic void *us"(object data) { to& + ne, )ntry(to& data); !

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases &ublic object *o&() { i- (to& ++ null) t"ro, ne, $nvalid%&eration)#ce&tion(); object result + to&.data; to& + to&.ne#t; return result; ! class )ntry { &ublic )ntry ne#t; &ublic object data; &ublic )ntry()ntry ne#t t"is.ne#t + ne#t; t"is.data + data; ! ! ! ! object data) {

se declara una clase denominada Stac( en un espacio de nombres llamado 'cme.Collections. El nombre completo de esta clase es 'cme.Collections.Stac(. 8a clase contiene varios miembrosG un campo denominado to&, dos m)todos denominados *us" y *o&, y una clase anidada denominada )ntry. 8a clase )ntry contiene tres miembros m(sG un campo denominado ne#t, un campo denominado data y un constructor. .uponiendo ?ue el c-digo 0uente del e$emplo se almacena en el arc=ivo acme.cs, la l5nea de comandos
csc .t/library acme.cs

compila el e$emplo como una biblioteca Oc-digo sin un punto de entrada MainR y genera un ensamblado denominado acme.dll. 8os ensamblados contienen c-digo e$ecutable en 0orma de instrucciones de 0eng!a1e inter edio O!8R e in0ormaci-n simb-lica en 0orma de etadatos. &ntes de e$ecutarse, el c-digo !8 de un ensamblado se convierte autom(ticamente en c-digo espec50ico del procesador mediante el compilador JustB!nBTime OJ!TR de .4ET Common 8anguage ;untime. 2ado ?ue un ensamblado es una unidad autodescriptiva de 0uncionalidad ?ue contiene c-digo y metadatos, las directivas 0include y los arc=ivos de encabe1ado no son necesarios en C#. 8os tipos y miembros pHblicos contenidos en un ensamblado determinado estar(n disponibles en un programa de C# =aciendo re0erencia a dic=o ensamblado al compilar el programa. 'or e$emplo, este programa utili1a la clase 'cme.Collections.Stac( desde el ensamblado acme.dllG
using System; using 'cme.Collections; class 1est { static void Main() { Stac( s + ne, Stac((); s.*us"(2); s.*us"(23); s.*us"(233); Console.WriteLine(s.*o&()); Console.WriteLine(s.*o&()); Console.WriteLine(s.*o&()); ! !

.i el programa se almacena en el arc=ivo test.cs, cuando se compila test.cs se puede =acer re0erencia al ensamblado acme.dll utili1ando la opci-n del compilador .rG
csc .r/acme.dll test.cs

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Especificacin del lenguaje C#

2e este modo se crea un ensamblado e$ecutable denominado test.e#e ?ue, cuando se e$ecuta, genera el resultadoG
233 23 2

C# permite el almacenamiento del texto de origen de un programa en varios arc=ivos de c-digo 0uente. Cuando se compila un programa de C# de varios arc=ivos, se procesan todos los arc=ivos de c-digo 0uente $untos, y )stos pueden =acer re0erencia libremente unos a otros. Conceptualmente, es como si todos los arc=ivos de c-digo 0uente se concatenaran en un gran arc=ivo antes de procesarse. En C# nunca son necesarias las declaraciones adelantadas por?ue, salvo alguna excepci-n, el orden de la declaraci-n no es signi0icativo. C# no limita un arc=ivo de c-digo 0uente a declarar un Hnico tipo pHblico ni exige ?ue el nombre del arc=ivo de c-digo 0uente coincida con un tipo declarado en el arc=ivo de c-digo 0uente.

1.3 Tipos y ariables


Hay dos clases de tipos en C#G tipos de valor y tipos de referencia. 8as variables de tipos de valor contienen directamente sus datos mientras ?ue las variables de tipos de re0erencia almacenan las re0erencias a sus datos, ?ue se conocen como ob$etos. En el caso de los tipos de re0erencia, es posible ?ue dos variables =agan re0erencia al mismo ob$eto y, por tanto, ?ue las operaciones en una variable a0ecten al ob$eto al ?ue =ace re0erencia la otra variable. En el caso de los tipos de valor, cada variable tiene su propia copia de los datos, de manera ?ue no es posible ?ue las operaciones de una a0ecten a la otra Oexceptuando las variables de los par(metros re- y outR. 8os tipos de valor de C# se dividen a su ve1 en tipos si ples, tipos de en! eraci,n, tipos de estr!ct!ra, y tipos "!e aceptan valores 2300, y los tipos de re0erencia de C# en tipos de clase, tipos de interfa-, tipos de atri- y tipos de delegado.

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

8a tabla siguiente proporciona in0ormaci-n general sobre el sistema de tipos de C#. Categor0a Tipos de valor Tipos simples +escripcin !ntegrales con signoG sbyte, s"ort, int, long !ntegrales sin signoG byte, us"ort, uint, ulong Caracteres 7nicodeG c"ar 'unto 0lotante !EEEG -loat, double 2ecimal de gran precisi-nG decimal AooleanoG bool Tipos de enumeraci-n Tipos de estructura Tipos ?ue aceptan valores 4788 Tipos de re0erencia Tipos de clase Tipos de0inidos por el usuario en 0orma de enum ) {...! Tipos de0inidos por el usuario en 0orma de struct S {...! Extensiones de todos los dem(s tipos de valores con un valor
null

Clase base Hltima de los dem(s tiposG object Cadenas de 7nicodeG string Tipos de0inidos por el usuario en 0orma class C {...!

Tipos de inter0a1 Tipos de matri1 Tipos de delegados

Tipos de0inidos por el usuario en 0orma de inter-ace $


{...!

7nidimensional y multidimensional, por e$emplo, int45 e


int4 5

Tipos de0inidos por el usuario por e$. en 0orma de delegate


int 6(...)

8os oc=o tipos integrales admiten los valores de 8 bits, 1# bits, 32 bits y #4 bits, con y sin signo. 8os dos tipos de punto 0lotante -loat y double se representan utili1ando los 0ormatos !EEE * 4 de 32 bits de precisi-n simple y de #4 bits de doble precisi-n. El tipo decimal es un tipo de datos de 128 bits apto para c(lculos 0inancieros y monetarios. El tipo bool de C# permite representar valores booleanos, ?ue son true o -alse. El procesamiento de caracteres y cadenas en C# utili1a la codi0icaci-n 7nicode. El tipo c"ar representa una unidad de c-digo 7T: de 1# bits y el tipo string representa una secuencia de unidades de c-digo 7T: de 1# bits.

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Especificacin del lenguaje C#

8a tabla siguiente resume los tipos num)ricos de C#. Categor0a !ntegral con signo -its 8 1# 32 #4 !ntegral sin signo 8 1# 32 #4 'unto 0lotante 2ecimal 32 #4 128 Tipo
sbyte s"ort int long byte us"ort uint ulong -loat double decimal

Inter%alo1precisin W128...12* W32.*#8...32.*#* W2.14*.483.#48...2.14*.483.#4* W+.223.3*2."3#.8 4.** .8"8...+.223.3*2."3#.8 4.** .8"* "...2 "...# . 3 "...4.2+4.+#*.2+ "...18.44#.*44."*3.*"+. 1.#1 1, X 1"Y4 a 3,4 X 1"38, con precisi-n de * d5gitos ," X 1"Y324 a 1,* X 1"3"8, con precisi-n de 1 d5gitos 1," X 1"Y28 a *,+ X 1"28, con precisi-n de 28 d5gitos

8os programas de C# utili1an declaraciones de tipo para crear nuevos tipos. 7na declaraci-n de tipo especi0ica el nombre y los miembros del nuevo tipo. Cinco de las categor5as de tipos de C# son de0inibles por el usuarioG tipos de clase, tipos de estructura, tipos de inter0a1, tipos de enumeraci-n y tipos de delegado. 7n tipo de clase de0ine una estructura de datos ?ue contiene miembros de datos OcamposR y miembros de 0unci-n Om)todos, propiedades y otrosR. 8os tipos de clase admiten la =erencia simple y el polimor0ismo, mecanismos mediante los ?ue las clases derivadas pueden ampliar y especiali1ar clases base. 7n tipo de estructura es similar a un tipo de clase en cuanto a ?ue ambas representan una estructura con miembros de datos y miembros de 0unci-n. 4o obstante, a di0erencia de las clases, las estructuras son tipos de valores y no re?uieren asignaci-n del mont-n. 8os tipos de estructura no admiten la =erencia especi0icada por el usuario y =eredan impl5citamente del tipo object. 7n tipo de inter0a1 de0ine un contrato como un con$unto con nombre de miembros de 0unci-n pHblica. 7na clase o estructura ?ue implementa una inter0a1 debe proporcionar implementaciones de los miembros de 0unci-n de la inter0a1. 7na inter0a1 puede derivarse de varias inter0aces base, y una clase o estructura puede implementar varias inter0aces. 7n tipo delegado representa las re0erencias a los m)todos con una lista de par(metros determinada y un tipo de valor devuelto. 8os delegados permiten tratar m)todos como entidades, ?ue se pueden asignar a las variables y pasarse como par(metros. 8os delegados son similares al concepto de punteros a 0unci-n de otros lengua$es, pero al contrario de los punteros a 0unci-n, los delegados est(n orientados a ob$etos y proporcionan seguridad de tipos. 8os tipos de delegado, inter0a1, estructura y clase admiten gen)ricos, lo ?ue permite su parametri1aci-n con otros tipos. 7n tipo de enumeraci-n es un tipo distinto con constantes con nombre. Todos los tipos de enumeraci-n tienen un tipo subyacente, ?ue debe ser uno de los oc=o tipos integrales. El con$unto de valores de un tipo de enumeraci-n es el mismo ?ue el del con$unto de valores del tipo subyacente.

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

C# admite matrices unidimensionales y multidimensionales de cual?uier tipo. &l contrario ?ue los tipos mencionados antes, los tipos de matri1 no tienen ?ue ser declarados antes de poder utili1arse. En su lugar, los tipos de matri1 se crean mediante un nombre de tipo seguido de corc=etes. 'or e$emplo, int45 es una matri1 unidimensional de int, int4 5 es una matri1 bidimensional de int e int4545 es una matri1 unidimensional de matrices unidimensionales de int. 8os tipos ?ue aceptan valores 4788 tampoco tienen ?ue ser declarados antes de poder utili1arse. 'ara cada tipo de valor 1 ?ue no acepta valores 4788 =ay un tipo correspondiente de valor 17 ?ue acepta valores 4788, el ?ue puede contener un valor null adicional. 'or e$emplo int7 es un tipo ?ue puede contener cual?uier valor entro de 32 bits o el valor null. El sistema de tipos de C# est( uni0icado, de manera ?ue un valor de cual?uier tipo puede tratarse como un ob$eto. Todos los tipos de C# se derivan directa o indirectamente del tipo de clase object, ?ue es la clase base de0initiva de todos los tipos. 8os valores de los tipos de re0erencia se tratan como ob$etos consider(ndolos sencillamente como del tipo object. 8os valores de los tipos de valor se tratan como ob$etos mediante la reali1aci-n de operaciones de conversi-n /o.ing y !n/o.ing. En el e$emplo siguiente, se convierte un valor int en object y de nuevo en int.
using System; class 1est { static void Main() { int i + 289; object o + i; int j + (int)o; ! !

.. :o#ing .. ;nbo#ing

Cuando un valor de un tipo de valor se convierte en el tipo object, se asigna una instancia de ob$eto, tambi)n denominada PboxQ, para ?ue contenga el valor, y )ste se copia en dic=a instancia. & la inversa, cuando se convierte una re0erencia object en un tipo de valor, se comprueba ?ue el ob$eto al ?ue se =ace re0erencia es un cuadro del tipo con el valor correcto, y si la comprobaci-n se lleva a cabo con )xito, el valor del cuadro se copia externamente. El sistema de tipos uni0icado de C# signi0ica en la pr(ctica ?ue los tipos de valor pueden convertirse en ob$etosPa petici-nQ. 2ebido a la uni0icaci-n, las bibliotecas de uso general ?ue utili1an el tipo object pueden utili1arse tanto con los tipos de re0erencia como con los tipos de valor.

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Especificacin del lenguaje C#

Hay varios tipos de varia/les en C#, entre los ?ue se incluyen campos, elementos de matri1, variables locales y par(metros. 8as variables representan ubicaciones de almacenamiento, y cada variable tiene un tipo ?ue determina ?u) valores se pueden almacenar en ella, como se muestra en la tabla siguiente. Tipo de %ariable Tipo de valor ?ue no acepta valores 4788 Tipo de valor ?ue acepta valores 4788
object

2osible contenido 7n valor de ese tipo exacto

7n valor 4788 o un valor de ese tipo exacto

7na re0erencia nula, una re0erencia a un ob$eto de cual?uier tipo de re0erencia o una re0erencia a un valor de tipo box de cual?uier tipo de valor 7na re0erencia nula, una re0erencia a una instancia de ese tipo de clase o una re0erencia a una instancia de una clase derivada de dic=o tipo de clase 7na re0erencia nula, una re0erencia a una instancia de un tipo de clase ?ue implemente dic=o tipo de inter0a1 o una re0erencia a un valor de tipo box ?ue implemente dic=o tipo de inter0a1 7na re0erencia nula, una re0erencia a una instancia de dic=o tipo de matri1 o una re0erencia a una instancia de un tipo de matri1 compatible 7na re0erencia nula o una re0erencia a una instancia de dic=o tipo delegado

Tipo de clase

Tipo de inter0a1

Tipo de matri1 Tipo delegado

1.! E"presiones
8as e.presiones se construyen a partir de operandos y operadores. 8os operadores de una expresi-n indican ?u) operaciones se aplican a los operandos. Entre los e$emplos de operadores se incluyen <, =, >, . y ne,. .on e$emplos de operandos los literales, campos, variables locales y expresiones. Cuando una expresi-n contiene varios operadores, la prioridad de los operadores controla el orden de evaluaci-n de los operadores individuales. 'or e$emplo, la expresi-n # < y > ? se evalHa como # < (y > ?) por?ue el operador > tiene prioridad sobre <. 8a mayor5a de los operadores se pueden so/recargar. 8a sobrecarga de operadores permite utili1ar implementaciones de operadores de0inidas por el usuario en operaciones en las ?ue al menos uno de los operandos es de un tipo estructura o clase de0inido por el usuario.

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

En la tabla siguiente se resumen los operadores de C#, enumerando las categor5as en orden de prioridad de mayor a menorG 8os operadores de la misma categor5a tienen la misma prioridad. Categor0a 'rincipal Expresin
#.m #(...) #4...5 #<< #== ne, 1(...) ne, 1(...){...! ne, {...! ne, 14...5 ty&eo-(1) c"ec(ed(#) unc"ec(ed(#) de-ault(1) delegate {...!

+escripcin &cceso a miembros !nvocaci-n de m)todos y delegados %atri1 y acceso del indi1ador !ncremento posterior 2ecremento posterior Creaci-n de ob$etos y de delegados Creaci-n de ob$eto con el iniciali1ador !niciali1ador de ob$eto an-nimo Creaci-n de matrices /btiene el ob$eto System.1y&e para 1 EvalHa la expresi-n en contexto comprobado EvalHa la expresi-n en contexto no comprobado /btiene el valor predeterminado del tipo 1 :unci-n an-nima Om)todo an-nimoR !dentidad 4egaci-n 4egaci-n l-gica 4egaci-n bit a bit !ncremento previo 2ecremento previo Convierte expl5citamente # en el tipo 1 %ultiplicaci-n 2ivisi-n ;esto .uma, concatenaci-n de cadenas, combinaci-n de delegados ;esta, eliminaci-n de delegados

7nario

<# =# @# A# <<# ==# (1)#

%ultiplicativo

# > y # . y # B y

.umatorio

# < y # C y

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

"

Especificacin del lenguaje C#

2espla1amiento Comprobaci-n de tipos y relacionales

# DD y # EE y # D y # E y # D+ y # E+ y # is 1 # as 1

2espla1amiento a la i1?uierda 2espla1amiento a la derec=a %enor ?ue %ayor ?ue %enor o igual ?ue %ayor o igual ?ue 2evuelve true si # es 1, de lo contrario, -alse 2evuelve # escrito como 1 o null si # no es un 1 !gual 4o igual &42 bit a bit entero, &42 l-gico booleano N/; bit a bit entero, N/; l-gico booleano /; bit a bit entero, /; l-gico booleano EvalHa y s-lo si # es true EvalHa y s-lo si # es -alse .e evalHa como y si # es null, de lo contrario, como
#

!gualdad &42 l-gico N/; l-gico /; l-gico &42 condicional /; condicional 7so combinado de 4ull Condicional &signaci-n o 0unci-n an-nima

# ++ y # @+ y # F y # G y # H y # FF y # HH y I 77 y # 7 y / ? # + y # op+ y (1 #) +E y

EvalHa y si # es true, ? si # es -alse &signaci-n &signaci-n compuestaV los operadores compatibles son
>+ .+ B+ <+ =+ DD+ EE+ F+ G+ H+

:unci-n an-nima Oexpresi-n lambdaR

1.# Instrucciones
8as acciones de un programa se expresan utili1ando instr!cciones. C# admite varios tipos de instrucciones, algunos de los cuales se de0inen en t)rminos de instrucciones incrustadas. 7n blo?ue O/loc4R permite escribir varias instrucciones en contextos donde se permite una Hnica instrucci-n. 7n blo?ue se compone de una lista de instrucciones escrita entre delimitadores { y !. 8as instr!cciones de declaraci,n se utili1an para declarar constantes y variables locales. 8as instr!cciones de e.presi,n se utili1an para evaluar las expresiones. 8as expresiones ?ue pueden utili1arse como instrucciones incluyen invocaciones de m)todo, asignaciones de ob$etos utili1ando el operador ne,, asignaciones ?ue usan + operadores de asignaci-n compuesta y operadores de incremento y decremento ?ue utili1an los operadores << y ==. 8as instr!cciones de selecci,n seleccionan una de las instrucciones ?ue se van a e$ecutar en 0unci-n del valor de alguna expresi-n. En este grupo est(n las instrucciones i- y s,itc". 8as instr!cciones de iteraci,n se utili1an para e$ecutar repetidamente una instrucci-n incrustada. En este grupo est(n las instrucciones ,"ile, do, -or y -oreac".

1'

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

8as instr!cciones de salto se utili1an para trans0erir el control. En este grupo est(n las instrucciones brea(, continue, goto, t"ro,, return y yield. 8a instrucci-n try...catc" se utili1a para detectar las excepciones ?ue se producen durante la e$ecuci-n de un blo?ue y la instrucci-n try...-inally se usa para especi0icar el c-digo de 0inali1aci-n ?ue siempre se e$ecuta, apare1ca o no una excepci-n. 8as instrucciones c"ec(ed y unc"ec(ed se utili1an con el 0in de controlar el contexto de comprobaci-n de desbordamiento para operaciones aritm)ticas y conversiones. 8a instrucci-n loc( se utili1a para blo?uear un ob$eto determinado mediante exclusi-n mutua, e$ecutar una instrucci-n y, a continuaci-n, liberar el blo?ueo. 8a instrucci-n using se utili1a para obtener un recurso, e$ecutar una instrucci-n y, a continuaci-n, eliminar dic=o recurso. 8a tabla siguiente muestra las instrucciones de C# y proporciona un e$emplo para cada una. Instruccin 2eclaraciones de variables locales Eje)plo
static void Main() { int a; int b + 8 c + 9; a + 2; Console.WriteLine(a < b < c); ! static void Main() { const -loat &i + 9.2J2KL8M-; const int r + 8K; Console.WriteLine(&i > r > r); ! static void Main() { int i; i + 289; Console.WriteLine(i); i<<; Console.WriteLine(i); !

2eclaraciones de constantes locales

!nstrucciones de expresiones

.. .. .. ..

)#&ression )#&ression )#&ression )#&ression

statement statement statement statement

!nstrucci-n i-

static void Main(string45 args) { i- (args.Lengt" ++ 3) { Console.WriteLine("No arguments"); ! else { Console.WriteLine("%ne or more arguments"); ! !

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

11

Especificacin del lenguaje C#

!nstrucci-n s,itc"

static void Main(string45 args) { int n + args.Lengt"; s,itc" (n) { case 3/ Console.WriteLine("No arguments"); brea(; case 2/ Console.WriteLine("%ne argument"); brea(; de-ault/ Console.WriteLine("{3! arguments" n); brea(; ! ! ! static void Main(string45 args) { int i + 3; ,"ile (i D args.Lengt") { Console.WriteLine(args4i5); i<<; ! ! static void Main() { string s; do { s + Console.OeadLine(); i- (s @+ null) Console.WriteLine(s); ! ,"ile (s @+ null); ! static void Main(string45 args) { -or (int i + 3; i D args.Lengt"; i<<) { Console.WriteLine(args4i5); ! ! static void Main(string45 args) { -oreac" (string s in args) { Console.WriteLine(s); ! ! static void Main() { ,"ile (true) { string s + Console.OeadLine(); i- (s ++ null) brea(; Console.WriteLine(s); ! ! static void Main(string45 args) { -or (int i + 3; i D args.Lengt"; i<<) { i- (args4i5.StartsWit"(".")) continue; Console.WriteLine(args4i5); ! !

!nstrucci-n ,"ile

!nstrucci-n do

!nstrucci-n -or

!nstrucci-n -oreac"

!nstrucci-n brea(

!nstrucci-n
continue

12

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

!nstrucci-n goto

static void Main(string45 args) { int i + 3; goto c"ec(; loo&/ Console.WriteLine(args4i<<5); c"ec(/ i- (i D args.Lengt") goto loo&; ! static int 'dd(int a return a < b; ! int b) {

!nstrucci-n return

static void Main() { Console.WriteLine('dd(2 return; !

8));

!nstrucci-n yield

static $)numerableDintE Oange(int -rom -or (int i + -rom; i D to; i<<) { yield return i; ! yield brea(; ! static void Main() { -oreac" (int # in Oange(=23 23)) { Console.WriteLine(#); ! !

int to) {

!nstrucciones t"ro, y try

static double 6ivide(double # double y) { i- (y ++ 3) t"ro, ne, 6ivide:yPero)#ce&tion(); return # . y; ! static void Main(string45 args) { try { i- (args.Lengt" @+ 8) { t"ro, ne, )#ce&tion("1,o numbers reQuired"); ! double # + double.*arse(args435); double y + double.*arse(args425); Console.WriteLine(6ivide(# y)); ! catc" ()#ce&tion e) { Console.WriteLine(e.Message); ! -inally { Console.WriteLine(RSood bye@T); ! !

!nstrucciones c"ec(ed y
unc"ec(ed

static void Main() { int i + int.Ma#Ualue; c"ec(ed { Console.WriteLine(i < 2); ! unc"ec(ed { Console.WriteLine(i < 2); ! !

.. )#ce&tion .. %ver-lo,

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

13

Especificacin del lenguaje C#

!nstrucci-n loc(

class 'ccount { decimal balance; &ublic void Wit"dra,(decimal amount) { loc( (t"is) { i- (amount E balance) { t"ro, ne, )#ce&tion("$nsu--icient -unds"); ! balance =+ amount; ! ! !

!nstrucci-n using

static void Main() { using (1e#tWriter , + Vile.Create1e#t("test.t#t")) { ,.WriteLine("Line one"); ,.WriteLine("Line t,o"); ,.WriteLine("Line t"ree"); ! !

1.$ %lases y objetos


8as clases son el tipo m(s importante de C#. 7na clase es una estructura de datos ?ue combina estados OcamposR y acciones Om)todos y otros miembros de 0unci-nR en una unidad Hnica. 7na clase proporciona una de0inici-n para las instancias de la clase creadas din(micamente, tambi)n conocidas como o/1etos. 8as clases admiten la herencia y el poli orfis o, mecanismos mediante los ?ue una clase derivada puede ampliar y especiali1ar una clase /ase. 8as clases nuevas se crean utili1ando declaraciones de clase. 8as declaraciones de clase se inician con un encabe1ado ?ue especi0ica los atributos y modi0icadores de la clase, el nombre, la clase base Osi se conoceR y las inter0aces implementadas por ella. El encabe1ado va seguido por el cuerpo de la clase, ?ue consiste en una lista de declaraciones de miembros escritas entre los delimitadores { y !. 8a siguiente es una declaraci-n de una clase simple denominada *ointG
&ublic class *oint { &ublic int # y; &ublic *oint(int # t"is.# + #; t"is.y + y; ! ! int y) {

8as instancias de clases se crean utili1ando el operador ne,, ?ue asigna memoria para una nueva instancia, invoca un constructor para iniciali1ar la instancia y devuelve una re0erencia a la misma. 8as instrucciones siguientes crean dos ob$etos *oint y almacenan las re0erencias a dic=os ob$etos en dos variablesG
*oint &2 + ne, *oint(3 3); *oint &8 + ne, *oint(23 83);

8a memoria ocupada por un ob$eto se reclama autom(ticamente cuando el ob$eto de$a de estar en uso. 4o es posible ni necesario desasignar expl5citamente ob$etos en C#. 1.$.1 &iembros 8os miembros de una clase son o ie /ros est5ticos o ie /ros de instancia. 8os miembros est(ticos pertenecen a las clases y los miembros de instancia pertenecen a los ob$etos Oinstancias de clasesR.

1#

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

8a tabla siguiente proporciona in0ormaci-n general sobre los tipos de miembros ?ue puede contener una clase. *ie)bro Constantes Campos %)todos 'ropiedades !ndi1adores Eventos /peradores Constructores 2estructores Tipos +escripcin >alores constantes asociados a la clase >ariables de la clase C(lculos y acciones ?ue puede reali1ar la clase &cciones asociadas a la lectura y escritura de propiedades con nombre de la clase &cciones asociadas a instancias de indi1aci-n de la clase como una matri1 4oti0icaciones ?ue pueden ser generadas por la clase Conversiones y operadores de expresi-n admitidos por la clase &cciones re?ueridas para iniciali1ar instancias de la clase o la propia clase &cciones ?ue =ay ?ue llevar a cabo antes de ?ue las instancias de la clase sean descartadas de 0orma permanente Tipos anidados declarados por la clase

1.$.2 'ccesibilidad Cada miembro de una clase tiene asociada una accesibilidad, ?ue controla las regiones del texto del programa a las ?ue tiene acceso el miembro. Existen cinco 0ormas posibles de accesibilidad. Zstas se resumen en la siguiente tabla. ,ccesibilidad
&ublic &rotected internal &rotected internal &rivate

3ignificado &cceso no limitado &cceso limitado a esta clase o a las clases derivadas de la misma &cceso limitado a este programa &cceso limitado a este programa o a las clases derivadas de la misma &cceso limitado a esta clase

1.$.3 (ar)metros de tipo 7na de0inici-n de clase puede especi0icar con$unto de par(metros de tipo si a continuaci-n del nombre de clase se colocan corc=etes angulares ?ue contengan una lista con los nombres de los par(metros de tipo. 8os par(metros de tipo se pueden utili1ar dentro de las declaraciones de clase para de0inir a los miembros de la clase. En el e$emplo siguiente los par(metros de tipo de *air son 1Virst y 1Second/
&ublic class *airD1Virst 1SecondE { &ublic 1Virst Virst; &ublic 1Second Second; !

7n tipo de clase declarado para incluir par(metros de tipo se denomina tipo de clase gen)rico. 8os tipos struct, inter0ace y delegate tambi)n pueden ser gen)ricos.

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

1!

Especificacin del lenguaje C#

Cuando se usa la clase gen)rica, se deben proporcionar argumentos de tipo para cada par(metro de tipo.
*airDint stringE &air + ne, *airDint stringE { Virst + 2 int i + &air.Virst; .. 1Virst is int string s + &air.Second; .. 1Second is string Second + Rt,oT !;

7n tipo gen)rico con los argumentos de tipo proporcionados, como *airDint stringE en el e$emplo anterior, se denomina tipo construido. 1.$.! %lases base 7na declaraci-n de clase puede especi0icar una clase base si a continuaci-n del nombre de clase y los par(metros de tipo se colocan dos puntos y el nombre de la clase base. /mitir una especi0icaci-n de clase base es igual ?ue derivar del tipo object. En el e$emplo siguiente, la clase base de *oint96 es *oint, y la clase base de *oint es objectG
&ublic class *oint { &ublic int # y; &ublic *oint(int # t"is.# + #; t"is.y + y; ! ! &ublic class *oint96/ *oint { &ublic int ?; &ublic *oint96(int # t"is.? + ?; ! ! int y int ?)/ base(# y) { int y) {

8as clases =eredan los miembros de sus clases base. 8a =erencia signi0ica ?ue una clase contiene impl5citamente todos los miembros de su clase base, salvo los constructores de la clase base. 7na clase derivada puede agregar nuevos miembros a los =eredados, pero no puede ?uitar la de0inici-n de un miembro =eredado. En el e$emplo anterior, *oint96 =ereda los campos # e y de *oint, y cada instancia de *oint96 contiene tres campos #, y y ?. Existe una conversi-n impl5cita desde un tipo de clase a cual?uiera de sus tipos de clase base. 'or consiguiente, una variable de un tipo de clase puede =acer re0erencia a una instancia de dic=a clase o a una instancia de cual?uier clase derivada. 'or e$emplo, teniendo en cuenta las declaraciones de clase anteriores, una variable de tipo *oint puede =acer re0erencia a un *oint o a un *oint96G
*oint a + ne, *oint(23 83); *oint b + ne, *oint96(23 83 93);

1.$.# %ampos 7n campo es una variable ?ue est( asociada a una clase o a una instancia de una clase. 7n campo declarado con el modi0icador static de0ine un ca po est5tico. 7n campo est(tico identi0ica exactamente una ubicaci-n de almacenamiento. !ndependientemente del nHmero de instancias ?ue se creen de una clase, s-lo =abr( una copia de un campo est(tico. 7n campo declarado sin el modi0icador static de0ine un ca po de instancia. Todas las instancias de una clase contienen una copia independiente de todos los campos de instancia de esa clase. En el e$emplo siguiente, cada instancia de la clase Color tiene una copia independiente de los campos de instancia r, g y b, pero s-lo =ay una copia de los campos est(ticos :lac(, W"ite, Oed, Sreen y :lueG

16

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases &ublic class Color { &ublic static readonly &ublic static readonly &ublic static readonly &ublic static readonly &ublic static readonly &rivate byte r g b; byte g byte b) { &ublic Color(byte r t"is.r + r; t"is.g + g; t"is.b + b; ! !

Color Color Color Color Color

:lac( + ne, Color(3 3 3); W"ite + ne, Color(8KK 8KK 8KK); Oed + ne, Color(8KK 3 3); Sreen + ne, Color(3 8KK 3); :lue + ne, Color(3 3 8KK);

Como se puede ver en el e$emplo anterior, los ca pos de s,lo lect!ra se pueden declarar con un modi0icador readonly. .olamente se pueden reali1ar asignaciones a un campo readonly como parte de la declaraci-n del campo o en un constructor en la misma clase. 1.$.$ &*todos 7n 6todo es un miembro ?ue implementa un c(lculo o una acci-n ?ue puede reali1ar un ob$eto o una clase. El acceso a los 6todos est5ticos se obtiene a trav)s de la clase. .e tiene acceso a los 6todos de instancia a trav)s de las instancias de la clase. 8os m)todos tienen una lista Oposiblemente vac5aR de par5 etros, ?ue representa valores o re0erencias variables ?ue se pasan al m)todo y un tipo de valor dev!elto ?ue especi0ica el tipo del valor calculado y devuelto por el m)todo. El tipo de valor devuelto de un m)todo es void si no devuelve ningHn valor. &l igual ?ue los tipos, los m)todos tambi)n pueden tener un con$unto de par(metros de tipo, para los ?ue se deben especi0icar argumentos de tipo cuando se llama al m)todo. & di0erencia de los tipos, los argumentos de tipo por lo general se pueden in0erir a partir de los argumentos de una llamada de m)todo y no necesitan darse de manera expl5cita. 8a fir a de un m)todo debe ser Hnica en la clase en la ?ue se declara el m)todo. 8a 0irma de un m)todo se compone del nombre del m)todo, el nHmero de par(metros de tipo, as5 como del nHmero, modi0icadores y tipos de sus par(metros. 8a 0irma de un m)todo no incluye el tipo de valor devuelto. 1.6.6.1 Parmetros 8os par(metros se utili1an para pasar valores o re0erencias variables a los m)todos. 8os par(metros de un m)todo reciben sus valores reales de los arg! entos ?ue se especi0ican cuando se invoca el m)todo. Existen cuatro clases de par(metrosG par(metros de valores, par(metros de re0erencias, par(metros de salida y matrices de par(metros. 'ara pasar el par(metro de entrada se utili1a un par5 etro de valor. 7n par(metro de valor corresponde a una variable local ?ue obtiene su valor inicial del argumento proporcionado para el par(metro. 8as modi0icaciones de un par(metro de valor no a0ectan al argumento proporcionado para el par(metro. 7n par5 etro de referencia se utili1a tanto para proporcionar par(metros de entrada como de salida. El argumento pasado para un par(metro de re0erencia debe ser una variable, y durante la e$ecuci-n del m)todo, el par(metro de re0erencia representa la misma ubicaci-n de almacenamiento ?ue la variable del argumento. 8os par(metros de re0erencia se declaran con el modi0icador re-. El e$emplo siguiente ilustra el uso de los par(metros re-.

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

1(

Especificacin del lenguaje C# using System; class 1est { static void S,a&(re- int # int tem& + #; # + y; y + tem&; !

re- int y) {

static void Main() { int i + 2 j + 8; S,a&(re- i re- j); Console.WriteLine("{3! {2!" ! !

j);

.. %ut&uts "8 2"

'ara pasar par(metros de salida se utili1a un par5 etro de salida. 7n par(metro de salida es similar a un par(metro de re0erencia, excepto en ?ue el valor inicial del argumento suministrado por el llamador no es importante. 8os par(metros de salida se declaran con un modi0icador out. El e$emplo siguiente ilustra el uso de los par(metros out.
using System; class 1est { static void 6ivide(int # result + # . y; remainder + # B y; !

int y

out int result

out int remainder) {

static void Main() { int res rem; 6ivide(23 9 out res out rem); Console.WriteLine("{3! {2!" res ! !

rem);

.. %ut&uts "9 2"

7na atri- de par5 etros permite pasar un nHmero variable de argumentos a un m)todo. 7na matri1 de par(metros se declara con un modi0icador &arams. .-lo el Hltimo par(metro de un m)todo puede ser una matri1 de par(metros y el tipo de una matri1 de par(metros debe ser un tipo de matri1 unidimensional. 8os m)todos Write y WriteLine de la clase System.Console son buenos e$emplos del uso de una matri1 de par(metros. .e declaran del siguiente modoG
&ublic class Console { &ublic static void Write(string -mt ... ! &arams object45 args) {...! &arams object45 args) {...!

&ublic static void WriteLine(string -mt

2entro de un m)todo ?ue utili1a una matri1 de par(metros, la matri1 de par(metros se comporta exactamente como un par(metro normal de un tipo de matri1. .in embargo, en una invocaci-n de un m)todo con una matri1 de par(metros, es posible pasar un argumento Hnico del tipo de matri1 de par(metros o cual?uier nHmero de argumentos del tipo elemento de la matri1 de par(metros. En este Hltimo caso, se crea autom(ticamente una instancia de matri1 y se iniciali1a con los argumentos especi0icados. Este e$emplo
Console.WriteLine("#+{3! y+{2! ?+{8!" # y ?);

e?uivale a escribir lo siguiente.

1$

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases string s + "#+{3! y+{2! ?+{8!"; object45 args + ne, object495; args435 + #; args425 + y; args485 + ?; Console.WriteLine(s args);

1.6.6.2 Cuerpo del mtodo y variables locales El cuerpo de un m)todo especi0ica las instrucciones ?ue se deben e$ecutar cuando se invo?ue el m)todo. 7n cuerpo del m)todo puede declarar variables espec50icas para la invocaci-n del m)todo. Tales variables se denominan varia/les locales. 7na declaraci-n de variable local especi0ica un nombre de tipo, un nombre de variable y posiblemente un valor inicial. El e$emplo siguiente declara una variable local i con un valor inicial de cero y una variable local j sin valor inicial.
using System; class SQuares { static void Main() { int i + 3; int j; ,"ile (i D 23) { j + i > i; Console.WriteLine("{3! # {3! + {2!" i + i < 2; ! ! !

j);

C# exige ?ue las variables locales est)n definitiva ente asignadas para ?ue se puedan obtener sus valores. 'or e$emplo, si la declaraci-n de i anterior no incluyera un valor inicial, el compilador noti0icar5a un error para la utili1aci-n subsiguiente de i, por?ue i no estar5a de0initivamente asignada en dic=os puntos del programa. 7n m)todo puede utili1ar instrucciones return para devolver el control a su llamador. En un m)todo ?ue devuelve void, las instrucciones return no pueden especi0icar una expresi-n. En un m)todo ?ue no devuelve void, las instrucciones return deben incluir una expresi-n ?ue calcule el valor devuelto. 1.6.6.3 Mtodos estticos y de instancia 7n m)todo declarado con un modi0icador static es un 6todo est5tico. 7n m)todo est(tico no 0unciona en una instancia espec50ica y s-lo tiene acceso directamente a miembros est(ticos. 7n m)todo declarado sin un modi0icador static es un 6todo de instancia. 8os m)todos de instancia 0uncionan en instancias espec50icas y pueden tener acceso tanto a miembros est(ticos como a los de instancia. .e puede tener acceso expl5citamente a la instancia en la ?ue se invoc- un m)todo de instancia como t"is. Es incorrecto =acer re0erencia a t"is en un m)todo est(tico. 8a clase )ntity siguiente tiene tanto miembros est(ticos como de instancia.
class )ntity { static int ne#tSerialNo; int serialNo; &ublic )ntity() { serialNo + ne#tSerialNo<<; ! &ublic int SetSerialNo() { return serialNo; !

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

1"

Especificacin del lenguaje C# &ublic static int SetNe#tSerialNo() { return ne#tSerialNo; ! &ublic static void SetNe#tSerialNo(int value) { ne#tSerialNo + value; ! !

Cada instancia )ntity contiene un nHmero de serie Oy probablemente alguna otra in0ormaci-n ?ue no se muestra a?u5R. El constructor )ntity O?ue es como un m)todo de instanciaR iniciali1a la nueva instancia con el siguiente nHmero de serie disponible. 2ado ?ue el constructor es un miembro de instancia, se puede tener acceso tanto al campo de instancia serialNo como al campo est(tico ne#tSerialNo. 8os m)todos est(ticos SetNe#tSerialNo y SetNe#tSerialNo pueden tener acceso al campo est(tico ne#tSerialNo, pero ser5a incorrecto ?ue tuvieran acceso directamente al campo de instancia serialNo. En el e$emplo siguiente se muestra el uso de la clase )ntity.
using System; class 1est { static void Main() { )ntity.SetNe#tSerialNo(2333); )ntity e2 + ne, )ntity(); )ntity e8 + ne, )ntity(); Console.WriteLine(e2.SetSerialNo()); Console.WriteLine(e8.SetSerialNo()); Console.WriteLine()ntity.SetNe#tSerialNo()); ! ! .. %ut&uts "2333" .. %ut&uts "2332" .. %ut&uts "2338"

Tenga en cuenta ?ue los m)todos est(ticos SetNe#tSerialNo y SetNe#tSerialNo se invocan en la clase, mientras ?ue el m)todo de instancia SetSerialNo se invoca en las instancias de la clase. 1.6.6.4 Mtodos virtuales, de invalidacin y abstractos Cuando una declaraci-n de m)todo de instancia incluye un modi0icador virtual, se dice ?ue el m)todo es un 6todo virt!al. .i no existe un modi0icador virtual, se dice ?ue el m)todo es un 6todo no virt!al. En la invocaci-n de un m)todo virtual, el tipo en tie po de e1ec!ci,n de la instancia para la ?ue tiene lugar la invocaci-n determina la implementaci-n del m)todo real ?ue se va a invocar. Cuando se invoca a un m)todo no virtual, el 0actor determinante es el tipo en tie po de co pilaci,n de la instancia. En las clases derivadas, los m)todos virtuales se pueden invalidar. Cuando una declaraci-n del m)todo de instancia incluye un modi0icador override, el m)todo invalida un m)todo virtual =eredado con la misma 0irma. %ientras ?ue una declaraci-n de m)todo virtual introd ce un m)todo nuevo, una declaraci-n de m)todo de invalidaci-n especiali0a un m)todo virtual =eredado existente proporcionando una nueva implementaci-n de ese m)todo. 7n m)todo a/stract es un m)todo virtual sin implementaci-n. 8os m)todos abstractos se declaran con el modi0icador abstract y s-lo se permiten en una clase ?ue tambi)n se declare como abstract. 8os m)todos abstractos deben invalidarse en cada clase derivada no abstracta. El e$emplo siguiente declara una clase abstracta, )#&ression, ?ue representa un nodo de (rbol de expresi-n y tres clases derivadas Constant, UariableOe-erence y %&eration, ?ue implementan los nodos de (rbol de expresi-n para las constantes, re0erencias variables y operaciones aritm)ticas. OEsto es similar a los tipos de (rbol de expresiones introducidos en la secci-n [4.#, aun?ue no debe con0undirse con los mismosR.

2'

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases using System; using System.Collections; &ublic abstract class )#&ression { &ublic abstract double )valuate(Has"table vars); ! &ublic class Constant/ )#&ression { double value; &ublic Constant(double value) { t"is.value + value; ! &ublic override double )valuate(Has"table vars) { return value; ! ! &ublic class UariableOe-erence/ )#&ression { string name; &ublic UariableOe-erence(string name) { t"is.name + name; ! &ublic override double )valuate(Has"table vars) { object value + vars4name5; i- (value ++ null) { t"ro, ne, )#ce&tion(";n(no,n variable/ " < name); ! return Convert.1o6ouble(value); ! ! &ublic class %&eration/ )#&ression { )#&ression le-t; c"ar o&; )#&ression rig"t; &ublic %&eration()#&ression le-t t"is.le-t + le-t; t"is.o& + o&; t"is.rig"t + rig"t; ! c"ar o& )#&ression rig"t) {

&ublic override double )valuate(Has"table vars) { double # + le-t.)valuate(vars); double y + rig"t.)valuate(vars); s,itc" (o&) { case W<W/ return # < y; case W=W/ return # = y; case W>W/ return # > y; case W.W/ return # . y; ! t"ro, ne, )#ce&tion(";n(no,n o&erator"); ! !

8as cuatro clases anteriores se pueden utili1ar para modelar expresiones aritm)ticas. 'or e$emplo, utili1ando instancias de estas clases, la expresi-n # < 9 se puede representar como sigue.

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

21

Especificacin del lenguaje C# )#&ression e + ne, %&eration( ne, UariableOe-erence("#") W<W ne, Constant(9));

El m)todo )valuate de una instancia )#&ression se invoca para evaluar la expresi-n determinada y generar un valor double. El m)todo toma como argumento un Has"table ?ue contiene nombres de variable Ocomo claves de las entradasR y valores Ocomo valores de las entradasR. El m)todo )valuate es un m)todo abstracto virtual, lo ?ue signi0ica ?ue deben invalidarlo las clases derivadas no abstractas para proporcionar una implementaci-n real. 7na implementaci-n de Constant de )valuate simplemente devuelve la constante almacenada. 7na implementaci-n de UariableOe-erence busca el nombre de la variable en la tabla =as= y devuelve el valor resultante. 7na implementaci-n de %&eration evalHa primero los operandos i1?uierdo y derec=o Oinvocando de 0orma recursiva sus m)todos )valuateR y, a continuaci-n, lleva a cabo la operaci-n aritm)tica correspondiente. El programa siguiente utili1a las clases )#&ression para evaluar la expresi-n # > (y < 8) para distintos valores de # e y.
using System; using System.Collections; class 1est { static void Main() { )#&ression e + ne, %&eration( ne, UariableOe-erence("#") W>W ne, %&eration( ne, UariableOe-erence("y") W<W ne, Constant(8) ) ); Has"table vars + ne, Has"table(); vars4"#"5 + 9; vars4"y"5 + K; Console.WriteLine(e.)valuate(vars)); vars4"#"5 + 2.K; vars4"y"5 + L; Console.WriteLine(e.)valuate(vars)); ! !

.. %ut&uts "82"

.. %ut&uts "2X.K"

1.6.6. !obrecar"a de mtodos 8a so/recarga de m)todos permite ?ue varios m)todos de la misma clase tengan el mismo nombre siempre ?ue sus 0irmas sean Hnicas. &l compilar una invocaci-n de un m)todo sobrecargado, el compilador utili1a la resol!ci,n de so/recarga para determinar el m)todo concreto ?ue se va a invocar. 8a resoluci-n de sobrecarga busca el m)todo ?ue me$or se a$usta a los argumentos o in0orma de un error si no se puede encontrar ningHn a$uste adecuado. El e$emplo siguiente muestra la resoluci-n de sobrecarga en vigor. El comentario para cada invocaci-n en el m)todo Main muestra ?u) m)todo se =a invocado.
class 1est { static void V() { Console.WriteLine("V()"); !

22

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases static void V(object #) { Console.WriteLine("V(object)"); ! static void V(int #) { Console.WriteLine("V(int)"); ! static void V(double #) { Console.WriteLine("V(double)"); ! static void VD1E(1 #) { Console.WriteLine("VD1E(1)"); ! static void V(double # double y) { Console.WriteLine("V(double double)"); ! static void Main() { V(); .. $nvo(es V() V(2); .. $nvo(es V(int) V(2.3); .. $nvo(es V(double) V("abc"); .. $nvo(es V(object) V((double)2); .. $nvo(es V(double) V((object)2); .. $nvo(es V(object) VDintE(2); .. $nvo(es VD1E(1) V(2 2); .. $nvo(es V(double double) !

Como muestra el e$emplo, un m)todo determinado siempre puede ser seleccionado convirtiendo expl5citamente los argumentos en los tipos de par(metros exactos yTo proporcionando expl5citamente los argumentos de tipo. 1.$.+ ,tros miembros de funcin 8os miembros ?ue contienen c-digo e$ecutable se conocen colectivamente como ie /ros de f!nci,n de una clase. 8a secci-n anterior describe m)todos, ?ue son el tipo primario de miembros de 0unci-n. En esta secci-n se describen los otros tipos de miembros de 0unci-n admitidos por C#G constructores, propiedades, indi1adores, eventos, operadores y destructores. 8a tabla siguiente muestra una clase gen)rica llamada ListD1E ?ue implementa una lista creciente de ob$etos. 8a clase contiene varios e$emplos de los tipos m(s comunes de miembros de 0unci-n.

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

23

Especificacin del lenguaje C#

&ublic class ListD1E { const int de-aultCa&acity + J; 145 items; int count; &ublic List()/ t"is(de-aultCa&acity) {! &ublic List(int ca&acity) { items + ne, 14ca&acity5; ! &ublic int Count { get { return count; ! ! &ublic int Ca&acity { get { return items.Lengt"; ! set { i- (value D count) value + count; i- (value @+ items.Lengt") { 145 ne,$tems + ne, 14value5; 'rray.Co&y(items 3 ne,$tems 3 items + ne,$tems; ! ! ! &ublic 1 t"is4int inde#5 { get { return items4inde#5; ! set { items4inde#5 + value; %nC"anged(); ! ! &ublic void 'dd(1 item) { i- (count ++ Ca&acity) Ca&acity + count > 8; items4count5 + item; count<<; %nC"anged(); ! &rotected virtual void %nC"anged() { i- (C"anged @+ null) C"anged(t"is ! )vent'rgs.)m&ty);

Constante Campos Constructores

'ropiedades

count);

!ndi1ador

%)todos

&ublic override bool )Quals(object ot"er) { return )Quals(t"is ot"er as ListD1E); ! static bool )Quals(ListD1E a ListD1E b) { i- (a ++ null) return b ++ null; i- (b ++ null HH a.count @+ b.count) return -alse; -or (int i + 3; i D a.count; i<<) { i- (@object.)Quals(a.items4i5 b.items4i5)) { return -alse; ! ! return true; !

2#

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

&ublic event )ventHandler C"anged; &ublic static bool o&erator ++(ListD1E a return )Quals(a b); ! &ublic static bool o&erator @+(ListD1E a return @)Quals(a b); ! ! ListD1E b) {

Evento /peradores

ListD1E b) {

1.6.#.1 Constructores C# admite tanto constructores de instancia como est(ticos. 7n constr!ctor de instancia es un miembro ?ue implementa las acciones ?ue se re?uieren para iniciali1ar una instancia de una clase. 7n constr!ctor est5tico es un miembro ?ue implementa las acciones exigidas para iniciali1ar una clase cuando se carga por primera ve1. 7n constructor se declara como m)todo sin devoluci-n de tipo y con el mismo nombre ?ue la clase contenedora. .i una declaraci-n de un constructor incluye un modi0icador static, declara un constructor est(tico. 2e lo contrario, declara un constructor de instancia. 8os constructores de instancia se pueden sobrecargar. 'or e$emplo, la clase ListD1E declara dos constructores de instancia, uno sin par(metros y otro ?ue toma un par(metro int. 8os constructores de instancia se invocan utili1ando el operador ne,. 8as siguientes instrucciones asignan dos instancias ListDstringE utili1ando cada uno de los constructores de la clase List.
ListDstringE list2 + ne, ListDstringE(); ListDstringE list8 + ne, ListDstringE(23);

&l contrario ?ue otros miembros, los constructores de instancia no se =eredan, y una clase s-lo tiene los constructores de instancia realmente declarados en la clase. .i no se suministra ningHn constructores de instancia para una clase, se proporcionar( autom(ticamente uno vac5o sin par(metros. 1.6.#.2 Propiedades 8as propiedades son una extensi-n natural de los campos. 8os dos son miembros denominados con tipos asociados, y la sintaxis ?ue se utili1a para el acceso a campos y propiedades es la misma. 4o obstante, a di0erencia de los campos, las propiedades no denotan ubicaciones de almacenamiento. 8as propiedades tienen descriptores de acceso ?ue especi0ican las instrucciones ?ue deben e$ecutarse para leer o escribir sus valores. 7na propiedad se declara como un campo, s-lo ?ue la declaraci-n 0inali1a con un descriptor de acceso get yTo un descriptor de acceso set escrito entre los delimitadores { y ! en lugar de 0inali1ar con un punto y coma. 7na propiedad ?ue tiene un descriptor de acceso get y un set es una propiedad de lect!ra y escrit!ra, una propiedad ?ue tiene s-lo un descriptor de acceso get es una propiedad de s,lo lect!ra, y una propiedad ?ue tiene s-lo un descriptor de acceso set es una propiedad de s,lo escrit!ra. 7n descriptor de acceso get corresponde a un m)todo sin par(metros ?ue devuelve un valor del tipo de la propiedad. Exceptuando cuando se trata del destino de una asignaci-n, al =acer re0erencia a una propiedad en una expresi-n, se invoca al descriptor de acceso get de la propiedad para calcular su valor. 7n descriptor de acceso set corresponde a un m)todo con un par(metro Hnico denominado value y ningHn tipo de valor devuelto. Cuando se =ace re0erencia a una propiedad como el destino de una asignaci-n o como el operando de << o ==, se invoca al descriptor de acceso set con un argumento ?ue proporciona el nuevo valor. 8a clase ListD1E declara dos propiedades, Count y Ca&acityV la primera de ellas es de s-lo lectura y la segunda de lectura y escritura. El siguiente es un e$emplo del uso de estas propiedades.

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

2!

Especificacin del lenguaje C# ListDstringE names + ne, ListDstringE(); names.Ca&acity + 233; .. $nvo(es set accessor int i + names.Count; .. $nvo(es get accessor int j + names.Ca&acity; .. $nvo(es get accessor

&l igual ?ue los campos y m)todos, C# admite tanto las propiedades de instancia como las propiedades est(ticas. 8as propiedades est(ticas se declaran con el modi0icador static, y las propiedades de instancias, sin )l. 8os descriptores de acceso de una propiedad pueden ser virtuales. Cuando una declaraci-n de propiedad incluye un modi0icador virtual, abstract u override, se aplica a los descriptores de acceso de la propiedad. 1.6.#.3 $ndi%adores 7n indi-ador es un miembro ?ue permite indi1ar ob$etos de la misma manera ?ue una matri1. 7n indi1ador se declara como una propiedad, salvo en ?ue el nombre del miembro sea t"is seguido de una lista de par(metros escritos entre delimitadores 4 y 5. 8os par(metros est(n disponibles en los descriptores de acceso del indi1ador. &l igual ?ue las propiedades, los indi1adores pueden ser de lectura y escritura, de s-lo lectura y de s-lo escritura, y los descriptores de acceso de un indi1ador pueden ser virtuales. 8a clase List declara un indi1ador de lectura y escritura Hnico ?ue toma un par(metro int. El indi1ador permite indi1ar instancias List con valores int. 'or e$emploG
ListDstringE names + ne, ListDstringE(); names.'dd("Li?"); names.'dd("Mart"a"); names.'dd(":et""); -or (int i + 3; i D names.Count; i<<) { string s + names4i5; names4i5 + s.1o;&&er(); !

8os indi1adores se pueden sobrecargar, lo ?ue signi0ica ?ue pueden declararse varios indi1adores siempre y cuando sus par(metros di0ieran en nHmero o tipos. 1.6.#.4 &ventos 7n evento es un miembro ?ue permite a una clase u ob$eto proporcionar noti0icaciones. 7n evento se declara como un campo, salvo ?ue la declaraci-n incluya una palabra clave event y el tipo deba ser un tipo delegado. En una clase ?ue declara un miembro de evento, el evento se comporta como un campo de un tipo delegado Osiempre ?ue el evento no sea abstracto y no declare descriptores de accesoR. El campo almacena una re0erencia a un delegado ?ue representa los controladores de eventos ?ue se =an agregado al evento. .i no =ay ningHn controlador de eventos presente, el campo es null. 8a clase ListD1E declara un miembro de evento Hnico llamado C"anged, ?ue indica ?ue se =a agregado un nuevo elemento a la lista. El m)todo virtual %nC"anged inicia el evento C"anged comprobando previamente ?ue el evento es null Olo ?ue signi0ica ?ue no =ay ningHn controlador presenteR. 8a noci-n de iniciar un evento e?uivale exactamente a invocar el delegado representado por el eventoV por lo tanto, no =ay construcciones especiales del lengua$e para producir eventos. 8os clientes reaccionan a los eventos a trav)s de los controladores de eventos. 8os controladores de eventos se asocian utili1ando el operador <+ y se ?uitan utili1ando el operador =+. El e$emplo siguiente asocia un controlador de eventos al evento C"anged deListDstringE.

26

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases using System; class 1est { static int c"angeCount; static void ListC"anged(object sender c"angeCount<<; ! )vent'rgs e) {

static void Main() { ListDstringE names + ne, ListDstringE(); names.C"anged <+ ne, )ventHandler(ListC"anged); names.'dd("Li?"); names.'dd("Mart"a"); names.'dd(":et""); Console.WriteLine(c"angeCount); .. %ut&uts "9" ! !

'ara escenarios avan1ados donde se busca el control del almacenamiento subyacente de un evento, una declaraci-n de evento puede proporcionar expl5citamente descriptores de acceso add y remove ?ue en cierto modo son similares al descriptor de acceso set de una propiedad. 1.6.#. 'peradores 7n operador es un miembro ?ue de0ine el signi0icado de aplicar un operador de expresi-n determinado a las instancias de una clase. 'ueden de0inirse tres categor5as de operadoresG operadores unarios, operadores binarios y operadores de conversi-n. Todos los operadores deber(n declararse como &ublic y static. 8a clase ListD1E declara dos operadores o&erator++ y o&erator@+, proporcionando de este modo un nuevo signi0icado a expresiones ?ue aplican dic=os operadores a instancias List. Espec50icamente, los operadores de0inen la igualdad de dos instancias ListD1E comparando todos los ob$etos contenidos ?ue utili1an sus m)todos )Quals. El e$emplo siguiente utili1a el operador ++ para comparar dos instancias ListDintE.
using System; class 1est { static void Main() { ListDintE a + ne, ListDintE(); a.'dd(2); a.'dd(8); ListDintE b + ne, ListDintE(); b.'dd(2); b.'dd(8); Console.WriteLine(a ++ b); .. %ut&uts "1rue" b.'dd(9); Console.WriteLine(a ++ b); .. %ut&uts "Valse" ! !

El resultado del primer Console.WriteLine es 1rue por?ue las dos listas contienen el mismo nHmero de ob$etos con los mismos valores en el mismo orden. .i ListD1Eno de0iniera o&erator++, el primer Console.WriteLine =abr5a generado Valse por?ue a y b =acen re0erencia a dos instancias ListDintE di0erentes. 1.6.#.6 (estructores 7n destr!ctor es un miembro ?ue implementa las acciones necesarias para destruir una instancia de una clase. 8os destructores no pueden tener par(metros, no pueden tener modi0icadores de accesibilidad y no se pueden invocar de 0orma expl5cita. El destructor de una instancia se invoca autom(ticamente durante la recolecci-n de elementos no utili1ados.
Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

2(

Especificacin del lenguaje C#

El recolector de elementos no utili1ados tiene una amplia libertad para decidir cu(ndo debe recolectar ob$etos y e$ecutar destructores. En concreto, el control de tiempo de las invocaciones del destructor no es determinista y los destructores se pueden e$ecutar en cual?uier subproceso. 'or estas y otras ra1ones, las clases s-lo deber5an implementar los destructores cuando no es 0actible ninguna otra soluci-n. 8a instrucci-n using constituye una alternativa m(s recomendable para la destrucci-n de ob$etos.

1.+ Estructuras
Como las clases, las str!cts son estructuras de datos ?ue pueden contener miembros de datos y miembros de 0unci-n, pero al contrario ?ue las clases, las estructuras son tipos de valor y no re?uieren asignaci-n del mont-n. 7na variable de un tipo de estructura almacena directamente los datos de la estructura, mientras ?ue una variable de un tipo de clase almacena una re0erencia a un ob$eto din(micamente asignado. 8os tipos de estructura no admiten la =erencia especi0icada por el usuario y =eredan impl5citamente del tipo object. 8as estructuras son particularmente Htiles para estructuras de datos pe?ueUas ?ue tienen sem(nticas de valor. 8os nHmeros comple$os, los puntos de un sistema de coordenadas o los pares de valores clave de un diccionario son buenos e$emplos de estructuras. El uso de estructuras en lugar de clases para estructuras de datos pe?ueUas puede suponer una di0erencia sustancial en el nHmero de asignaciones de memoria ?ue reali1a una aplicaci-n. 'or e$emplo, el programa siguiente crea e iniciali1a una matri1 de 1"" puntos. Con *oint implementada como una clase, se iniciali1an 1"1 ob$etos separados, uno para la matri1 y uno para cada uno de los 1"" elementos.
class *oint { &ublic int # y; int y) {

&ublic *oint(int # t"is.# + #; t"is.y + y; ! !

class 1est { static void Main() { *oint45 &oints + ne, *oint42335; -or (int i + 3; i D 233; i<<) &oints4i5 + ne, *oint(i ! !

i);

7na alternativa es convertir *oint en una estructura.


struct *oint { &ublic int # y; int y) {

&ublic *oint(int # t"is.# + #; t"is.y + y; ! !

&=ora, s-lo se crea una instancia de un ob$eto, el de la matri1, y las instancias de *oint se almacenan en l5nea en la matri1. 8os constructores de estructuras se invocan con el operador ne,, pero esto no implica ?ue se est) asignando la memoria. En lugar de asignar din(micamente un ob$eto y devolver una re0erencia al mismo, un constructor de estructuras simplemente devuelve el propio valor de la estructura Onormalmente en una ubicaci-n temporal en la pilaR y a continuaci-n se copia este valor como sea necesario.

2$

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

En el caso de las clases, es posible ?ue dos variables =agan re0erencia al mismo ob$eto y, por tanto, ?ue las operaciones en una variable a0ecten al ob$eto al ?ue =ace re0erencia la otra variable. En el caso de las estructuras, cada variable tiene su propia copia de los datos, de manera ?ue no es posible ?ue las operaciones de una a0ecten a la otra. 'or e$emplo, el resultado generado por el 0ragmento de c-digo siguiente depende de si *oint es una clase o una estructura.
*oint a + ne, *oint(23 23); *oint b + a; a.# + 83; Console.WriteLine(b.#);

.i *oint es una clase, el resultado es 83 por?ue a y b =acen re0erencia al mismo ob$eto. .i *oint es una estructura, el resultado es 23 por?ue la asignaci-n de a a b crea una copia del valor y esta copia no resulta a0ectada por la subsiguiente asignaci-n a a.#. El e$emplo anterior resalta dos de las limitaciones de estructuras. En primer lugar, copiar una estructura completa normalmente es menos e0ica1 ?ue copiar una re0erencia a un ob$eto, por lo ?ue la asignaci-n y el modo de pasar par(metros de valor puede ser m(s costoso con estructuras ?ue con tipos de re0erencia. En segundo lugar, salvo en el caso de los par(metros re- y out, no es posible crear re0erencias a estructuras, lo ?ue descarta su uso en varias situaciones.

1.- &atrices
7na atri- es una estructura de datos ?ue contiene una serie de variables a las ?ue se obtiene acceso a trav)s de 5ndices calculados. 8as variables contenidas en una matri1, tambi)n conocidas como ele entos de la matri1, son todas del mismo tipo, denominado tipo de ele ento de la atri-. 8os tipos de matri1 son tipos de re0erencia, por lo ?ue la declaraci-n de una variable matricial solamente reserva espacio para una instancia de matri1. 8as instancias de matri1 reales se crean din(micamente en tiempo de e$ecuci-n utili1ando el operador ne,. 8a operaci-n ne, especi0ica la longit!d de la nueva instancia de matri1, ?ue se establece para el per5odo de duraci-n de la instancia. 8os 5ndices de los elementos de una matri1 pueden ir desde 3 a Lengt" = 2. El operador ne, iniciali1a autom(ticamente los elementos de una matri1 con su valor predeterminado ?ue, por e$emplo, es cero para todos los tipos num)ricos y null para todos los tipos de re0erencia. El e$emplo siguiente crea una matri1 de elementos int, iniciali1a la matri1 e imprime su contenido.
using System; class 1est { static void Main() { int45 a + ne, int4235; -or (int i + 3; i D a.Lengt"; i<<) { a4i5 + i > i; ! -or (int i + 3; i D a.Lengt"; i<<) { Console.WriteLine("a4{3!5 + {2!" i ! ! !

a4i5);

Este e$emplo crea y 0unciona en una atri- !nidi ensional. C# tambi)n admite las atrices !ltidi ensionales. El nHmero de dimensiones de un tipo de matri1, tambi)n conocido como el rango del tipo de matri1, es uno m(s el nHmero de comas escrito entre los corc=etes del tipo de matri1. El e$emplo siguiente asigna una matri1 unidimensional, una bidimensional y una tridimensional.
int45 a2 + ne, int4235; int4 5 a8 + ne, int423 K5; int4 5 a9 + ne, int423 K 85;

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

2"

Especificacin del lenguaje C#

8a matri1 a2 contiene 1" elementos, la matri1 a8 contiene " O1" X R elementos y la matri1 a9 contiene 1"" O1" X X 2R elementos. 8os elementos de una matri1 pueden ser de cual?uier tipo, incluido un tipo de matri1. 7na matri1 con elementos de tipo de matri1 a veces se denomina atri- escalonada por?ue las longitudes de las matrices de elementos no tienen ?ue ser siempre las mismas. El e$emplo siguiente asigna una matri1 de matrices de intG
int4545 a + ne, int49545; a435 + ne, int4235; a425 + ne, int4K5; a485 + ne, int4835;

8a primera l5nea crea una matri1 con tres elementos, cada uno de tipo int45 y cada uno con un valor inicial null. & continuaci-n, las l5neas subsiguientes iniciali1an los tres elementos con re0erencias a instancias de matri1 individuales de longitudes diversas. El operador ne, permite especi0icar los valores iniciales de los elementos de matri1 utili1ando un iniciali-ador de atrices, ?ue es una lista de expresiones escrita entre los delimitadores { y !. El e$emplo siguiente asigna e iniciali1a un int45 con tres elementos.
int45 a + ne, int45 {2 8 9!;

/bserve ?ue la longitud de la matri1 se in0iere del nHmero de expresiones existentes entre { y !. 8a variable local y las declaraciones de campo se pueden acortar m(s, de tal modo ?ue no es necesario volver a especi0icar el tipo de matri1.
int45 a + {2 8 9!;

8os dos e$emplos anteriores son e?uivalentes a lo siguienteG


int45 t + ne, int495; t435 + 2; t425 + 8; t485 + 9; int45 a + t;

1.. Interfaces
7na interfa- de0ine un contrato ?ue puede ser implementado por clases y estructuras. 7na inter0a1 puede contener m)todos, propiedades, eventos e indi1adores. 7na inter0a1 no proporciona implementaciones de los miembros ?ue de0ine, simplemente especi0ica los miembros ?ue deben proporcionar las clases o estructuras ?ue implementan la inter0a1. 8as inter0aces pueden utili1ar una herencia $1e#t:o# y de $List:o#.
inter-ace $Control { void *aint(); ! inter-ace $1e#t:o#/ $Control { void Set1e#t(string te#t); ! inter-ace $List:o#/ $Control { void Set$tems(string45 items); ! inter-ace $Combo:o#/ $1e#t:o# $List:o# {!

7ltiple. En el e$emplo siguiente, la inter0a1 $Combo:o# =ereda de

3'

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

8as clases y las estructuras pueden implementar varias inter0aces. En el e$emplo siguiente, la clase )dit:o# implementa $Control e $6ata:ound.
inter-ace $6ata:ound { void :ind(:inder b); ! &ublic class )dit:o#/ $Control { &ublic void *aint() {...! ! $6ata:ound

&ublic void :ind(:inder b) {...!

Cuando una clase o estructura implementa una inter0a1 determinada, las instancias de dic=a clase o estructura se pueden convertir impl5citamente en dic=o tipo de inter0a1. 'or e$emploG
)dit:o# edit:o# + ne, )dit:o#(); $Control control + edit:o#; $6ata:ound data:ound + edit:o#;

En los casos en los ?ue no se sabe est(ticamente ?ue una inter0a1 pueda implementar una inter0a1 determinada, se pueden utili1ar conversiones de tipo din(micas. 'or e$emplo, las instrucciones siguientes utili1an conversiones de tipo din(micas para obtener implementaciones de inter0aces $Control e $6ata:ound de un ob$eto. 2ado ?ue el tipo real del ob$eto es )dit:o#, las conversiones se reali1aron con )xito.
object obj + ne, )dit:o#(); $Control control + ($Control)obj; $6ata:ound data:ound + ($6ata:ound)obj;

En la clase )dit:o# anterior, el m)todo *aint de la inter0a1 $Control y el m)todo :ind de la inter0a1 $6ata:ound se implementan utili1ando miembros &ublic. C# tambi)n admite i ple entaciones e.plcitas de ie /ro de la interfa- y, al utili1arlas la clase o la estructura, se puede evitar ?ue los miembros sean &ublic. 7na implementaci-n expl5cita de miembro de inter0a1 se escribe utili1ando el nombre completo de miembro de inter0a1. 'or e$emplo, la clase )dit:o# podr5a implementar los m)todos $Control.*aint e $6ata:ound.:ind utili1ando implementaciones expl5citas de miembro de inter0a1 del siguiente modo.
&ublic class )dit:o#/ $Control { void $Control.*aint() {...! ! $6ata:ound

void $6ata:ound.:ind(:inder b) {...!

.-lo se puede tener acceso a los miembros de inter0a1 expl5citos mediante el tipo de inter0a1. 'or e$emplo, la implementaci-n de $Control.*aint proporcionada por la clase )dit:o# anterior s-lo se puede invocar convirtiendo primero la re0erencia )dit:o# en el tipo de inter0a1 $Control.
)dit:o# edit:o# + ne, )dit:o#(); edit:o#.*aint(); .. )rror $Control control + edit:o#; control.*aint(); .. %( no suc" met"od

1.10 Enumeraciones
7n tipo en! Oenumeraci-nR es un tipo de valor distinto con un con$unto de constantes con nombre. El e$emplo siguiente declara y utili1a un tipo enum denominado Color con tres valores constantesG Oed, Sreen y :lue.

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

31

Especificacin del lenguaje C# using System; enum Color { Oed Sreen :lue ! class 1est { static void *rintColor(Color color) { s,itc" (color) { case Color.Oed/ Console.WriteLine("Oed"); brea(; case Color.Sreen/ Console.WriteLine("Sreen"); brea(; case Color.:lue/ Console.WriteLine(":lue"); brea(; de-ault/ Console.WriteLine(";n(no,n color"); brea(; ! ! static void Main() { Color c + Color.Oed; *rintColor(c); *rintColor(Color.:lue); ! !

Cada tipo enum tiene un tipo integral correspondiente denominado tipo s!/yacente del tipo enum. 7n tipo enum ?ue no declara expl5citamente un tipo subyacente tiene int como tipo subyacente. El 0ormato de almacenamiento y el intervalo de posibles valores de un tipo enum vienen determinados por su tipo subyacente. El con$unto de valores ?ue puede tomar un tipo enum no est( limitado por sus miembros de enumeraci-n. En concreto, cual?uier valor del tipo subyacente de una enumeraci-n puede convertirse en el tipo enum, y es un valor aceptado y distintivo de dic=o tipo enum. El e$emplo siguiente declara un tipo enum denominado 'lignment con un tipo subyacente de sbyte.
enum 'lignment/ sbyte { Le-t + =2 Center + 3 Oig"t + 2 !

Como se muestra en el e$emplo anterior, una declaraci-n de miembro de enumeraci-n puede incluir una expresi-n constante ?ue especi0ica el valor del miembro. El valor constante de cada miembro de enumeraci-n debe estar comprendido en el intervalo del tipo subyacente de la enumeraci-n. Cuando una declaraci-n de miembro de enumeraci-n no especi0ica expl5citamente un valor, se da al miembro el valor cero Osi es el primer miembro del tipo enumR o el valor del miembro de la enumeraci-n precedente m(s uno. 8os valores de enumeraci-n se pueden convertir en valores de tipo integral y viceversa, utili1ando las conversiones de tipo. 'or e$emploG
int i + (int)Color.:lue; Color c + (Color)8; .. int i + 8; .. Color c + Color.:lue;

32

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

El valor predeterminado de cual?uier tipo de enumeraci-n es el valor cero de tipo integral convertido en el tipo enum. En los casos en los ?ue las variables se iniciali1an autom(ticamente con un valor predeterminado, )ste es el valor proporcionado para las variables de tipos enum. 'ara ?ue el valor predeterminado de un tipo enum est) 0(cilmente disponible, el literal " se convierte impl5citamente en cual?uier tipo enum. 2e este modo, se permite lo siguiente.
Color c + 3;

1.11 /elegados
7n tipo delegado representa las re0erencias a los m)todos con una lista de par(metros determinada y un tipo de valor devuelto. 8os delegados permiten tratar m)todos como entidades, ?ue se pueden asignar a las variables y pasarse como par(metros. 8os delegados son similares al concepto de punteros a 0unci-n de otros lengua$es, pero al contrario de los punteros a 0unci-n, los delegados est(n orientados a ob$etos y proporcionan seguridad de tipos. El e$emplo siguiente declara y utili1a un tipo delegado denominado Vunction.
using System; delegate double Vunction(double #); class Multi&lier { double -actor; &ublic Multi&lier(double -actor) { t"is.-actor + -actor; ! &ublic double Multi&ly(double #) { return # > -actor; ! ! class 1est { static double SQuare(double #) { return # > #; ! static double45 '&&ly(double45 a Vunction -) { double45 result + ne, double4a.Lengt"5; -or (int i + 3; i D a.Lengt"; i<<) result4i5 + -(a4i5); return result; ! static void Main() { double45 a + {3.3 3.K 2.3!; SQuare); Mat".Sin);

double45 sQuares + '&&ly(a double45 sines + '&&ly(a

Multi&lier m + ne, Multi&lier(8.3); double45 doubles + '&&ly(a m.Multi&ly); ! !

7na instancia del tipo delegado Vunction puede =acer re0erencia a cual?uier m)todo ?ue tome un argumento double y ?ue devuelva un valor double. El m)todo '&&ly aplica un tipo Vunction determinado a los elementos de un tipo double45 y devuelve un tipo double45 con los resultados. En el m)todo Main, se utili1a '&&ly para aplicar tres 0unciones di0erentes a un double45.

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

33

Especificacin del lenguaje C#

7n delegado puede =acer re0erencia a un m)todo est(tico Ocomo SQuare o Mat".Sin en el e$emplo anteriorR o a un m)todo de instancia Ocomo m.Multi&ly en el e$emplo anteriorR. 7n delegado ?ue =ace re0erencia a un m)todo de instancia tambi)n =ace re0erencia a un ob$eto determinado y, cuando se invoca el m)todo de instancia a trav)s del delegado, dic=o ob$eto pasa a ser t"is en la invocaci-n. 8os delegados tambi)n se pueden crear mediante 0unciones an-nimas, ?ue son Pm)todos insertadosQ creados sobre la marc=a. 8as 0unciones an-nimas pueden ver las variables locales de los m)todos adyacentes. &s5, el e$emplo anterior del multiplicador se puede escribir m(s 0(cilmente sin usar una clase Multi&lierG
double45 doubles + '&&ly(a (double #) +E # > 8.3);

7na propiedad interesante y Htil de un delegado es ?ue no conoce ni necesita conocer la clase del m)todo a la ?ue =ace re0erenciaV lo Hnico ?ue importa es ?ue el m)todo al ?ue se =ace re0erencia tenga los mismos par(metros y el mismo tipo de valor devuelto ?ue el delegado.

1.12 'tributos
8os tipos, miembros y otras entidades de un programa de C# admiten modi0icadores ?ue controlan ciertos aspectos de su comportamiento. 'or e$emplo, la accesibilidad de un m)todo se controla utili1ando los modi0icadores &ublic, &rotected, internal y &rivate. C# generali1a esta 0unci-n de tal 0orma ?ue los tipos de0inidos por el usuario de in0ormaci-n declarativa puedan agregarse a las entidades del programa y ser recuperados en tiempo de e$ecuci-n. 8os programas especi0ican esta in0ormaci-n declarativa adicional de0iniendo y utili1ando atri/!tos. El e$emplo siguiente declara un atributo Hel&'ttribute ?ue se puede colocar en entidades de programa para proporcionar v5nculos a la documentaci-n asociada.
using System; &ublic class Hel&'ttribute/ 'ttribute { string url; string to&ic; &ublic Hel&'ttribute(string url) { t"is.url + url; ! &ublic string ;rl { get { return url; ! ! &ublic string 1o&ic { get { return to&ic; ! set { to&ic + value; ! ! !

Todas las clases de atributo derivan de la clase base System.'ttribute proporcionada por .4ET :rame9or6. 8os atributos se pueden aplicar indicando su nombre, $unto con los argumentos, entre corc=etes, $usto antes de la declaraci-n asociada. .i el nombre de un atributo termina en 'ttribute, se puede omitir dic=a parte del nombre si se =ace re0erencia al atributo. 'or e$emplo, el atributo Hel&'ttribute se puede utili1ar del siguiente modo.
4Hel&(""tt&/..msdn.microso-t.com.....MyClass."tm")5 &ublic class Widget { 4Hel&(""tt&/..msdn.microso-t.com.....MyClass."tm" &ublic void 6is&lay(string te#t) {! !

1o&ic + "6is&lay")5

3#

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

Este e$emplo asocia un Hel&'ttribute a la clase Widget y otro Hel&'ttribute al m)todo 6is&lay de la clase. 8os constructores pHblicos de una clase de atributo controlan la in0ormaci-n ?ue debe proporcionarse al asociar el atributo a una entidad de programa. 'uede proporcionarse in0ormaci-n adicional =aciendo re0erencia a las propiedades pHblicas de lectura y escritura de la clase de atributo Ocomo la re0erencia previa a la propiedad 1o&icR. El e$emplo siguiente muestra c-mo utili1ar la re0lexi-n para recuperar en tiempo de e$ecuci-n la in0ormaci-n de atributos para una entidad determinada del programa.
using System; using System.Oe-lection; class 1est { static void S"o,Hel&(Member$n-o member) { Hel&'ttribute a + 'ttribute.SetCustom'ttribute(member ty&eo-(Hel&'ttribute)) as Hel&'ttribute; i- (a ++ null) { Console.WriteLine("No "el& -or {3!" member); ! else { Console.WriteLine("Hel& -or {3!/" member); Console.WriteLine(" ;rl+{3! 1o&ic+{2!" a.;rl a.1o&ic); ! ! static void Main() { S"o,Hel&(ty&eo-(Widget)); S"o,Hel&(ty&eo-(Widget).SetMet"od("6is&lay")); ! !

Cuando se solicita un atributo determinado a trav)s de la re0lexi-n, se invoca al constructor para la clase de atributo con la in0ormaci-n proporcionada en el c-digo 0uente del programa y se devuelve la instancia de atributo resultante. .i la in0ormaci-n adicional se proporciona a trav)s de propiedades, dic=as propiedades se establecen en los valores dados antes de ?ue se devuelva la instancia de atributo.

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

3!

Especificacin del lenguaje C#

2. Estructura l*"ica
2.1 (rogramas
7n progra a de C# consta de uno o varios archivos de c,digo f!ente, 0ormalmente conocidos como !nidades de co pilaci,n O[+.1R. 7n arc=ivo de c-digo 0uente es una secuencia ordenada de caracteres 7nicode. 8os arc=ivos de c-digo 0uente normalmente tienen una correspondencia de uno a uno con los arc=ivos de un sistema de arc=ivos, pero esta correspondencia no es necesaria. 'ara maximi1ar la portabilidad, se recomienda utili1ar la codi0icaci-n 7T:B8 para los arc=ivos de un sistema de arc=ivos. En t)rminos conceptuales, un programa se compila en tres 0asesG 1. Trans0ormaci-n, ?ue convierte un arc=ivo, a partir de un repertorio de caracteres y un es?uema de codi0icaci-n concretos, en una secuencia de caracteres 7nicode. 2. &n(lisis l)xico, ?ue convierte una secuencia de caracteres de entrada 7nicode en una secuencia de s5mbolos Oto6enR. 3. &n(lisis sint(ctico, ?ue convierte la secuencia de to6ens en c-digo e$ecutable.

2.2 0ram)ticas
Esta especi0icaci-n presenta la sintaxis del lengua$e de programaci-n C# mediante el uso de dos gram(ticas. 8a gra 5tica l6.ica O[2.2.2R de0ine c-mo se combinan los caracteres 7nicode para 0ormar terminadores de l5nea, espacios en blanco, comentarios, s5mbolos Oto6ensR y directivas de preprocesamiento. 8a gra 5tica sint5ctica O[2.2.3R de0ine c-mo se combinan los to6ens resultantes de la gram(tica l)xica para 0ormar programas de C#. 2.2.1 1otacin gramatical 8as gram(ticas l)xica y sint(ctica se presentan mediante prod!cciones gra aticales. Cada producci-n gramatical de0ine un s5mbolo no terminal y las posibles expansiones de dic=o s5mbolo en secuencias de s5mbolos no terminales o terminales. En las producciones gramaticales, los s5mbolos no ter%inales se muestran en cursiva, y los s5mbolos terminal se muestran en una 0uente de anc=o 0i$o. 8a primera l5nea de una producci-n gramatical es el nombre del s5mbolo no terminal ?ue se de0ine, seguido de un car(cter de dos puntos. Cada l5nea con sangr5a sucesiva contiene una expansi-n posible del s5mbolo no terminal dado como una secuencia de s5mbolos no terminales o terminales. 'or e$emplo, la producci-nG while-state%ent1 ,"ile ( -oolean-e2pression ) e%-edded-state%ent de0ine una instrucci-n 9=ile Owhile-state%entR 0ormada por el s5mbolo Oto6enR ,"ile, seguida del s5mbolo P(Q, de una expresi-n booleana O-oolean-e2pressionR, del s5mbolo P)Q y de una instrucci-n incrustada Oe%-eddedstate%entR. Cuando =ay m(s de una expansi-n posible de un s5mbolo no terminal, las alternativas se muestran en l5neas individuales. 'or e$emplo, la producci-nG state%ent-list1 state%ent state%ent-list state%ent

36

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

de0ine una lista de instrucciones Ostate%ent-listR ?ue consta de una instrucci-n Ostate%entR o de una lista de instrucciones Ostate%ent-listR seguida de una instrucci-n Ostate%entR. Es decir, la de0inici-n es recursiva y especi0ica ?ue una lista de instrucciones consta de una o varias instrucciones. .e utili1a un su0i$o en sub5ndice PoptQ para indicar un s5mbolo opcional. 8a producci-nG -loc31
{ state%ent-listopt !

es una 0orma abreviada deG -loc31


{ ! { state%ent-list !

y de0ine un blo?ue O-loc3R compuesto por una lista de instrucciones Ostate%ent-listR opcional entre los to6ens P{Q y P!Q. 8as alternativas normalmente se enumeran en l5neas distintas, aun?ue en los casos en los ?ue =ay varias alternativas, el texto Puna de las siguientesQ puede preceder a una lista de expansiones proporcionadas en la misma l5nea. Esto es sencillamente una 0orma abreviada de mostrar todas las alternativas en l5neas distintas. 'or e$emplo, la producci-nG real-t#pe-s ffi21
V 6 d

no de
M m

es una 0orma abreviada deG real-t#pe-s ffi21


V 6 d M m

2.2.2 0ram)tica l*"ica 8a gram(tica l)xica de C# se presenta en [2.3, [2.4 y [2. . 8os s5mbolos terminales de la gram(tica l)xica son los caracteres del $uego de caracteres 7nicode, y la gram(tica l)xica especi0ica c-mo se combinan los caracteres para 0ormar to6ens O[2.4R, espacios en blanco O[2.3.3R, comentarios O[2.3.2R y directivas de preprocesamiento O[2. R. Todos los arc=ivos de c-digo 0uente de un programa de C# deben a$ustarse a la producci-n entrada Oinp tR de la gram(tica l)xica O[2.3R. 2.2.3 0ram)tica sint)ctica 8a gram(tica sint(ctica de C# se presenta en los cap5tulos y ap)ndices ?ue siguen a este cap5tulo. 8os s5mbolos terminales de la gram(tica sint(ctica son los to6ens de0inidos por la gram(tica l)xica, mientras la gram(tica sint(ctica es la ?ue especi0ica c-mo se combinan los s5mbolos para 0ormar programas de C#. Todos los arc=ivos de c-digo 0uente de un programa de C# deben cumplir con la producci-n de unidades de compilaci-n Oco%pilation- nitR de la gram(tica sint(ctica O[+.1R.

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

3(

Especificacin del lenguaje C#

2.3 'n)lisis l*"ico


8a producci-n entrada Oinp tR de0ine la estructura l)xica de un arc=ivo de c-digo 0uente de C#. 7n arc=ivo de c-digo 0uente de un programa de C# debe a$ustarse a esta producci-n de la gram(tica l)xica. inp t1 inp t-sectionopt inp t-section1 inp t-section-part inp t-section inp t-section-part inp t-section-part1 inp t-ele%entsopt new-line pp-directive inp t-ele%ents1 inp t-ele%ent inp t-ele%ents inp t-ele%ent inp t-ele%ent1 whitespace co%%ent to3en Cinco elementos b(sicos constituyen la estructura l)xica de un arc=ivo de c-digo 0uente de C#G los terminadores de l5nea O[2.3.1R, el espacio en blanco O[2.3.3R, los comentarios O[2.3.2R, los s5mbolos Oto6enR O[2.4R y las directivas de preprocesamiento O[2. R. 2e estos elementos b(sicos, solamente los to6ens son signi0icativos en la gram(tica sint(ctica de un programa de C# O[2.2.3R. El procesamiento l)xico de un arc=ivo de c-digo 0uente de C# consiste en reducir el arc=ivo a una secuencia de to6ens para 0ormar la entrada del an(lisis sint(ctico. 8os terminadores de l5nea, el espacio en blanco y los comentarios pueden corresponder a to6ens di0erentes, y las directivas de preprocesamiento pueden =acer ?ue se omitan secciones del arc=ivo de c-digo 0uente, pero por lo dem(s estos elementos l)xicos no tienen repercusiones en la estructura sint(ctica de un programa de C#. Cuando varias producciones de la gram(tica l)xica coinciden con una secuencia de caracteres de un arc=ivo de c-digo 0uente, el procesamiento l)xico siempre 0orma el elemento l)xico m(s largo posible. 'or e$emplo, la secuencia de caracteres .. se procesa como el principio de un comentario en una sola l5nea, por?ue este elemento l)xico es m(s largo ?ue un to6en de una sola .. 2.3.1 Terminadores de l2nea 8os terminadores de l5nea dividen los caracteres de un arc=ivo de c-digo 0uente de C# en l5neas. new-line1 Car,cter de retorno de carro 4;<33365 Car,cter de salto de l*nea 4;<333'5 Car,cter de retorno de carro 4;<33365 se& ido de n car,cter de salto de l*nea 4;<333'5 Car,cter de l*nea si& iente 4;<33YK5 Car,cter separador de l*nea 4;<838Y5 Car,cter separador de p,rrafo 4;<838L5 'or compatibilidad con las =erramientas de edici-n de c-digo 0uente ?ue agregan marcadores de 0in de arc=ivo, y para permitir ?ue un arc=ivo de c-digo 0uente pueda verse como una secuencia de l5neas terminadas correctamente, se aplican las siguientes trans0ormaciones, por orden, a todos los arc=ivos de c-digo 0uente de un programa de C#G

3$

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

.i el Hltimo car(cter del arc=ivo de c-digo 0uente es un car(cter ControlB\ O;<332'R, el car(cter se elimina. &l 0inal del arc=ivo de c-digo de 0uente se agrega un car(cter de retorno de carro O;<3336R si este arc=ivo no est( vac5o y si su Hltimo car(cter no es un retorno de carro O;<3336R, un salto de l5nea O;<333'R, un separador de l5nea O;<838YR o un separador de p(rra0o O;<838L6R.

2.3.2 %omentarios .e aceptan dos 0ormas de comentariosG comentarios en una l5nea y comentarios delimitados. 8os co entarios de !na sola lnea empie1an con los caracteres .. y se extienden =asta el 0inal de la l5nea de c-digo 0uente. 8os co entarios deli itados empie1an con los caracteres .> y terminan con los caracteres >.. Estos comentarios pueden estar en varias l5neas. co%%ent1 sin&le-line-co%%ent deli%ited-co%%ent sin&le-line-co%%ent1 .. inp t-charactersopt inp t-characters1 inp t-character inp t-characters inp t-character inp t-character1 C al6 ier car,cter (nicode e2cepto n new-line-character 4car,cter de n eva l*neaR new-line-character1 Car,cter de retorno de carro 4;<33365 Car,cter de salto de l*nea 4;<333'5 Car,cter de l*nea si& iente 4;<33YK5 Car,cter separador de l*nea 4;<838Y5 Car,cter separador de p,rrafo 4;<838L5 deli%ited-co%%ent1 .> deli%ited-co%%ent-te2topt asteris3s . deli%ited-co%%ent-te2t1 deli%ited-co%%ent-section deli%ited-co%%ent-te2t deli%ited-co%%ent-section deli%ited-co%%ent-section1
.

asteris3sopt not-slash-or-asteris3 asteris3s1


>

asteris3s > not-slash-or-asteris31 C al6 ier car,cter (nicode e2cepto . o > 8os comentarios no pueden anidarse. 8as secuencias de caracteres .> y >. no tienen ningHn signi0icado especial dentro de un comentario .., y las secuencias de caracteres.. y .> no tienen ningHn signi0icado especial dentro de un comentario delimitado. 8os comentarios no se procesan dentro de literales de car(cter y de cadena.

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

3"

Especificacin del lenguaje C#

El e$emplo
.> Hello ,orld &rogram 1"is &rogram ,rites R"ello ,orldT to t"e console >. class Hello { static void Main() { System.Console.WriteLine(""ello ,orld"); ! !

incluye un comentario delimitado. El e$emplo


.. Hello ,orld &rogram .. 1"is &rogram ,rites R"ello ,orldT to t"e console .. class Hello .. any name ,ill do -or t"is class { static void Main() { .. t"is met"od must be named "Main" System.Console.WriteLine(""ello ,orld"); ! !

muestra varios comentarios en una l5nea. 2.3.3 Espacio en blanco Espacio en blanco se de0ine como cual?uier car(cter con la clase 7nicode \s O?ue incluye el car(cter de espacioR as5 como el car(cter de tabulaci-n =ori1ontal, el car(cter de tabulaci-n vertical y el car(cter de avance de p(gina. whitespace1 C al6 ier car,cter con clase (nicode 7s Car,cter de ta- laci/n hori0ontal 4;<333L5 Car,cter de ta- laci/n vertical 4;<333:5 Car,cter de avance de p,&ina 4;<333C5

2.! To3ens
Existen varias clases de s5mbolos Oto6enRG identi0icadores, palabras clave, literales, operadores y signos de puntuaci-n. 8os espacios en blanco y los comentarios no son s5mbolos Oto6enR, si bien actHan como separadores entre ellos. to3en1 identificador 3e#word inte&er-literal real-literal character-literal strin&-literal operator-or-p nct ator 2.!.1 4ecuencias de escape de caracteres 5nicode 7na secuencia de escape de caracteres 7nicode representa un car(cter 7nicode. 8as secuencias de escape de car(cter 7nicode se procesan en identi0icadores O[2.4.2R, literales de car(cter O[2.4.4.4R y literales de cadena normales O[2.4.4. R. 7n car(cter de escape 7nicode no se procesa en ninguna otra ubicaci-n Opor e$emplo, para 0ormar un operador, un signo de puntuaci-n o una palabra claveR.

#'

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

nicode-escape-se6 ence1 Zu he2-di&it he2-di&it he2-di&it he2-di&it Z; he2-di&it he2-di&it he2-di&it he2-di&it he2-di&it he2-di&it he2-di&it he2-di&it 7na secuencia de escape 7nicode representa el Hnico car(cter 7nicode 0ormado por el nHmero =exadecimal ?ue sigue a los caracteres PZuQ o PZ;Q. 2ado ?ue C# usa una codi0icaci-n de 1# bits de los puntos de c-digo 7nicode en caracteres y valores de cadena, un car(cter 7nicode en el intervalo de 7S1"""" a 7S1":::: no est( permitido en un literal de caracteres y se representa mediante un par 7nicode suplente en un literal de cadena. 8os caracteres 7nicode con puntos de c-digo por encima de "x1":::: no se aceptan. 4o se llevan a cabo conversiones mHltiples. 'or e$emplo, el literal de cadena PZu33KCu33KCQ es e?uivalente a PZu33KCQ en lugar ?ue a PZQ. El valor 7nicode Zu33KC es el car(cter PZQ. En el e$emplo
class Class2 { static void 1est(bool Zu33XX) { c"ar c + WZu33XXW; i- (Zu33XX) System.Console.WriteLine(c.1oString()); ! !

se muestran varios usos de Zu33XX, ?ue es la secuencia de escape de la letra P-Q. El programa e?uivale a
class Class2 { static void 1est(bool -) { c"ar c + W-W; i- (-) System.Console.WriteLine(c.1oString()); ! !

2.!.2 Identificadores 8as reglas de los identi0icadores explicadas en esta secci-n se corresponden exactamente con las recomendadas por la norma 7nicode &nexo 1 , a excepci-n del car(cter de subrayado, ?ue est( permitido como car(cter inicial Ocomo era tradicional en el lengua$e de programaci-n CR. 8as secuencias de escape 7nicode est(n permitidas en los identi0icadores y el car(cter P]Q est( permitido como pre0i$o para =abilitar el uso de palabras clave como identi0icadores. identifier1 availa-le-identifier [ identifier-or-3e#word availa-le-identifier1 (n identifier-or-3e#word 4identificador o pala-ra clave5 6 e no es na 3e#word Opalabra claveR identifier-or-3e#word1 identifier-start-character identifier-part-charactersopt identifier-start-character1 letter-character \ 4el car,cter de s -ra#ado ;<33KV5 identifier-part-characters1 identifier-part-character identifier-part-characters identifier-part-character

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

#1

Especificacin del lenguaje C#

identifier-part-character1 letter-character deci%al-di&it-character connectin&-character co%-inin&-character for%attin&-character letter-character1 (n car,cter (nicode de las clases + , +l, +t, +%, +o o 8l (na sec encia de escape (nicode 4 nicode-escape-se6 ence) 6 e representa a n car,cter de clases + , +l, +t, +%, +o o 8l co%-inin&-character1 (n car,cter (nicode de las clases Mn o Mc (na sec encia de escape (nicode 4 nicode-escape-se6 ence5 6 e representa n car,cter de clases Mn o Mc deci%al-di&it-character1 (n car,cter (nicode de la clase 8d. (na nicode-escape-se6 ence 4sec encia de escape (nicode5 6 e representa n car,cter de la clase 8d connectin&-character1 (n car,cter (nicode de la clase 9c (na sec encia de escape (nicode 4 nicode-escape-se6 ence5 6 e representa n car,cter de la clase 9c for%attin&-character1 (n car,cter (nicode de la clase Cf (na sec encia de escape (nicode 4 nicode-escape-se6 ence5 6 e representa n car,cter de la clase Cf 'ara obtener m(s in0ormaci-n sobre las anteriores clases de caracteres, consulte la secci-n 4. de la versi-n 3." de la norma 7nicode O(nicode :tandard, Version ;.0R. Entre los e$emplos de identi0icadores v(lidos se incluyen Pidenti-ier2Q, P\identi-ier8Q y P[i-Q. 8os identi0icadores incluidos en programas segHn la norma deber(n seguir el 0ormato can-nico de0inido en el documento (nicode 8or%ali0ation <or% C Oanexo 1 de la norma 7nicodeR. El comportamiento ante identi0icadores ?ue no se a$usten a dic=o 0ormato depender( de la implementaci-nV no obstante, no ser(n necesarios diagn-sticos. El pre0i$o P[Q =abilita el uso de palabras clave como identi0icadores, lo cual resulta Htil cuando se interactHa con otros lengua$es de programaci-n. El car(cter [ en realidad no 0orma parte del identi0icador, por lo ?ue el identi0icador podr5a considerarse en otros lengua$es como un identi0icador normal, sin el pre0i$o. 8os identi0icadores con pre0i$o [ se conocen como identificadores te.t!ales. El uso del pre0i$o [ para los identi0icadores ?ue no son palabras clave est( permitido, pero no se recomienda por cuesti-n de estilo. En el e$emploG
class [class { &ublic static void [static(bool [bool) { i- ([bool) System.Console.WriteLine("true"); else System.Console.WriteLine("-alse"); ! !

#2

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases class Class2 { static void M() { clZu33X2ss.stZu33X2tic(true); ! !

se de0ine una clase denominada PclassQ con un m)todo est(tico llamado PstaticQ ?ue toma un par(metro denominado PboolQ. Tenga en cuenta ?ue, dado ?ue los escapes de 7nicode no est(n permitidos en las palabras clave, el to6en PclZu33X2ssQ es un identi0icador id)ntico a P[classQ. 2os identi0icadores se consideran el mismo si son id)nticos despu)s de aplicarse las siguientes trans0ormaciones, por ordenG El pre0i$o P[Q, si aparece, se ?uitar(. Cada secuencia de escape 7nicode O nicode-escape-se6 enceR se trans0ormar( en su car(cter 7nicode correspondiente. Todos los caracteres de 0ormato Ofor%attin&-charactersR ser(n ?uitados.

8os identi0icadores ?ue contienen dos caracteres de subrayado O;<33KVR consecutivos se reservan para uso de la implementaci-n. 'or e$emplo, una implementaci-n podr5a proporcionar palabras clave extendidas ?ue empiecen por dos caracteres de subrayado. 2.!.3 (alabras cla e 7na pala/ra clave es una secuencia de caracteres similar a un identi0icador ?ue est( reservada y no puede utili1arse como identi0icador excepto cuando tiene como pre0i$o el car(cter [. palabra clave O3e#wordRG una de
abstract byte class delegate event -i#ed iinternal ne, override readonly s"ort struct try unsa-e volatile as case const do e#&licit -loat im&licit es null &arams resi?eos,itc" ty&eous"ort ,"ile base catc" continue double e#tern -or in loc( object &rivate return stac(alloc t"is uint using bool c"ar decimal else -alse -oreac" int long o&erator &rotected sbyte static t"ro, ulong virtual brea( c"ec(ed de-ault enum -inally goto inter-ace names&ace out &ublic sealed string true unc"ec(ed void

En algunos lugares de la gram(tica, =ay identi0icadores espec50icos con signi0icados especiales, pero no son palabras clave. 'or e$emplo, en una declaraci-n de propiedad, los identi0icadores PgetQ y PsetQ tienen un signi0icado especial O[1".*.2R. En estas ubicaciones no se permite usar identi0icadores distintos de get o set, por lo ?ue este uso no presenta con0lictos si se utili1an estas palabras como identi0icadores.

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

#3

Especificacin del lenguaje C#

2.!.! 6iterales 7n literal es una representaci-n en c-digo 0uente de un valor. literal1 -oolean-literal inte&er-literal real-literal character-literal strin&-literal n ll-literal 2.4.4.1 *iterales booleanos Existen dos valores literales booleanosG true y -alse. -oolean-literal1
true -alse

El tipo de un literal booleano O-oolean-literalR es bool. 2.4.4.2 *iterales enteros 8os literales enteros permiten escribir valores de los tipos int, uint, long, y ulong. 8os literales enteros tienen dos 0ormatos posiblesG decimal y =exadecimal. inte&er-literal1 deci%al-inte&er-literal he2adeci%al-inte&er-literal deci%al-inte&er-literal1 deci%al-di&its inte&er-t#pe-s ffi2opt deci%al-di&its1 deci%al-di&it deci%al-di&its deci%al-di&it deci%al-di&it1 no de
3 ; 2 u 8 L 9 l J ;L K ;l X M uL Y ul L L; Lu l; lu

inte&er-t#pe-s ffi21 no de he2adeci%al-inte&er-literal1 3# he2-di&its inte&er-t#pe-s ffi2opt 3I he2-di&its inte&er-t#pe-s ffi2opt he2-di&its1 he2-di&it he2-di&its he2-di&it he2-di&it1 no de
3 2 8 9 J K X M Y L ' : C 6 ) V a b c d e -

El tipo de un literal entero se determina como sigueG .i el literal no tiene su0i$o, su tipo es el primero de los tipos en los cuales se puede representar su valorG int, uint, long, ulong.

##

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

.i el literal tiene el su0i$o ; o u, su tipo es el primero de los tipos en los cuales se puede representar su valorG uint, ulong. .i el literal tiene el su0i$o L o l, su tipo es el primero de los tipos en los cuales se puede representar su valorG long, ulong. .i el literal tiene el su0i$o ;L, ;l, uL, ul, L;, Lu, l;, o lu, es de tipo ulong.

.i el valor representado por un literal entero est( 0uera del intervalo de valores del tipo ulong, se produce un error en tiempo de compilaci-n. 'or cuestiones de estilo, a la =ora de escribir literales de tipo long se recomienda el uso de PLQ en lugar de PlQ para evitar la 0(cil con0usi-n de la letra PlQ con el d5gito P2Q. 'ara ?ue el nHmero de valores int y long escritos como literales enteros decimales sea el m5nimo posible, existen las dos reglas siguientesG Cuando aparece un literal entero decimal Odeci%al-inte&er-literalR con el valor 214*483#48 O231R y sin su0i$o de tipo entero Ointe&er-t#pe-s ffi2R como el s5mbolo Oto6enR inmediatamente posterior a un s5mbolo de operador unario menos O[*.#.2R, el resultado es una constante de tipo int con el valor Y214*483#48 OY231R. En todas las dem(s situaciones, un literal entero decimal Odeci%al-inte&er-literalR de estas caracter5sticas es de tipo uint. Cuando aparece un literal entero decimal Odeci%al-inte&er-literalR con el valor +2233*2"3#8 4** 8"8 O2#3R y sin su0i$o de tipo entero Ointe&er-t#pe-s ffi2R o con el su0i$o de tipo entero L o l como to6en inmediatamente posterior de un to6en de operador unario menos O[*.#.2R, el resultado es una constante de tipo long con el valor Y+2233*2"3#8 4** 8"8 OY2#3R. En todas las dem(s situaciones, un literal entero decimal Odeci%al-inte&er-literalR de estas caracter5sticas es de tipo ulong.

2.4.4.3 *iterales reales 8os literales reales permiten escribir valores de los tipos -loat, double y decimal. real-literal1 deci%al-di&its . deci%al-di&its e2ponent-partopt real-t#pe-s ffi2opt . deci%al-di&its e2ponent-partopt real-t#pe-s ffi2opt deci%al-di&its e2ponent-part real-t#pe-s ffi2opt deci%al-di&its real-t#pe-s ffi2 e2ponent-part1 e si&nopt deci%al-di&its ) si&nopt deci%al-di&its si&n1 no de
< V = 6 d M m

real-t#pe-s ffi21 no de .i no se especi0ica el su0i$o de tipo real Oreal-t#pe-s ffi2R, el tipo del literal real es double. 2e lo contrario, el su0i$o de tipo real determina el tipo del literal real, como sigueG 7n literal real con el su0i$o V o - es de tipo -loat. 'or e$emplo, los literales 2-, 2.K-, 2e23- y 289.JKXV son de tipo -loat. 7n literal real con el su0i$o 6 o d es de tipo double. 'or e$emplo, los literales 2d, 2.Kd, 2e23d y 289.JKX6 son de tipo double.

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

#!

Especificacin del lenguaje C#

7n literal real con el su0i$o M o m es de tipo decimal. 'or e$emplo, los literales 2m, 2.Km, 2e23m y 289.JKXM son de tipo decimal. Este literal se convierte en un valor decimal tomando el valor exacto y, si es necesario, redondeando al valor m(s cercano ?ue se pueda representar mediante el redondeo de banca O[4.1.*R. .e conserva cual?uier escala ?ue se detecte en el literal, salvo ?ue el valor est) redondeado o sea cero Oen este caso, el signo y la escala son "R. 'or lo tanto, el an(lisis del literal 8.L33m se interpreta para 0ormar un decimal con signo 3, coe0iciente 8L33 y escala 9.

.i el literal especi0icado no puede representarse en el tipo indicado, se produce un error en tiempo de compilaci-n. El valor de un literal real de tipo -loat o double se determina mediante el uso del modo Predondeo al m(s cercanoQ de !EEE. Tenga en cuenta ?ue, en un literal real, siempre son necesarios d5gitos decimales tras el punto decimal. 'or e$emplo, 2.9V es un literal real pero 2.V no lo es. 2.4.4.4 *iterales de carcter 7n literal de car(cter representa un car(cter Hnico y normalmente est( compuesto por un car(cter entre comillas, como por e$emplo WaW. character-literal1 W character W character1 sin&le-character si%ple-escape-se6 ence he2adeci%al-escape-se6 ence nicode-escape-se6 ence sin&le-character1 C al6 ier car,cter e2ceptoW 4;<338M5, Z 4;<33KC5 # n new-line-character 4car,cter de n eva l*neaR si%ple-escape-se6 ence1 no de
ZW Z" ZZ Z3 Za Zb ZZn Zr Zt Zv

he2adeci%al-escape-se6 ence1 Z# he2-di&it he2-di&itopt he2-di&itopt he2-di&itopt Todo car(cter ?ue siga a un car(cter de barra diagonal OZR en un car(cter OcharacterR debe ser uno de los siguientes caracteresG W, ", Z, 3, a, b, -, n, r, t, u, ;, #, v. En caso contrario, se producir( un error en tiempo de compilaci-n. 7na secuencia de escape =exadecimal representa un solo car(cter 7nicode cuyo valor est( 0ormado por el nHmero =exadecimal ?ue siga a PZ#Q. .i el valor representado por un literal de car(cter es mayor ?ue ;<VVVV, se produce un error en tiempo de compilaci-n. 7na secuencia de escape de caracteres 7nicode O[2.4.1R en un literal de caracteres debe estar comprendido en el intervalo de ;<3333 a ;<VVVV. 7na secuencia de escape sencilla representa una codi0icaci-n de caracteres 7nicode, como se describe en la tabla in0erior.

#6

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

3ecuencia de escape
ZW Z" ZZ Z3 Za Zb ZZn Zr Zt Zv

4o)bre del car cter Comilla simple Comilla doble Aarra invertida 4ulo &lerta ;etroceso &vance de p(gina 4ueva l5nea ;etorno de carro Tabulaci-n =ori1ontal Tabulaci-n vertical

Codificacin 5nicode
3#338M 3#3388 3#33KC 3#3333 3#333M 3#333Y 3#333C 3#333' 3#3336 3#333L 3#333:

El tipo de un literal de caracteres Ocharacter-literalR es c"ar. 2.4.4. *iterales de cadena C# admite dos 0ormatos de literales de cadena8 literales de cadena reg!lares y literales de cadena te.t!ales. 7n literal de cadena regular consta de cero o m(s caracteres entre comillas dobles Ocomo en ^"ello^R y puede incluir secuencias de escape sencillas Ocomo Zt para el car(cter de tabulaci-nR y secuencias de escape =exadecimales y 7nicode. 7n literal de cadena textual consta de un car(cter [ seguido de un car(cter de comillas dobles, cero o m(s caracteres y un car(cter de comillas dobles de cierre. 7n e$emplo sencillo puede ser [""ello". En un literal de cadena textual, los caracteres comprendidos entre los delimitadores se interpretan de manera literal, siendo la Hnica excepci-n una secuencia de escape comillas O6 ote-escape-se6 enceR. En concreto, las secuencias de escape sencillas, las secuencias de escape =exadecimales y 7nicode no se procesan en los literales de cadena textuales. 7n literal de cadena textual puede estar en varias l5neas. strin&-literal1 re& lar-strin&-literal ver-ati%-strin&-literal re& lar-strin&-literal1 " re& lar-strin&-literal-charactersopt " re& lar-strin&-literal-characters1 re& lar-strin&-literal-character re& lar-strin&-literal-characters re& lar-strin&-literal-character

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

#(

Especificacin del lenguaje C#

re& lar-strin&-literal-character1 sin&le-re& lar-strin&-literal-character si%ple-escape-se6 ence he2adeci%al-escape-se6 ence nicode-escape-se6 ence sin&le-re& lar-strin&-literal-character1 C al6 ier car,cter e2cepto" 4;<33885, Z 4;<33KC5 # n new-line-character 4car,cter de n eva l*neaR ver-ati%-strin&-literal1 [" ver-ati% -strin&-literal-charactersopt " ver-ati%-strin&-literal-characters1 ver-ati%-strin&-literal-character ver-ati%-strin&-literal-characters ver-ati%-strin&-literal-character ver-ati%-strin&-literal-character1 sin&le-ver-ati%-strin&-literal-character 6 ote-escape-se6 ence sin&le-ver-ati%-strin&-literal-character1 C al6 ier car,cter e2cepto " 6 ote-escape-se6 ence1
""

Todo car(cter ?ue siga a un car(cter de barra diagonal OZR en un car(cter literal de cadena regular Ore& larstrin&-literal-characterR debe ser uno de los siguientes caracteresG W, ", Z, 3, a, b, -, n, r, t, u, ;, #, v. En caso contrario, se producir( un error en tiempo de compilaci-n. El e$emplo
string a + ""ello ,orld"; string b + [""ello ,orld"; string c + ""ello Zt ,orld"; string d + [""ello Zt ,orld"; string e + "]oe said Z"HelloZ" to me"; string - + ["]oe said ""Hello"" to me"; .. "ello .. "ello ,orld ,orld

.. "ello ,orld .. "ello Zt ,orld .. ]oe said "Hello" to me .. ]oe said "Hello" to me

string g + "ZZZZserverZZs"areZZ-ile.t#t"; .. ZZserverZs"areZ-ile.t#t string " + ["ZZserverZs"areZ-ile.t#t"; .. ZZserverZs"areZ-ile.t#t string i + "oneZrZnt,oZrZnt"ree"; string j + ["one t,o t"ree";

muestra varios literales de cadena. El Hltimo literal de cadena, j, es un literal de cadena textual ?ue ocupa varias l5neas. 8os caracteres encerrados entre comillas, incluidos los espacios en blanco Opor e$emplo, caracteres de nueva l5neaR, se conservan literalmente. 'uesto ?ue una secuencia de escape =exadecimal puede tener un nHmero variable de d5gitos =exadecimales, el literal de cadena "Z#289" contiene un solo car(cter con un valor =exadecimal de 123. 'ara crear una cadena ?ue contenga el car(cter con el valor =exadecimal 12 seguido del car(cter 3, se podr5a escribir "Z#33289" o "Z #28" < "9" en su lugar. El tipo de un literal de cadena Ostrin&-literalR es string.

#$

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

Cada literal de cadena no genera necesariamente una nueva instancia de cadena. Cuando aparecen dos o m(s literales de cadena e?uivalentes segHn el operador de igualdad de cadenas O[*.+.*R en el mismo programa, estos literales se re0ieren a la misma instancia de cadena. 'or e$emplo, el resultado del programa
class 1est { static void Main() { object a + ""ello"; object b + ""ello"; System.Console.WriteLine(a ++ b); ! !

es 1rue por?ue los dos literales =acen re0erencia a la misma instancia de cadena. 2.4.4.6 &l literal null n ll-literal1
null

n ll-literal se puede convertir de manera impl5cita en un tipo de re0erencia o un tipo ?ue acepta valores 4788. 2.!.# ,peradores y signos de puntuacin Existen varias clases de operadores y signos de puntuaci-n. 8os operadores se utili1an en las expresiones para describir operaciones ?ue implican uno o m(s operandos. 'or e$emplo, la expresi-n a < b usa el operador < para sumar los dos operandos, a y b. 8os signos de puntuaci-n permiten agrupar y separar. operator-or-p nct ator1
{ < + =E F+ ! = D ++ H+ 4 > E @+ G+

no de
5 . 7 D+ DD ( B 77 E+ DD+ ) F // <+ +E . H << =+ G == >+ / @ FF .+ ; A HH B+

ri&ht-shift1 E=E ri&ht-shift-assi&n%ent1 E=E+ 8a barra vertical en las producciones de despla1amiento a la derec=a Ori&ht-shiftR y de asignaci-n de despla1amiento a la derec=a Ori&ht-shift-assi&n%entR, al contrario de lo ?ue ocurre con otras producciones en la gram(tica sint(ctica, no se puede insertar ningHn tipo de caracteres Oni si?uiera espacios en blancoR entre s5mbolos Oto6enR. Estas producciones se tratan de manera especial para permitir el correcto control de t#pepara%eter-lists O[1".1.3R.

2.# /irecti as de preprocesamiento


8as directivas de preprocesamiento o0recen la capacidad de omitir condicionalmente secciones de los arc=ivos de c-digo 0uente, con el 0in de noti0icar errores y advertencias, as5 como de delimitar regiones caracter5sticas del c-digo 0uente. El t)rmino Pdirectivas de preprocesamientoQ se utili1a por motivos de co=erencia con los lengua$es de programaci-n C y CSS. En C#, no existe un paso de preprocesamiento individualV las directivas de preprocesamiento se procesan como parte de la 0ase de an(lisis l)xico.

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

#"

Especificacin del lenguaje C#

pp-directive1 pp-declaration pp-conditional pp-line pp-dia&nostic pp-re&ion pp-pra&%a & continuaci-n se indican las directivas de preprocesamiento disponiblesG
0de-ine y 0unde-, ?ue permiten de0inir y anular, respectivamente, s5mbolos de compilaci-n condicional

O[2. .3R.
0i-, 0eli-, 0else, y 0endi-, para omitir de 0orma condicional secciones de arc=ivos de c-digo 0uente

O[2. .4R.
0line, ?ue permite controlar nHmeros de l5nea de errores y advertencias O[2. .*R. 0error y 0,arning, ?ue permiten emitir errores y advertencias, respectivamente O[2. . R. 0region y 0endregion, para marcar de 0orma expl5cita secciones del c-digo 0uente O[2. .#R. 0&ragma, ?ue se utili1a para especi0icar in0ormaci-n contextual opcional en el compilador O[2. .8R.

7na directiva de preprocesamiento siempre ocupa una l5nea independiente del c-digo 0uente y siempre empie1a por un car(cter 0 y un nombre de directiva de preprocesamiento. 'uede =aber un espacio en blanco antes del car(cter 0 y entre )ste y el nombre de la directiva. 7na l5nea del c-digo 0uente ?ue contiene una directiva 0de-ine, 0unde-, 0i-, 0eli-, 0else, 0endi- o 0line puede terminar con un comentario de una sola l5nea. 8os comentarios delimitados Oel estilo de comentarios .> >.R no est(n permitidos en las l5neas de c-digo 0uente ?ue contienen directivas de preprocesamiento. 8as directivas de preprocesamiento no son s5mbolos Oto6ensR y no 0orman parte de la gram(tica sint(ctica de C#. 4o obstante, las directivas de preprocesamiento pueden utili1arse para incluir o excluir secuencias de to6ens y, de esta 0orma, pueden a0ectar al signi0icado de un programa de C#. 'or e$emplo, una ve1 compilado, el programaG
0de-ine ' 0unde- : class C { 0i- ' void V() {! 0else void S() {! 0endi0i- : void H() {! 0else void $() {! 0endi!

produce como resultado exactamente la misma secuencia de to6ens ?ue el programaG

!'

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases class C { void V() {! void $() {! !

'or lo tanto, aun?ue los dos programas sean muy di0erentes l)xicamente, sint(cticamente son id)nticos. 2.#.1 42mbolos de compilacin condicional 8a compilaci-n condicional ?ue suministran 0uncionalmente las directivas 0i-, 0eli-, 0else, y 0endi- se controla mediante expresiones de preprocesamiento O[2. .2R y s5mbolos de compilaci-n condicional. conditional-s#%-ol1 C al6 ier identificador o pala-ra clave 4identifier-or-3e#word5 e2cepto true o -alse 7n s5mbolo de compilaci-n condicional tiene dos estados posiblesG definido o no definido. &l principio del procesamiento l)xico de un arc=ivo de c-digo 0uente, un s5mbolo de compilaci-n condicional tiene el estado no de0inido, a menos ?ue =aya sido de0inido de 0orma expl5cita por un mecanismo externo Ocomo una opci-n del compilador de la l5nea de comandosR. Cuando se procesa una directiva 0de-ine, el s5mbolo de compilaci-n condicional nombrado en la directiva ?ueda de0inido en el arc=ivo de c-digo 0uente. El s5mbolo permanece de0inido =asta ?ue se procesa una directiva 0unde- del mismo s5mbolo o =asta ?ue se llega al 0inal del arc=ivo de c-digo 0uente. 7na de las implicaciones es ?ue las directivas 0de-ine y 0unde- de un arc=ivo de c-digo 0uente no surten e0ecto en otros arc=ivos de c-digo 0uente del mismo programa. Cuando se =ace re0erencia a un s5mbolo de compilaci-n condicional de0inido en una expresi-n de preprocesamiento, )ste ad?uiere el valor booleano true, y un s5mbolo de compilaci-n condicional no de0inido tiene el valor booleano -alse. 4o es necesario ?ue los s5mbolos de compilaci-n condicional se declaren expl5citamente antes de ?ue se =aga re0erencia a ellos en expresiones de preprocesamiento. En lugar de ello, los s5mbolos no declarados simplemente no se de0inen y, por lo tanto, tienen el valor -alse. El espacio de nombres de los s5mbolos de compilaci-n condicional es Hnico y exclusivo de todas las dem(s entidades con nombre de un programa de C#. .-lo puede =acerse re0erencia a los s5mbolos de compilaci-n condicional en directivas 0de-ine y 0unde- y en expresiones de preprocesamiento. 2.#.2 E"presiones de preprocesamiento 8as expresiones de preprocesamiento pueden encontrarse en las directivas 0i- y 0eli-. En las expresiones de preprocesamiento se permiten los operadores @, ++, @+, FF y HH, adem(s de los par)ntesis, empleados para agrupar. pp-e2pression1 whitespaceopt pp-or-e2pression whitespaceopt pp-or-e2pression1 pp-and-e2pression pp-or-e2pression whitespaceopt HH whitespaceopt pp-and-e2pression pp-and-e2pression1 pp-e6 alit#-e2pression pp-and-e2pression whitespaceopt FF whitespaceopt pp-e6 alit#-e2pression pp-e6 alit#-e2pression1 pp- nar#-e2pression pp-e6 alit#-e2pression whitespaceopt ++ whitespaceopt pp- nar#-e2pression pp-e6 alit#-e2pression whitespaceopt @+ whitespaceopt pp- nar#-e2pression

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

!1

Especificacin del lenguaje C#

pp- nar#-e2pression1 pp-pri%ar#-e2pression @ whitespaceopt pp- nar#-e2pression pp-pri%ar#-e2pression1


true -alse

conditional-s#%-ol ( whitespaceopt pp-e2pression whitespaceopt ) Cuando se =ace re0erencia a un s5mbolo de compilaci-n condicional de0inido en una expresi-n de preprocesamiento, )ste ad?uiere el valor booleano true, y un s5mbolo de compilaci-n condicional no de0inido tiene el valor booleano -alse. 8a evaluaci-n de una expresi-n de preprocesamiento siempre produce un valor booleano. 8as reglas de evaluaci-n de una expresi-n de preprocesamiento son las mismas ?ue las de una expresi-n constante O[*.18R, excepto en ?ue las Hnicas entidades de0inidas por el usuario a las ?ue puede =acerse re0erencia son s5mbolos de compilaci-n condicional. 2.#.3 /irecti as de declaracin 8as directivas de declaraci-n permiten de0inir o anular la de0inici-n de s5mbolos de compilaci-n condicional. pp-declaration1 whitespaceopt 0 whitespaceopt de-ine whitespace conditional-s#%-ol pp-new-line whitespaceopt 0 whitespaceopt unde- whitespace conditional-s#%-ol pp-new-line pp-new-line1 whitespaceopt sin&le-line-co%%entopt new-line El procesamiento de una directiva 0de-ine causa la de0inici-n del s5mbolo de compilaci-n condicional dado, empe1ando en la l5nea del c-digo 0uente ?ue sigue a la directiva. 2e igual manera, el procesamiento de una directiva 0unde- causa la eliminaci-n de la de0inici-n del s5mbolo de compilaci-n condicional dado, empe1ando en la l5nea del c-digo 0uente ?ue sigue a la directiva. Todas las directivas 0de-ine y 0unde- de un arc=ivo de c-digo 0uente deben aparecer antes del primer s5mbolo Oto3enR O[2.4R en el arc=ivo de c-digo 0uenteV de lo contrario, se producir( un error en tiempo de compilaci-n. En t)rminos intuitivos, las directivas 0de-ine y 0unde- deben preceder a cual?uier Pc-digo realQ en el arc=ivo de c-digo 0uente. El e$emploG
0de-ine )nter&rise 0i- *ro-essional HH )nter&rise 0de-ine 'dvanced 0endinames&ace Megacor&.6ata { 0i- 'dvanced class *ivot1able {...! 0endi!

es v(lido por?ue las directivas 0de-ine preceden al primer s5mbolo Oto6enR Ola palabra clave names&aceR en el arc=ivo de c-digo 0uente. El siguiente e$emplo dar5a como resultado un error en tiempo de compilaci-n por?ue en )l =ay una directiva 0de-ine despu)s del c-digo realG

!2

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases 0de-ine ' names&ace N { 0de-ine : 0i- : class Class2 {! 0endi!

'uede utili1arse 0de-ine para de0inir un s5mbolo de compilaci-n condicional ?ue ya est) de0inido, sin necesidad de ?ue intervenga ningHn s5mbolo 0unde- para ello. El e$emplo siguiente de0ine un s5mbolo de compilaci-n condicional ' y despu)s lo de0ine otra ve1.
0de-ine ' 0de-ine ' 0unde- puede Panular la de0inici-nQ de un s5mbolo de compilaci-n condicional ?ue no est) de0inido. En el siguiente e$emplo se de0ine un s5mbolo de compilaci-n condicional ' para despu)s eliminar dic=a de0inici-n dos vecesV el segundo 0unde-, pese a no surtir ningHn e0ecto, sigue siendo v(lido. 0de-ine ' 0unde- ' 0unde- '

2.#.! /irecti as de compilacin condicional 8as directivas de compilaci-n condicional permiten incluir o excluir de 0orma condicional partes de un arc=ivo de c-digo 0uente. pp-conditional1 pp-if-section pp-elif-sectionsopt pp-else-sectionopt pp-endif pp-if-section1 whitespaceopt 0 whitespaceopt i- whitespace pp-e2pression pp-new-line conditionalsectionopt pp-elif-sections1 pp-elif-section pp-elif-sections pp-elif-section pp-elif-section1 whitespaceopt 0 whitespaceopt eli- whitespace pp-e2pression pp-new-line conditionalsectionopt pp-else-section1 whitespaceopt 0 whitespaceopt else pp-new-line conditional-sectionopt pp-endif1 whitespaceopt 0 whitespaceopt endi- pp-new-line conditional-section1 inp t-section s3ipped-section s3ipped-section1 s3ipped-section-part s3ipped-section s3ipped-section-part s3ipped-section-part1 s3ipped-charactersopt new-line pp-directive

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

!3

Especificacin del lenguaje C#

s3ipped-characters1 whitespaceopt not-n %-er-si&n inp t-charactersopt not-n %-er-si&n1 C al6 ier car,cter de entrada 4inp t-character5 e2cepto 0 Como indica la sintaxis, las directivas de compilaci-n condicional deben escribirse como con$untos 0ormados por Oen este ordenRG una directiva 0i-, cero o m(s directivas 0eli-, cero o m(s directivas 0else y una directiva 0endi-. Entre las directivas se encuentran secciones condicionales de c-digo 0uente. Cada secci-n est( controlada por la directiva inmediatamente precedente. 7na secci-n condicional puede contener directivas de compilaci-n condicional anidadas a condici-n de ?ue dic=as directivas 0ormen con$untos completos. 7na condicional pp Opp-conditionalR selecciona como muc=o una de las secciones condicionales OconditionalsectionsR contenidas para el procesamiento l)xico normalG 8as expresiones pp Opp-e2pressionR de las directivas 0i- y 0eli- se evalHan por orden =asta ?ue una produce un resultado true. .i una expresi-n produce true, se selecciona la secci-n condicional Oconditional-sectionR de la directiva correspondiente. .i el resultado de todas las expresiones pp Opp-e2pressionR es -alse, y si =ay presente una directiva 0else, se selecciona la secci-n condicional Oconditional-sectionR de la directiva 0else. En caso contrario, no se selecciona la secci-n condicional Oconditional-sectionR.

8a secci-n condicional seleccionada, si existe, se procesa como una secci-n entrada Oinp t-sectionR normalG el c-digo 0uente de la secci-n debe cumplir la gram(tica l)xicaV se generan s5mbolos Oto6ensR a partir de dic=o c-digo y las directivas de preprocesamiento de la secci-n tienen los e0ectos prescritos. 8as secciones condicionales restantes Oconditional-sectionsR, si existen, se procesan como secciones omitidas Os3ipped-sectionsRG excepto en lo ?ue respeta a las directivas de preprocesamiento, el c-digo 0uente de la secci-n no tiene por ?u) cumplir la gram(tica l)xicaV no se generan to6ens a partir del c-digo 0uente de la secci-nV y las directivas de preprocesamiento de la secci-n deben ser l)xicamente correctas, pero en caso contrario no se procesan. 2entro de una secci-n condicional Oconditional-sectionR ?ue se =a procesado como secci-n omitidaOs3ipped-sectionR, cual?uier secci-n condicional Oconditional-sectionR anidada Ocontenida en construcciones 0i-...0endi- y 0region...0endregion anidadasR tambi)n se procesa como secci-n omitida Os3ipped-sectionR. En el e$emplo siguiente se ilustra c-mo pueden anidarse directivas de compilaci-n condicionalG
0de-ine 6ebug 0unde- 1race .. 6ebugging on .. 1racing o--

class *urc"ase1ransaction { void Commit() { 0i- 6ebug C"ec(Consistency(); 0i- 1race Write1oLog(t"is.1oString()); 0endi0endiCommitHel&er(); ! !

Excepto por las directivas de preprocesamiento, el c-digo 0uente omitido no se somete al an(lisis l)xico. 'or e$emplo, el c-digo siguiente es v(lido, a pesar del comentario sin terminaci-n de la secci-n 0elseG

!#

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases 0de-ine 6ebug .. 6ebugging on

class *urc"ase1ransaction { void Commit() { 0i- 6ebug C"ec(Consistency(); 0else .> 6o somet"ing else 0endi! !

4o obstante, debe tenerse en cuenta ?ue las directivas de preprocesamiento deben ser l)xicamente correctas aun?ue se encuentren en secciones omitidas del c-digo 0uente. 8as directivas de preprocesamiento no se procesan cuando aparecen en elementos de entrada ?ue ocupan varias l5neas. 'or e$emplo, el programaG
class Hello { static void Main() { System.Console.WriteLine([""ello 0i- 6ebug ,orld 0else Nebras(a 0endi"); ! !

da como resultadoG
"ello 0i- 6ebug ,orld 0else Nebras(a 0endi-

En casos concretos, el con$unto de directivas de preprocesamiento ?ue se procesa puede depender de la evaluaci-n de la expresi-n pp Opp-e2pressionR. En el e$emploG
0i- I .> 0else .> >. class ^ { ! 0endi-

se muestra siempre la misma secuencia de to6ens Oclass ^ { !R, independientemente de ?ue I est) de0inido o no. .i I est( de0inido, las Hnicas directivas ?ue se procesan son 0i- y 0endi-, a causa del comentario en varias l5neas. .i I no est( de0inido, las tres directivas O0i-, 0else, 0endi-R 0orman parte del con$unto de directivas. 2.#.# /irecti as de diagnstico 8as directivas de diagn-stico permiten generar de 0orma expl5cita mensa$es de error y advertencias ?ue se noti0ican de la misma manera ?ue otros errores y advertencias en tiempo de compilaci-n. pp-dia&nostic1 whitespaceopt 0 whitespaceopt error pp-%essa&e whitespaceopt 0 whitespaceopt ,arning pp-%essa&e

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

!!

Especificacin del lenguaje C#

pp-%essa&e1 new-line whitespace inp t-charactersopt new-line En el e$emploG


0,arning Code revie, needed be-ore c"ec(=in 0i- 6ebug FF Oetail 0error ' build canWt be bot" debug and retail 0endiclass 1est {...!

se muestra siempre la advertencia OPCode revie9 needed be0ore c=ec6BinQR. &dem(s, si est(n de0inidos los s5mbolos condicionales 6ebug y Oetail, se muestra el error en tiempo de compilaci-n P& build can_t be bot= debug and retailQ. /bserve ?ue en un mensa$e pp Opp-%essa&eR puede especi0icarse cual?uier textoG no es necesario incluir to6ens 0ormados correctamente, como indica el ap-stro0o Ocomilla simpleR de la palabra can_t. 2.#.$ /irecti as de regin 8as directivas de regi-n marcan de 0orma expl5cita regiones del c-digo 0uente. pp-re&ion1 pp-start-re&ion conditional-sectionopt pp-end-re&ion pp-start-re&ion1 whitespaceopt 0 whitespaceopt region pp-%essa&e pp-end-re&ion1 whitespaceopt 0 whitespaceopt endregion pp-%essa&e 4o se asocia ningHn signi0icado sem(ntico a las regionesV los programadores y las =erramientas autom(ticas las utili1an para marcar secciones del c-digo 0uente. El mensa$e especi0icado en una directiva 0region o 0endregion tampoco tiene un signi0icado sem(nticoV sencillamente se usa para identi0icar la regi-n. 8as directivas 0region y 0endregion correspondientes pueden tener mensa$es pp Opp-%essa&eR di0erentes. El procesamiento l)xico de una regi-nG
0region ... 0endregion

se corresponde exactamente con el procesamiento l)xico de una directiva de compilaci-n condicional de la 0ormaG
0i- true ... 0endi-

2.#.+ /irecti as de l2nea 8as directivas de l5nea permiten cambiar los nHmeros de l5nea y los nombres de arc=ivo de c-digo 0uente ?ue comunica el compilador en resultados del tipo de advertencias y errores. 8as directivas de l5nea suelen utili1arse en =erramientas de metaprogramaci-n ?ue generan c-digo 0uente C# a partir de otras entradas de texto. pp-line1 whitespaceopt 0 whitespaceopt line whitespace line-indicator pp-new-line

!6

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

line-indicator1 deci%al-di&its whitespace file-na%e deci%al-di&its


de-ault "idden

file-na%e1 " file-na%e-characters " file-na%e-characters1 file-na%e-character file-na%e-characters file-na%e-character file-na%e-character1 C al6 ier car,cter de entrada 4inp t-character5 e2cepto " Cuando no aparecen directivas 0line, el compilador muestra en su resultado los nHmeros de l5nea y nombres de arc=ivo de c-digo 0uente reales. Cuando se procesa una directiva 0line ?ue incluye un indicador de l5nea OlineindicatorR ?ue no es de-ault, el compilador trata la l5nea si& iente a la directiva como si tuviera el nHmero de l5nea dado Oy el nombre de arc=ivo, si se especi0icaR. 7na directiva 0line de-ault invierte el e0ecto de todas las directivas #line anteriores. El compilador comunica la in0ormaci-n de l5nea real para las l5neas posteriores, exactamente igual ?ue si no se =ubieran procesado directivas 0line. 7na directiva 0line "idden no produce ningHn e0ecto sobre el arc=ivo ni sobre los nHmeros de l5nea de los ?ue se in0orma en los mensa$es de error, pero s5 a0ecta a la depuraci-n en el nivel de c-digo 0uente. 2urante la depuraci-n, las l5neas entre una directiva 0line "idden y la siguiente directiva 0line Ono 0line "iddenR carecer(n de in0ormaci-n de nHmero de l5nea. Cuando se recorre el c-digo en el depurador, estas l5neas se omiten por completo. /bserve ?ue los nombres de arc=ivo Ofile-na%eR se di0erencian de los literales de cadena ordinarios en ?ue los caracteres de escape no se procesanV en los nombres de arc=ivo, el car(cter `Za s-lo designa un car(cter convencional de barra diagonal inversa. 2.#.- /irecti as pragma 8a directiva de preprocesamiento 0&ragma se utili1a para especi0icar in0ormaci-n contextual opcional en el compilador. 8a in0ormaci-n suministrada en una directiva 0&ragma nunca cambiar( la sem(ntica del programa. pp-pra&%a1 whitespaceopt 0 whitespaceopt &ragma whitespace pra&%a--od# pp-new-line pra&%a--od#1 pra&%a-warnin&--od# C# proporciona directivas 0&ragma para controlar advertencias del compilador. Es posible ?ue en 0uturas versiones del lengua$e se incluyan directivas 0&ragma adicionales. 'ara garanti1ar la interoperabilidad con otros compiladores de C#, el compilador de %icroso0t C# no genera errores de compilaci-n para directivas 0&ragma conocidasV sin embargo, dic=as directivas s5 generan advertencias. 2. .+.1 Pra"ma ,arnin" 8a directiva 0&ragma ,arning se utili1a para des=abilitar o restaurar todos los mensa$es de advertencia o un con$unto en particular durante la compilaci-n del texto del programa subsiguiente.

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

!(

Especificacin del lenguaje C#

pra&%a-warnin&--od#1 ,arning whitespace warnin&-action ,arning whitespace warnin&-action whitespace warnin&-list warnin&-action1
disable restore

warnin&-list1 deci%al-di&its warnin&-list whitespaceopt

whitespaceopt deci%al-di&its

7na directiva 0&ragma ,arning ?ue omite la lista de advertencias a0ecta a todas las advertencias. 7na directiva 0&ragma ,arning ?ue incluye una lista de advertencias a0ecta Hnicamente a a?uellas advertencias especi0icadas en la lista. 7na directiva 0&ragma ,arning disable des=abilita todas las advertencias o un con$unto determinado de las mismas. 7na directiva 0&ragma ,arning restore restaura todas las advertencias o un con$unto dado de las mismas al estado en el ?ue se encontraban al inicio de la unidad de compilaci-n. Tenga en cuenta ?ue si una advertencia concreta se des=abilit- externamente, una directiva 0&ragma ,arning restore Opara todas las advertencias o para una espec50icaR no re=abilitar( dic=a advertencia. En el siguiente e$emplo se muestra el uso de 0&ragma ,arning para des=abilitar temporalmente la advertencia noti0icada al =acer re0erencia a miembros obsoletos, con el nHmero de advertencia del compilador de %icroso0t C#.
using System; class *rogram { 4%bsolete5 static void Voo() {! static void Main() { 0&ragma ,arning disable X28 Voo(); 0&ragma ,arning restore X28 ! !

!$

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

3. %onceptos b)sicos
3.1 Inicio de la aplicacin
7na aplicaci,n es un ensamblado ?ue contiene un p!nto de entrada. Cuando se e$ecuta una aplicaci-n, se crea un nuevo do inio de aplicaci,n. 'ueden existir varias creaciones de instancias di0erentes de una aplicaci-n simult(neamente en el mismo e?uipo, cada una con su propio dominio de aplicaci-n. 7n dominio de aplicaci-n =abilita el aislamiento de aplicaciones, al actuar como contenedor del estado de una aplicaci-n. 7n dominio de aplicaci-n se comporta como contenedor y l5mite de los tipos de0inidos en la aplicaci-n y en las bibliotecas de clases ?ue utili1a. 8os tipos cargados en un dominio de aplicaci-n son distintos de los mismos tipos cargados en otro, y las instancias de los ob$etos no se comparten directamente entre dominios de aplicaci-n. 'or e$emplo, cada dominio de aplicaci-n mantiene su propia copia de variables est(ticas para estos tipos, y un constructor est(tico de un tipo se e$ecuta como m(ximo una ve1 por dominio de aplicaci-n. 8as implementaciones tienen libertad para proporcionar mecanismos o directivas espec50icas de la implementaci-n para la creaci-n y destrucci-n de los dominios de aplicaci-n. 7n inicio de progra a se produce cuando el entorno de e$ecuci-n llama a un m)todo designado, ?ue se conoce como punto de entrada de la aplicaci-n. Este m)todo de punto de entrada siempre se denomina Main y puede tener una de las 0irmas siguientesG
static void Main() {...! static void Main(string45 args) {...! static int Main() {...! static int Main(string45 args) {...!

Como se muestra, el punto de entrada de manera opcional puede devolver un valor int. El valor devuelto se utili1a en la 0inali1aci-n de la aplicaci-n O[3.2R. El punto de entrada puede tener, opcionalmente, un par(metro 0ormal. El par(metro puede tener cual?uier nombre, pero el tipo del par(metro debe ser string45. .i el par(metro 0ormal est( presente, el entorno de e$ecuci-n crea y pasa un argumento string45 ?ue contiene los argumentos de l5nea de comandos especi0icados al iniciar la aplicaci-n. El argumento string45 nunca es null, pero puede tener longitud cero si no se encuentra especi0icado ningHn argumento de l5nea de comandos. 2ado ?ue C# acepta la sobrecarga de m)todos, una clase o una estructura puede contener varias de0iniciones del mismo m)todo, a condici-n de ?ue todas tengan una 0irma di0erente. 4o obstante, ninguna clase o estructura de un mismo programa podr( contener m(s de un m)todo denominado Main cuya de0inici-n lo certi0i?ue para ser utili1ado como punto de entrada de aplicaci-n. .in embargo, s5 se permiten otras versiones sobrecargadas de Main, a condici-n de ?ue tengan m(s de un par(metro o de ?ue su Hnico par(metro no sea de tipo string45. 7na aplicaci-n puede estar compuesta por varias clases o estructuras. Es posible para m(s de una de esas clases o estructuras contener un m)todo denominado Main cuya de0inici-n lo certi0ica para ser utili1ado como punto de entrada de la aplicaci-n. En tales casos, debe utili1arse un mecanismo externo Opor e$emplo, una opci-n de compilador de l5nea de comandosR para seleccionar uno de estos m)todos Main como punto de entrada. En C#, todos los m)todos deben estar de0inidos como miembros de una clase o una estructura. 4ormalmente, la accesibilidad declarada O[3. .1R de un m)todo est( determinada por los modi0icadores de acceso O[1".3. R especi0icados en su declaraci-n y, de 0orma similar, la accesibilidad declarada de un tipo est( determinada por los modi0icadores de acceso especi0icados en su declaraci-n. 'ara ?ue un m)todo dado de un tipo concreto sea
!"

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Especificacin del lenguaje C#

invocable, tanto el tipo como el miembro deben ser accesibles. 4o obstante, el punto de entrada de la aplicaci-n es un caso especial. En concreto, el entorno de e$ecuci-n puede tener acceso al punto de entrada de la aplicaci-n con independencia de su accesibilidad declarada y de la accesibilidad declarada de sus declaraciones de tipo envolvente. Es posible ?ue el m)todo de punto de entrada de la aplicaci-n no se encuentre dentro de una declaraci-n de clase gen)rica. & todos los dem(s respectos, los m)todos de punto de entrada se comportan como los de punto de no entrada.

3.2 7inali8acin de la aplicacin


8a finali-aci,n de la aplicaci,n devuelve el control al entorno de e$ecuci-n. .i el tipo del valor devuelto por el m)todo de punto de entrada de la aplicaci-n es int, el valor devuelto cumple la 0unci-n de cdigo de estado de finali6acin de la misma. El prop-sito de este c-digo es permitir la comunicaci-n del )xito o el error al entorno de e$ecuci-n. .i el tipo del valor devuelto del m)todo de punto de entrada es void, cuando se alcan1a la llave de cierre O!R, ?ue 0inali1a el m)todo, o cuando se e$ecuta una instrucci-n return ?ue no contiene una expresi-n, se produce un c-digo de estado de 0inali1aci-n igual a 3. &ntes de la 0inali1aci-n de una aplicaci-n, se llama a destructores para todos los ob$etos ?ue aHn no =ayan sido sometidos a la recolecci-n de elementos no utili1ados Osalvo ?ue se =aya suprimido este tipo de limpie1a mediante, por e$emplo, una llamada al m)todo de biblioteca SC.Su&&ressVinali?eR.

3.3 /eclaraciones
8as declaraciones de un programa de C# de0inen los elementos constituyentes del programa. 8os programas de C# se organi1an mediante el uso de espacios de nombres O[+R, ?ue pueden contener declaraciones de tipo y declaraciones de espacio de nombres anidadas. 8as declaraciones de tipo O[+.#R se utili1an para de0inir clases O[1"R, estructuras O[1".14R, inter0aces O[13R, enumeraciones O[14R y delegados O[1 R. 8as categor5as de los miembros permitidos en una declaraci-n de tipo dependen de la 0orma de la declaraci-n. 'or e$emplo, las declaraciones de clase pueden contener declaraciones para las constantes O[1".4R, campos O[1". R, m)todos O[1".#R, propiedades O[1".*R, eventos O[1".8R, indi1adores O[1".+R, operadores O[1".1"R, constructores de instancia O[1".11R, constructores est(ticos O[1".12R, destructores O[1".13R y tipos anidados. 7na declaraci-n de0ine un nombre en el espacio de declaraci-n Odeclaration spaceR al ?ue pertenece la declaraci-n. Con la excepci-n de los miembros sobrecargados O[3.#R, es un error en tiempo de compilaci-n contar con dos o m(s declaraciones ?ue introducen miembros con el mismo nombre en un espacio de declaraci-n. 4o est( permitido ?ue un espacio de declaraci-n contenga categor5as de miembros di0erentes con el mismo nombre. 'or e$emplo, un espacio de declaraci-n no puede contener un campo y un m)todo con el mismo nombre. Existen varios tipos di0erentes de espacios de declaraci-n, como se explica a continuaci-n. 2entro de todos los arc=ivos de c-digo 0uente de un programa, las declaraciones de miembros de espacios de nombres Ona%espace-%e%-er-declarationsR sin una declaraci-n de espacio de nombres envolvente son miembros de un solo espacio de declaraci-n combinado, denominado espacio de declaraci-n global Oglo/al declaration spaceR. 2entro de todos los arc=ivos de c-digo 0uente de un programa, las declaraciones de miembros de espacios de nombres Ona%espace-%e%-er-declarationsR de las declaraciones de espacio de nombres Ona%espacedeclarationsR ?ue tienen el mismo nombre completo del espacio de nombres son miembros de un solo espacio de declaraci-n combinado.

6'

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

Cada declaraci-n de clase, estructura o inter0a1 crea un nuevo espacio de declaraci-n. 8os nombres se introducen en este espacio de declaraci-n mediante declaraciones de miembros de clase Oclass-%e%-erdeclarationsR, declaraciones de miembros de estructura Ostr ct-%e%-er-declarationsR, declaraciones de miembros de inter0a1 Ointerface-%e%-er-declarationsR o par(metros de tipo t#pe-para%eters. Excepto en las declaraciones de constructores de instancia y declaraciones de constructor est(tico sobrecargadas, una clase o estructura no puede contener una declaraci-n de miembro con el mismo nombre ?ue la clase o la estructura. 7na clase, estructura o inter0a1 permite la declaraci-n de m)todos e indi1adores sobrecargados. &simismo, las clases y estructuras admiten la declaraci-n de operadores y constructores de instancia sobrecargados. 'or e$emplo, una clase, una estructura o una inter0a1 pueden contener varias declaraciones de m)todo con el mismo nombre, a condici-n de ?ue dic=as declaraciones di0ieran en su 0irma O[3.#R. 2ebe tenerse en cuenta ?ue las clases base no contribuyen al espacio de declaraci-n de una clase, y ?ue las inter0aces base no contribuyen al espacio de declaraci-n de una inter0a1. 'or lo tanto, una clase o inter0a1 derivada tiene permitido declarar un miembro con el mismo nombre ?ue un miembro =eredado. .e dice ?ue un miembro como )ste oc!lta al miembro =eredado. 7na declaraci-n de delegado crea un espacio de declaraci-n nuevo. 8os nombres se introducen en este espacio de declaraci-n a trav)s de par(metros 0ormales Opar,%etros de tipo fi>ado y %atrices de par,%etrosR y par,%etros de tipo. 7na declaraci-n de enumeraci-n crea un espacio de declaraci-n nuevo. 8os nombres se introducen en este espacio de declaraci-n mediante declaraciones de miembros de enumeraci-n Oen %-%e%-er-declarationsR. Cada declaraci-n de m)todo, declaraci-n de indi1ador, declaraci-n de operador, declaraci-n de constructor de instancia y 0unci-n an-nima crea un nuevo espacio de declaraci-n denominado espacio de declaraci,n de la varia/le local. 8os nombres se introducen en este espacio de declaraci-n a trav)s de par(metros 0ormales Opar,%etros de tipo fi>ado y %atrices de par,%etrosR y par,%etros de tipo. El cuerpo del miembro de 0unci-n o de la 0unci-n an-nima, si existe, se considera anidado dentro del espacio de declaraci-n de la variable local. bue el espacio de declaraci-n de una variable local y el espacio de declaraci-n de una variable local anidado contengan elementos con el mismo nombre supone un error. 'or lo tanto, dentro de un espacio de declaraci-n anidado no es posible declarar una variable o constante local con el mismo nombre ?ue una variable o constante local contenida en un espacio de declaraci-n. Es posible ?ue dos espacios de declaraci-n contengan elementos con el mismo nombre siempre y cuando ninguno de los espacios de declaraci-n contenga al otro. Cada -lo6 e o blo?ue s9itc= Oswitch--loc3R, as5 como una instrucci-n for, foreach y sin&, crea un espacio de declaraci-n de la variable local para variables y constantes locales. 8os nombres se introducen en este espacio de declaraci-n mediante declaraciones de variable local Olocal-varia-le-declarationsR y declaraciones de constante local Olocal-constant-declarationsR. Tenga en cuenta ?ue los blo?ues ?ue tienen lugar como o dentro del cuerpo de un miembro de 0unci-n o una 0unci-n an-nima se anidan dentro del espacio de declaraci-n de la variable local declarado por a?uellas 0unciones para sus par(metros. bue, por e$emplo, un m)todo con una variable local y un par(metro tengan el mismo nombre supone un error. Cada blo?ue O-loc3R o blo?ue s9itc= Oswitch--loc3R crea un espacio de declaraci-n independiente para las eti?uetas. 8os nombres se introducen en este espacio de declaraci-n mediante instrucciones con eti?uetas Ola-eled-state%entsR y se =ace re0erencia a ellos mediante instrucciones goto O&oto-state%entsR. El espacio de declaraci,n de eti"!etas de un blo?ue incluye blo?ues anidados. 'or lo tanto, dentro de un blo?ue anidado no es posible declarar una eti?ueta del mismo nombre ?ue una eti?ueta contenida en un blo?ue contenedor.

El orden textual de declaraci-n de los nombres generalmente carece de importancia. &s5, el orden textual no resulta signi0icativo para la declaraci-n o el uso de espacios de nombres, constantes, m)todos, propiedades, eventos, indi1adores, operadores, constructores de instancia, destructores, constructores est(ticos o tipos. El orden de declaraci-n es signi0icativo de las siguientes 0ormasG

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

61

Especificacin del lenguaje C#

El orden de declaraci-n de las declaraciones de campos y de variables locales determina el orden en ?ue se e$ecutan sus iniciali1adores Osi existenR. 8as variables locales no se pueden utili1ar antes de su de0inici-n O[3.*R. El orden de declaraci-n para las declaraciones de miembros de enumeraci-n O[14.3R es importante cuando se omiten los valores de expresi-n constante Oconstant-e2pressionR.

El espacio de declaraci-n de un espacio de nombres es Pde extremo abiertoQ, es decir, dos declaraciones de espacio de nombres con un mismo nombre completo contribuir(n al mismo espacio de declaraci-n. 'or e$emploG
names&ace Megacor&.6ata { class Customer { ... ! ! names&ace Megacor&.6ata { class %rder { ... ! !

8as dos declaraciones de espacios de nombres anteriores contribuyen al mismo espacio de declaraci-n, en este caso declarando dos clases con los nombres completos Megacor&.6ata.Customer y Megacor&.6ata.%rder. Como las dos declaraciones contribuyen al mismo espacio de declaraci-n, si cada una contiene una declaraci-n de clase con el mismo nombre se producir( un error en tiempo de compilaci-n. Como se especi0ic- anteriormente, el espacio de declaraci-n de un blo?ue incluye cual?uier blo?ue anidado. 2e este modo, en el siguiente e$emplo, los m)todos V y S producen errores en tiempo de compilaci-n por?ue el nombre i est( declarado en el blo?ue exterior y no se puede volver a declarar en el blo?ue interior. .in embargo, los m)todos H e $ son v(lidos por?ue los dos caracteres i se declaran en blo?ues independientes no anidados.
class ' { void V() { int i + 3; i- (true) { int i + 2; ! ! void S() { i- (true) { int i + 3; ! int i + 2; ! void H() { i- (true) { int i + 3; ! i- (true) { int i + 2; ! !

62

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases void $() { -or (int i + 3; i D 23; i<<) H(); -or (int i + 3; i D 23; i<<) H(); ! !

3.! &iembros
8os espacios de nombres y los tipos tienen ie /ros. 8os miembros de una entidad est(n generalmente disponibles mediante el uso de un nombre completo compuesto por una re0erencia a la entidad seguida de un to6en P.Q y el nombre del miembro. 8os miembros de un tipo se declaran en la declaraci-n de tipo o se heredan de la clase base del tipo. .i un tipo se deriva de una clase base, todos los miembros de dic=a clase, excepto los constructores de instancia, destructores y constructores est(ticos, pasan a ser miembros del tipo derivado. 8a accesibilidad declarada de un miembro de clase base no controla si el miembro se =eredaG la =erencia se ampl5a a cual?uier miembro ?ue no sea un constructor de instancia, un constructor est(tico o un destructor. 4o obstante, un miembro =eredado puede no estar accesible en un tipo derivado, ya sea a causa de su accesibilidad declarada O[3. .1R o por?ue est( oculto por una declaraci-n del propio tipo O[3.*.1.2R. 3.!.1 &iembros de espacio de nombres 8os espacios de nombres y los tipos ?ue no tienen un espacio de nombres envolvente son miembros del espacio de no /res glo/al. Esto corresponde directamente a los nombres declarados en el espacio de declaraci-n global. 8os espacios de nombres y los tipos declarados en de un espacio de nombres son miembros de dic=o espacio. Esto corresponde directamente a los nombres declarados en el espacio de declaraci-n del espacio de nombres. 8os espacios de nombres no presentan restricciones de acceso. 4o es posible declarar espacios de nombres privados, protegidos o internos, y los nombres de los espacios de nombres siempre son accesibles pHblicamente. 3.!.2 &iembros de estructura 8os miembros de una estructura son los miembros declarados en la estructura y los miembros =eredados de la clase base directa de la estructura System.Ualue1y&e y la clase base indirecta object. 8os miembros de un tipo simple se corresponden directamente con los del tipo de la estructura con alias por el tipo simpleG 8os miembros de sbyte son los miembros de la estructura System.S:yte. 8os miembros de byte son los miembros de la estructura System.:yte. 8os miembros de s"ort son los miembros de la estructura System.$nt2X. 8os miembros de us"ort son los miembros de la estructura System.;$nt2X. 8os miembros de int son los miembros de la estructura System.$nt98. 8os miembros de uint son los miembros de la estructura System.;$nt98. 8os miembros de long son los miembros de la estructura System.$ntXJ. 8os miembros de ulong son los miembros de la estructura System.;$ntXJ. 8os miembros de c"ar son los miembros de la estructura System.C"ar. 8os miembros de -loat son los miembros de la estructura System.Single.
63

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Especificacin del lenguaje C#

8os miembros de double son los miembros de la estructura System.6ouble. 8os miembros de decimal son los miembros de la estructura System.6ecimal. 8os miembros de bool son los miembros de la estructura System.:oolean.

3.!.3 &iembros de enumeraciones 8os miembros de una enumeraci-n son las constantes declaradas en la enumeraci-n y los miembros =eredados de la clase base directa de la enumeraci-n System.)num y las clases base indirectas System.Ualue1y&e y object. 3.!.! &iembros de clase 8os miembros de una clase son a?uellos ?ue se declaran en la clase y los ?ue se =eredan de la clase base Oa excepci-n de la clase object, ?ue no tiene clase baseR. Entre los miembros =eredados de la clase base se incluyen las constantes, los campos, los m)todos, las propiedades, los eventos, los indi1adores, los operadores y los tipos de la clase base, pero no los constructores de instancia, los destructores ni los constructores est(ticos de la clase base. 8os miembros de la base clase se =eredan con independencia de su accesibilidad. 8a declaraci-n de una clase puede contener declaraciones de constantes, campos, m)todos, propiedades, eventos, indi1adores, operadores, constructores de instancia, destructores, constructores est(ticos y tipos. 8os miembros de object y string se corresponden directamente con los miembros de los tipos de clases de los ?ue son aliasG 8os miembros de object son los miembros de la clase System.%bject. 8os miembros de string son los miembros de la clase System.String.

3.!.# &iembros de interfa8 8os miembros de una inter0a1 son los miembros declarados en la inter0a1 y en todas las inter0aces base de la misma. 8os miembros de la clase object no son, estrictamente =ablando, miembros de ninguna inter0a1 O[13.2R. .in embargo, los miembros de la clase object est(n disponibles a trav)s de la bHs?ueda de miembros en cual?uier tipo de inter0a1 O[*.3R. 3.!.$ &iembros de matri8 8os miembros de una matri1 son los miembros =eredados de la clase System.'rray. 3.!.+ &iembros de delegados 8os miembros de un delegado son los miembros =eredados de la clase System.6elegate.

3.# 'cceso a miembros


8as declaraciones a miembros aportan control sobre el acceso a los miembros. 8a accesibilidad de un miembro se establece mediante la accesibilidad declarada O[3. .1R del miembro combinada con la accesibilidad del tipo contenedor inmediato, si existe. Cuando se permite el acceso a un miembro concreto, se dice ?ue )ste es accesi/le. 'or otro lado, cuando no se permite el acceso a un miembro concreto, se dice ?ue )ste es inaccesi/le. El acceso a un miembro est( permitido cuando la ubicaci-n textual en la ?ue tiene lugar el acceso est( incluida en el dominio de accesibilidad O[3. .2R del miembro.

6#

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

3.#.1 'ccesibilidad declarada 8a accesi/ilidad declarada de un miembro puede ser cual?uiera de las siguientesG 'ublic, ?ue se selecciona mediante la inclusi-n de un modi0icador &ublic en la declaraci-n del miembro. El signi0icado intuitivo de &ublic es Pacceso sin restriccionesQ. 'rotected, ?ue se selecciona mediante la inclusi-n de un modi0icador &rotected en la declaraci-n del miembro. El signi0icado intuitivo de &rotected es Pacceso restringido para la clase contenedora o los tipos derivados de ellaQ. !nternal, ?ue se selecciona mediante la inclusi-n de un modi0icador internal en la declaraci-n del miembro. El signi0icado intuitivo de internal es Pacceso restringido al programaQ. 'rotected internal Oes decir, protegida o internaR, ?ue se selecciona mediante la inclusi-n de los modi0icadores &rotected e internal en la declaraci-n del miembro. El signi0icado intuitivo de &rotected internal es Pacceso restringido al programa actual o a los tipos derivados de la clase contenedoraQ. 'rivate, ?ue se selecciona mediante la inclusi-n de un modi0icador &rivate en la declaraci-n del miembro. El signi0icado intuitivo de &rivate es Pacceso restringido al tipo contenedorQ.

.egHn el contexto en el ?ue se produce la declaraci-n de un miembro, s-lo se permite declarar ciertos tipos de accesibilidad. &dem(s, si una declaraci-n del miembro no incluye modi0icadores de acceso, el contexto en ?ue tiene lugar la declaraci-n determina la accesibilidad declarada predeterminada. 8os espacios de nombres tienen impl5citamente la accesibilidad declarada &ublic. 8os modi0icadores de acceso no se pueden utili1ar en las declaraciones de espacios de nombres. 8os tipos declarados en las unidades de compilaci-n o los espacios de nombres pueden tener la accesibilidad declarada &ublic o internal y su valor predeterminado puede ser internal. 8os miembros de clase pueden tener cual?uiera de las cinco clases de accesibilidad declarada y el valor predeterminado de la accesibilidad declarada &rivate. O2ebe tenerse en cuenta ?ue un tipo declarado como miembro de una clase s-lo puede tener una de las cinco clases de accesibilidad declarada, mientras ?ue un tipo declarado como miembro de un espacio de nombres s-lo puede tener la accesibilidad declarada &ublic o internal.R 8os miembros de estructura pueden tener la accesibilidad declarada &ublic, internal o &rivate, siendo el valor predeterminado &rivate, puesto ?ue las estructuras son impl5citamente de tipo sealed. 8os miembros de estructura introducidos en una estructura Oes decir, no =eredados por ellaR no pueden tener una accesibilidad declarada &rotected o &rotected internal. Tenga en cuenta ?ue un tipo declarado como miembro de una estructura accesibilidad declarada &ublic, internal o &rivate, mientras ?ue un tipo declarado como miembro de un espacio de nombres s-lo puede tener la accesibilidad declarada &ublic o internal. 8os miembros de inter0a1 tienen impl5citamente la accesibilidad declarada &ublic. 8os modi0icadores de acceso no se pueden utili1ar en las declaraciones de miembros de inter0a1. 8os miembros de enumeraci-n tienen impl5citamente la accesibilidad declarada &ublic. 8os modi0icadores de acceso no pueden utili1arse en las declaraciones de miembros de enumeraci-n.

3.#.2 /ominios de accesibilidad El do inio de accesi/ilidad de un miembro est( 0ormado por las secciones Oposiblemente separadasR de texto del programa en las ?ue est( permitido el acceso al miembro. 'ara de0inir el dominio de accesibilidad de un miembro, se dice ?ue un miembro es de nivel s!perior si no est( declarado dentro de un tipo, y se dice ?ue est( anidado si se declara dentro de otro tipo. &simismo, el te.to de progra a de un programa se de0ine como todo
Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

6!

Especificacin del lenguaje C#

el texto de programa contenido en todos los arc=ivos de c-digo 0uente. El texto de programa de un tipo se de0ine como todo el texto del programa contenido entre los to6ens de apertura y cierre P{Q y P!Q del cuerpo de clase Oclass--od#R, del cuerpo de estructura Ostr ct--od#R, del cuerpo de inter0a1 Ointerface--od#R o del cuerpo de enumeraci-n Oen %--od#R del tipo Oincluidos, posiblemente, los tipos anidados dentro del tipoR. El dominio de accesibilidad de un tipo prede0inido Ocomo object, int o doubleR es ilimitado. El dominio de accesibilidad de un tipo sin enla1ar de nivel superior 1 O[R declarado en un programa * se de0ine como sigueG 8a accesibilidad declarada de 1 es &ublic, el dominio de accesibilidad de 1 es el texto del programa de * y cual?uier programa ?ue =aga re0erencia a *. .i la accesibilidad declarada de 1 es internal, el dominio de accesibilidad de 1 es el texto del programa de *.

& partir de estas de0iniciones, se deduce ?ue el dominio de accesibilidad de un tipo sin enla1ar de nivel superior es, al menos, el texto del programa en el ?ue se declara ese tipo. El dominio de accesibilidad para un tipo construido 1D'2 ... 'NE es la intersecci-n entre el dominio de accesibilidad del tipo gen)rico sin enla1ar 1 y los dominios de accesibilidad de los argumentos de tipo '2 ... 'N. El dominio de accesibilidad de un miembro anidado M declarado en un tipo 1 dentro de un programa * se de0ine como sigue Oteniendo en cuenta ?ue M probablemente sea un tipoRG .i la accesibilidad declarada de M es &ublic, el dominio de accesibilidad de M es el dominio de 1. .i la accesibilidad declarada de M es &rotected internal, 6 ser( la uni-n del texto del programa de * y del texto del programa de cual?uier tipo derivado de 1, ?ue se declara 0uera de *. El dominio de accesibilidad de M es la intersecci-n del dominio de accesibilidad de 1 con 6. .i la accesibilidad declarada de M es &rotected internal, 6 ser( la uni-n del texto del programa de 1 y del texto del programa de cual?uier tipo derivado de 1. El dominio de accesibilidad de M es la intersecci-n del dominio de accesibilidad de 1 con 6. .i la accesibilidad declarada de M es internal, el dominio de accesibilidad de M es la intersecci-n del dominio de accesibilidad de 1 con el texto de programa de *. .i la accesibilidad declarada de M es &rivate, el dominio de accesibilidad de M es el texto del programa de 1.

2e estas de0iniciones se deduce ?ue el dominio de accesibilidad de un tipo anidado es siempre, al menos, el texto de programa del tipo donde el miembro aparece declarado. &simismo, se concluye ?ue el dominio de accesibilidad de un miembro nunca es m(s inclusivo ?ue el dominio de accesibilidad del tipo en el ?ue se declara el miembro. En t)rminos intuitivos, cuando se obtiene acceso a un tipo o un miembro M, se evalHan los pasos siguientes para garanti1ar ?ue el acceso est) permitidoG En primer lugar, si M se declara dentro de un tipo Opor oposici-n a una unidad de compilaci-n o un espacio de nombresR, se produce un error en tiempo de compilaci-n si el tipo no est( accesible. Entonces, si M es &ublic, el acceso est( permitido. / bien, si M es &rotected internal, el acceso est( permitido si se produce dentro del programa en el ?ue est( declarado M o si se produce dentro de una clase derivada de la clase en la ?ue est( declarado M y tiene lugar por medio del tipo de la clase derivada O[3. .3R.

66

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

/ bien, si M es &rotected, el acceso est( permitido si se produce dentro de la clase en la ?ue est( declarado M o si se produce dentro de una clase derivada de la clase en la ?ue est( declarado M y tiene lugar por medio del tipo de la clase derivada O[3. .3R. / bien, si M es internal, el acceso est( permitido si ocurre dentro del programa en el ?ue est( declarado M. / bien, si M es &rivate, el acceso est( permitido si ocurre dentro del programa en el ?ue est( declarado M. 2e lo contrario, el tipo o el miembro es inaccesible y se produce un error en tiempo de compilaci-n.
&ublic class ' { &ublic static int I; internal static int `; &rivate static int P; ! internal class : { &ublic static int I; internal static int `; &rivate static int P; &ublic class C { &ublic static int I; internal static int `; &rivate static int P; ! &rivate class 6 { &ublic static int I; internal static int `; &rivate static int P; ! !

En el e$emplo

las clases y los miembros tienen los siguientes dominios de accesibilidadG El dominio de accesibilidad de ' y '.I es ilimitado. El dominio de accesibilidad de '.`, :, :.I, :.`, :.C, :.C.I, y :.C.` es el texto del programa contenedor. El dominio de accesibilidad de '.P es el texto del programa de '. El dominio de accesibilidad de :.P y :.6 es el texto de programa de :, incluido el texto de programa de :.C y de :.6. El dominio de accesibilidad de :.C.P es el texto del programa de :.C. El dominio de accesibilidad de :.6.I y :.6.` es el texto de programa de :, incluido el texto de programa de :.C y de :.6. El dominio de accesibilidad de :.6.P es el texto del programa de :.6.

Como muestra el e$emplo, el dominio de accesibilidad de un miembro nunca es mayor ?ue el de un tipo contenedor. 'or e$emplo, aun?ue todos los miembros I tengan una accesibilidad declarada como public, todos excepto '.I tienen dominios de accesibilidad ?ue est(n restringidos por un tipo contenedor.

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

6(

Especificacin del lenguaje C#

Como se explica en la [3.4, todos los miembros de una clase base, a excepci-n de los constructores de instancia, destructores y constructores est(ticos, son =eredados por tipos derivados. Esto incluye incluso a los miembros privados de una clase base. 4o obstante, el dominio de accesibilidad de un miembro privado s-lo incluye el texto del programa del tipo donde el miembro aparece declarado. En el e$emplo
class ' { int #; static void V(: b) { b.# + 2; .. %( ! ! class :/ ' { static void V(: b) { b.# + 2; .. )rror ! !

# not accessible

la clase : =ereda el miembro privado # de la clase '. 2ado ?ue el miembro es privado, s-lo est( accesible dentro del cuerpo de clase Oclass--od#R de '. 'or lo tanto, el acceso a b.# es correcto en el m)todo '.V, pero no en el m)todo :.V. 3.#.3 'cceso protegido para miembros de instancia Cuando se obtiene acceso a un miembro de instancia &rotected 0uera del texto del programa de la clase en la ?ue est( declarado, y cuando se obtiene acceso a un miembro de instancia &rotected internal 0uera del texto del programa en el ?ue est( declarado, el acceso debe tener lugar dentro de una declaraci-n de clase derivada de la clase en la ?ue est( declarada. Es m(s, es necesario ?ue el acceso se produ1ca a trav?s de una instancia de ese tipo de clase derivada o un tipo de clase construido a partir de la misma. Esta restricci-n impide ?ue una clase derivada tenga acceso a miembros protegidos de otras clases derivadas, incluso cuando los miembros son =eredados de la misma clase base. .upongamos ?ue : es una clase base ?ue declara un miembro de instancia M protegido, y ?ue 6 es una clase ?ue se deriva de :. 2entro del cuerpo de clase Oclass--od#R de 6, el acceso a M puede tener uno de los siguientes 0ormatosG 7n nombre de tipo Ot#pe-na%eR o expresi-n primaria Opri%ar#-e2pressionR sin cali0icar de la 0orma M. 7na expresi-n primaria Opri%ar#-e2pressionR de la 0orma ).M, siempre ?ue el tipo de ) sea 1 o una clase derivada de 1, donde 1 es el tipo de clase 6, o un tipo de clase construido a partir de 6. 7na expresi-n primaria Opri%ar#-e2pressionR de la 0orma base.M.

&dem(s de estas 0ormas de acceso, una clase derivada puede tener acceso a un constructor de instancia protegido de una clase base en un iniciali1ador de constructor Oconstr ctor-initiali0erR O[1".11.1R. En el e$emplo
&ublic class ' { &rotected int #; static void V(' a : b) { a.# + 2; .. %( b.# + 2; .. %( ! !

6$

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases &ublic class :/ ' { static void V(' a : b) { a.# + 2; .. )rror must access t"roug" instance o- : b.# + 2; .. %( ! !

dentro de ', es posible obtener acceso a # mediante instancias de ' y de :, puesto ?ue en cual?uiera de los dos casos el acceso tiene lugar %ediante una instancia de ' o una clase derivada de '. 4o obstante, dentro de :, no es posible el acceso a # por medio de una instancia de ', puesto ?ue ' no se deriva de :. En el e$emplo
class CD1E { &rotected 1 #; ! class 6D1E/ CD1E { static void V() { 6D1E dt + ne, 6D1E(); 6DintE di + ne, 6DintE(); 6DstringE ds + ne, 6DstringE(); dt.# + de-ault(1); di.# + 289; ds.# + "test"; ! !

se permiten las tres asignaciones a # por?ue todas se dan gracias a instancias de tipos de clase construidos desde el tipo gen)rico. 3.#.! 9estricciones de accesibilidad &lgunas construcciones del lengua$e C# re?uieren ?ue un tipo sea al enos tan accesi/le co o un miembro u otro tipo. .e dice ?ue un tipo 1 es por lo menos tan accesible como un miembro o un tipo M si el dominio de accesibilidad de 1 es un supracon$unto del dominio de accesibilidad de M. Es decir, 1 es por lo menos tan accesible como M si 1 es accesible en todos los contextos donde M es accesible. Existen las siguientes restricciones de la accesibilidadG 8a clase base directa de un tipo de clase debe ser al menos tan accesible como el propio tipo de clase. 8as inter0aces base expl5citas de un tipo de inter0a1 deben ser al menos tan accesibles como el propio tipo de inter0a1. El tipo de valor devuelto y los tipos de los par(metros de un tipo delegado deben ser al menos tan accesibles como el propio tipo delegado. El tipo de una constante debe ser al menos tan accesible como la propia constante. El tipo de un campo debe ser al menos tan accesible como el propio campo. El tipo de valor devuelto y los tipos de par(metros de un m)todo deben ser al menos tan accesibles como el propio m)todo. El tipo de una propiedad debe ser al menos tan accesible como la misma propiedad. El tipo de un evento debe ser al menos tan accesible como el propio evento.

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

6"

Especificacin del lenguaje C#

El tipo y los tipos de par(metros de un indi1ador deben ser al menos tan accesibles como el propio indi1ador. El tipo de valor devuelto y los tipos de par(metros de un operador deben ser al menos tan accesibles como el propio operador. 8os tipos de par(metros de un constructor de instancia deben ser al menos tan accesibles como el propio constructor de instancia.
class ' {...! &ublic class :/ ' {...!

En el e$emplo

la clase : produce un error en tiempo de compilaci-n por?ue ' no tiene una capacidad de acceso m5nima como :. &n(logamente, en el e$emploG
class ' {...! &ublic class : { ' V() {...! internal ' S() {...! &ublic ' H() {...! !

el m)todo H de : produce un error en tiempo de compilaci-n por?ue el tipo de valor devuelto ' no es por lo menos tan accesible como el m)todo.

3.$ 7irmas y sobrecargas


8os m)todos, constructores de instancia, indi1adores y operadores est(n caracteri1ados por sus fir asG 8a 0irma de un m)todo se compone del nombre del m)todo, el nHmero de par(metros de tipo y el tipo y la categor5a Ovalor, re0erencia o resultadoR de sus par(metros 0ormales, considerados de i1?uierda a derec=a. Con este 0in, todo par(metro de tipo del m)todo ?ue se produce en el tipo de un par(metro 0ormal se identi0ica no por su nombre, sino por su posici-n ordinal en la lista de argumentos de tipo del m)todo. 8a 0irma de un m)todo no incluye espec50icamente el tipo de valor devuelto, el modi0icador &arams ?ue puede especi0icarse para el par(metro situado m(s a la derec=a, ni la restricci-n de par(metro de tipo opcional. 8a 0irma de un constructor de instancias se compone del tipo y la categor5a Ovalor, re0erencia o resultadoR de sus par(metros 0ormales, considerados de i1?uierda a derec=a. 8a 0irma de un constructor de instancias no incluye espec50icamente el modi0icador &arams, ?ue puede especi0icarse para el par(metro situado m(s a la derec=a. 8a 0irma de un indi1ador est( 0ormada por el tipo de sus par(metros 0ormales, considerados de i1?uierda a derec=a. 8a 0irma de un indi1ador no incluye espec50icamente el tipo de elemento ni el modi0icador &arams ?ue puede estar especi0icado para el par(metro situado m(s a la derec=a. 8a 0irma de un operador se compone del nombre del operador y del tipo de sus par(metros 0ormales, considerados de i1?uierda a derec=a. 8a 0irma de un operador no incluye espec50icamente el tipo del resultado.

8as 0irmas constituyen el mecanismo de =abilitaci-n ?ue permite so/recargar los miembros de clases, estructuras e inter0acesG

('

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

8a sobrecarga de los m)todos permite ?ue una clase, estructura o inter0a1 declare varios m)todos con el mismo nombre, siempre ?ue sus 0irmas sean Hnicas dentro de esa clase, estructura o inter0a1. 8a sobrecarga de los constructores de instancia permite ?ue una clase o una estructura declare varios constructores de instancia, a condici-n de ?ue sus 0irmas sean Hnicas dentro de esa clase o estructura. 8a sobrecarga de los indi1adores permite ?ue una clase, estructura o inter0a1 declare varios indi1adores, siempre ?ue sus 0irmas sean Hnicas dentro de esa clase, estructura o inter0a1. 8a sobrecarga de los operadores permite ?ue una clase o una estructura declare varios operadores con el mismo nombre, siempre ?ue sus 0irmas sean Hnicas dentro de esa clase o estructura.

&un?ue los modi0icadores de par(metros out y re- se consideran como parte de una 0irma, los miembros declarados en un tipo Hnico no pueden di0erir en la 0irma Hnicamente por re- y out. .i dos miembros se declaran en el mismo tipo con 0irmas ?ue ser5an iguales si todos los par(metros de ambos m)todos con modi0icadores out se cambiaran a modi0icadores re-, se produce un error de compilaci-n. 'ara otros prop-sitos de coincidencia de 0irma Opor e$emplo, para ocultar o invalidarR, re- y out se consideran como parte de la 0irma y no coinciden entre s5. OEsta restricci-n se utili1a para permitir traducir con 0acilidad los programas de C# para ?ue se e$ecuten en Common 8anguage !n0rastructure OC8!R, ?ue no proporciona una manera de de0inir m)todos ?ue solamente se di0erencian en re- y out.R El siguiente e$emplo muestra un con$unto de declaraciones de m)todos sobrecargados con sus 0irmas.
inter-ace $1est { void V(); void V(int #); void V(re- int #); void V(out int #); void V(int # int V(int #); void V(string45 a); void V(&arams string45 a); ! int y); int V(string s); .. V() .. V(int) .. V(re- int) .. V(out int) .. V(int .. V(int) .. V(string45) .. V(string45) error int) error .. V(string) error

.e debe tener en cuenta ?ue los modi0icadores de par(metros re- y out O[1".#.1R 0orman parte de una 0irma. 'or lo tanto, V(int) y V(re- int) son 0irmas Hnicas. .in embargo, V(re-int) y V(outint) no se pueden declarar dentro de la misma inter0a1 por?ue sus 0irmas se di0erencian Hnicamente en re- y out. &simismo, el tipo de valor devuelto y el modi0icador &arams no 0orman parte de una 0irma, por lo ?ue no es posible sobrecargar bas(ndose exclusivamente en el tipo de valor devuelto o en la inclusi-n o exclusi-n del modi0icador &arams. Como tales, las declaraciones de los m)todos V(int) y V(&arams string45) anteriormente identi0icadas producen un error en tiempo de compilaci-n.

3.+ :mbitos
El 5 /ito OscopeR de un nombre es la regi-n del texto del programa en la cual es posible re0erirse a la entidad declarada por el nombre sin la cali0icaci-n de )ste. 8os (mbitos se pueden anidar y un (mbito interno puede volver a declarar el signi0icado de un nombre de un (mbito exterior Osin embargo, de esta 0orma no se ?uita la restricci-n impuesta por [3.3 de ?ue, dentro de un blo?ue anidado, no se puede declarar una variable local con el mismo nombre de una variable local de un blo?ue contenedorR. En este caso, se dice ?ue el nombre del (mbito e.terno est( oculto en la regi-n del texto del programa cubierta por el (mbito interno, y el acceso al nombre externo s-lo es posible si se certi0ica el nombre.

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

(1

Especificacin del lenguaje C#

El (mbito de un miembro de espacio de nombres declarado por una declaraci-n de miembro de espacio de nombres Ona%espace-%e%-er-declarationR O[R sin declaraci-n envolvente de espacio de nombres Ona%espace-declarationR es todo el texto del programa. El (mbito de un miembro de espacio de nombres declarado mediante una declaraci-n de miembro de espacio de nombres Ona%espace-%e%-er-declarationR, dentro de una declaraci-n de espacio de nombres Ona%espace-declarationR cuyo nombre completo sea N, ser( el cuerpo de espacio de nombres Ona%espace-od#R de todas las declaraciones de espacio de nombres Ona%espace-declarationR cuyo nombre completo sea N o empiece por N, seguido por un punto. El (mbito de un nombre de0inido por una directiva de alias extern se extiende a trav)s de directivas using O sin&-directivesR, atributos globales O&lo-al-attri- tesR y declaraciones de miembros de espacios de nombres Ona%espace-%e%-er-declarationsR de la unidad de compilaci-n o del cuerpo de espacio de nombres inmediato. 7na directiva de alias extern Oe2tern-alias-directiveR no contribuye con ningHn miembro nuevo al espacio de declaraci-n subyacente. En otras palabras, una directiva de alias extern Oe2tern-aliasdirectiveR no es transitiva, sino ?ue s-lo a0ecta a la unidad de compilaci-n o al cuerpo de espacio de nombres en el ?ue se da. El (mbito de un nombre de0inido o importado por una directiva using O sin&-directiveR O[+.4R se ampl5a a las declaraciones de miembros de espacios de nombres Ona%espace-%e%-er-declarationsR de la unidad de compilaci-n Oco%pilation- nitR o del cuerpo de espacio de nombres Ona%espace--od#R en ?ue tiene lugar la directiva using O sin&-directiveR. 7na directiva using O sin&-directiveR puede o0recer cero o m(s espacios de nombres o nombres de tipos disponibles dentro de una unidad de compilaci-n Oco%pilation- nitR o cuerpo de espacio de nombres Ona%espace--od#R en particular, pero no aporta ningHn miembro nuevo al espacio de declaraci-n subyacente. Es decir, una directiva using O sin&-directiveR no es transitiva, sino ?ue a0ecta Hnicamente a la unidad de compilaci-n Oco%pilation- nitR o al cuerpo de espacio de nombres Ona%espace-od#R en ?ue tiene lugar. El (mbito de un par(metro de tipo declarado por una lista de par(metros de tipo Ot#pe-para%eter-listR en una declaraci-n de clase Oclass-declarationR O[R es la clase base Oclass--aseR, las cl(usulas de restricciones de par(metros de tipo Ot#pe-para%eter-constraints-cla sesR, y el cuerpo de clase Oclass--od#R de esa declaraci-n de clase Oclass-declarationR. El (mbito de un par(metro de tipo declarado por una lista de par(metros de tipo Ot#pe-para%eter-listR en una declaraci-n de estructura Ostr c-declarationR O[R son las inter0aces de estructuras Ostr ct-interfacesR, las cl(usulas de restricciones de par(metros de tipo Ot#pe-para%eter-constraints-cla sesR, y el cuerpo de estructura Ostr ct--od#R de esa declaraci-n de estructura Oclass-str ctR. El (mbito de un par(metro de tipo declarado por una lista de par(metros de tipo Ot#pe-para%eter-listR en una declaraci-n de inter0a1 Ointerface-declarationR O[13.1R es la base de inter0a1 Ointerface--aseR, las cl(usulas de restricciones de par(metros de tipo Ot#pe-para%eter-constraints-cla sesR, y el cuerpo de inter0a1 Ointerface--od#R de esa declaraci-n de inter0a1 Ointerface-declarationR. El (mbito de un par(metro de tipo declarado por una lista de par(metros de tipo Ot#pe-para%eter-listR en una declaraci-n de delegado Odele&ate-declarationR O[1 .1R es el tipo devuelto Oret rn-t#peR, la lista de par(metros 0ormales Ofor%al-para%eter-listR, y las cl(usulas de restricciones de par(metros de tipo Ot#pepara%eter-constraints-cla sesR de esa declaraci-n de delegado Odele&ate-declarationR. El (mbito de un miembro declarado por una declaraci-n de miembro de clase Oclass-%e%-er-declarationR O[1".1.#R es el cuerpo de clase Oclass--od#R en ?ue se produce la declaraci-n. &simismo, el (mbito de un miembro de clase se ampl5a al cuerpo de clase Oclass--od#R de las clases derivadas ?ue est)n incluidas en el dominio de accesibilidad O[3. .2R del miembro. El (mbito de un miembro declarado por una declaraci-n de miembro de estructura Ostr ct-%e%-erdeclarationR O[11.2R es el cuerpo de estructura Ostr ct--od#R en ?ue se produce la declaraci-n.

(2

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

El (mbito de un miembro declarado por una declaraci-n de miembro de enumeraci-n Oen %-%e%-erdeclarationR O[14.3R es el cuerpo de enumeraci-n Oen %--od#R en el ?ue se produce la declaraci-n. El (mbito de un par(metro declarado en una declaraci-n de m)todo O%ethod-declarationR O[1".#R es el cuerpo del m)todo O%ethod--od#R de dic=a declaraci-n de m)todo O%ethod-declarationR. El (mbito de un par(metro declarado en una declaraci-n de indi1ador Oinde2er-declarationR O[1".+R son las declaraciones de descriptor de acceso Oaccessor-declarationsR de dic=a declaraci-n de indi1ador Oinde2erdeclarationR. El (mbito de un par(metro declarado en una declaraci-n de operador Ooperator-declarationR O[1".1"R es el blo?ue O-loc3R de dic=a declaraci-n de operador Ooperator-declarationR. El (mbito de un par(metro declarado en una declaraci-n de constructor Oconstr ctor-declarationR O[1".11R es el iniciali1ador de constructor Oconstr ctor-initiali0erR y el blo?ue O-loc3R de dic=a declaraci-n de constructor Oconstr ctor-declarationR. El (mbito de un par(metro declarado en una expresi-n de lambda la%-da-e2pression O[R es el cuerpo de expresi-n de lambda Ola%-da-e2pression--od#R de dic=a expresi-n de lambda Ola%-da-e2pressionR. El (mbito de un par(metro declarado en una expresi-n de m)todo an-nimo anon#%o s-%ethod-e2pression O[R es el blo?ue O-loc3R de dic=a expresi-n de m)todo an-nimo Oanon#%o s-%ethod-e2pressionR. El (mbito de una eti?ueta declarada en una instrucci-n con eti?ueta Ola-eled-state%entR O[8.4R es el blo?ue O-loc3R en ?ue se produce la declaraci-n. El (mbito de una variable local declarada en una declaraci-n de variable local Olocal-varia-le-declarationR O[R es el blo?ue donde se produce la declaraci-n. El (mbito de una variable local declarada en un blo?ue s9itc= Oswitch--loc3R de una instrucci-n s,itc" O[8.*.2R es el blo?ue s9itc= Oswitch--loc3R. El (mbito de una variable local declarada en un iniciali1ador 0or Ofor-initiali0erR de una instrucci-n -or O[8.8.3R es el iniciali1ador 0or Ofor-initiali0erR, la condici-n 0or Ofor-conditionR, el iterador 0or Ofor-iteratorR y la instrucci-n Ostate%entR contenida de la instrucci-n -or. El (mbito de una constante local declarada en una declaraci-n de constante local Olocal-constantdeclarationR O[R es el blo?ue donde se produce la declaraci-n. Es un error en tiempo de compilaci-n =acer re0erencia a una constante local en una posici-n textual ?ue precede a su declarador de constante OconstantdeclaratorR. El (mbito de una variable declarada como parte de una instrucci-n 0oreac= Oforeach-state%entR, instrucci-n using O sin&-state%entR, instrucci-n loc6 Oloc3-state%entR o expresi-n de consulta O6 er#-e2pressionR est( determinado por la expansi-n de la construcci-n determinada.

2entro del (mbito de un miembro de espacio de nombres, clase, estructura o enumeraci-n es posible =acer re0erencia al miembro en una posici-n textual ?ue precede a la declaraci-n del miembro. 'or e$emploG
class ' { void V() { i + 2; ! int i + 3; !

'or lo tanto, es v(lido ?ue V =aga re0erencia a i antes de su declaraci-n.

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

(3

Especificacin del lenguaje C#

En el (mbito de una variable local, es un error en tiempo de compilaci-n =acer re0erencia a la variable local en una posici-n textual ?ue preceda al declarador de la variable local Olocal-varia-le-declaratorR. 'or e$emploG
class ' { int i + 3; void V() { i + 2; int i; i + 8; ! void S() { int j + (j + 2); ! void H() { int a + 2 ! ! b + <<a; .. )rror use &recedes declaration

.. Ualid

.. Ualid

En el m)todo V anterior, la primera asignaci-n de i no =ace ninguna re0erencia concreta al campo declarado en el (mbito externo. En lugar de ello, =ace re0erencia a la variable local, con lo ?ue se produce un error durante la compilaci-n, por?ue precede textualmente a la declaraci-n de la variable. En el m)todo S, el uso de j en el iniciali1ador de la declaraci-n de j es v(lido por?ue no precede al declarador de variable local Olocal-varia-ledeclaratorR. En el m)todo H, un declarador de variable local Olocal-varia-le-declaratorR posterior =ace re0erencia correctamente a una variable local declarada en un declarador de variable local Olocal-varia-ledeclaratorR anterior con la misma declaraci-n de variable local Olocal-varia-le-declarationR. 8as reglas ?ue rigen el (mbito de las variables locales pretenden garanti1ar ?ue el signi0icado de un nombre utili1ado en el contexto de una expresi-n no var5e dentro de un blo?ue. .i el (mbito de una variable local s-lo se extiende desde su declaraci-n =asta el 0inal del blo?ue, entonces, en el e$emplo anterior, la primera asignaci-n asignar( a la variable de instancia y la segunda a la variable local, lo ?ue posiblemente producir( errores en tiempo de compilaci-n si m(s adelante 0uera necesario reorgani1ar las instrucciones del blo?ue. El signi0icado de un nombre contenido en un blo?ue puede di0erir segHn el contexto en ?ue se utilice el nombre. En el e$emplo
using System; class ' {! class 1est { static void Main() { string ' + ""ello string s + '; 1y&e t + ty&eo-('); Console.WriteLine(s); Console.WriteLine(t); ! !

,orld"; .. e#&ression conte#t .. ty&e conte#t .. ,rites ""ello .. ,rites "'" ,orld"

el nombre ' se utili1a en el contexto de una expresi-n para =acer re0erencia a la variable local ' y en un contexto de tipo para =acer re0erencia a la clase '. 3.+.1 ,cultar nombres El (mbito de una entidad =abitualmente abarca m(s texto del programa ?ue el espacio de declaraci-n de la entidad. En concreto, el (mbito de una entidad puede incluir declaraciones ?ue introducen nuevos espacios de

(#

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

declaraci-n ?ue contienen entidades con el mismo nombre. 8as declaraciones de este tipo =acen ?ue la entidad original ?uede oculta OhiddenR. & la inversa, se dice ?ue una entidad es visi/le cuando no est( oculta. 8a ocultaci-n de nombres se produce cuando los (mbitos se superponen a causa del anidamiento y cuando se superponen por =erencia. 8as caracter5sticas de los dos tipos de ocultaci-n se explican en las pr-ximas secciones. 3.#.1.1 'cultar mediante anidacin 8a ocultaci-n de nombres por medio del anidamiento puede ser el resultado del anidamiento de espacios de nombres o tipos contenidos en espacios de nombres, la consecuencia del anidamiento de tipos dentro de clases o estructuras y el resultado de las declaraciones de par(metros y variables locales. En el e$emplo
class ' { int i + 3; void V() { int i + 2; ! void S() { i + 2; ! !

dentro del m)todo V, la variable de instancia i ?ueda oculta por la variable local i, pero dentro del m)todo S, i se sigue re0iriendo a la variable de instancia. Cuando un nombre en un (mbito interno oculte otro nombre en el (mbito externo, ocultar( tambi)n todas sus apariciones sobrecargadas. En el e$emplo
class %uter { static void V(int i) {! static void V(string s) {! class $nner { void S() { V(2); V("Hello"); ! ! !

.. $nvo(es %uter.$nner.V .. )rror

static void V(long l) {!

la llamada V(2) invoca la V declarada en $nner por?ue la declaraci-n interna oculta todas las apariciones externas de V. 'or el mismo motivo, la llamada V("Hello") produce un error en tiempo de compilaci-n. 3.#.1.2 'cultar mediante -erencia 8a ocultaci-n de nombres por medio de la =erencia ocurre cuando clases o estructuras vuelven a declarar nombres ?ue se =an =eredado de clases base. Este tipo de ocultaci-n de nombres toma una de las siguientes 0ormasG 7na constante, campo, propiedad, evento o tipo introducido en una clase o estructura ?ue oculta todos los miembros de la clase base con el mismo nombre.

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

(!

Especificacin del lenguaje C#

7n m)todo introducido en una clase o estructura ?ue oculta todos los miembros de clase base no de m)todo con el mismo nombre, y todos los m)todos de clase base con la misma 0irma Onombre de m)todo y nHmero de par(metros, modi0icadores y tiposR. !ndi1ador introducido en una clase o estructura ?ue oculta todos los indi1adores de la clase base con la misma 0irma OnHmero de par(metros y tiposR.

8as reglas ?ue gobiernan las declaraciones de operador O[1".1"R imposibilitan la declaraci-n por una clase derivada de un operador con la misma 0irma ?ue un operador de una clase base. 'or lo tanto, los operadores nunca se ocultan mutuamente. &l contrario ?ue cuando se oculta un nombre de un (mbito externo, cuando se oculta un nombre accesible desde un (mbito =eredado se genera una advertencia. En el e$emplo
class :ase { &ublic void V() {! ! class 6erived/ :ase { &ublic void V() {! !

.. Warning

"iding an in"erited name

la declaraci-n de V en 6erived genera una advertencia. /cultar un nombre =eredado no es espec50icamente un error, puesto ?ue esto impedir5a la evoluci-n independiente de las clases base. 'or e$emplo, la situaci-n anterior podr5a =aberse producido por?ue una versi-n posterior de :ase introdu$o un m)todo V ?ue no estaba presente en una versi-n anterior de la clase. .i la situaci-n anterior =ubiera sido un error, c al6 ier cambio reali1ado a una clase base en una versi-n independiente de la biblioteca de clases podr5a =aber invalidado las clases derivadas. 8a advertencia causada por la ocultaci-n de un nombre =eredado puede eliminarse mediante uso del modi0icador ne,G
class :ase { &ublic void V() {! ! class 6erived/ :ase { ne, &ublic void V() {! !

El modi0icador ne, indica ?ue V de 6erived es PnuevoQ, y ?ue su prop-sito real es ocultar el miembro =eredado. 7na declaraci-n de un miembro nuevo oculta un miembro =eredado s-lo dentro del (mbito del nuevo miembro.
class :ase { &ublic static void V() {! ! class 6erived/ :ase { ne, &rivate static void V() {! ! class More6erived/ 6erived { static void S() { V(); ! !

.. Hides :ase.V in 6erived only

.. $nvo(es :ase.V

(6

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

En el e$emplo anterior, la declaraci-n de m)todo V en la clase 6erived oculta el m)todo V ?ue se =ered- de :ase, pero, como el nuevo m)todo V de 6erived tiene acceso de tipo privado, su (mbito no se extiende a More6erived. 2e este modo, la llamada V() de More6erived.S es v(lida e invocar( a :ase.V.

3.- Espacios de nombres y nombres de tipos


&lgunos contextos de un programa de C# re?uieren ?ue se especi0i?ue un nombre de espacio de nombres Ona%espace-na%eR o un nombre de tipo Ot#pe-na%eR. na%espace-na%e1 na%espace-or-t#pe-na%e t#pe-na%e1 na%espace-or-t#pe-na%e na%espace-or-t#pe-na%e1 identifier t#pe-ar& %ent-listopt na%espace-or-t#pe-na%e . identifier t#pe-ar& %ent-listop 6 alified-alias-%e%-er 7n nombre de espacio de nombres Ona%espace-na%eR es un nombre de espacio de nombres o de tipo Ona%espace-or-t#pe-na%eR ?ue =ace re0erencia a un espacio de nombres. Con0orme a la resoluci-n explicada m(s adelante, el nombre de espacio de nombres o de tipo Ona%espace-or-t#pe-na%eR de un nombre de espacio de nombres Ona%espace-na%eR debe =acer re0erencia a un espacio de nombres o, de lo contrario, se producir( un error en tiempo de compilaci-n. 4o puede =aber argumentos de tipo O[4.4.1R en un nombre de espacio de nombres Ona%espace-na%eRV s-lo los tipos pueden tener argumentos de tipo. 7n nombre de tipo Ot#pe-na%eR es un nombre de espacio de nombres o de tipo Ona%espace-or-t#pe-na%eR ?ue =ace re0erencia a un tipo. Con0orme a la resoluci-n explicada m(s adelante, el nombre de espacio de nombres o de tipo Ona%espace-or-t#pe-na%eR de un nombre de tipo Ot#pe-na%eR debe =acer re0erencia a un tipo o, de lo contrario, se producir( un error en tiempo de compilaci-n. .i el nombre de espacio de nombres o de tipo Ona%espace-or-t#pe-na%eR es un miembro de alias completo su signi0icado es como se describe en [. En caso contrario, un nombre de espacio de nombres o de tipo Ona%espace-or-t#pe-na%eR adopta una de las cuatro estructuras siguientesG
$ $D'2 ... 'aE N.$ N.$D'2 ... 'aE

donde $ es un solo identi0icador, N es un nombre de espacio de nombres o de tipo Ona%espace-or-t#pe-na%eR y D'2 ... 'aE es una lista de argumentos de tipo Ot#pe-ar& %ent-listR. .i no se especi0ica ninguna lista de argumentos de tipo Ot#pe-ar& %ent-listR, se considera ?ue a es cero. El signi0icado de un nombre de espacio de nombres o de tipo Ona%espace-or-t#pe-na%eR se determina como sigueG .i el nombre de espacio de nombres o de tipo Ona%espace-or-t#pe-na%eR tiene la estructura $ o $D'2 ... 'aEG o .i a es cero y el nombre de espacio de nombres o de tipo Ona%espace-or-t#pe-na%eR aparece dentro de una declaraci-n de m)todo gen)rico O[1".#R y si dic=a declaraci-n incluye un par(metro de tipo O[1".1.3R con el nombre $, el nombre de espacio de nombres o de tipo Ona%espace-or-t#pe-na%eR =ace re0erencia a dic=o par(metro de tipo.

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

((

Especificacin del lenguaje C#

2e lo contrario, si el nombre de espacio de nombres o de tipo Ona%espace-or-t#pe-na%eR aparece dentro de una declaraci-n de tipo, para cada tipo de instancia 1O[1".3.1R, empe1ando por el tipo de instancia de dic=a declaraci-n tipo y continuando con el tipo de instancia para cada clase envolvente o declaraci-n de estructura Osi las =ubieraRG .i a es cero y la declaraci-n de 1 incluye un par(metro de tipo con el nombre $, el nombre de espacio de nombres o de tipo Ona%espace-or-t#pe-na%eR =ace re0erencia a dic=o par(metro de tipo. 2e lo contrario, si el nombre de espacio de nombres o de tipo Ona%espace-or-t#pe-na%eR aparece dentro del cuerpo de a declaraci-n de tipo y 1 o alguno de sus tipos base contiene un tipo accesible anidado con el nombre $ y par(metros de tipo a, el nombre de espacio de nombres o de tipo Ona%espace-or-t#pe-na%eR =ace re0erencia a dic=o tipo construido con los argumentos de tipo dados. .i =ay m(s de uno de esos tipos, se selecciona el tipo declarado dentro del tipo m(s derivado. Tenga en cuenta ?ue los miembros ?ue no son de tipo Oconstantes, campos, m)todos, propiedades, indi1adores, operadores, constructores de instancia, destructores y constructores est(ticosR y miembros de tipo con un nHmero di0erente de par(metros de tipo se omiten a la =ora de determinar el signi0icado de un nombre de espacio de nombres o de tipo Ona%espace-or-t#pe-na%eR.

.i los pasos anteriores no produ$eron resultados satis0actorios, para cada espacio de nombres N, empe1ando por el espacio de nombres en el ?ue se produce el nombre de espacio de nombres o de tipo Ona%espace-or-t#pe-na%eR, continuando por cada uno de los espacios de nombres envolventes Osi los =ubieraR y terminando por el espacio de nombres global, se ir(n evaluando los siguientes pasos =asta ?ue se localice una entidadG .i a es cero e $ es el nombre de un espacio de nombres en NG o .i la ubicaci-n donde tiene lugar el nombre de espacio de nombres o de tipo Ona%espace-ort#pe-na%eR tiene una declaraci-n de espacio de nombres para N y la declaraci-n de espacio de nombres contiene una directiva de alias extern Oe2tern-alias-directiveR o una directiva de alias using O sin&-alias-directiveR ?ue asocia el nombre $ con un nombre de espacio de nombres o de tipo, el nombre de espacio de nombres o de tipo Ona%espace-or-t#pe-na%eR es ambiguo y se genera un error en tiempo de compilaci-n. 2e lo contrario, el nombre de espacio de nombres o de tipo Ona%espace-or-t#pe-na%eR =ace re0erencia al espacio de nombres denominado $ en N. .i a es cero y la ubicaci-n donde tiene lugar el nombre de espacio de nombres o de tipo Ona%espace-or-t#pe-na%eR tiene una declaraci-n de espacio de nombres para N y la declaraci-n de espacio de nombres contiene una directiva de alias extern Oe2tern-alias-directiveR o una directiva de alias using O sin&-alias-directiveR ?ue asocia el nombre con un nombre de espacio de nombres o de tipo, el nombre de espacio de nombres o de tipo Ona%espace-or-t#pe-na%eR es ambiguo y se genera un error en tiempo de compilaci-n. 2e lo contrario, el nombre de espacio de nombres o de tipo Ona%espace-or-t#pe-na%eR =ace re0erencia al tipo construido con los argumentos de tipo dados.

2e lo contrario, si N contiene un tipo accesible con un nombre $ y par(metros de tipo aG o

2e lo contrario, si la ubicaci-n donde tiene lugar el nombre de espacio de nombres o de tipo Ona%espace-or-t#pe-na%eR tiene una declaraci-n de espacio de nombres para NG o .i a es cero y la declaraci-n de espacio de nombres contiene una directiva de alias extern Oe2tern-alias-directiveR o una directiva de alias using O sin&-alias-directiveR ?ue asocia el nombre $ a un espacio de nombres o tipo importado, entonces el nombre de espacio de nombres o de tipo Ona%espace-or-t#pe-na%eR =ace re0erencia a dic=o espacio de nombres o tipo.

($

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

2e lo contrario, si los espacios de nombres importados por las directivas using de espacio de nombres O sin&-na%espace-directivesR de la declaraci-n del espacio de nombres contienen exactamente un Hnico tipo con el nombre $ y par(metros de tipo a, entonces el nombre de espacio de nombres o de tipo Ona%espace-or-t#pe-na%eR =ace re0erencia al tipo construido con los argumentos de tipo dados. 2e lo contrario, si los espacios de nombres importados por las directivas using de espacio de nombres O sin&-na%espace-directivesR de la declaraci-n del espacio de nombres contienen m(s de un tipo con el nombre $ y par(metros de tipo a, entonces el nombre de espacio de nombres o de tipo Ona%espace-or-t#pe-na%eR ser( ambiguo y se producir( un error.

2e lo contrario, el nombre de espacio de nombres o de tipo Ona%espace-or-t#pe-na%eR no est( de0inido y se produce un error en tiempo de compilaci-n.

2e lo contrario, el nombre de espacio de nombres o de tipo Ona%espace-or-t#pe-na%eR tiene la estructura N.$ o N.$D'2 ... 'aE. .e resuelve primero N como nombre de espacio de nombres o de tipo Ona%espaceor-t#pe-na%eR. .i la resoluci-n de N no es correcta, se produce un error en tiempo de compilaci-n. 2e lo contrario, N.$ o N.$D'2 ... 'aE se resuelve de la siguiente maneraG o .i a es cero y N =ace re0erencia a un espacio de nombres y N contiene un espacio de nombres anidado con el nombre $, el nombre de espacio de nombres o de tipo Ona%espace-or-t#pe-na%eR =ace re0erencia a dic=o espacio de nombres anidado. 2e lo contrario, si N contiene un espacio de nombres y N contiene un tipo accesible con el nombre $ y par(metros de tipo a, el nombre de espacio de nombres o de tipo Ona%espace-or-t#pe-na%eR =ace re0erencia a dic=o tipo construido con los argumentos de tipo dados. 2e lo contrario, si N =ace re0erencia a una clase Oposiblemente construidaR o a un tipo struct y N o algunas de sus clases base contiene un tipo accesible anidado con el nombre $ y par(metros de tipo a, el nombre de espacio de nombres o de tipo Ona%espace-or-t#pe-na%eR =ace re0erencia a dic=o tipo construido con los argumentos de tipo dados. .i =ay m(s de uno de esos tipos, se selecciona el tipo declarado dentro del tipo m(s derivado. Tenga en cuenta ?ue si el signi0icado de N.$ se determina como parte de la resoluci-n de la especi0icaci-n de la clase base de N, la clase base directa de N se considera ob$ect O[R. 2e lo contrario, N.$ es un nombre de espacio de nombres o de tipo no v(lido Oinvalid na%espace-ort#pe-na%eR y se produce un error en tiempo de compilaci-n.

.e permite ?ue un nombre de espacio de nombres o de tipo Ona%espace-or-t#pe-na%eR O[1".1.1.3R =aga re0erencia a una clase est(tica s-lo si El nombre de espacio de nombres o de tipo Ona%espace-or-t#pe-na%eR es 1 en un nombre de espacio de nombres o de tipo Ona%espace-or-t#pe-na%eR con la estructura 1.$, o bien El nombre de espacio de nombres o de tipo Ona%espace-or-t#pe-na%eR es 1 en una expresi-n typeo0 Ot#peof-e2pressionR O[*. .11R con la estructura ty&eo-(1).

3.-.1 1ombres completos Todos los espacios de nombres y todos los tipos tienen un no /re co pleto, ?ue los identi0ica de 0orma exclusiva. El nombre completo de un espacio de nombres o un tipo N se determina como sigueG .i N es un miembro del espacio de nombres global, su nombre completo es N. 2e lo contrario, su nombre completo es S.N, donde S es el nombre completo del espacio de nombres o el tipo donde N est( declarado.

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

("

Especificacin del lenguaje C#

Esto es, el nombre completo de N es la ruta de acceso $er(r?uica completa de los identi0icadores ?ue conducen a N, empe1ando desde el espacio de nombres global. 2ado ?ue todos los miembros de un espacio de nombres o un tipo deben tener un nombre Hnico, se deduce ?ue el nombre completo de un espacio de nombres o tipo siempre es Hnico. En el e$emplo siguiente se muestran varias declaraciones de espacio de nombres y tipo con sus nombres completos asociados.
class ' {! names&ace I { class : { class C {! ! names&ace ` { class 6 {! ! ! names&ace I.` { class ) {! ! .. I.` .. I.`.) .. ' .. I .. I.: .. I.:.C .. I.` .. I.`.6

3.. 'dministracin autom)tica de la memoria


C# usa la administraci-n autom(tica de memoria, ?ue exime a los programadores de la asignaci-n manual y la liberaci-n de la memoria ocupada por ob$etos. 8as directivas de administraci-n autom(tica de la memoria se implementan mediante un recolector de ele entos no !tili-ados. El ciclo de vida de la administraci-n de la memoria de un ob$eto esG 1. activo. 2. En caso de ?ue no se pueda obtener acceso al ob$eto o alguna de sus partes por medio de las posibles continuaciones de la e$ecuci-n, en lugar de iniciar los destructores, el ob$eto de$ar( de considerarse en uso y ?uedar( expuesto al proceso de destrucci-n. El compilador de C# y el recolector de elementos no utili1ados pueden optar por anali1ar el c-digo para determinar ?u) re0erencias a un ob$eto podr(n utili1arse en el 0uturo. 'or e$emplo, si una variable local ?ue se encuentra dentro del (mbito es la Hnica re0erencia existente a un ob$eto, pero no se =ace ninguna re0erencia a tal variable local en ninguna continuaci-n posible de la e$ecuci-n desde el punto actual de e$ecuci-n dentro del procedimiento, el recolector de elementos no utili1ados puede tratar los ob$etos Oaun?ue no necesariamenteR como si ya no estuvieran en uso. Cuando el ob$eto ya es candidato a la destrucci-n, el destructor del ob$eto Osi existeR se e$ecuta en un momento posterior no especi0icado O[1".13R. .alvo ?ue sea invalidado por llamadas expl5citas, el destructor del ob$eto s-lo se e$ecutar( una ve1. .i, una ve1 e$ecutado el destructor de un ob$eto, las posibles continuaciones de la e$ecuci-n Oincluida la e$ecuci-n de los destructoresR no pudieran obtener acceso al ob$eto o a alguna de sus partes, se considerar( ?ue ya no se encuentra accesible y ?uedar( expuesto al proceso de recolecci-n. 'or Hltimo, cuando el ob$eto ya es candidato para la recolecci-n, en un momento posterior, el recolector de elementos no utili1ados libera la memoria asociada al ob$eto. Cuando se crea el ob$eto, se le asigna memoria, se e$ecuta el constructor y el ob$eto se considera

3.

4.

El recolector de elementos no utili1ados mantiene in0ormaci-n acerca de la utili1aci-n de ob$etos y la utili1a para tomar decisiones sobre la administraci-n de memoria. 'or e$emplo, contiene datos como en ?u) parte de la

$'

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

memoria se ubica un ob$eto reci)n creado, cu(ndo se reubica un ob$eto y cu(ndo un ob$eto ya no se utili1a o est( inaccesible. !gual ?ue otros lengua$es ?ue dan por supuesta la existencia de un recolector de elementos no utili1ados, C# se =a diseUado para ?ue el recolector de elementos no utili1ados pueda implementar una amplia gama de directivas de administraci-n de la memoria. 'or e$emplo, C# no exige ?ue se lleve a cabo la e$ecuci-n de destructores ni la recolecci-n de ob$etos en el momento en ?ue pasen a ser candidatos a ella, ni ?ue los destructores se e$ecuten en un orden concreto o en un subproceso concreto. El comportamiento del recolector de elementos no utili1ados puede controlarse, en cierta medida, mediante m)todos est(ticos de la clase System.SC, una clase ?ue puede utili1arse para solicitar la e$ecuci-n de la recolecci-n o de los destructores Oo su no e$ecuci-nR, etc. 2ado ?ue el recolector de elementos no utili1ados tiene una amplia libertad para decidir cu(ndo debe recolectar ob$etos y e$ecutar destructores, una implementaci-n compatible puede producir resultados di0erentes de los mostrados en el c-digo siguiente. El programa
using System; class ' { A'() { Console.WriteLine("6estruct instance o- '"); ! ! class : { object Oe-; &ublic :(object o) { Oe- + o; ! A:() { Console.WriteLine("6estruct instance o- :"); ! ! class 1est { static void Main() { : b + ne, :(ne, '()); b + null; SC.Collect(); SC.WaitVor*endingVinali?ers(); ! !

crea una instancia de la clase ' y otra de la clase :. Estos ob$etos se convierten en candidatos a la recolecci-n de elementos no utili1ados cuando se asigna a la variable b el valor null, puesto ?ue, despu)s de ello, no se puede obtener acceso a ellos mediante ningHn c-digo escrito por el usuario. El resultado podr5a ser
6estruct instance o- ' 6estruct instance o- :

o
6estruct instance o- : 6estruct instance o- '

puesto ?ue el lengua$e no impone restricciones al orden en ?ue se lleva a cabo la recolecci-n de elementos de los ob$etos no utili1ados.

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

$1

Especificacin del lenguaje C#

En casos concretos, la distinci-n entre Pcandidato a la destrucci-nQ y Pcandidato a la recolecci-nQ puede ser importante. 'or e$emplo,
using System; class ' { A'() { Console.WriteLine("6estruct instance o- '"); ! &ublic void V() { Console.WriteLine("'.V"); 1est.Oe-' + t"is; ! ! class : { &ublic ' Oe-; A:() { Console.WriteLine("6estruct instance o- :"); Oe-.V(); ! ! class 1est { &ublic static ' Oe-'; &ublic static : Oe-:; static void Main() { Oe-: + ne, :(); Oe-' + ne, '(); Oe-:.Oe- + Oe-'; Oe-: + null; Oe-' + null; .. ' and : no, eligible -or destruction SC.Collect(); SC.WaitVor*endingVinali?ers(); .. : no, eligible -or collection but ' is not i- (Oe-' @+ null) Console.WriteLine("Oe-' is not null"); ! !

En el programa anterior, si el recolector de elementos no utili1ados decide e$ecutar el destructor de ' antes ?ue el de :, el resultado de este programa puede serG
6estruct instance o- ' 6estruct instance o- : '.V Oe-' is not null

2ebe tenerse en cuenta ?ue, aun?ue la instancia de ' no estaba en uso cuando se e$ecut- el destructor de ', todav5a es posible llamar a los m)todos de ' Oen este caso, VR desde otro destructor. &simismo, no debe olvidarse ?ue la e$ecuci-n de un destructor puede =acer ?ue un ob$eto vuelva a ser utili1able desde el programa principal. En este caso, la e$ecuci-n del destructor de : =ace ?ue una instancia de ' ?ue no estaba anteriormente en uso est) a=ora accesible desde la re0erencia activa 1est.Oe-'. Tras la llamada a WaitVor*endingVinali?ers, la instancia de : pasa a ?uedar expuesta a la recolecci-n, pero no as5 la instancia de ', debido a la re0erencia 1est.Oe-'.

$2

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

'ara evitar con0usiones y comportamientos inesperados, generalmente es recomendable ?ue los destructores solamente realicen la limpie1a de los datos almacenados en los campos propios de sus ob$etos, y ?ue no realicen acciones en los ob$etos a los ?ue se =ace re0erencia o en campos est(ticos. 7na alternativa al uso de destructores consiste en permitir ?ue una clase implemente la inter0a1 System.$6is&osable. &s5 se permite al cliente del ob$eto determinar cu(ndo liberar los recursos del ob$eto, normalmente mediante el acceso al ob$eto como recurso en una instrucci-n using O[8.13R.

3.10 ,rden de ejecucin


8a e$ecuci-n de los programas de C# se reali1a de tal modo ?ue los e0ectos secundarios de cada subproceso en e$ecuci-n se van conservando en puntos cr5ticos de e$ecuci-n. 7n efecto sec!ndario se de0ine como la lectura o escritura de un campo vol(til, la escritura en una variable no vol(til, la escritura en un recurso externo o el inicio de una excepci-n. 8os puntos de e$ecuci-n cr5ticos en los ?ue deben conservarse tales e0ectos secundarios son las re0erencias a campos vol(tiles O[1". .3R, las instrucciones de blo?ueo Oloc(R O[8.12R y la creaci-n y terminaci-n de subprocesos. El entorno de e$ecuci-n puede cambiar el orden de e$ecuci-n de un programa de C#, con las siguientes restriccionesG .e conservar( la dependencia de datos dentro de un subproceso de e$ecuci-n. Es decir, el valor de cada variable se calcular( como si todas las instrucciones del subproceso se e$ecutaran en el orden del programa original. .e conservan las reglas de orden de iniciali1aci-n O[1". .4 y [1". . R. .e conserva el orden de los e0ectos secundarios respecto a las lecturas y escrituras vol(tiles O[1". .3R. &dem(s, el entorno de e$ecuci-n no necesitar( evaluar parte de una expresi-n si puede deducir ?ue el valor de esa expresi-n no se utili1a y ?ue no se producen e0ectos secundarios necesarios Oincluidos los causados por la llamada a un m)todo o el acceso a un campo vol(tilR. Cuando un evento asincr-nico Otal como una excepci-n iniciada por otro subprocesoR interrumpe la e$ecuci-n de un programa, no =abr( garant5as de ?ue los e0ectos secundarios observables resulten visibles en el orden del programa original.

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

$3

Especificacin del lenguaje C#

!. Tipos
8os tipos del lengua$e C# se dividen en dos categor5as principalesG tipos de valor y tipos de referencia. &mbos, los tipos de valor y los tipos de re0erencia, pueden ser tipos gen6ricos, ?ue adoptan uno o m(s par(metros de tipo. 8os par(metros de tipo pueden designar tanto a tipos de valor como a tipos de re0erencia. t#pe1 val e-t#pe reference-t#pe t#pe-para%eter 7na tercera categor5a de tipos, los punteros, s-lo est( disponible en el c-digo no seguro. Esta categor5a se explica con m(s detalle en la secci-n [18.2. 8os tipos de valor se di0erencian de los tipos de re0erencia en ?ue sus variables contienen directamente sus datos, mientras ?ue las variables de los tipos de re0erencia contienen referencias a sus datos, ?ue se conocen como o/1etos. En el caso de los tipos de re0erencia, es posible ?ue dos variables =agan re0erencia al mismo ob$eto y, por tanto, ?ue las operaciones en una variable a0ecten al ob$eto al ?ue =ace re0erencia la otra variable. En el caso de los tipos de valor, cada variable tiene su propia copia de los datos, de manera ?ue no es posible ?ue las operaciones de una a0ecten a la otra. El sistema de tipos de C# est( uni0icado, de manera ?ue n valor de c al6 ier tipo p ede tratarse co%o n o->eto. Todos los tipos de C# se derivan directa o indirectamente del tipo de clase object, ?ue es la clase base de0initiva de todos los tipos. 8os valores de los tipos de re0erencia se tratan como ob$etos consider(ndolos sencillamente como del tipo object. 8os valores de los tipos de valor se tratan como ob$etos mediante la reali1aci-n de operaciones de conversi-n boxing y unboxing O[4.3R.

!.1 Tipos de alor


7n tipo de valor es un tipo struct o un tipo enum. C# proporciona un con$unto de tipos struct prede0inidos denominados tipos si ples. 8os tipos simples se identi0ican mediante palabras reservadas. val e-t#pe1 str ct-t#pe en %-t#pe str ct-t#pe1 t#pe-na%e si%ple-t#pe n lla-le-t#pe si%ple-t#pe1 n %eric-t#pe
bool

n %eric-t#pe1 inte&ral-t#pe floatin&-point-t#pe


decimal

$#

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

inte&ral-t#pe1
sbyte byte s"ort us"ort int uint long ulong c"ar

floatin&-point-t#pe1
-loat double

n lla-le-t#pe1 non-n lla-le-val e-t#pe 7 non-n lla-le-val e-t#pe1 t#pe en %-t#pe1 t#pe-na%e & di0erencia de las variables de un tipo de re0erencia, las variables de los tipos de valor pueden contener el valor null s-lo si el tipo de valor acepta valores 4788. 'ara cada tipo de valor ?ue no acepta valores 4788 =ay un tipo de valor correspondiente ?ue s5 acepta valores 4788 y ?ue denota el mismo con$unto de valores m(s el valor null. 8a asignaci-n a una variable de un tipo de valor crea una copia del valor ?ue se asigna, lo cual di0iere de la asignaci-n a una variable de un tipo de re0erencia, ?ue copia la re0erencia, pero no el ob$eto identi0icado por ella. !.1.1 Tipo 4ystem.ValueType Todos los tipos de valor se =eredan impl5citamente de la clase System.Ualue1y&e, ?ue, a su ve1, se =ereda de la clase object. 4o es posible ?ue cual?uier tipo se derive de un tipo de valor y, por lo tanto, los tipos de valor son impl5citamente tipos sealed O[1".1.1.2R. /bserve ?ue System.Ualue1y&e no es en s5 ningHn tipo de valor Oval e-t#peR. %(s bien, es un tipo de clase Oclass-t#peR del ?ue se derivan autom(ticamente todos los tipos de valores Oval e-t#pesR. !.1.2 %onstructores predeterminados Todos los tipos de valor declaran impl5citamente un constructor de instancia pHblico sin par(metros denominado constr!ctor predeter inado. El constructor predeterminado devuelve una instancia iniciali1ada en cero conocida como el valor predeter inado del tipo de valorG 'ara todos los tipos simples Osi%ple-t#pesR, el valor predeterminado es el generado por un modelo de bits de todo cerosG o o o o 'ara sbyte, byte, s"ort, us"ort, int, uint, long y ulong, el valor predeterminado es 3. 'ara c"ar, el valor predeterminado es WZ#3333W. 'ara -loat, el valor predeterminado es 3.3-. 'ara double, el valor predeterminado es 3.3d.

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

$!

Especificacin del lenguaje C#

o o

'ara decimal, el valor predeterminado es 3.3m. 'ara bool, el valor predeterminado es -alse.

'ara un tipo enum Oen %-t#peR ) el valor predeterminado es 3, convertido en el tipo ). 'ara un tipo struct Ostr ct-t#peR, el valor predeterminado es el ?ue se genera al con0igurar todos los campos de tipos de valores en su valor predeterminado y todos los tipos de re0erencia en null. 'ara un tipo ?ue acepta valores 4788 On lla-le-t#peR el valor predeterminado es una instancia para la ?ue propiedad HasUalue es 0alsa y la propiedad Ualue no est( de0inida. El valor predeterminado tambi)n se conoce como el valor 2300 del tipo ?ue acepta valores 4788.

!gual ?ue con cual?uier otro constructor de instancia, se llama al constructor predeterminado de un tipo de valor mediante el operador ne,. 'or ra1ones de e0icacia, el ob$etivo de este re?uisito no es lograr ?ue la implementaci-n genere una llamada de constructor. En el e$emplo siguiente, las dos variables i y j se iniciali1an en cero.
class ' { void V() { int i + 3; int j + ne, int(); ! !

2ado ?ue todos los tipos de valor impl5citamente tienen un constructor de instancias pHblico sin par(metros, un tipo struct no puede contener una declaraci-n expl5cita de un constructor sin par(metros. 4o obstante, en un tipo struct se pueden declarar constructores de instancia con par(metros O[11.3.8R. !.1.3 Tipos de estructura 7n tipo struct es un tipo de valor ?ue puede declarar constantes, campos, m)todos, propiedades, indi1adores, operadores, constructores de instancia, constructores est(ticos y tipos anidados. 8a declaraci-n de los tipos struct se describe en [11.1. !.1.! Tipos simples C# proporciona un con$unto de tipos struct prede0inidos denominados tipos si ples. 8os tipos simples se identi0ican mediante palabras reservadas, pero )stas son sencillamente alias de tipos struct prede0inidos del espacio de nombres System, como se explica en la tabla siguiente.

$6

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

2alabra reser%ada
sbyte byte s"ort us"ort int uint long ulong c"ar -loat double bool decimal

Tipo con alias


System.S:yte System.:yte System.$nt2X System.;$nt2X System.$nt98 System.;$nt98 System.$ntXJ System.;$ntXJ System.C"ar System.Single System.6ouble System.:oolean System.6ecimal

Como un tipo simple e?uivale a un tipo struct, todos los tipos simples tienen miembros. 'or e$emplo, int tiene los miembros declarados en System.$nt98 y los miembros =eredados de System.%bject, y se permiten las siguientes instruccionesG
int i + int.Ma#Ualue; string s + i.1oString(); string t + 289.1oString(); .. System.$nt98.Ma#Ualue constant .. System.$nt98.1oString() instance met"od .. System.$nt98.1oString() instance met"od

8os tipos simples se di0erencian de otros tipos struct en ?ue permiten determinadas operaciones adicionalesG 8a mayor5a de los tipos simples permiten la creaci-n de valores mediante la escritura de literales O[2.4.4R. 'or e$emplo, 289 es un literal del tipo int y WaW es un literal del tipo c"ar. C# no proporciona literales de tipos struct en general, y los valores no predeterminados de otros tipos struct se crean siempre en Hltimo t)rmino mediante constructores de instancia de dic=os tipos struct. Cuando todos los operandos de una expresi-n son constantes de tipo simple, es posible ?ue el compilador evalHe la expresi-n en tiempo de compilaci-n. 2ic=a expresi-n se conoce por el nombre de expresi-n constante Oconstant-e2pressionR O[*.18R. 8as expresiones ?ue incluyen operadores de0inidos por otros tipos struct no se consideran expresiones constantes. %ediante las declaraciones const es posible declarar constantes de los tipos simples O[1".4R. 4o es posible tener constantes de otros tipos struct, pero se consigue un e0ecto similar mediante campos static readonly. 8as conversiones ?ue involucran tipos simples pueden participar en la evaluaci-n de los operadores de conversi-n de0inidos por otros tipos struct, pero un operador de conversi-n de0inido por el usuario no puede participar en la evaluaci-n de otros operadores de0inidos por el usuario O[#.4.3R.

!.1.# Tipos integrales C# admite nueve tipos integralesG sbyte, byte, s"ort, us"ort, int, uint, long integrales tienen los siguientes tamaUos e intervalos de valoresG
ulong y c"ar. 8os tipos

El tipo sbyte, ?ue representa enteros de 8 bits con signo con valores comprendidos entre W128 y 12*. El tipo byte, ?ue representa enteros de 8 bits sin signo con valores comprendidos entre " y 2 .

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

$(

Especificacin del lenguaje C#

El tipo s"ort, ?ue representa enteros de 1# bits con signo con valores comprendidos entre W32*#8 y 32*#*. El tipo us"ort, ?ue representa enteros de 1# bits sin signo con valores comprendidos entre " y # 3 . El tipo int, ?ue representa enteros de 32 bits con signo con valores comprendidos entre W214*483#48 y 214*483#4*. El tipo uint, ?ue representa enteros de 32 bits sin signo con valores comprendidos entre " y 42+4+#*2+ . El tipo long, ?ue representa enteros de #4 bits con signo con valores comprendidos entre W +2233*2"3#8 4** 8"8 y +2233*2"3#8 4** 8"*. El tipo ulong, ?ue representa enteros de #4 bits sin signo con valores comprendidos entre " y 1844#*44"*3*"+ 1#1 . El tipo c"ar representa enteros sin signo de 1# bits con valores entre " y # 3 . El con$unto de valores posibles para el tipo c"ar corresponde al $uego de caracteres 7nicode. &un?ue c"ar tiene la misma representaci-n ?ue us"ort, no todas las operaciones permitidas en un tipo est(n permitidas en el otro.

8os operadores unarios y binarios de tipos integrales siempre traba$an con precisi-n de 32 bits con signo, precisi-n de 32 bits sin signo, precisi-n de #4 bits con signo o precisi-n de #4 bits sin signoG 'ara los operadores unarios < y A, el operando se convierte al tipo 1, donde 1 es el primero de int, uint, long y ulong ?ue puede representar completamente todos los valores posibles del operando. 2espu)s se e$ecuta la operaci-n con la precisi-n del tipo 1, y el tipo del resultado es 1. 'ara el operador unario C, el operando se convierte al tipo 1, donde 1 es el primero de int y long ?ue puede representar completamente todos los valores posibles del operando. 2espu)s se e$ecuta la operaci-n con la precisi-n del tipo 1, y el tipo del resultado es 1. El operador unario C no se puede aplicar a operandos del tipo ulong. 'ara los operadores binarios <, C, >, ., B, F, G, H, ++, @+, E, D, E+ y D+, los operandos se convierten al tipo 1, donde 1 es el primero de int, uint, long y ulong ?ue puede representar completamente todos los valores posibles de los dos operandos. 2espu)s se e$ecuta la operaci-n con la precisi-n del tipo 1, y el tipo del resultado es 1 Oo bool para los operadores relacionalesR. 8os operadores binarios no permiten ?ue un operando sea de tipo long y el otro de tipo ulong. 'ara los operadores binarios DD y EE, el operando i1?uierdo se convierte al tipo 1, donde 1 es el primero de int, uint, long y ulong ?ue puede representar completamente todos los valores posibles del operando. 2espu)s se e$ecuta la operaci-n con la precisi-n del tipo 1, y el tipo del resultado es 1. 4o existen conversiones impl5citas desde otros tipos al tipo c"ar. En concreto, aun?ue los tipos sbyte, byte y us"ort tienen intervalos de valores ?ue son totalmente representables mediante el tipo c"ar, las conversiones impl5citas de sbyte, byte o us"ort a c"ar no existen. 8as constantes de tipo c"ar deben escribirse como literales de caracteres Ocharacter-literalsR o como literales de enteros Ointe&er-literalsR en combinaci-n con una conversi-n al tipo c"ar. 'or e$emplo, (c"ar)23 es lo mismo ?ue WZ#333'W.

El tipo c"ar se clasi0ica como un tipo integral, pero di0iere de otros tipos integrales en dos aspectosG

8os operadores e instrucciones c"ec(ed y unc"ec(ed se utili1an para controlar la comprobaci-n del desbordamiento para las operaciones y conversiones aritm)ticas de tipos integrales O[*. .12R. En un contexto c"ec(ed, un desbordamiento produce un error de tiempo de compilaci-n o causa una excepci-n System.%ver-lo,)#ce&tion. En un contexto unc"ec(ed, los desbordamientos no se tienen en cuenta y los bits de orden superior ?ue no son aceptables para el tipo de destino se descartan.

$$

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

!.1.$ Tipos de punto flotante C# admite dos tipos de punto 0lotanteG -loat y double. 8os tipos -loat y double se representan mediante los 0ormatos !EEE * 4 de 32 bits de precisi-n simple y de #4 bits de precisi-n doble, ?ue proporcionan los siguientes con$untos de valoresG Cero positivo y cero negativo. En la mayor5a de las situaciones, cero positivo y cero negativo tienen un comportamiento id)ntico al del valor simple cero, pero algunas operaciones distinguen entre los dos O[*.*.2R. !n0inito positivo e in0inito negativo. 8os in0initos son generados por operaciones como dividir por cero un nHmero distinto de cero. 'or e$emplo, el resultado de 2.3 . 3.3 es in0inito positivo, y el de C2.3 . 3.3 es in0inito negativo. El valor no num)rico O2ot-a-2! /erR, abreviado normalmente como 4a4. 8os valores 4a4 se generan por operaciones de punto 0lotante no v(lidas, como dividir cero por cero. El con$unto 0inito de valores distintos de cero con el 0ormato s X % X 2e, donde s es 1 o Y1, y % y e est(n determinados por el tipo de punto 0lotante concretoG para -loat, " L % L 224 y Y14+ c e c 1"4, y para double, " L % L 2 3 y Y1"* c e c +*". 8os nHmeros de punto 0lotante sin normali1ar se consideran valores v(lidos distintos de cero.

El tipo -loat puede representar valores comprendidos entre aproximadamente 1. X 1"Y4 y 3.4 X 1"38 con una precisi-n de * d5gitos. El tipo double puede representar valores comprendidos entre aproximadamente ." X 1"Y324 y 1.* X 1"3"8 con una precisi-n de 1 B1# d5gitos. .i uno de los operandos de un operador binario es un tipo de punto 0lotante, el otro debe ser un tipo integral o un tipo de punto 0lotante, y la operaci-n se evalHa como sigueG .i uno de los operandos es un tipo integral, se convierte al tipo de punto 0lotante del otro operando. 2espu)s, si uno de los operandos es de tipo double, el otro se convierte a double, la operaci-n se e$ecuta utili1ando por lo menos el intervalo y la precisi-n double, y el tipo del resultado es double Oo bool para los operadores relacionalesR. / bien, la operaci-n se e$ecuta utili1ando por lo menos el intervalo y la precisi-n -loat y el tipo del resultado es -loat Oo bool para los operadores relacionalesR.

8os operadores de punto 0lotante, incluidos los operadores de asignaci-n, nunca producen excepciones. En lugar de ello, en situaciones excepcionales, las operaciones de punto 0lotante producen cero, in0inito o 4a4, como se explica a continuaci-nG .i el resultado de una operaci-n de punto 0lotante es demasiado pe?ueUo para el 0ormato de destino, el resultado de la operaci-n es cero positivo o cero negativo. .i el resultado de una operaci-n de punto 0lotante es demasiado grande para el 0ormato de destino, el resultado de la operaci-n es in0inito positivo o in0inito negativo. .i una operaci-n de punto 0lotante no es v(lida, el resultado de la operaci-n es 4a4. .i uno o los dos operandos de una operaci-n de punto 0lotante es 4a4, el resultado de la operaci-n es 4a4.

8as operaciones de punto 0lotante pueden reali1arse con mayor precisi-n ?ue el tipo de resultado de la operaci-n. 'or e$emplo, algunas ar?uitecturas de =ard9are admiten el tipo de punto 0lotante PextendedQ o Plong doubleQ con un intervalo y precisi-n mayores ?ue el tipo double, e impl5citamente reali1an todas las operaciones de punto 0lotante utili1ando este tipo de mayor precisi-n. .e puede conseguir ?ue las ar?uitecturas de =ard9are de esta clase realicen operaciones de punto 0lotante con %enor precisi-n s-lo a cambio de un costo

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

$"

Especificacin del lenguaje C#

excesivo en el rendimientoV en ve1 de re?uerir una implementaci-n ?ue penalice tanto el rendimiento como la precisi-n, C# permite utili1ar un tipo de mayor precisi-n para todas las operaciones de punto 0lotante. &parte de proporcionar resultados m(s precisos, esto rara ve1 tiene e0ectos medibles. 4o obstante, en expresiones con la 0orma # > y . ?, donde la multiplicaci-n genera un resultado ?ue sale del intervalo de double, pero la siguiente divisi-n devuelve el resultado temporal al intervalo de double, el =ec=o de ?ue la expresi-n se evalHe en un 0ormato de intervalo mayor puede producir un resultado 0inito en lugar de in0inito. !.1.+ Tipo decimal El tipo decimal es un tipo de datos de 128 bits apto para c(lculos 0inancieros y monetarios. El tipo decimal puede representar valores comprendidos entre aproximadamente 1." X 1"Y28 y *.+ X 1"28 con 28B2+ d5gitos signi0icativos. El con$unto 0inito de valores de tipo decimal tiene la 0orma OW1Rs X c X 1"Be, donde el signo s es " o 1, el coe0iciente c viene dado por " c c L 2+# y la escala e es " c e c 28. El tipo decimal no admite ceros con signo, valores in0initos ni valores 4a4. 7n decimal se representa como un entero de +# bits elevado a die1. 'ara valores decimal con un valor absoluto menor ?ue 2.3m, el valor es exacto s-lo =asta la posici-n decimal 28. 'ara valores decimal con un valor absoluto mayor o igual ?ue 2.3m, el valor es exacto =asta el d5gito 28 o 2+. &l contrario ?ue los tipos de datos -loat y double, los nHmeros 0raccionarios decimales como ",1 pueden representarse exactamente en la representaci-n decimal. En las representaciones -loat y double, estos nHmeros con 0recuencia son 0racciones in0initas, lo ?ue las =ace m(s susceptibles de errores de redondeo. .i uno de los operandos de un operador binario es de tipo decimal, el otro debe ser un tipo integral o un tipo decimal. .i est( presente un operando de tipo integral, se convertir( a decimal antes de reali1ar la operaci-n. El resultado de una operaci-n con valores de tipo decimal es el ?ue resultar5a de calcular un resultado exacto Oconservando la escala, segHn lo de0inido por cada operadorR y, a continuaci-n, redondearlo para a$ustarse a la representaci-n. El resultado se redondea =asta el valor representable m(s pr-ximo y, en caso de ?ue un resultado tenga la misma proximidad con dos valores representables, se redondea al valor ?ue tenga un nHmero par en la posici-n del d5gito menos signi0icativo Oesto se conoce como Predondeo de bancaQR. 7n resultado cero siempre tiene un signo " y una escala ". .i una operaci-n aritm)tica decimal genera un valor menor o igual ?ue X 1"B2+ en valor absoluto, el resultado de la operaci-n es cero. .i una operaci-n aritm)tica decimal genera un resultado demasiado grande para el 0ormato decimal, se origina una excepci-n System.%ver-lo,)#ce&tion. El tipo decimal tiene una precisi-n mayor, pero un intervalo menor, ?ue los tipos de punto 0lotante. 'or lo tanto, las conversiones de los tipos de punto 0lotante a decimal pueden producir excepciones de desbordamiento, y las conversiones de decimal a los tipos de punto 0lotante pueden causar una p)rdida de precisi-n. 'or estos motivos, no existen conversiones impl5citas entre los tipos de punto 0lotante y decimal, y sin conversiones expl5citas, no es posible combinar operandos de punto 0lotante y decimal en la misma expresi-n. !.1.- Tipo bool El tipo bool representa cantidades l-gicas booleanas. 8os valores posibles del tipo bool son true y -alse. 4o existen conversiones est(ndar entre bool y otros tipos. En concreto, el tipo bool es Hnico y exclusivo de los tipos integrales, y un valor bool no puede sustituir a un valor integral, ni viceversa. En los lengua$es C y CSS, un valor integral o de punto 0lotante cero, o un puntero de valor null, pueden convertirse al valor booleano -alse, y un valor integral o de punto 0lotante distinto de cero o un puntero con un valor distinto de null pueden convertirse al valor booleano true. En C#, las conversiones de esta categor5a se llevan a cabo mediante la comparaci-n expl5cita de un valor integral o de punto 0lotante con cero, o mediante la comparaci-n expl5cita de una re0erencia de ob$eto con null.

"'

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

!.1.. Tipos de enumeracin 7n tipo de enumeraci-n es un tipo exclusivo con constantes con nombre. Todos los tipos de enumeraci-n tienen un tipo subyacente, ?ue debe ser byte, sbyte, s"ort, us"ort, int uint long o ulong. El con$unto de valores del tipo de enumeraci-n es el mismo ?ue el del con$unto de valores del tipo subyacente. 8os valores del tipo de la enumeraci-n no se restringen a los valores de las constantes nombradas. 8os tipos de enumeraci-n se de0inen mediante declaraciones de enumeraci-n O[14.1R. !.1.10 Tipos ;ue aceptan alores 1566 7n tipo ?ue acepta valores 4788 puede representar todos los valores de su tipo s!/yacente m(s un valor 4788 adicional. 7n tipo 4788 se escribe como 17, donde 1 es el tipo subyacente. Esta sintaxis es la 0orma abreviada de System.NullableD1E y las dos 0ormas se pueden utili1ar indistintamente. 2e manera inversa, un tipo de valor "!e no acepta valores 2300 es cual?uier tipo de valor distinto de System.NullableD1E y su 0orma abreviada 17 Opara cual?uier 1R, m(s cual?uier par(metro de tipo restringido a tipos de valor ?ue no acepten valores 4788 Oes decir, cual?uier par(metro de tipo con una restricci-n structR. El tipo System.NullableD1E especi0ica la restricci-n de tipo de valor para 1 ([1".1. ), lo ?ue signi0ica ?ue el tipo de valor subyacente de un tipo ?ue acepta valores 4788 puede ser cual?uier valor ?ue no acepte valores 4788. El tipo subyacente de un tipo ?ue no acepte valores 4788 no puede ser un tipo ?ue acepte valores 4788 ni un tipo de re0erencia. 'or e$emplo, int77 y string7 no son tipos v(lidos. 7na instancia de un tipo 17 ?ue acepta valores 4788 tiene dos propiedades de s-lo lectura pHblicasG 7na propiedad HasUalue del tipo bool 7na propiedad Ualue del tipo 1

7na instancia para la ?ue HasUalue es verdadera no es 4788. 7na instancia ?ue no es 4788 contiene un valor conocido y Ualue devuelve dic=o valor. 7na instancia para la ?ue HasUalue es 0also se dice ?ue es 4788. 7na instancia 4788 tiene un valor no de0inido. .i intenta leer Ualue de una instancia 4788 se genera una excepci-n System.$nvalid%&eration)#ce&tion. El proceso de tener acceso a la propiedad Ualue de una instancia ?ue acepta valores 4788 se conoce como desa1!star. &dem(s del constructor predeterminado, cada tipo 17 ?ue acepta valores 4788 tiene un constructor pHblico ?ue adopta un argumento Hnico del tipo 1. 2ado un valor # del tipo 1, una invocaci-n de constructor con la estructura
ne, 17(#)

crea una instancia 17 ?ue no acepta valores 4788 para los ?ue la propiedad Ualue es #. El proceso de crear una instancia ?ue no acepta valores 4788 de un tipo ?ue s5 acepta valores 4788 para un valor dado se conoce como a1!star. Existen conversiones impl5citas desde el literal null a 17 O[R y desde 1 a 17 O[#.1.4R.

!.2 Tipos de referencia


7n tipo de re0erencia es un tipo de clase, un tipo de inter0a1, un tipo de matri1 o un tipo delegado. reference-t#pe1 class-t#pe interface-t#pe arra#-t#pe dele&ate-t#pe

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

"1

Especificacin del lenguaje C#

class-t#pe1 t#pe-na%e
object string

interface-t#pe1 t#pe-na%e arra#-t#pe1 non-arra#-t#pe ran3-specifiers non-arra#-t#pe1 t#pe ran3-specifiers1 ran3-specifier ran3-specifiers ran3-specifier ran3-specifier1 4 di%-separatorsopt 5 di%-separators1 di%-separators dele&ate-t#pe1 t#pe-na%e 7n valor de tipo de re0erencia es una re0erencia a una instancia del tipo, ?ue se conoce como o/1eto. El valor especial null es compatible con todos los tipos de re0erencia e indica la ausencia de una instancia. !.2.1 Tipos de clase 7n tipo de clase de0ine una estructura de datos ?ue contiene miembros de datos Oconstantes y camposR, miembros de 0unci-n Om)todos, propiedades, eventos, indi1adores, operadores, constructores de instancia, destructores y constructores est(ticosR y tipos anidados. 8os tipos de clase admiten la =erencia, un mecanismo mediante el cual una clase derivada puede extender y especiali1ar a las clases base. 8as instancias de los tipos de clase se crean mediante expresiones de creaci-n de ob$etos Oo->ect-creation-e2pressionsR O[*. .1".1R. 8os tipos de clase se describen en [1". Ciertos tipos de clases prede0inidos tienen un signi0icado especial en el lengua$e C#, tal como se describe en la siguiente tabla. Tipo de clase
System.%bject System.String System.Ualue1y&e System.)num System.'rray System.6elegate System.)#ce&tion

+escripcin Clase base de0initiva de todos los dem(s tipos. >ea [. El tipo de cadena del lengua$e de C#. >ea [. 8a clase base de todos los tipos de valor. >ea [. 8a clase base de todos los tipos enum. >ea [. 8a clase base de todos los tipos de matri1. >ea [. 8a clase base de todos los tipos de delegado. >ea [. 8a clase base de todos los tipos de excepci-n. >ea [.

"2

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

!.2.2 Tipo object El tipo de clase object es la clase base de0initiva de todos los dem(s tipos. Todos los tipos de C# se derivan directa o indirectamente del tipo de clase object. 8a palabra clave object no es m(s ?ue un alias de la clase prede0inida System.%bject. !.2.3 Tipo string El tipo string es un tipo de clase sealed ?ue =ereda directamente de object. 8as instancias de la clase string representan cadenas de caracteres 7nicode. 8os valores del tipo string pueden escribirse como literales de cadena O[2.4.4. R. 8a palabra clave string no es m(s ?ue un alias de la clase prede0inida System.String. !.2.! Tipos de interfa8 7na inter0a1 de0ine un contrato. 7na clase o estructura ?ue implementa una inter0a1 debe ad=erirse a su contrato. 7na inter0a1 puede derivarse de varias inter0aces base, y una clase o estructura puede implementar varias inter0aces. 8os tipos de inter0a1 se describen en [13. !.2.# Tipos de matri8 7na matri1 es una estructura de datos ?ue contiene cero o m(s variables, a las ?ue se obtiene acceso a trav)s de 5ndices calculados. 8as variables contenidas en una matri1, tambi)n conocidas como elementos de la matri1, son todas del mismo tipo, denominado tipo de elemento de la matri1. 8os tipos de matri1 se describen en [12. !.2.$ Tipos de delegados 7n delegado es una estructura de datos ?ue =ace re0erencia a uno o m(s m)todos. 'ara los m)todos de instancia, se re0iere tambi)n a sus correspondientes instancias de ob$eto. El e?uivalente m(s cercano de un delegado en C o CSS es un puntero a una 0unci-n pero, mientras ?ue )ste s-lo puede =acer re0erencia a 0unciones est(ticas, un delegado puede =acer re0erencia tanto a m)todos est(ticos como a m)todos de instancia. En este caso, el delegado no s-lo almacena una re0erencia al punto de entrada del m)todo, sino ?ue tambi)n almacena una re0erencia a la instancia de ob$eto para el ?ue se invoca el m)todo. 8os tipos de delegado se describen en [1 .

!.3 %on ersiones bo"ing y unbo"ing


El concepto de boxing y unboxing desempeUa un papel central en el sistema de tipos de C#. .irven como enlace entre los tipos de valor Oval e-t#pesR y los tipos de re0erencia Oreference-t#pesR, al permitir la conversi-n de cual?uier valor de un tipo de valor Oval e-t#peR al tipo object y viceversa. 8as conversiones boxing y unboxing =abilitan una visi-n uni0icada del sistema de tipos en la ?ue un valor de cual?uier tipo puede tratarse b(sicamente como un ob$eto. !.3.1 %on ersiones bo"ing 7na conversi-n boxing permite ?ue un tipo de valor Oval e-t#peR se convierta impl5citamente en un tipo de re0erencia Oreference-t#peR. Existen los siguientes tipos de conversiones boxingG 2e cual?uier tipo de valor Oval e-t#peR al tipo object.

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

"3

Especificacin del lenguaje C#

2e cual?uier tipo de valor Oval e-t#peR al tipo System.Ualue1y&e. 2e cual?uier tipo de valor ?ue no acepta valores 4788 Onon-n lla-le-val e-t#peR a cual?uier tipo de inter0a1 Ointerface-t#peR implementada por el tipo de valor Oval e-t#peR. 2e cualquier tipo de valor ?ue no acepta valores 4788 Onon-n lla-le-val e-t#peR a cual?uier tipo de inter0a1 Ointerface-t#peR implementada por el tipo subyacente del tipo ?ue acepta valores 4788 On lla-le-t#peR. 2e cual?uier tipo enum Oen %-t#peR al tipo System.)num. 2e cual?uier tipo ?ue acepta valores 4788 On lla-le-t#peR con un tipo enum Oen %-t#peR subyacente al tipo System.)num. Tenga en cuenta ?ue una conversi-n impl5cita desde un par(metro de tipo se e$ecutar( como una conversi-n boxing si, en tiempo de e$ecuci-n, termina convirti)ndose desde un tipo de valor a un tipo de re0erencia O[#.1.+R.

8a conversi-n boxing de un tipo de valor ?ue no acepta valores 4788 Onon-n lla-le-val e-t#peR consiste en asignar una instancia del ob$eto y despu)s copiar el tipo de valor ?ue no acepta valores 4788 Onon-n lla-leval e-t#peR en esa instancia. 8a conversi-n boxing de un valor de un tipo ?ue acepta valores 4788 On lla-le-t#peR produce una re0erencia 4788 si se trata de un valor null OHasUalue es -alseR, o el resultado de desa$ustar y reali1ar una conversi-n boxing en el valor subyacente de lo contrario. El proceso real de conversi-n boxing del valor de un tipo de valor ?ue no acepta valores 4788 Onon-n lla-leval e-t#peR se entiende me$or si uno se imagina la existencia de una clase /o.ing gen)rica, ?ue se comporta como si estuviera declarada de la siguiente 0ormaG
sealed class :o#D1E/ System.Ualue1y&e { 1 value; &ublic :o#(1 t) { value + t; ! !

8a conversi-n boxing de un valor v de tipo 1 consiste a=ora en e$ecutar la expresi-n :o#D1E(v) y devolver la instancia resultante como un valor de tipo object. 'or lo tanto, las instrucciones
int i + 289; object bo# + i;

conceptualmente se corresponden con


int i + 289; object bo# + ne, :o#DintE(i);

8a conversi-n boxing de una clase como :o#D1E no existe en realidad y el tipo din(mico de un valor al ?ue se =a aplicado la conversi-n boxing no es realmente un tipo de clase. En lugar de ello, un valor convertido mediante boxing de tipo 1 tiene el tipo din(mico 1, y una comprobaci-n de tipo din(mico ?ue usa el operador is sencillamente puede =acer re0erencia al tipo 1. 'or e$emploG
int i + 289; object bo# + i; i- (bo# is int) { Console.Write(":o# contains an int"); !

devolver( la cadena P:o# contains an intQ en la consola.

"#

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

7na conversi-n boxing implica la creaci/n de na copia del valor al ?ue se aplica la conversi-n. Esto es distinto de la conversi-n de un tipo de re0erencia Oreference-t#peR a un tipo object, en la cual el valor sigue =aciendo re0erencia a la misma instancia y sencillamente se considera como el tipo object menos derivado. 'or e$emplo, dada la declaraci-n
struct *oint { &ublic int # y; int y) {

&ublic *oint(int # t"is.# + #; t"is.y + y; ! !

las siguientes instrucciones


*oint & + ne, *oint(23 23); object bo# + &; &.# + 83; Console.Write(((*oint)bo#).#);

muestran en la consola el valor 1", por?ue la operaci-n boxing impl5cita ?ue ocurre en la asignaci-n de & a bo# causa la copia del valor de &. En cambio, si se =ubiera declarado *oint como class, el resultado ser5a 2", puesto ?ue & y bo# =ar5an re0erencia a la misma instancia. !.3.2 %on ersiones 5nbo"ing 7na conversi-n unboxing permite ?ue un tipo de re0erencia Oreference-t#peR se convierta expl5citamente en un tipo de valor Oval e-t#peR. Existen los siguientes tipos de conversiones unboxingG 2e cual?uier tipo object a cual?uier tipo de valor Oval e-t#peR. 2e cual?uier tipo System.Ualue1y&e a cual?uier tipo de valor Oval e-t#peR. 2e cual?uier tipo de inter0a1 Ointerface-t#peR a cual?uier tipo de valor ?ue no acepta valores 4788 Ononn lla-le-val e-t#peR ?ue implementa el tipo de inter0a1 Ointerface-t#peR. 2e cual?uier tipo de inter0a1 Ointerface-t#peR a cual?uier tipo ?ue acepta valores 4788 On lla-le-t#peR cuyo tipo subyacente implementa el tipo de inter0a1 Ointerface-t#peR. 2el tipo System.)num a cual?uier tipo enum Oen %-t#peR. 2e tipo System.)num a cual?uier tipo ?ue acepta valores 4788 On lla-le-t#peR con un tipo enum Oen %t#peR subyacente. Tenga en cuenta ?ue una conversi-n expl5cita a un par(metro de tipo se e$ecutar( como una conversi-n unboxing si, en tiempo de e$ecuci-n, termina convirti)ndose desde un tipo de re0erencia a un tipo de valor O[#.2.#R.

7na operaci-n unboxing a un tipo de valor ?ue no acepta valores 4788 Onon-n lla-le-val e-t#peR consiste en comprobar primero ?ue la instancia del ob$eto es un valor al ?ue se =a aplicado la conversi-n boxing de un tipo de valor determinado ?ue no acepta valores 4788 Onon-n lla-le-val e-t#peR, y copiar despu)s el valor 0uera de la instancia. 8a conversi-n unboxing a un tipo ?ue acepta valores 4788 On lla-le-t#peR produce el valor 4788 de dic=o tipo si el operando de origen es null, o el resultado desa$ustado de reali1ar una conversi-n unboxing en la instancia de ob$eto al tipo de valor subyacente desde el tipo ?ue acepta valores 4788 On lla-le-t#peR en caso contrario.

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

"!

Especificacin del lenguaje C#

En cuanto a la clase boxing imaginaria descrita en la secci-n anterior, una conversi-n unboxing de un ob$eto bo# a un tipo de valor 1 consiste en e$ecutar la expresi-n ((:o#D1E)bo#).value. 'or lo tanto, las instrucciones
object bo# + 289; int i + (int)bo#;

conceptualmente se corresponden con


object bo# + ne, :o#DintE(289); int i + ((:o#DintE)bo#).value;

'ara ?ue una conversi-n unboxing a un tipo de valor dado ?ue no acepta valores 4788 Onon-n lla-le-val et#peR se e$ecute correctamente en tiempo de e$ecuci-n, el valor del operando de origen debe ser una re0erencia a un ob$eto creado mediante una conversi-n boxing de ese tipo de valor ?ue no acepta valores 4788 Ononn lla-le-val e-t#peR. .i el operando de origen tiene valor null, se producir( una excepci-n System.NullOe-erence)#ce&tion. .i el operando de origen es una re0erencia a un ob$eto incompatible, se producir( una excepci-n System.$nvalidCast)#ce&tion. 'ara ?ue una conversi-n unboxing a un tipo de valor dado ?ue acepta valores 4788 On lla-le-t#peR se e$ecute correctamente en tiempo de e$ecuci-n, el valor del operando de origen debe ser null o una re0erencia a un valor creado mediante la conversi-n boxing del tipo de valor ?ue no acepta valores 4788 Onon-n lla-le-val e-t#peR subyacente del tipo ?ue acepta valores 4788 n lla-le-t#pe. .i el operando de origen es una re0erencia a un ob$eto incompatible, se producir( una excepci-n System.$nvalidCast)#ce&tion.

!.! Tipos construidos


7na declaraci-n de tipo gen)rico, por s5 misma, denota un tipo gen6rico sin enla-ar ?ue se utili1a como P=uellaQ para 0ormar muc=os tipos di0erentes aplicando arg! entos de tipo. 8os argumentos de tipo se escriben entre corc=etes angulares OD y ER inmediatamente despu)s del nombre de la declaraci-n de tipo gen)rico. 7n tipo ?ue incluye al menos un argumento de tipo se llama un tipo constr!ido. 7n tipo construido se puede utili1ar en la mayor5a de lugares en el idioma en el ?ue puede aparecer el nombre del tipo. 7n tipo gen)rico independiente s-lo se puede utili1ar dentro de una expresi-n typeo0 Ot#peof-e2pressionR O[*. .11R. 8os tipos construidos tambi)n se pueden utili1ar en expresiones como nombres simples O[*. .2R o cuando se obtiene acceso a un miembro O[*. .4R. &l evaluar un nombre de espacio de nombres o de tipo Ona%espace-or-t#pe-na%eR s-lo se tienen en cuenta los tipos gen)ricos con el nHmero correcto de par(metros tipo. 'or lo tanto, es posible utili1ar el mismo identi0icador para identi0icar tipos di0erentes siempre y cuando los tipos tengan di0erente nHmero de par(metros de tipo. Esto resulta Htil al me1clar clases gen)ricas y no gen)ricas en el mismo programaG
names&ace Widgets { class ^ueue {...! class ^ueueD1)lementE {...! ! names&ace My'&&lication { using Widgets; class I { ^ueue Q2; ^ueueDintE Q8; ! !

.. Non=generic Widgets.^ueue .. Seneric Widgets.^ueue

Es posible ?ue un nombre de tipo Ot#pe-na%eR identi0i?ue un tipo construido aun?ue )ste no especi0i?ue directamente par(metros de tipo. Esto puede ocurrir si un tipo est( anidado dentro de una declaraci-n de clase

"6

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

gen)rica y el tipo de instancia de la declaraci-n contenedor se utili1a de manera impl5cita para la bHs?ueda de nombres O[1".3.8.#RG
class %uterD1E { &ublic class $nner {...! &ublic $nner i; ! .. 1y&e o- i is %uterD1E.$nner

En c-digo no seguro, un tipo construido no se puede utili1ar como un tipo no administrado O n%ana&ed-t#peR O[18.2R. !.!.1 'rgumentos de tipo Cada argumento de una lista de argumentos de tipo es simplemente un tipo Ot#peR. t#pe-ar& %ent-list1 D t#pe-ar& %ents E t#pe-ar& %ents1 t#pe-ar& %ent t#pe-ar& %ents t#pe-ar& %ent1 t#pe En c-digo no seguro O[18R, es posible ?ue un argumento de tipo Ot#pe-ar& %entR no sea un tipo de puntero. Cada argumento de tipo debe respetar todas las restricciones del par(metro tipo correspondiente O[1".1. R. !.!.2 Tipos cerrados y abiertos Todos los tipos se pueden clasi0icar como tipos a/iertos o tipos cerrados. 7n tipo abierto es un tipo ?ue implica par(metros de tipo. ConcretamenteG 7n par(metro de tipo de0ine un tipo abierto. 7n tipo de matri1 es un tipo abierto solamente si su tipo de elemento es un tipo abierto. 7n tipo construido es un tipo abierto s-lo si uno o m(s de sus argumentos de tipo es un tipo abierto. 7n tipo anidado construido es un tipo abierto s-lo si uno o m(s de sus argumentos de tipo o los argumentos de tipo de sus tipos contenedores son un tipo abierto.

t#pe-ar& %ent

7n tipo cerrado es un tipo ?ue no es abierto. En tiempo de e$ecuci-n, todos los c-digos de una declaraci-n de tipo gen)rico se e$ecutan en el contexto de un tipo construido cerrado creado al aplicar argumentos de tipo a la declaraci-n gen)rica. Cada par(metro de tipo dentro del tipo gen)rico est( enla1ado a un tipo concreto en tiempo de e$ecuci-n. El proceso en tiempo de e$ecuci-n de todas las instrucciones y expresiones siempre tiene lugar con tipos cerradosV los tipos abiertos s-lo tienen lugar durante el proceso en tiempo de compilaci-n. Cada tipo construido cerrado tiene su propio con$unto de variables est(ticas, ?ue no se comparten con otros tipos construidos cerrados. 8os tipos abiertos no se dan en tiempo de e$ecuci-n y, por lo tanto, no tienen variables est(ticas asociadas. 2os tipos construidos cerrados son el mismo tipo si est(n construidos desde el mismo tipo gen)rico independiente y sus argumentos de tipo correspondientes son el mismo tipo. !.!.3 Tipos enla8ados y sin enla8ar El t)rmino tipo sin enla-ar =ace re0erencia a un tipo no gen)rico o a un tipo gen)rico sin enla1ar. El t)rmino tipo enla-ado =ace re0erencia a un tipo no gen)rico o a un tipo construido.

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

"(

Especificacin del lenguaje C#

7n tipo sin enla1ar =ace re0erencia a la entidad declarada por una declaraci-n de tipo. 7n tipo gen)rico sin enla1ar no es un tipo en s5 mismo, y no se puede usar como tipo de una variable, argumento o valor devuelto, ni como un tipo base. 8a Hnica construcci-n en la ?ue se puede =acer re0erencia a un tipo gen)rico sin enla1ar es la expresi-n ty&eo- O[*. .11R. !.!.! %umplimiento de las restricciones .iempre ?ue se =aga re0erencia a un tipo construido o a un m)todo gen)rico, los argumentos de tipo suministrados se cote$an con las restricciones de par(metro de tipo declaradas en el tipo o m)todo gen)ricos O[1".1. R. 'ara cada cl(usula ,"ere, el argumento de tipo ' ?ue corresponde al par(metro de tipo denominado se cote$a con cada una de las restricciones de la siguiente maneraG .i la restricci-n es un tipo de clase o de inter0a1, o un par(metro de tipo, C debe representar dic=a restricci-n con los argumentos de tipo suministrados sustituidos por cual?uier par(metro de tipo ?ue apare1ca en la restricci-n. 'ara cumplir la restricci-n se debe dar el caso de ?ue el tipo ' se pueda convertir en el tipo C por uno de los siguientes m)todosG o o o o 7na conversi-n de identidad O[#.1.1R 7na conversi-n de re0erencia impl5cita O[#.1.4R 7na conversi-n boxing O[#.1. R, siempre y cuando el tipo & sea un tipo ?ue no acepta valores 4788. 7na conversi-n de re0erencia impl5cita, boxing o de par(metro de tipo a partir de un par(metro de tipo ' a C O[R.

.i la restricci-n es la restricci-n de tipo de re0erencia OclassR, el tipo ' debe cumplir las siguientes condicionesG o o
' es un tipo de inter0a1, de clase, de delegado o de matri1. Tenga en cuenta ?ue System.Ualue1y&e y System.)num son tipos de re0erencia ?ue cumplen esta restricci-n. ' es un par(metro de tipo ?ue es un tipo de re0erencia O[1".1. R.

.i la restricci-n es la restricci-n de tipo de valor OstructR, el tipo ' debe cumplir una de las siguientes condicionesG o o
' es un tipo struct o un tipo enum, pero no un tipo ?ue acepte valores 4788. Tenga en cuenta ?ue System.Ualue1y&e y System.)num son tipos de re0erencia ?ue no cumplen esta restricci-n. ' es un par(metro de tipo ?ue tiene la restricci-n de tipo de valor O[1".1. R.

.i la restricci-n es la restricci-n del constructor ne,(), el tipo ' no debe ser abstract y debe tener un constructor pHblico sin par(metros. Esta condici-n se cumple si una de las siguientes a0irmaciones es verdaderaG o o o o o
' es un tipo de valor puesto ?ue todos los tipos de valor tienen un constructor pHblico predeterminado

O[4.1.2R.
' es un par(metro de tipo ?ue tiene la restricci-n de constructor O[1".1. R. ' es un par(metro de tipo ?ue tiene la restricci-n de tipo de valor O[1".1. R. ' es una clase ?ue no es abstract y contiene un constructor &ublic expl5citamente declarado sin

par(metros.
' no es abstract y tiene un constructor predeterminado O[1".1".4R.

.e genera un error en tiempo de compilaci-n si los argumentos de tipo dados no cumplen una o m(s de las restricciones de un par(metro de tipo.
"$
Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

'uesto ?ue los par(metros tipo no se =eredan, tampoco se =eredan las restricciones. En el siguiente e$emplo, 6 debe especi0icar la restricci-n en su par(metro de tipo 1 para ?ue 1 cumpla con la restricci-n impuesta por la clase base :D1E. 'or el contrario, no es necesario ?ue ) especi0i?ue una restricci-n por?ue ListD1E implementa $)numerable para cual?uier 1.
class :D1E ,"ere 1/ $)numerable {...! class 6D1E/ :D1E ,"ere 1/ $)numerable {...! class )D1E/ :DListD1EE {...!

!.# (ar)metros de tipo


7n par(metro de tipo es un identi0icador ?ue designa un tipo de valor o tipo de re0erencia al ?ue el par(metro est( enla1ado en tiempo de e$ecuci-n. t#pe-para%eter1 identificador 'uesto ?ue se puede crear una instancia para un par(metro de tipo con muc=os argumentos de tipo reales di0erentes, los par(metros de tipo tienen operaciones y restricciones ligeramente di0erentes a las de otros tipos. & continuaci-n se enumeran algunas de ellasG 7n par(metro de tipo no se puede utili1ar directamente para declarar una inter0a1 o una clase base O[1".2.4R. 8as reglas para la bHs?ueda de miembros en par(metros de tipo dependen de las restriccionesV si existe alguna, se aplica al par(metro de tipo. En la secci-n [*.3 se proporcionan m(s detalles. 8as conversiones disponibles para un par(metro de tipo dependen de las restricciones, si existen, ?ue se apli?uen al par(metro de tipo. En las secciones [ y [ se proporcionan m(s detalles. El literal null no se puede convertir a un tipo dado por un par(metro de tipo a menos ?ue el par(metro de tipo sea un tipo de re0erencia O[#.1.+R. .in embargo, se puede utili1ar en su lugar una expresi-n de-ault O[*. .13R. &dem(s, un valor con un tipo dado por un par(metro de tipo se p ede comparar con null utili1ando ++ y @+ O[*.+.#R, a menos ?ue el par(metro de tipo tenga la restricci-n de tipo de valor. 7na expresi-n ne, O[*. .1".1R s-lo se puede utili1ar con un par(metro de tipo si el par(metro de tipo est( restringido por una restricci-n de constructor Oconstr ctor-constraintR o la restricci-n del tipo de valor O[1".1. R. 7n par(metro de tipo no se puede utili1ar en cual?uier parte dentro de un atributo. 7n par(metro de tipo no se puede utili1ar en un acceso a miembros O[*. .4R ni en un nombre de tipo O[3.8R para identi0icar un miembro static o un tipo anidado. En c-digo no seguro, un par(metro de tipo no se puede utili1ar como un tipo n%ana&ed-t#pe O[18.2R.

Como un tipo, los par(metros de tipo son una construcci-n en tiempo de compilaci-n. En tiempo de e$ecuci-n, cada par(metro de tipo est( vinculado a un tipo en tiempo de e$ecuci-n ?ue se especi0ica al proporcionar un argumento de tipo a la declaraci-n de tipo gen)rico. 'or lo tanto, el tipo de una variable declarado con un par(metro de tipo ser( un tipo construido cerrado en tiempo de e$ecuci-n O[4.4.2R. 8a e$ecuci-n en tiempo de e$ecuci-n de todas las instrucciones y expresiones ?ue implican los par(metros de tipo utili1a el tipo real ?ue se proporcion- como el argumento de tipo para dic=o par(metro.

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

""

Especificacin del lenguaje C#

!.$ Tipos de )rbol de e"presiones


8os 5r/oles de e.presiones permiten ?ue las 0unciones an-nimas sean representadas como estructuras de datos en lugar de como c-digo e$ecutable. 8os (rboles de expresiones son valores de tipos de 5r/ol de e.presiones con la estructura System.LinQ.)#&ressions.)#&ressionD6E, donde 6 es cual?uier tipo delegado. En adelante =aremos re0erencia a estos tipos mediante la 0orma abreviada )#&ressionD6E. .i existe una conversi-n desde una 0unci-n an-nima a un tipo delegado 6, tambi)n existe una conversi-n al tipo de (rbol expresiones )#&ressionD6E. %ientras ?ue la conversi-n de una 0unci-n an-nima a un tipo delegado genera un delegado ?ue =ace re0erencias a c-digo e$ecutable para la 0unci-n an-nima, la conversi-n a un tipo de (rbol de expresiones crea una representaci-n de (rbol de expresiones de la 0unci-n an-nima. 8os (rboles de expresiones son representaciones e0icientes de datos en memoria de 0unciones an-nimas y =acen ?ue la estructura de la 0unci-n an-nima sea transparente y expl5cita. &l igual ?ue un tipo delegado 6, se considera ?ue )#&ressionD6E tiene tipos devueltos y de par(metro, ?ue son los mismos de 6. En el e$emplo siguiente se representa una 0unci-n an-nima como c-digo e$ecutable y como (rbol de expresiones. 2ado ?ue existe una conversi-n a VuncDint intE, tambi)n existe una conversi-n a )#&ressionDVuncDint intEEG
VuncDint intE del + # +E # < 2; )#&ressionDVuncDint intEE e#& + # +E # < 2; .. Code .. 6ata

.iguiendo estas asignaciones, el delegado del =ace re0erencia a un m)todo ?ue devuelve # < 2, y el (rbol de expresiones e#& =ace re0erencia a la estructura de datos ?ue describe la expresi-n # +E # < 2. Tanto la de0inici-n exacta del tipo gen)rico )#&ressionD6E como las reglas precisas para construir un (rbol de expresiones cuando una 0unci-n an-nima se convierte a un tipo de (rbol de expresiones superan el (mbito de este documento, por lo ?ue se describen en otros. Es importante seUalar dos cosas. 4o todas las 0unciones an-nimas se pueden representar como (rboles de expresiones. 'or e$emplo, no se pueden representar 0unciones an-nimas con cuerpos de instrucci-n, ni 0unciones an-nimas ?ue contengan expresiones de asignaciones. !ncluso en estos casos existe una conversi-n, pero no se producir( correctamente en tiempo de compilaci-n.
)#&ressionD6E o0rece un m)todo de instancia Com&ile ?ue produce un delegado de tipo 6G VuncDint intE del8 + e#&.Com&ile();

&l invocar a este delegado se provoca la e$ecuci-n del c-digo representado por el (rbol de expresiones. &s5, dadas las de0iniciones anteriores, del y del2 son e?uivalentes, y las dos instrucciones siguientes tendr(n el mismo e0ectoG
int i2 + del(2); int i8 + del8(2);

2espu)s de e$ecutar este c-digo, tanto i2 como i8 tendr(n el valor 8.

1''

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

#. Variables
8as variables representan ubicaciones de almacenamiento. Toda variable tiene un tipo, ?ue determina los valores ?ue pueden almacenarse en ella. C# es un lengua$e con seguridad de tipos, y el compilador de C# garanti1a ?ue los valores almacenados en variables siempre son del tipo apropiado. El valor de una variable puede modi0icarse mediante una asignaci-n o con el uso de los operadores << y ==. 7na variable debe estar definitiva ente asignada O[ .3R para ?ue pueda obtenerse su valor. Como se explica en las secciones siguientes, las variables pueden ser asignadas inicial ente o no asignadas inicial ente. 7na variable asignada inicialmente tiene un valor inicial bien de0inido y siempre se considera asignada de0initivamente. 7na variable no asignada inicialmente no tiene un valor inicial. 'ara ?ue una variable no asignada inicialmente se considere asignada de0initivamente en una ubicaci-n determinada, debe ocurrir una asignaci-n de la variable en todas las rutas de e$ecuci-n posibles ?ue condu1can a dic=a ubicaci-n.

#.1 %ategor2as de ariables


C# de0ine siete categor5as de variablesG variables est(ticas, variables de instancia, elementos de matri1, par(metros de valores, par(metros de re0erencia, par(metros de salida y variables locales. En las pr-ximas secciones se describen estas categor5as. En el e$emplo
class ' { &ublic static int #; int y; void V(int45 v int a int i + 2; c + a < b<<; ! ! # es una variable est(tica, y es una variable de instancia, v435 es un elemento de matri1, a es un par(metro de valores, b es un par(metro de re0erencias, c es un par(metro de salida e i es una variable local. re- int b out int c) {

#.1.1 Variables est)ticas 7n campo declarado con el modi0icador static se denomina varia/le est5tica. 7na variable est(tica se genera antes de la e$ecuci-n del constructor est(tico O[1".12R de su tipo contenedor, y de$a de existir a la ve1 ?ue el dominio de aplicaci-n asociado. El valor inicial de una variable est(tica es el valor predeterminado O[ .2R del tipo de la variable. 'ara los 0ines de comprobaci-n de asignaci-n de0initiva, una variable est(tica se considera asignada inicialmente. #.1.2 Variables de instancia 7n campo declarado sin el modi0icador static se denomina varia/le de instancia.

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

1'1

Especificacin del lenguaje C#

.1.2.1 .ariables de instancia en clases 7na variable de instancia de una clase se genera cuando se crea una nueva instancia de esa clase, y de$a de existir cuando no =ay re0erencias a esa instancia y se =a e$ecutado el destructor de la instancia Osi existeR. El valor inicial de una variable de instancia de una clase es el valor predeterminado O[ .2R del tipo de la variable. 'ara los 0ines de comprobaci-n de asignaci-n de0initiva, una variable de instancia de una clase se considera asignada inicialmente. .1.2.2 .ariables de instancia en estructuras 7na variable de instancia de una estructura tiene exactamente el mismo per5odo de duraci-n ?ue la variable de estructura a la ?ue pertenece. Es decir, cuando se genera o de$a de existir una variable de tipo de estructura, le ocurre lo mismo a las variables de instancia de la estructura. El estado de asignaci-n inicial de una variable de instancia de una estructura es el mismo ?ue el de la variable ?ue contiene la estructura. Es decir, si una variable de estructura se considera asignada inicialmente, lo mismo le ocurre a sus variables de instancia, y si una variable de estructura se considera no asignada inicialmente, sus variables de instancia tampoco lo est(n. #.1.3 Elementos matriciales 8os elementos de una matri1 comien1an a existir cuando se crea una instancia de la matri1 y cesa su existencia cuando de$an de existir re0erencias a dic=a instancia. El valor inicial de los elementos de una matri1 es el valor predeterminado O[ .2R del tipo de los elementos de la matri1. 'ara los 0ines de comprobaci-n de asignaci-n de0initiva, un elemento de matri1 se considera asignado inicialmente. #.1.! (ar)metros de alor 7n par5 etro de valor es un par(metro ?ue se declara sin re- u out. 7n par(metro de valor se genera al invocar el miembro de 0unci-n Om)todo, constructor de instancia, descriptor de acceso u operadorR o la 0unci-n an-nima a la ?ue pertenece el par(metro, y se iniciali1a con el valor del argumento especi0icado en la invocaci-n. 7n par(metro de valores normalmente de$a de existir tras la devoluci-n del miembro de 0unci-n o la 0unci-n an-nima. .in embargo, si una 0unci-n an-nima captura el par(metro de valor O[*.14R, su duraci-n se extiende al menos =asta ?ue el (rbol de expresiones o el delegado creados a partir de esa 0unci-n an-nima son susceptibles de recolecci-n de elementos no utili1ados. 'ara los 0ines de comprobaci-n de asignaci-n de0initiva, un par(metro de valores se considera asignado inicialmente. #.1.# (ar)metros de referencia 7n par5 etro de referencia es un par(metro ?ue se declara con un modi0icador re-. 7n par(metro de re0erencia no crea una nueva ubicaci-n de almacenamiento. En lugar de ello, un par(metro de re0erencia representa la misma ubicaci-n de almacenamiento ?ue la variable especi0icada como argumento en la invocaci-n de la 0unci-n an-nima o del miembro de 0unci-n. 'or lo tanto, el valor de un par(metro de re0erencia siempre es el mismo ?ue el de la variable subyacente. .e aplican las siguientes reglas de asignaci-n de0initiva a los par(metros de re0erencia. 2eben tenerse en cuenta las distintas reglas de los par(metros de resultados explicadas en [ .1.#.

1'2

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

7na variable debe estar asignada de0initivamente O[ .3R para ?ue pueda pasarse como par(metro de re0erencia en la invocaci-n de un miembro de 0unci-n o un delegado. 2entro de un miembro de 0unci-n o una 0unci-n an-nima, un par(metro de re0erencia se considera asignado inicialmente.

2entro de un m)todo de instancia o un descriptor de acceso de instancia de tipo struct, la palabra clave t"is tiene exactamente el mismo comportamiento ?ue un par(metro de re0erencia de tipo struct O[*. .*R. #.1.$ (ar)metros de salida 7n par5 etro de salida es un par(metro ?ue se declara con un modi0icador out. 7n par(metro de salida no crea una nueva ubicaci-n de almacenamiento. En lugar de ello, un par(metro de salida representa la misma ubicaci-n de almacenamiento ?ue la variable especi0icada como argumento en la invocaci-n del delegado o del miembro de 0unci-n. 'or lo tanto, el valor de un par(metro de salida siempre es el mismo ?ue el de la variable subyacente. .e aplican las siguientes reglas de asignaci-n de0initiva a los par(metros de salida. 2eben tenerse en cuenta las distintas reglas de los par(metros de re0erencia explicadas en [ .1. . 7na variable no tiene por ?u) estar asignada de0initivamente para poder pasarla como par(metro de salida en una invocaci-n de delegado o miembro de 0unci-n. Tras la 0inali1aci-n normal de la invocaci-n de un delegado o miembro de 0unci-n, cada variable ?ue se pase como par(metro de salida se considera asignada en esa ruta de e$ecuci-n. 2entro de un miembro de 0unci-n o una 0unci-n an-nima, un par(metro de salida se considera asignado inicialmente. Cada par(metro de salida de un miembro de 0unci-n o de una 0unci-n an-nima se debe estar asignado de0initivamente O[ .3R para poder obtener la salida del miembro de 0unci-n o la 0unci-n an-nima con normalidad.

2entro de un constructor de instancia del tipo struct, la palabra clave t"is tiene exactamente el mismo comportamiento ?ue un par(metro de salida de tipo struct O[*. .*R. #.1.+ Variables locales 7na varia/le local se declara mediante una declaraci-n de variable local Olocal-varia-le-declarationR, lo cual puede ocurrir en un blo?ue O-loc3R, una instrucci-n 0or Ofor-state%entR, una instrucci-n s9itc= Oswitchstate%entRo una instrucci-n using O sin&-state%entR, o mediante una instrucci-n 0oreac= Oforeach-state%entR o una cl(usula catc= espec50ica Ospecific-catch-cla seR en una instrucci-n try Otr#-state%entR. 8a vigencia de una variable local representa la parte de la e$ecuci-n del programa durante la cual se garanti1a ?ue =ay un espacio de almacenamiento reservado para ella. Esta vigencia se prolonga al menos desde la entrada en el blo?ue O-loc3R, instrucci-n 0or Ofor-state%entR, instrucci-n s9itc= Oswitch-state%entR, instrucci-n using O sin&-state%entR, instrucci-n 0oreac= Oforeach-state%entR, o cl(usula catc= espec50ica Ospecific-catch-cla seR a los ?ue est( asociada, =asta ?ue la e$ecuci-n de dic=o blo?ue, instrucci-n 0or, instrucci-n s9itc=, instrucci-n using, instrucci-n 0oreac=, o cl(usula catc= espec50ica 0inali1a de cual?uier modo. O8a entrada en un blo?ue contenedor o la llamada a un m)todo suspende, aun?ue no 0inali1a, la e$ecuci-n del blo?ue, instrucci-n 0or, instrucci-n s9itc=, instrucci-n using, instrucci-n 0oreac=, o cl(usula catc= espec50ica actuales.R .i una 0unci-n an-nima captura la variable local O[*.14.4.1R, su duraci-n se extiende al menos =asta ?ue el (rbol de expresiones o el delegado creados a partir de esa 0unci-n an-nima, $unto con cual?uier otro ob$eto ?ue =aga re0erencia a la variable capturada, sean susceptibles de recolecci-n de elementos no utili1ados.

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

1'3

Especificacin del lenguaje C#

.i se entra de manera recursiva en el blo?ue primario, la instrucci-n 0or, la instrucci-n s9itc=, la instrucci-n using, la instrucci-n 0oreac=, o la cl(usula catc= espec50ica, se crear( una instancia nueva de la variable local cada ve1, y su iniciali1ador de variable local Olocal-varia-le-initiali0erR, si existe, se evaluar( en cada ocasi-n. 7na variable local introducida por una declaraci-n de variable local Olocal-varia-le-declarationR no se iniciali1a autom(ticamente y, por lo tanto, no tiene un valor predeterminado. 'ara los 0ines de comprobaci-n de asignaci-n de0initiva, una variable local se considera no asignada inicialmente. 7na declaraci-n de variable local Olocal-varia-le-declarationR puede incluir un iniciali1ador de variable local Olocal-varia-le-initiali0erR, en cuyo caso la variable se considera asignada de0initivamente en todo su (mbito, a excepci-n de la expresi-n suministrada en el iniciali1ador de la variable local. En el (mbito de una variable local introducida por una declaraci-n de variable local, es un error en tiempo de compilaci-n =acer re0erencia a esa variable local en una posici-n textual ?ue preceda al declarador de la variable local Olocal-varia-le-declaratorR. .i la declaraci-n de variable local est( impl5cita O[8. .1R, tambi)n se considera un error =ace re0erencia a la variable local dentro de un declarador de variable local Olocal-varia-le-declaratorR. 7na variable local introducida por una instrucci-n 0oreac= Oforeach-state%entR o una cl(usula catc= espec50ica Ospecific-catch-cla seR se considera asignada de 0orma de0initiva en todo su (mbito. 8a duraci-n real de una variable local depende de la implementaci-n. 'or e$emplo, un compilador puede determinar est(ticamente ?ue una variable local de un blo?ue s-lo se utili1a para una pe?ueUa parte del blo?ue, y usar este an(lisis para ?ue el compilador genere un c-digo ?ue d) como resultado ?ue el almacenamiento de la variable tenga una duraci-n m(s corta ?ue la de su blo?ue contenedor. El almacenamiento a ?ue se re0iere una variable de re0erencia local se reclama independientemente de la duraci-n de esa variable de re0erencia local O[3.+R.

#.2 Valores predeterminados


8as categor5as de variables siguientes se iniciali1an de 0orma autom(tica a sus valores predeterminadosG >ariables est(ticas. >ariables de instancia de instancias de clase. Elementos matriciales. 'ara una variable de un tipo de valor Oval e-t#peR, el valor predeterminado es el mismo ?ue el valor calculado por el constructor predeterminado del tipo de valor Oval e-t#peR O[4.1.2R. 'ara una variable de tipo de re0erencia Oreference-t#peR, el valor predeterminado es null.

El valor predeterminado de una variable depende de su tipo y se determina como sigueG

8a iniciali1aci-n a valores predeterminados, la suelen llevar a cabo el administrador de la memoria o el recolector de elementos no utili1ados, ?ue iniciali1an la memoria a todos los bits cero antes de asignarla para su uso. 'or este motivo, es conveniente utili1ar todos los bits cero para representar la re0erencia nula.

#.3 Estado de asignacin definiti a


En una ubicaci-n dada dentro del c-digo e$ecutable de un miembro de 0unci-n, se dice ?ue una variable est( asignada definitiva ente si el compilador puede probar, mediante un an(lisis de 0lu$o est(tico concreto O[R, ?ue la variable se =a iniciali1ado autom(ticamente o =a sido el destino de por lo menos una asignaci-n. 2ic=o de una manera in0ormal, las reglas de la asignaci-n de0initiva sonG 7na variable asignada inicialmente O[ .3.1R siempre se considera asignada de0initivamente.

1'#

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

7na variable no asignada inicialmente O[ .3.2R se considera asignada de0initivamente en una ubicaci-n dada si todas las rutas de e$ecuci-n posibles ?ue llevan a ella contienen por lo menos uno de los siguientes elementosG o o o 7na asignaci-n simple O[*.1#.1R en la cual la variable es el operando i1?uierdo. 7na expresi-n de invocaci-n O[*. . R o una expresi-n de creaci-n de ob$eto O[*. .1".1R ?ue pasa la variable como par(metro de salida. 'ara una variable local, una declaraci-n de variable local O[8. .1R ?ue incluye un iniciali1ador de variable.

8a especi0icaci-n 0ormal subyacente a las reglas in0ormales anteriores se describe en los apartados [ .3.1, [ .3.2 y [ .3.3. El estado de asignaci-n de0initiva de las variables de instancia de una variable de tipo struct Ostr ct-t#peR puede tener un seguimiento individual y tambi)n colectivo. &dem(s de las reglas anteriores, se aplican las reglas siguientes a las variables de tipo struct Ostr ct-t#peR y a sus variables de instanciaG 7na variable de instancia se considera asignada de0initivamente si la variable de tipo struct Ostr ct-t#peR ?ue la contiene se considera asignada de0initivamente. 7na variable de tipo struct Ostr ct-t#peR se considera asignada de0initivamente si todas sus variables de instancia se consideran asignadas de0initivamente. 7na variable debe estar asignada de0initivamente en cada ubicaci-n donde se obtenga su valor. Esto asegura ?ue nunca puedan ocurrir valores no de0inidos. .e considera ?ue la ocurrencia de una variable en una expresi-n obtiene el valor de la variable, excepto cuandoG o o o la variable es el operando i1?uierdo de una asignaci-n simple, la variable se pasa como un par(metro de salida, o la variable es de tipo struct Ostr ct-t#peR y opera como el operando i1?uierdo de un acceso a miembros.

8a asignaci-n de0initiva es un re?uisito obligatorio en los contextos siguientesG

7na variable debe estar asignada de0initivamente en cada ubicaci-n donde se pase como un par(metro de re0erencia. Esto asegura ?ue el miembro de 0unci-n ?ue se invoca puede considerar al par(metro de re0erencias como asignado inicialmente. Todos los par(metros de resultado de un miembro de 0unci-n deben estar asignados de0initivamente en cada ubicaci-n donde se producen devoluciones del miembro de 0unci-n Omediante una instrucci-n return o cuando la e$ecuci-n llega al 0inal del cuerpo del miembro de 0unci-nR. Esto asegura ?ue los miembros de 0unci-n no devuelven valores no de0inidos en los par(metros de salida, lo ?ue permite al compilador considerar la invocaci-n de un miembro de 0unci-n ?ue llame a una variable como un par(metro de salida e?uivalente a una asignaci-n de la variable. 8a variable t"is de un constructor de instancia de tipo struct Ostr ct-t#peR debe estar asignada de0initivamente en cada ubicaci-n donde se produ1can devoluciones del constructor de instancia.

#.3.1 Variables asignadas inicialmente 8as siguientes categor5as de variables se clasi0ican como asignadas inicialmenteG >ariables est(ticas. >ariables de instancia de instancias de clase. >ariables de instancia de variables de estructura asignadas inicialmente.
1'!

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Especificacin del lenguaje C#

Elementos matriciales. 'ar(metros de valor. 'ar(metros de re0erencia. >ariables declaradas en una cl(usula catc" o en una instrucci-n -oreac".

#.3.2 Variables no asignadas inicialmente 8as siguientes categor5as de variables se clasi0ican como no asignadas inicialmenteG >ariables de instancia de variables de estructura no asignadas inicialmente. 'ar(metros de salida, incluida la variable t"is de constructores de instancia de estructuras. >ariables locales, excepto a?uellas declaradas en una cl(usula catc" o en una instrucci-n -oreac".

#.3.3 9eglas precisas para determinar asignaciones definiti as 'ara determinar ?ue cada variable utili1ada est( asignada de0initivamente, el compilador debe utili1ar un proceso e?uivalente al descrito en esta secci-n. El compilador procesa el cuerpo de cada miembro de 0unci-n ?ue tenga una o m(s variables no asignadas inicialmente. El compilador determina un estado de asignaci,n definitiva para cada variable v no asignada inicialmente, en cada uno de los siguientes puntos del miembro de 0unci-nG &l principio de cada instrucci-n En el punto 0inal O[8.1R de cada instrucci-n En cada arco ?ue trans0iere el control a otra instrucci-n o al punto 0inal de una instrucci-n &l principio de cada expresi-n &l 0inal de cada expresi-n &signada de0initivamente. !ndica ?ue en todos los posibles 0lu$os de control para este punto, a v se le =a asignado un valor. 4o asignada de0initivamente. 'ara el estado de una variable al 0inal de una expresi-n de tipo bool, el estado de una variable ?ue no se =a asignado de0initivamente puede caer Oaun?ue no necesariamenteR en uno de los siguientes subestadosG o &signada de0initivamente despu)s de una expresi-n true. Este estado indica ?ue si la expresi-n booleana se evalHa como true, v estar( asignada de0initivamente, pero si la expresi-n booleana se evalHa como 0alse, no tiene por ?u) estar asignada. &signada de0initivamente despu)s de una expresi-n 0alse. Este estado indica ?ue si la expresi-n booleana se evalHa como 0alse, v estar( asignada de0initivamente, pero si la expresi-n booleana se evalHa como true, no tiene por ?u) estar asignada.

El estado de asignaci-n de0initiva de v puede serG

8as reglas siguientes rigen la 0orma en la ?ue se determina el estado de una variable v en cada posici-n. .3.3.1 /e"las "enerales para instrucciones v no se asigna de0initivamente al principio del cuerpo de un miembro de 0unci-n. v se asigna de0initivamente al principio de cual?uier instrucci-n inalcan1able.

1'6

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

El estado de asignaci-n de0initiva de v al principio de cual?uier otra instrucci-n se determina mediante la comprobaci-n del estado de asignaci-n de0initiva de v en todas las trans0erencias de 0lu$o de control ?ue apunten al principio de esa instrucci-n. .i Oy s-lo en este casoR v se asigna de0initivamente en todas estas trans0erencias de 0lu$o de control, v se asigna tambi)n de0initivamente al principio de la instrucci-n. El con$unto de posibles trans0erencias de 0lu$o de control se determina del mismo modo ?ue en la comprobaci-n del alcance de la instrucci-n O[8.1R. El estado de asignaci-n de0initiva de v en el punto 0inal de una instrucci-n de blo?ue, c"ec(ed, unc"ec(ed, i-, ,"ile, do, -or, -oreac", loc(, using o s,itc" se determina mediante la comprobaci-n del estado de asignaci-n de0initiva de v en todas las trans0erencias de 0lu$o de control ?ue apunten al punto 0inal de esa instrucci-n. .i v se asigna de0initivamente en todas estas trans0erencias de 0lu$o de control, entonces v se asigna de0initivamente en el punto 0inal de la instrucci-n. 2e lo contrario, v no se asigna de0initivamente en el punto 0inal de la instrucci-n. El con$unto de posibles trans0erencias de 0lu$o de control se determina del mismo modo ?ue en la comprobaci-n del alcance de la instrucci-n O[8.1R. .3.3.2 $nstrucciones de blo0ues e instrucciones c-ec1ed y unc-ec1ed

El estado de asignaci-n de0initiva de v en la trans0erencia de control a la primera instrucci-n de la lista de instrucciones del blo?ue Oo al punto 0inal del blo?ue, si la lista de instrucciones est( vac5aR, es el mismo ?ue el de la instrucci-n de asignaci-n de0initiva de v antes de la instrucci-n de blo?ue c"ec(ed o unc"ec(ed. .3.3.3 $nstrucciones de e2presiones 'ara una instrucci-n de expresi-n st%t ?ue consta de la expresi-n e2prG v tiene el mismo estado de asignaci-n de0initiva al principio de e2pr ?ue al principio de st%t. .i v se asigna de0initivamente al 0inal de e2pr, tambi)n lo =ar( en el punto 0inal de st%tV de lo contrario, este punto no recibir( tal asignaci-n. .3.3.4 $nstrucciones de declaracin .i st%t es una instrucci-n de declaraci-n sin iniciali1adores, entonces v tiene el mismo estado de asignaci-n de0initiva en el punto 0inal de st%t ?ue al principio de st%t. .i st%t es una instrucci-n de declaraci-n con iniciali1adores, el estado de asignaci-n de0initiva de v se determina como si st%t 0uera una lista de instrucciones, con una instrucci-n de asignaci-n para cada declaraci-n con un iniciali1ador Oen el orden de la declaraci-nR. .3.3. $nstrucciones $3 'ara una instrucci-n i- st%t con la estructuraG
i- ( e2pr ) then-st%t else else-st%t

v tiene el mismo estado de asignaci-n de0initiva al principio de e2pr ?ue al principio de st%t. .i v est( de0initivamente asignada al 0inal de e2pr, tambi)n lo estar( en la trans0erencia de 0lu$o de control a then-st%t y a else-st%t, o bien al punto 0inal de st%t si no =ay cl(usula else. .i v est( Pde0initivamente asignada despu)s de una expresi-n trueQ al 0inal de e2pr, entonces tambi)n lo estar( en la trans0erencia de 0lu$o de control a then-st%tV si no =ay cl(usula else, no estar( de0initivamente asignada en la trans0erencia de 0lu$o de control a else-st%t o al punto 0inal de st%t. .i v tiene el estado Pde0initivamente asignada despu)s de expresi-n 0alseQ al 0inal de e2pr, entonces est( de0initivamente asignada en la trans0erencia de 0lu$o de control a else-st%t y no lo est( a then-st%t en la

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

1'(

Especificacin del lenguaje C#

trans0erencia de 0lu$o de control. Est( de0initivamente asignada al punto 0inal de st%t solamente si est( tambi)n de0initivamente asignada al punto 0inal de then-st%t. 2e lo contrario, v se considera no asignada de0initivamente a then-st%t o a else-st%t en la trans0erencia de 0lu$o de control o, si no =ay cl(usula else, al punto 0inal de st%t. .3.3.6 $nstrucciones !,itcEn una instrucci-n s,itc", st%t con una expresi-n de control e2prG El estado de asignaci-n de0initiva de v al principio de e2pr es el mismo ?ue el estado de v al principio de st%t. El estado de asignaci-n de0initiva de v en la trans0erencia de 0lu$o de control a una lista de instrucciones de blo?ue s9itc= alcan1able es el mismo ?ue al 0inal de e2pr. .3.3.# $nstrucciones 4-ile 'ara una instrucci-n ,"ile st%t con la siguiente estructuraG
,"ile ( e2pr ) while--od#

v tiene el mismo estado de asignaci-n de0initiva al principio de e2pr ?ue al principio de st%t. .i v est( asignada de0initivamente al 0inal de e2pr, entonces est( de0initivamente asignada en la trans0erencia de 0lu$o de control a while--od# y al punto 0inal de st%t. .i el estado de v al 0inal de e2pr es Pde0initivamente asignada despu)s de una expresi-n trueQ, est( de0initivamente asignada en la trans0erencia de 0lu$o de control a while--od#, pero no en el punto 0inal de st%t. .i el estado de v al 0inal de e2pr es Pde0initivamente asignada despu)s de una expresi-n 0alseQ, est( de0initivamente asignada en la trans0erencia de 0lu$o de control al punto 0inal de st%t, pero no a while--od# en la trans0erencia de 0lu$o de control. .3.3.+ $nstrucciones (o

'ara una instrucci-n do st%t con la siguiente estructuraG


do do--od# ,"ile ( e2pr ) ;

v tiene el mismo estado de asignaci-n de0initiva en la trans0erencia de 0lu$o de control, desde el principio de st%t a do--od#, ?ue al principio de st%t. v tiene el mismo estado de asignaci-n de0initiva al principio de e2pr ?ue en el punto 0inal de do--od#. .i v est( asignada de0initivamente al 0inal de e2pr, tambi)n lo est( en la trans0erencia de 0lu$o de control al punto 0inal de st%t. .i el estado de v al 0inal de e2pr es Pasignada de0initivamente despu)s de una expresi-n 0alseQ, entonces est( de0initivamente asignada en la trans0erencia de 0lu$o de control al punto 0inal de st%t. .3.3.5 $nstrucciones 6or

8a comprobaci-n de asignaci-n de0initiva de una instrucci-n -or con la estructura


-or ( for-initiali0er ; for-condition ; for-iterator ) e%-edded-state%ent

se reali1a como si la instrucci-n estuviera escrita de la siguiente 0ormaG

1'$

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases {

for-initiali0er ; ,"ile ( for-condition ) { e%-edded-state%ent ; for-iterator ;


! !

.i se omite la condici-n 0or Ofor-conditionR en la instrucci-n -or, la evaluaci-n o la asignaci-n de0initiva continuar( como si se sustituyera la condici-n 0or por true en la expansi-n anterior. .3.3.17 $nstrucciones 8rea1, Continue y 9oto El estado de asignaci-n de0initiva de v en la trans0erencia de 0lu$o de control causada por una instrucci-n brea(, continue o goto es el mismo ?ue el de v al principio de la instrucci-n. .3.3.11 $nstrucciones :-ro, 'ara una instrucci-n st%t con la estructuraG
t"ro, e2pr ;

El estado de asignaci-n de0initiva de v al principio de e2pr es el mismo ?ue el de v al principio de st%t. .3.3.12 $nstrucciones /eturn 'ara una instrucci-n st%t con la estructuraG
return e2pr ;

El estado de asignaci-n de0initiva de v al principio de e2pr es el mismo ?ue el de v al principio de st%t. .i v es un par(metro de salida, debe asignarse de0initivamenteG o o despu)s de e2pr o bien al 0inal del blo?ue -inally de try=-inally o try=catc"=-inally ?ue incluya la instrucci-n return.
return ;

'ara una instrucci-n st%t con la estructuraG .i v es un par(metro de salida, debe asignarse de0initivamenteG o o antes de st%t o bien al 0inal del blo?ue -inally de try=-inally o try=catc"=-inally ?ue incluya la instrucci-n return.

.3.3.13 $nstrucciones :ry;catc'ara una instrucci-n st%t con la estructuraG


try tr#--loc3 catc"(...) catch--loc3-1 ... catc"(...) catch--loc3-n

El estado de asignaci-n de0initiva de v al principio de tr#--loc3 es igual al de v al principio de st%t.

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

1'"

Especificacin del lenguaje C#

El estado de asignaci-n de0initiva de v al principio de catch--loc3-i Opara cual?uier iR es el mismo ?ue el de v al principio de st%t. El estado de asignaci-n de0initiva de v en el punto 0inal de st%t est( asignado de0initivamente si Oy s-lo siR v est( de0initivamente asignada en el punto 0inal de tr#--loc3 y de todos los catch--loc3-i Opara cada i de 1 a nR. .3.3.14 $nstrucciones :ry;3inally

'ara una instrucci-n try st%t con la siguiente estructuraG


try tr#--loc3 -inally finall#--loc3

El estado de asignaci-n de0initiva de v al principio de tr#--loc3 es igual al de v al principio de st%t. El estado de asignaci-n de0initiva de v al principio de finall#--loc3 es igual al de v al principio de st%t. v estar( de0initivamente asignada en el punto 0inal de st%t si Oy s-lo siR al menos una de las siguientes a0irmaciones es verdaderaG o o v est( asignada de0initivamente en el punto 0inal de tr#--loc3 v est( asignada de0initivamente en el punto 0inal de finall#--loc3

.i se reali1a una trans0erencia de 0lu$o de control Opor e$emplo, una instrucci-n gotoR ?ue se inicia dentro de un blo?ue try Otr#--loc3R y termina 0uera del blo?ue try, entonces v tambi)n se considerar( asignada de0initivamente en esa trans0erencia de 0lu$o de control si tambi)n lo est( en el punto 0inal del blo?ue 0inally Ofinall#--loc3R. OEsta condici-n no es exclusivaG si v est( asignada de0initivamente por otra ra1-n en esta trans0erencia de 0lu$o de control, se considerar( asignada de0initivamenteR. .3.3.1 $nstrucciones :ry;3inally;catcEl an(lisis de asignaci-n de0initiva de una instrucci-n tryBcatc"B-inally con la estructuraG
try tr#--loc3 catc"(...) catch--loc3-1 ... catc"(...) catch--loc3-n -inally finall#--loc3

se reali1a como si la instrucci-n 0uera una instrucci-n try=-inally ?ue incluyera una instrucci-n try= catc"G
try { try tr#--loc3 catc"(...) catch--loc3-1 ... catc"(...) catch--loc3-n ! -inally finall#--loc3

El e$emplo siguiente demuestra c-mo a0ectan los di0erentes blo?ues de una instrucci-n try O[8.1"R a la asignaci-n de0initiva.

11'

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases class ' { static void V() { int i j; try { goto L':)L; .. neit"er i nor j de-initely assigned i + 2; .. i de-initely assigned ! catc" { .. neit"er i nor j de-initely assigned i + 9; .. i de-initely assigned ! -inally { .. neit"er i nor j de-initely assigned j + K; .. j de-initely assigned ! .. i and j de-initely assigned L':)L/; .. j de-initely assigned ! !

.3.3.16 $nstrucciones 6oreac'ara una instrucci-n -oreac" st%t con la siguiente estructuraG
-oreac" ( t#pe identificador in e2pr ) e%-edded-state%ent

El estado de asignaci-n de0initiva de v al principio de e2pr es el mismo ?ue el estado de v al principio de st%t. El estado de asignaci-n de0initiva de v en la trans0erencia de 0lu$o de control a una instrucci-n incrustada Oe%-edded-state%entR o al punto 0inal de st%t es el mismo ?ue el estado de v al 0inal de e2pr. .3.3.1# $nstrucciones <sin"

'ara una instrucci-n using st%t con la siguiente estructuraG


using ( reso rce-ac6 isition ) e%-edded-state%ent

El estado de asignaci-n de0initiva de v al principio de ad?uisici-n de recurso Oreso rce-ac6 isitionR es igual al estado de v al principio de st%t. El estado de asignaci-n de0initiva de v en la trans0erencia de 0lu$o de control a una instrucci-n incrustada Oe%-edded-state%entR es igual al de v al 0inal de la ad?uisici-n de recurso Oreso rce-ac6 isitionR. .3.3.1+ $nstrucciones *oc1

'ara una instrucci-n loc( st%t con la siguiente estructuraG


loc( ( e2pr ) e%-edded-state%ent

El estado de asignaci-n de0initiva de v al principio de e2pr es el mismo ?ue el estado de v al principio de st%t.

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

111

Especificacin del lenguaje C#

El estado de asignaci-n de0initiva de v en la trans0erencia de 0lu$o de control a una instrucci-n incrustada Oe%-edded-state%entR es igual ?ue el estado de v al 0inal de la expresi-n Oe2prR. .3.3.15 $nstrucciones yield

'ara una instrucci-n yield return st%t con la estructuraG


yield return e2pr ;

El estado de asignaci-n de0initiva de v al principio de e2pr es el mismo ?ue el estado de v al principio de st%t. El estado de asignaci-n de0initiva de v al principio de st%t es el mismo ?ue el estado de v al principio de e2pr. 7na instrucci-n yield brea( no tiene ningHn e0ecto sobre el estado de asignaci-n de0initiva. .3.3.27 /e"las "enerales para e2presiones simples

8a siguiente regla se aplica a estos tipos de expresionesG literales O[*. .1R, nombres simples O[*. .2R, expresiones de acceso a miembros O[*. .4R, expresiones de acceso a bases no indi1adas O[*. .8R, expresiones ty&eo- O[*. .11R y expresiones de valor predeterminadas O[*. .13R. El estado de asignaci-n de0initiva de v al 0inal de una expresi-n de este tipo es igual ?ue el de v al principio de la expresi-n. .3.3.21 /e"las "enerales para e2presiones con e2presiones incrustadas 8as reglas siguientes se aplican a estos tipos de expresionesG expresiones entre par)ntesis O[*. .3R, expresiones de acceso a elementos O[*. .#R, expresiones de acceso a bases con indi1aci-n O[*. .8R, expresiones de incremento y decremento O[*. .+, [*.#. R, expresiones de conversi-n de tipos O[*.#.#R, expresiones unarias <, =, A, >, expresiones binarias <, =, >, ., B, DD, EE, D, D+, E, E+, ++, @+, is, as, F, H, G O[*.*, [*.8, [*.+, [*.1"R, expresiones de asignaci-n compuestas O[*.1#.2R, expresiones c"ec(ed y unc"ec(ed O[*. .12R, y expresiones de creaci-n de matrices y de delegados O[*. .1"R. Cada una de estas expresiones tiene una o m(s subexpresiones ?ue se evalHan incondicionalmente en un orden 0i$o. 'or e$emplo, el operador binario B evalHa el lado i1?uierdo del operador y, a continuaci-n, el lado derec=o. 7na operaci-n de indi1aci-n evalHa la expresi-n indi1ada y, a continuaci-n, cada una de las expresiones de 5ndice por orden, de i1?uierda a derec=a. 'ara una expresi-n e2pr ?ue tiene las subexpresiones e2pr1, e2pr2, ..., e2prn, evaluadas en ese ordenG El estado de asignaci-n de0initiva de v al principio de e2pr1 es igual ?ue el estado de asignaci-n de0initiva al principio de e2pr. El estado de asignaci-n de0initiva de v al principio de e2pri Osiendo i mayor ?ue unoR es igual ?ue el estado al 0inal de e2pri-1. El estado de asignaci-n de0initiva de v al principio de e2pr es igual ?ue el estado al 0inal de e2prn. .3.3.22 &2presiones de invocacin y e2presiones de creacin de ob=etos 'ara una expresi-n de invocaci-n e2pr con la estructuraG pri%ar#-e2pression ( ar&1
ne, t#pe ( ar&1

ar&2
b

ar&n )

o una expresi-n de creaci-n de ob$eto con la estructuraG ar&2 ar&n )

112

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

'ara una expresi-n de invocaci-n, el estado de asignaci-n de0initiva de v antes de la expresi-n primaria Opri%ar#-e2pressionR es igual ?ue el estado de v antes de e2pr. 'ara una expresi-n de invocaci-n, el estado de asignaci-n de0initiva de v antes de ar&1 es igual ?ue el estado de v despu)s de la expresi-n primaria Opri%ar#-e2pressionR. 'ara una expresi-n de creaci-n de ob$eto, el estado de asignaci-n de0initiva de v antes de ar&1 es igual ?ue el estado de v antes de e2pr. 'ara cada argumento ar&i, el estado de asignaci-n de0initiva de v despu)s de ar&i est( determinado por las reglas de expresi-n normales omitiendo los modi0icadores re- u out. 'ara cada argumento argi, siendo i mayor ?ue uno, el estado de asignaci-n de0initiva de v antes de ar&i es el mismo ?ue el de v despu)s de ar&i-1. .i se pasa la variable v como un argumento out Oes decir, un argumento de 0orma ^out v^R en cual?uiera de los argumentos, el estado de v despu)s de e2pr se asigna de0initivamente. 2e lo contrario, el estado de v despu)s de e2pr es el mismo ?ue el estado de v despu)s de ar&n. 'ara los iniciali1adores de matri1 O[*. .1".4R, iniciali1adores de ob$etos O[*. .1".2R, iniciali1adores de colecci-n O[*. .1".3R e iniciali1adores de ob$etos an-nimos O[*. .1".#R, el estado de asignaci-n de0initiva est( determinado por la expansi-n en cuyos t)rminos est(n de0inidos estos constructores. .3.3.23 &2presiones de asi"nacin simples

'ara una expresi-n e2pr con la estructura w + e2pr-rhsG El estado de asignaci-n de0initiva de v antes de e2pr-rhs es igual ?ue el de v antes de e2pr. .i w es la misma variable ?ue v, el estado de asignaci-n de0initiva de v despu)s de e2pr se asigna de0initivamente. 2e lo contrario, el estado de asignaci-n de0initiva de v despu)s de e2pr ser( igual ?ue el de v despu)s de e2pr-rhs. .3.3.24 &2presiones >> 'ara una expresi-n e2pr con la estructura e2pr-first FF e2pr-secondG El estado de asignaci-n de0initiva de v antes de e2pr-first es igual ?ue el de v antes de e2pr. El estado de asignaci-n de0initiva de v antes de la segunda expresi-n Oe2pr-secondR se asigna de0initivamente, si el estado de v despu)s de la primera expresi-n Oe2pr-firstR se asigna de0initivamente o es Pasignado de0initivamente despu)s de una expresi-n trueQ. En cual?uier otro caso, no se asigna de0initivamente. El estado de asignaci-n de0initiva de v despu)s de e2pr se determina de la siguiente 0ormaG o o .i el estado de v despu)s de e2pr-first se asigna de0initivamente, tambi)n lo =ar( el estado de v despu)s de e2pr. 2e lo contrario, si el estado de v despu)s de la segunda expresi-n Oe2pr-secondR se asigna de0initivamente, y el estado de v despu)s de la primera expresi-n Oe2pr-firstR es Pasignado de0initivamente despu)s de una expresi-n 0alseQ, entonces el estado de v despu)s de la expresi-n Oe2prR se asigna de0initivamente. 2e lo contrario, si el estado de v despu)s de la segunda expresi-n Oe2pr-secondR se asigna de0initivamente o es Pasignado de0initivamente despu)s de expresi-n trueQ, entonces el estado de v despu)s de la expresi-n Oe2prR es Pasignado de0initivamente despu)s de una expresi-n trueQ.

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

113

Especificacin del lenguaje C#

2e lo contrario, si el estado de v despu)s de la primera expresi-n Oe2pr-firstR es Pasignado de0initivamente despu)s de una expresi-n 0alseQ y el estado de v despu)s de segunda expresi-n Oe2prsecondR es Pasignado de0initivamente despu)s de una expresi-n 0alseQ, entonces el estado de v despu)s de la expresi-n Oe2prR es Pasignado de0initivamente despu)s de una expresi-n 0alseQ. 2e lo contrario, el estado de v despu)s de e2pr no se asignar( de0initivamente.
class ' { static void V(int # int y) { int i; i- (# E+ 3 FF (i + y) E+ 3) { .. i de-initely assigned ! else { .. i not de-initely assigned ! .. i not de-initely assigned ! !

En el e$emplo

la variable i se considera asignada de0initivamente en una de las instrucciones incrustadas de una instrucci-n ipero no en la otra. En la instrucci-n i- del m)todo V, la variable i est( asignada de0initivamente en la primera instrucci-n incrustada por?ue la e$ecuci-n de la expresi-n (i + y) siempre precede a la e$ecuci-n de esta instrucci-n incrustada. 'or el contrario, la variable i no est( asignada de0initivamente en la segunda instrucci-n incrustada, puesto ?ue # E+ 3 podr5a dar como resultado 0alse y =acer ?ue la variable i no se asignara. .3.3.2 &2presiones ?? 'ara una expresi-n e2pr con la estructura e2pr-first HH e2pr-secondG El estado de asignaci-n de0initiva de v antes de e2pr-first es igual ?ue el de v antes de e2pr. El estado de asignaci-n de0initiva de v antes de la segunda expresi-n Oe2pr-secondR se asigna de0initivamente si el estado de v despu)s de la primera expresi-n Oe2pr-firstR se asigna de0initivamente o es Pasignado de0initivamente despu)s de una expresi-n 0alseQ. En cual?uier otro caso, no se asigna de0initivamente. 8a instrucci-n de asignaci-n de0initiva de v despu)s de e2pr se determina de la siguiente 0ormaG o o .i el estado de v despu)s de e2pr-first se asigna de0initivamente, tambi)n lo =ar( el estado de v despu)s de e2pr. 2e lo contrario, si el estado de v despu)s de la segunda expresi-n Oe2pr-secondR se asigna de0initivamente, y el estado de v despu)s de la primera expresi-n Oe2pr-firstR es Pasignado de0initivamente despu)s de una expresi-n trueQ, entonces el estado de v despu)s de e2pr se asignar( de0initivamente. 2e lo contrario, si el estado de v despu)s de la segunda expresi-n Oe2pr-secondR se asigna de0initivamente o es Pasignado de0initivamente despu)s de una expresi-n 0alseQ, entonces el estado de v despu)s de la expresi-n Oe2prR es Pasignado de0initivamente despu)s de una expresi-n 0alseQ. 2e lo contrario, si el estado de v despu)s de la primera expresi-n Oe2pr-firstR es Pasignado de0initivamente despu)s de una expresi-n trueQ, y el estado de v despu)s de la segunda expresi-n Oe2pr-secondR es Pasignado de0initivamente despu)s de una expresi-n trueQ, entonces el estado de v despu)s de e2pr es Pasignado de0initivamente despu)s de una expresi-n trueQ. 2e lo contrario, el estado de v despu)s de e2pr no se asignar( de0initivamente.

o
11#

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

En el e$emplo
class ' { static void S(int # int y) { int i; i- (# E+ 3 HH (i + y) E+ 3) { .. i not de-initely assigned ! else { .. i de-initely assigned ! .. i not de-initely assigned ! !

la variable i se considera asignada de0initivamente en una de las instrucciones incrustadas de una instrucci-n ipero no en la otra. En la instrucci-n i- del m)todo S, la variable i est( asignada de0initivamente en la segunda instrucci-n incrustada por?ue la e$ecuci-n de la expresi-n (i + y) siempre precede a la e$ecuci-n de esta instrucci-n incrustada. 'or el contrario, la variable i no est( asignada de0initivamente en la primera instrucci-n incrustada, puesto ?ue # E+ 3 podr5a dar como resultado true y =ace ?ue la variable i no se asigne. .3.3.26 &2presiones @ 'ara una expresi-n e2pr con la estructura @ e2pr-operandG El estado de asignaci-n de0initiva de v antes de e2pr-operand es igual ?ue el estado de asignaci-n de0initiva de v antes de e2pr. El estado de asignaci-n de0initiva de v despu)s de e2pr se determina de la siguiente 0ormaG o o o .i el estado de v despu)s de e2pr-operand se asigna de0initivamente, el estado de v despu)s de e2pr se asigna de0initivamente. .i el estado de v despu)s de e2pr-operand no se asigna de0initivamente, el estado de v despu)s de e2pr no se asigna de0initivamente. .i el estado de v despu)s del operando de la expresi-n Oe2pr-operand5 es Pasignado de0initivamente despu)s de una expresi-n 0alseQ, entonces el estado de v despu)s de la expresi-n Oe2prR es Pasignado de0initivamente despu)s de una expresi-n trueQ. .i el estado de v despu)s del operando de la expresi-n Oe2pr-operand5 es Pasignado de0initivamente despu)s de una expresi-n trueQ, entonces el estado de v despu)s de la expresi-n Oe2prR es Pasignado de0initivamente despu)s de una expresi-n 0alseQ.

.3.3.2# &2presiones AA 'ara una expresi-n e2pr con la estructura e2pr-first 77 e2pr-secondG El estado de asignaci-n de0initiva de v antes de e2pr-first es igual ?ue el de v antes de e2pr. El estado de asignaci-n de0initiva de v antes de e2pr-second es el mismo ?ue el de v despu)s de e2pr-first. 8a instrucci-n de asignaci-n de0initiva de v despu)s de e2pr se determina de la siguiente 0ormaG o .i e2pr-first es una expresi-n constante O[*.18R con valor null, entonces el estado de v despu)s de la expresi-n Oe2prR es el mismo ?ue el estado de v despu)s de e2pr-second.

2e lo contrario, el estado v despu)s de e2pr ser( igual ?ue el estado de asignaci-n de0initiva de v despu)s de e2pr-first.

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

11!

Especificacin del lenguaje C#

.3.3.2+ &2presiones AB 'ara una expresi-n e2pr con la estructura e2pr-cond 7 e2pr-tr e / e2pr-falseG El estado de asignaci-n de0initiva de v antes de e2pr-cond es igual al estado de v antes de e2pr. El estado de asignaci-n de0initiva de v antes de la expresi-n para true Oe2pr-tr eR se asigna de0initivamente solamente en el caso de ?ue el estado de v despu)s de la expresi-n condicional Oe2pr-cond5 se asigne de0initivamente o sea Pasignado de0initivamente despu)s de una expresi-n trueQ. El estado de asignaci-n de0initiva de v antes de la expresi-n para 0alse Oe2pr-false5 se asigna de0initivamente solamente en el caso de ?ue el estado de v despu)s de la expresi-n condicional Oe2pr-cond5 se asigne de0initivamente o sea Pasignado de0initivamente despu)s de una expresi-n 0alseQ. El estado de asignaci-n de0initiva de v despu)s de e2pr se determina de la siguiente 0ormaG o .i la expresi-n condicional Oe2pr-condR es una expresi-n constante O[R con valor true, entonces el estado de v despu)s de la expresi-n Oe2prR es el mismo ?ue el estado de v despu)s de la expresi-n para true Oe2pr-tr eR. 2e lo contrario, si la expresi-n condicional Oe2pr-condR es una expresi-n constante O[*.18R con valor -alse, entonces el estado de v despu)s de la expresi-n Oe2prR es el mismo ?ue el estado de v despu)s de la expresi-n para 0alse Oe2pr-falseR. 2e lo contrario, si el estado de v despu)s de e2pr-tr e y el estado de v despu)s de e2pr-false se asignan de0initivamente, entonces el estado de v despu)s de e2pr tambi)n se asignar( de0initivamente. 2e lo contrario, el estado de v despu)s de e2pr no se asignar( de0initivamente.

o o

.3.3.25 6unciones annimas 'ara una expresi-n lambda Ola%-da-e2pressionR o una expresi-n de m)todo an-nimo Oanon#%o s-%ethode2pression e2prR con un cuerpo Oya sea -loc3 o e2pressionR -od#G El estado de asignaci-n de0initiva de una variable externa v antes del cuerpo O-od#R es igual ?ue el estado de v antes de e2pr. Es decir, el estado de asignaci-n de0initiva de variables externas se =ereda desde el contexto de la 0unci-n an-nima. El estado de asignaci-n de0initiva de una variable externa v despu)s de e2pr ser( igual ?ue el estado de v antes de e2pr.
delegate bool Vilter(int i); void V() { int ma#; .. )rror ma# is not de-initely assigned Vilter - + (int n) +E n D ma#; ma# + K; 6oWor((-); !

En el e$emplo

se genera un error en tiempo de compilaci-n ya ?ue ma# no se asigna de manera de0initiva donde se declara la 0unci-n an-nima. En el e$emplo
delegate void 6(); void V() { int n; 6 d + () +E { n + 2; !;

116

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases d(); .. )rror n is not de-initely assigned Console.WriteLine(n); !

tambi)n se genera un error en tiempo de compilaci-n puesto ?ue la asignaci-n a n en la 0unci-n an-nima no a0ecta al estado de asignaci-n de0initivo de n 0uera de la 0unci-n an-nima.

#.! 9eferencias de ariables


7na re0erencia de variable Ovaria-le-referenceR es una expresi-n Oe2pressionR ?ue se clasi0ica como una variable. 7na re0erencia de variable Ovaria-le-referenceR es una ubicaci-n de almacenamiento a la ?ue se puede obtener acceso, tanto para obtener el valor actual, como para almacenar un valor nuevo. varia-le-reference1 e2pression En C y CSS, una re0erencia de variable Ovaria-le-referenceR se conoce como lval e.

#.# 'tomicidad de las referencias de ariable


8as lecturas y escrituras de los siguientes tipos de datos son at-micasG bool, c"ar, byte, sbyte, s"ort, us"ort, uint, int, -loat y tipos de re0erencia. &dem(s, las lecturas y escrituras de tipos enum cuyo tipo subyacente est( en la lista anterior son tambi)n at-micas. 4o se garanti1a ?ue las lecturas y escrituras de otros tipos Ocomo long, ulong, double o decimal, as5 como los tipos de0inidos por el usuarioR sean at-micas. &parte de las 0unciones de biblioteca diseUadas para este prop-sito, no =ay garant5a de lectura, modi0icaci-n ni escritura at-micas, como en el caso de incrementos o decrementos.

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

11(

Especificacin del lenguaje C#

$. %on ersiones
7na conversi,n permite ?ue una expresi-n sea tratada como parte de un tipo determinado. 7na conversi-n puede =acer ?ue una expresi-n de un tipo dado sea tratada como si tuviera un tipo di0erente, o ?ue una expresi-n sin un tipo lo consiga. 8as conversiones pueden ser i plcitas o e.plcitas, y esto determina si se re?uiere una conversi-n de tipo expl5cita. 'or e$emplo, la conversi-n del tipo int al tipo long es impl5cita, por lo ?ue las expresiones de tipo int pueden tratarse impl5citamente como del tipo long. 8a conversi-n opuesta, del tipo long a int, es expl5cita y, por ello, se re?uiere una conversi-n expl5cita.
int a + 289; long b + a; int c + (int) b; .. im&licit conversion -rom int to long .. e#&licit conversion -rom long to int

&lgunas conversiones est(n de0inidas por el lengua$e. 8os programas tambi)n pueden de0inir sus propias conversiones O[#.4R.

$.1 %on ersiones impl2citas


8as siguientes conversiones se clasi0ican como conversiones impl5citasG Conversiones de identidad Conversiones num)ricas impl5citas Conversiones de enumeraci-n impl5citas Conversiones impl5citas ?ue aceptan valores 4788 Conversiones de literal 4788 Conversiones de re0erencia impl5citas Conversiones boxing Conversiones impl5citas de expresi-n constante Conversiones de0inidas por el usuario impl5citas Conversiones de 0unci-n an-nima Conversiones de grupo de m)todos

8as conversiones impl5citas pueden ocurrir en distintas situaciones, incluyendo las invocaciones de miembros de 0unci-n O[*.4.4R, las expresiones de conversi-n O[*.#.#R y las asignaciones O[*.1#R. 8as conversiones impl5citas prede0inidas siempre tienen )xito y nunca causan excepciones. 8as conversiones impl5citas de0inidas por el usuario correctamente diseUadas tambi)n deben ex=ibir estas caracter5sticas. $.1.1 %on ersiones de identidad 7na conversi-n de identidad convierte de cual?uier tipo al mismo tipo. Esta conversi-n existe solamente para ?ue una entidad ?ue ya sea de un tipo re?uerido pueda considerarse convertible a dic=o tipo. $.1.2 %on ersiones num*ricas impl2citas 8as conversiones impl5citas num)ricas sonG
11$
Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

2e sbyte a s"ort, int, long, -loat, double o decimal. 2e byte a s"ort, us"ort, int, uint, long, ulong, -loat, double o decimal. 2e s"ort a int, long, -loat, double o decimal. 2e us"ort a int, uint, long, ulong, -loat, double o decimal. 2e int a long, -loat, double o decimal. 2e uint a long, ulong, -loat, double o decimal. 2e long a -loat, double o decimal. 2e ulong a -loat, double o decimal. 2e c"ar a us"ort, int, uint, long, ulong, -loat, double o decimal. 2e -loat a double.

8as conversiones de int, uint, long o ulong a ulong o -loat y de long o ulong a double pueden producir una p)rdida de precisi-n, pero no una p)rdida de magnitud. En las dem(s conversiones impl5citas num)ricas nunca se pierde in0ormaci-n. 4o =ay conversiones impl5citas al tipo c"ar, por tanto los valores de otros tipos integrales no se convierten autom(ticamente al tipo c"ar. $.1.3 %on ersiones de enumeracin impl2citas 7na conversi-n de enumeraci-n impl5cita permite convertir el literal entero decimal Odeci%al-inte&er-literalR 3 al tipo enum Oen %-t#peR y a cual?uier tipo ?ue acepte valores 4788 On lla-le-t#peR cuyo tipo subyacente sea enum Oen %-t#peR. En este Hltimo caso, la conversi-n se evalHa mediante la conversi-n al tipo enum Oen %t#peR subyacente y el a$uste del resultado O[4.1.1"R. $.1.! %on ersiones impl2citas ;ue aceptan alores 1566 8as conversiones impl5citas prede0inidas ?ue 0uncionan en tipos de valores ?ue no aceptan valores 4788 tambi)n se pueden utili1ar con 0ormas ?ue aceptan valores 4788 de dic=os tipos. 'ara cada una de las conversiones num)ricas y de identidad impl5citas ?ue se convierten de un tipo de valor S ?ue no acepta valores 4788 a un tipo de valor 1 ?ue no acepta valores 4788, existen las siguientes conversiones impl5citas ?ue aceptan valores 4788G 7na conversi-n impl5cita desde S7 a 17. 7na conversi-n impl5cita de S a 17.

8a evaluaci-n de una conversi-n impl5cita ?ue acepta valores 4788 basada en una conversi-n subyacente de S a 1 se reali1a de la siguiente maneraG .i la conversi-n ?ue acepta valores 4788 se reali1a de S7 a 17G o o .i el valor de origen es 4788 Ola propiedad HasUalue es 0alsaR, el resultado es el valor 4788 del tipo 17. 2e lo contrario, la conversi-n se evalHa como un desa$uste de S7 a S, seguido de la conversi-n subyacente de S a 1, seguido de un a$uste O[4.1.1"R de 1 a 17.

.i la conversi-n ?ue acepta valores 4788 se reali1a de S a 17, la conversi-n se evalHa como la conversi-n subyacente de S a 1 seguida de un a$uste de 1 a 17.

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

11"

Especificacin del lenguaje C#

$.1.# %on ersiones de literal 1566 Existe una conversi-n impl5cita desde el literal null a cual?uier tipo ?ue acepte valores 4788. Esta conversi-n genera el valor 4788 O[4.1.1"R del tipo ?ue admite valores 4788. $.1.$ %on ersiones de referencia impl2citas 8as conversiones impl5citas de re0erencia sonG 2e cual?uier tipo de re0erencia Oreference-t#peR a object. 2e cual?uier tipo de clase Oclass-t#peR S a cual?uier tipo de clase 1, a condici-n de ?ue S se derive de 1. 2e cual?uier tipo de clase Oclass-t#peR S a cual?uier tipo de inter0a1 Ointerface-t#peR 1, a condici-n de ?ue S implemente a 1. 2e cual?uier tipo de inter0a1 Ointerface-t#peR S a cual?uier tipo de inter0a1 1, a condici-n de ?ue S se derive de 1. 2e un tipo de matri1 Oarra#-t#peR S con un tipo de elemento S) a un tipo de matri1 1 con un tipo de elemento 1), siempre ?ue se cumpla todo lo siguienteG o o o
S y 1 di0ieren solamente en el tipo de elemento. Esto es, S y 1 tienen el mismo nHmero de dimensiones.

Tanto S) como 1) son tipos de re0erencia Oreference-t#pesR. Existe una conversi-n impl5cita de re0erencia de S) a 1).

2esde cual?uier tipo de matri1 Oarra#-t#peR a System.'rray y las inter0aces ?ue implementa. 2esde un tipo de matri1 unidimensional S45 a System.Collections.Seneric.$ListD1E y sus inter0aces base, siempre ?ue =aya una identidad impl5cita o una conversi-n de re0erencia de S a 1. 2esde cual?uier tipo delegado Odele&ate-t#peR a System.6elegate y las inter0aces ?ue implementa. 2el literal nulo a cual?uier tipo de re0erencia Oreference-t#peR. Conversiones impl5citas ?ue impli?uen par(metros de tipo ?ue se sabe ?ue son tipos de re0erencia. >ea la secci-n [ para obtener m(s datos acerca de las conversiones impl5citas ?ue implican par(metros de tipo.

8as conversiones impl5citas de re0erencia son a?uellas entre tipos de re0erencia Oreference-t#pesR ?ue se puede demostrar ?ue siempre se reali1an correctamente y, por lo tanto, no re?uieren comprobaciones en tiempo de e$ecuci-n. 8as conversiones de re0erencia, tanto impl5citas como expl5citas, nunca cambian la identidad re0erencial del ob$eto ?ue se convierte. Es decir, si bien una conversi-n de re0erencia puede cambiar el tipo de la re0erencia, nunca cambia el tipo o el valor del ob$eto al ?ue se re0iere. &l contrario de lo ?ue ocurre con los tipos de matrices, los tipos de re0erencia construidos no muestran conversiones PcovariantesQ. Esto signi0ica ?ue un tipo ListD:E no tiene conversi-n Oya sea impl5cita o expl5citaR a ListD'E incluso si : deriva de '. 2e manera similar, no existe una conversi-n de ListD:E a ListDobjectE. $.1.+ %on ersiones bo"ing 7na conversi-n boxing permite ?ue un tipo de valor Oval e-t#peR se convierta impl5citamente en un tipo de re0erencia. Existe una conversi-n boxing de cual?uier tipo de valor ?ue no acepta valores 4788 Onon-n lla-leval e-t#peR al tipo object, a System.Ualue1y&e, y a cual?uier tipo de inter0a1 Ointerface-t#peR implementado por el tipo de valor ?ue no acepta valores 4788 Onon-n lla-le-val e-t#peR. Es m(s, un tipo enum Oen %-t#peR se puede convertir al tipo System.)num.

12'

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

Existe una conversi-n boxing de cual?uier tipo de valor ?ue acepta valores 4788 On lla-le-val e-t#peR a un tipo de re0erencia, si y s-lo si existe una conversi-n boxing del tipo de valor ?ue no acepta valores 4788 Ononn lla-le-val e-t#peR subyacente al tipo de re0erencia. 8a conversi-n boxing de un tipo de valor ?ue no acepta valores 4788 Onon-n lla-le-val e-t#peR consiste en asignar una instancia del ob$eto y despu)s copiar el tipo de valorOval e-t#peR en esa instancia. .e puede aplicar a una estructura la conversi-n boxing al tipo System.Ualue1y&e, puesto ?ue )sa es una clase base para todas las estructuras O[11.3.2R. 7na conversi-n boxing desde un tipo ?ue acepta valores 4788 On lla-le-t#peR se procesa de la siguiente maneraG .i el valor de origen es 4788 Ola propiedad HasUalue es 0alsaR, el resultado es una re0erencia 4788 del tipo de destino. 2e lo contrario, el resultado es una re0erencia a un tipo 1 producido por el desa$uste y la conversi-n boxing del valor de origen.

8as conversiones boxing se describen m(s detalladamente en [4.3.1. $.1.- %on ersiones impl2citas de e"presin constante 7na conversi-n impl5cita de expresi-n constante permite las siguientes conversionesG 7na expresi-n constante Oconstant-e2pressionR O[*.18R de tipo int se puede convertir al tipo sbyte, byte, s"ort, us"ort, uint o ulong, siempre ?ue el valor de la expresi-n constante Oconstant-e2pressionR ?uede dentro del intervalo del tipo de destino. 7na expresi-n constante Oconstant-e2pressionR de tipo long se puede convertir al tipo ulong, a condici-n de ?ue el valor de la expresi-n constante no sea negativo.

$.1.. %on ersiones impl2citas con par)metros de tipo 'ara un par(metro de tipo 1 dado, existen las siguientes conversiones impl5citasG 2esde 1 a su clase base e0ectiva C, desde 1 a cual?uier clase base de C, y desde 1 a cual?uier inter0a1 implementada por C. En tiempo de e$ecuci-n, si 1 es un tipo de valor, la conversi-n se e$ecuta como una conversi-n boxing. 2e lo contrario, la conversi-n se e$ecuta como una conversi-n de re0erencia impl5cita o una conversi-n de identidad. 2esde 1 a un tipo de inter0a1 en el con$unto de inter0aces e0ectivas de 1, y desde 1 a cual?uier inter0a1 base de $. En tiempo de e$ecuci-n, si 1 es un tipo de valor, la conversi-n se e$ecuta como una conversi-n boxing. 2e lo contrario, la conversi-n se e$ecuta como una conversi-n de re0erencia impl5cita o una conversi-n de identidad. 2esde 1 a un par(metro de tipo ;, siempre ?ue 1 dependa de ; O[1".1. R. En tiempo de e$ecuci-n, si ; es un tipo de valor, entonces 1 y ; son necesariamente el mismo tipo y no se reali1a una conversi-n boxing. 2e lo contrario, si 1 es un tipo de re0erencia, ; tambi)n lo es y la conversi-n se e$ecuta como una conversi-n de re0erencia impl5cita o una conversi-n de identidad. 2esde el literal nulo a 1, siempre y cuando 1 sea un tipo de re0erencia.

.i 1 es un tipo de re0erencia O[1".1. R, todas las conversiones anteriores se clasi0ican como conversiones de re0erencia impl5citas O[R. .i 1 no es un tipo de re0erencia, las conversiones anteriores se clasi0ican como conversiones boxing O[R.

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

121

Especificacin del lenguaje C#

$.1.10 %on ersiones definidas por el usuario impl2citas 7na conversi-n impl5cita de0inida por el usuario consta de una conversi-n impl5cita opcional est(ndar, seguida por la e$ecuci-n de un operador de conversi-n impl5cita de0inido por el usuario, seguido por otra conversi-n impl5cita opcional est(ndar. 8as reglas exactas para la evaluaci-n de conversiones impl5citas de0inidas por el usuario se describen en [#.4.4. $.1.11 %on ersiones de funcin annima y con ersiones de grupo de m*todos 8as 0unciones an-nimas y los grupos de m)todos no tienen tipos de por s5, pero se pueden convertir impl5citamente en tipos delegados o tipos de (rbol de expresiones. 8as conversiones de 0unci-n an-nima y las conversiones de grupo de m)todos se describen en m(s detalle en la secci-n [#. .

$.2 %on ersiones e"pl2citas


8as siguientes conversiones se clasi0ican como conversiones expl5citasG Todas las conversiones impl5citas. Conversiones expl5citas num)ricas. Conversiones expl5citas de enumeraci-n. Conversiones expl5citas ?ue aceptan valores 4788. Conversiones expl5citas de re0erencia. Conversiones expl5citas de inter0a1. Conversiones 7nboxing. Conversiones expl5citas de0inidas por el usuario.

8as conversiones expl5citas pueden producirse en las expresiones de conversi-n de tipos O[*.#.#R. El con$unto de conversiones expl5citas incluye todas las conversiones impl5citas. Esto ?uiere decir ?ue est(n permitidas las expresiones de conversi-n de tipos redundantes. 8as conversiones expl5citas son conversiones ?ue no se puede demostrar ?ue siempre se reali1an correctamente, conversiones en las ?ue se sabe ?ue se puede producir p)rdida de in0ormaci-n y conversiones en dominios de tipos ?ue, por sus di0erencias, merecen una menci-n expl5cita. $.2.1 %on ersiones e"pl2citas num*ricas 8as conversiones num)ricas expl5citas son las conversiones de un tipo num)rico On %eric-t#peR a otro tipo num)rico para el ?ue no existe ya una conversi-n de tipo num)rico impl5cita O[#.1.2RG 2e sbyte a byte, us"ort, uint, ulong o c"ar. 2e byte a sbyte y c"ar. 2e s"ort a sbyte, byte, us"ort, uint, ulong o c"ar. 2e us"ort a sbyte, byte, s"ort o c"ar. 2e int a sbyte, byte, s"ort, us"ort, uint, ulong o c"ar. 2e uint a sbyte, byte, s"ort, us"ort, int o c"ar. 2e long a sbyte, byte, s"ort, us"ort, int, uint, ulong o c"ar. 2e ulong a sbyte, byte, s"ort, us"ort, int, uint, long o c"ar.

122

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

2e c"ar a sbyte, byte o s"ort. 2e -loat a sbyte, byte, s"ort, us"ort, int, uint, long, ulong, c"ar o decimal. 2e double a sbyte, byte, s"ort, us"ort, int, uint, long, ulong, c"ar, -loat o decimal. 2e decimal a sbyte, byte, s"ort, us"ort, int, uint, long, ulong, c"ar, -loat o double.

2ado ?ue las conversiones expl5citas incluyen todas las conversiones num)ricas impl5citas y expl5citas, siempre es posible convertir de cual?uier tipo num)rico On %eric-t#peR a cual?uier otro tipo num)rico mediante una expresi-n de conversi-n de tipos O[*.#.#R. 8as conversiones expl5citas num)ricas pueden producir p)rdida de in0ormaci-n o incluso provocar excepciones. 7na conversi-n expl5cita num)rica se procesa como se explica a continuaci-nG 'ara una conversi-n de un tipo integral a otro tipo integral, el procesamiento depende del contexto de comprobaci-n de desbordamiento O[*. .12R en el ?ue tiene lugar la conversi-nG o En un contexto c"ec(ed, la conversi-n termina correctamente si el valor del operando de origen ?ueda dentro del intervalo del tipo de destino, pero inicia una excepci-n System.%ver-lo,)#ce&tion si ?ueda 0uera de dic=o intervalo. En un contexto unc"ec(ed, la conversi-n siempre termina correctamente y se procesa como sigue. .i el tipo de origen es mayor ?ue el de destino, el valor de origen se trunca descartando sus bits PextraQ m(s signi0icativos. 2espu)s el resultado se trata como un valor del tipo de destino. .i el tipo de origen es menor ?ue el tipo de destino, el valor de origen se ampl5a con un signo o con ceros, de 0orma ?ue tenga el mismo tamaUo ?ue el tipo de destino. 8a ampliaci-n con signo se utili1a si el tipo de origen tiene signoV se utili1a la ampliaci-n con ceros si el tipo de origen no lleva signo. 2espu)s el resultado se trata como un valor del tipo de destino. .i el tipo del origen tiene el mismo tamaUo ?ue el tipo de destino, el valor de origen se trata como un valor del tipo de destino.

Cuando se convierte un valor de tipo decimal a un tipo integral, el valor de origen se redondea =acia cero =asta el valor entero m(s pr-ximo, y este valor integral pasa a ser el resultado de la conversi-n. .i el valor integral resultante ?ueda 0uera del intervalo del tipo de destino, se produce una excepci-n System.%ver-lo,)#ce&tion. 'ara la conversi-n de un tipo -loat o double a otro tipo integral, el procesamiento depende del contexto de comprobaci-n de desbordamiento O[*. .12R en el ?ue tiene lugar la conversi-nG o En un contexto c"ec(ed, la conversi-n sigue este procedimientoG .i el valor del operando es 4a4 o in0inito, se inicia una excepci-n System.%ver-lo,)#ce&tion. 2e lo contrario, el operando de origen se redondea =acia cero, =asta el valor integral m(s cercano. .i dic=o valor se encuentra dentro del intervalo del tipo de destino, pasar( a ser el resultado de la conversi-n. 2e lo contrario, se inicia una excepci-n System.%ver-lo,)#ce&tion. .i el valor del operando es 4a4 o in0inito, el resultado de la conversi-n es un valor no especi0icado del tipo de destino.

En un contexto unc"ec(ed, la conversi-n siempre termina correctamente y se procesa como sigue.

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

123

Especificacin del lenguaje C#

2e lo contrario, el operando de origen se redondea =acia cero, =asta el valor integral m(s cercano. .i dic=o valor se encuentra dentro del intervalo del tipo de destino, pasar( a ser el resultado de la conversi-n. 2e no ser as5, el resultado de la conversi-n ser( un valor no especi0icado del tipo de destino.

'ara una conversi-n de double a -loat, el valor double se redondea al valor -loat m(s pr-ximo. .i el valor double es demasiado pe?ueUo para representarlo como -loat, el resultado se convierte en cero positivo o cero negativo. .i el valor double es demasiado grande para representarlo como -loat, el resultado se convierte en in0inito positivo o in0inito negativo. .i el valor double es 4a4, el resultado tambi)n es 4a4. 'ara una conversi-n de -loat o double a decimal, el valor de origen se convierte a la representaci-n decimal y se redondea =asta el nHmero m(s pr-ximo despu)s de la posici-n decimal 28 si es necesario O[4.1.*R. .i el valor de origen es demasiado pe?ueUo para representarlo como decimal, el resultado es cero. .i el valor de origen es 4a4, in0inito o demasiado grande para representarlo como decimal, se inicia una excepci-n System.%ver-lo,)#ce&tion. 'ara una conversi-n de decimal a -loat o double, el valor decimal se redondea al valor -loat o double m(s pr-ximo. &un?ue esta conversi-n puede perder precisi-n, nunca produce una excepci-n.

$.2.2 %on ersiones de enumeracin e"pl2citas 8as conversiones expl5citas de enumeraci-n sonG 2e sbyte, byte, s"ort, us"ort, int, uint, long, ulong, c"ar, -loat, double o decimal a cual?uier tipo enum Oen %-t#peR. 2e cual?uier tipo enum Oen %-t#peR a sbyte, byte, s"ort, us"ort, int, uint, long, ulong, c"ar, -loat, double o decimal. 2e un tipo enum Oen %-t#peR a cual?uier otro tipo enum.

7na conversi-n expl5cita de enumeraci-n entre dos tipos se procesa tratando a uno de los tipos enum Oen %t#peR como tipo subyacente del otro, y reali1ando, a continuaci-n, una conversi-n num)rica impl5cita o expl5cita entre los tipos resultantes. 'or e$emplo, dado un tipo enum Oen %-t#peR ) con un tipo subyacente de int, una conversi-n de ) a byte se trata como una conversi-n expl5cita num)rica O[#.2.1R de int a byte, y una conversi-n de byte a ) se procesa como una conversi-n impl5cita num)rica O[#.1.2R de byte a int. $.2.3 %on ersiones e"pl2citas ;ue aceptan alores 1566 8as conversiones e.plcitas "!e aceptan valores 2300 permiten prede0inir conversiones expl5citas ?ue 0uncionan en tipos de valor ?ue no aceptan valores 4788 para ?ue sean utili1ados tambi)n con estructuras ?ue aceptan valores 4788 de dic=os tipos. 'ara cada una de las conversiones prede0inidas ?ue se convierten de un tipo de valor S ?ue no acepta valores 4788 a un tipo de valor 1 ?ue no acepta valores 4788 O[#.1.1, [#.1.2, [#.1.3, [#.2.1 y [#.2.2R, existen las siguientes conversiones ?ue aceptan valores 4788G 7na conversi-n expl5cita de S7 a 17. 7na conversi-n expl5cita de S a 17. 7na conversi-n expl5cita de S7 a 1.

8a evaluaci-n de una conversi-n ?ue acepta valores 4788 se basa en una conversi-n subyacente de S a 1 se reali1a de la siguiente maneraG .i la conversi-n ?ue acepta valores 4788 se reali1a de S7 a 17G

12#

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

o o

.i el valor de origen es 4788 Ola propiedad HasUalue es 0alsaR, el resultado es el valor 4788 del tipo 17. 2e lo contrario, la conversi-n se evalHa como un desa$uste de S7 a S, seguido de la conversi-n subyacente de S a 1, seguida de un a$uste de 1 a 17.

.i la conversi-n ?ue acepta valores 4788 se reali1a de S a 17, la conversi-n se evalHa como la conversi-n subyacente de S a 1 seguida de un a$uste de 1 a 17. .i la conversi-n ?ue acepta valores 4788 se reali1a de S7 a 1, la conversi-n se evalHa como un desa$uste de S7 a S seguida de la conversi-n subyacente de S a 1. Tenga en cuenta ?ue cual?uier intento por desa$ustar un valor ?ue acepta valores 4788 producir( una excepci-n si el valor es null.

$.2.! %on ersiones e"pl2citas de referencia 8as conversiones expl5citas de re0erencia sonG 2e object a cual?uier otro tipo de re0erencia Oreference-t#peR. 2e cual?uier tipo de clase Oclass-t#peR S a cual?uier tipo de clase Oclass-t#peR 1, siempre ?ue S sea una clase base de 1. 2e cual?uier tipo de clase Oclass-t#peR S a cual?uier tipo de inter0a1 Ointerface-t#peR 1, siempre ?ue S no sea sealed y ?ue S no implemente a 1. 2e cual?uier tipo de inter0a1 Ointerface-t#peR S a cual?uier tipo de clase Oclass-t#peR 1, siempre ?ue 1 no sea sealed ni implemente a S. 2e cual?uier tipo de inter0a1 Ointerface-t#peR S a cual?uier tipo de inter0a1 Ointerface-t#peR 1, a condici-n de ?ue S no se derive de 1. 2e un tipo de matri1 Oarra#-t#peR S con un tipo de elemento S) a un tipo de matri1 1 con un tipo de elemento 1), siempre ?ue se cumpla todo lo siguienteG o o o
S y 1 di0ieren solamente en el tipo de elemento. Esto es, S y 1 tienen el mismo nHmero de dimensiones.

Tanto S) como 1) son tipos de re0erencia Oreference-t#pesR. Existe una conversi-n expl5cita de re0erencia de S) a 1).

2esde System.'rray y las inter0aces ?ue implementa, a cual?uier tipo de matri1 Oarra#-t#peR. 2esde un tipo de matri1 unidimensional S45 a System.Collections.Seneric.$ListD1E y sus inter0aces base, siempre ?ue =aya una identidad expl5cita o una conversi-n de re0erencia de S a 1. 2esde System.Collections.Seneric.$ListDSE y sus inter0aces base a un tipo de matri1 unidimensional 145, siempre ?ue =aya una identidad expl5cita o una conversi-n de re0erencia de S a 1. 2e System.6elegate y las inter0aces ?ue implementa a cual?uier tipo delegado Odele&ate-t#peR. Conversiones expl5citas ?ue impli?uen par(metros de tipo ?ue se sabe ?ue son tipos de re0erencia. 'ara obtener m(s datos acerca de las conversiones expl5citas ?ue implican par(metros de tipo ve la secci-n [#.2.#.

8as conversiones expl5citas de re0erencia son a?uellas conversiones entre tipos de re0erencias ?ue re?uieren comprobaciones en tiempo de e$ecuci-n para asegurar ?ue son correctas. 'ara ?ue una conversi-n expl5cita de re0erencia se realice correctamente en tiempo de e$ecuci-n, el valor del operando de origen debe ser una re0erencia null, o el tipo real del ob$eto al ?ue =ace re0erencia el operando de
Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

12!

Especificacin del lenguaje C#

origen debe ser un tipo convertible al tipo de destino mediante una conversi-n impl5cita de re0erencia O[#.1.#R. .i una conversi-n expl5cita de re0erencia produce un error, se inicia una excepci-n System.$nvalidCast)#ce&tion. 8as conversiones de re0erencia, tanto impl5citas como expl5citas, nunca cambian la identidad re0erencial del ob$eto ?ue se convierte. Es decir, si bien una conversi-n de re0erencia puede cambiar el tipo de la re0erencia, nunca cambia el tipo o el valor del ob$eto al ?ue se re0iere. $.2.# %on ersiones 5nbo"ing 7na conversi-n unboxing permite ?ue un tipo de re0erencia Oreference-t#peR se convierta expl5citamente en un tipo de valor Oval e-t#peR. Existe una conversi-n unboxing de los tipos object y System.Ualue1y&e a cual?uier tipo de valor ?ue no acepta valores 4788 Onon-n lla-le-val e-t#peR, y de cual?uier tipo de inter0a1 Ointerface-t#peR a cual?uier tipo de valor ?ue no acepta valores 4788 Onon-n lla-le-val e-t#peR ?ue implementa el tipo de inter0a1 Ointerface-t#peR. Es m(s, se puede aplicar una conversi-n unboxing en un tipo System.)num para convertirlo en un tipo enum Oen %-t#peR. Existe una conversi-n unboxing de cual?uier tipo de re0erencia a un tipo ?ue acepta valores 4788 On lla-leval e-t#peR, si existe una conversi-n unboxing del tipo de re0erencia al tipo de valor ?ue no acepta valores 4788 Onon-n lla-le-val e-t#peR subyacente del tipo ?ue acepta valores 4788 On lla-le-t#peR. 7na operaci-n unboxing consiste en comprobar primero ?ue la instancia del ob$eto es un valor al ?ue se =a aplicado la conversi-n boxing del tipo de valor Oval e-t#peR dado, y copiar despu)s el valor 0uera de la instancia. 8a conversi-n unboxing de un valor de re0erencia a un tipo ?ue acepta valores 4788 On lla-le-t#peR produce una el valor 4788 del tipo ?ue acepta valores 4788 On lla-le-t#peR. .e puede aplicar a una estructura una conversi-n unboxing desde el tipo System.Ualue1y&e, por?ue )sa es una clase base para todas las estructuras O[11.3.2R. 8as conversiones unboxing se explican m(s detalladamente en [4.3.2. $.2.$ %on ersiones e"pl2citas con par)metros de tipo 'ara un par(metro de tipo 1 dado, existen las siguientes conversiones impl5citasG 2esde la clase base e0ectiva C de 1 a 1, y desde cual?uier clase base de C a 1. En tiempo de e$ecuci-n, si 1 es un tipo de valor, la conversi-n se e$ecuta como una conversi-n unboxing. 2e lo contrario, la conversi-n se e$ecuta como una conversi-n de re0erencia expl5cita o una conversi-n de identidad. 2esde cual?uier tipo de inter0a1 a 1. En tiempo de e$ecuci-n, si 1 es un tipo de valor, la conversi-n se e$ecuta como una conversi-n unboxing. 2e lo contrario, la conversi-n se e$ecuta como una conversi-n de re0erencia expl5cita o una conversi-n de identidad. 2esde 1 a cual?uier $ de tipo de inter0a1 Ointerface-t#peR siempre y cuando no exista ya una conversi-n impl5cita de 1 a $. En tiempo de e$ecuci-n, si 1 es un tipo de valor, la conversi-n se e$ecuta como una conversi-n boxing seguida de una conversi-n de re0erencia expl5cita. 2e lo contrario, la conversi-n se e$ecuta como una conversi-n de re0erencia expl5cita o una conversi-n de identidad. 2esde un par(metro de tipo ; o 1, siempre ?ue 1 dependa de ; O[1".1. R. En tiempo de e$ecuci-n, si ; es un tipo de valor, entonces 1 y ; son necesariamente el mismo tipo y no se reali1a una conversi-n boxing. 2e lo contrario, si 1 es un tipo de re0erencia, necesariamente ; tambi)n lo es y la conversi-n se e$ecuta como una conversi-n de re0erencia expl5cita o una conversi-n de identidad.

.i 1 es un tipo de re0erencia, las conversiones anteriores se clasi0ican como conversiones de re0erencia expl5citas O[R. .i T no es un tipo de re0erencia, las conversiones anteriores se clasi0ican como conversiones unboxing O[R.

126

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

8as reglas anteriores no permiten una conversi-n expl5cita directa desde un par(metro de tipo sin restricciones a un tipo de inter0a1, lo ?ue puede resultar sorprendente. El motivo es evitar la con0usi-n y =acer m(s 0(cil la sem(ntica de dic=as conversiones. 'or e$emplo, en la siguiente declaraci-nG
class ID1E { &ublic static long V(1 t) { return (long)t; ! !

.. )rror

.i se permitiese la conversi-n expl5cita directa de t a int, el resultado esperado de IDintE.V(M) ser5a ML. .in embargo, no es as5 por?ue las conversiones num)ricas est(ndar s-lo se consideran cuando los tipos son num)ricos en tiempo de compilaci-n. 'ara ?ue la sem(ntica sea m(s clara, el e$emplo anterior se debe escribir de la siguiente maneraG
class ID1E { &ublic static long V(1 t) { return (long)(object)t; ! !

.. %(

but ,ill only ,or( ,"en 1 is long

Este c-digo se compilar(, pero si se e$ecuta IDintE.V(M) se iniciar( una excepci-n en tiempo de e$ecuci-n, puesto ?ue int, al ?ue se =a aplicado una conversi-n boxing, no se puede convertir directamente en long. $.2.+ %on ersiones e"pl2citas definidas por el usuario 7na conversi-n expl5cita de0inida por el usuario consta de una conversi-n expl5cita opcional est(ndar, seguida por la e$ecuci-n de un operador de conversi-n impl5cita o expl5cita de0inida por el usuario, seguido por otra conversi-n expl5cita opcional est(ndar. 8as reglas exactas para la evaluaci-n de conversiones expl5citas de0inidas por el usuario se describen en [#.4. .

$.3 %on ersiones est)ndar


8as conversiones est(ndar son conversiones prede0inidas ?ue pueden ocurrir como parte de una conversi-n de0inida por el usuario. $.3.1 %on ersiones impl2citas est)ndar 8as siguientes conversiones impl5citas se clasi0ican como conversiones impl5citas est(ndarG Conversiones de identidad O[#.1.1R Conversiones num)ricas impl5citas O[#.1.2R Conversiones impl5citas ?ue aceptan valores 4788 O[#.1.4R Conversiones impl5citas de re0erencia O[#.1.#R Conversiones boxing O[#.1.*R Conversiones impl5citas de expresi-n constante O[#.1.8R Conversiones impl5citas con par(metros de tipo O[#.1.+R

8as conversiones impl5citas est(ndar excluyen de 0orma espec50ica las conversiones impl5citas de0inidas por el usuario.

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

12(

Especificacin del lenguaje C#

$.3.2 %on ersiones e"pl2citas est)ndar 8as conversiones expl5citas est(ndar son todas las conversiones impl5citas est(ndar m(s el subcon$unto de las conversiones expl5citas para las cuales existe una conversi-n impl5cita est(ndar opuesta. Es decir, si existe una conversi-n impl5cita est(ndar de un tipo ' a un tipo :, eso signi0ica ?ue existe una conversi-n expl5cita est(ndar del tipo ' al tipo : y del tipo : al tipo '.

$.! %on ersiones definidas por el usuario


C# permite la ampliaci-n de las conversiones expl5citas e impl5citas prede0inidas mediante conversiones definidas por el !s!ario. 8as conversiones de0inidas por el usuario se introducen mediante la declaraci-n de operadores de conversi-n O[1".1".3R en tipos de clase y struct. $.!.1 %on ersiones permitidas definidas por el usuario C# s-lo permite la declaraci-n de algunas conversiones de0inidas por el usuario. En concreto, no es posible rede0inir una conversi-n expl5cita o impl5cita ya existente. 'ara un tipo de origen S y de destino 1 dados, si S o 1 son tipos ?ue aceptan valores 4788, S3 y 13 =acen re0erencia a sus tipos subyacentes, en caso contrario S3 y 13 son iguales ?ue S y 1 respectivamente. 7na clase o estructura tiene permitido declarar una conversi-n de un tipo de origen S a un tipo de destino 1 solamente si son verdaderos todos los puntos siguientesG
S3 y 13 son tipos di0erentes. S3 o 13 es el tipo de clase o estructura en el ?ue tiene lugar la declaraci-n del operador.

4i S3 ni 13 es un tipo de inter0a1 Ointerface-t#peR. Excluyendo las conversiones de0inidas por el usuario, una conversi-n no existe de S a 1 ni de 1 a S.

8as restricciones aplicables a las conversiones de0inidas por el usuario se explican en [1".1".3. $.!.2 ,peradores de con ersin de ele acin 2ado un operador de conversi-n de0inida por el usuario ?ue reali1a conversiones de un tipo de valor ?ue no acepta valores 4788 S a un tipo de valor ?ue no acepta valores 4788 1, existe un operador de conversi,n de elevaci,n ?ue convierte de S7 a 17. Este operador de conversi-n de elevaci-n reali1a un desa$uste de S7 a S seguido de una conversi-n de0inida por el usuario de S a 1 seguida de un a$uste de 1 a 17, con la excepci-n de ?ue S7 con valor 4788 se convierte directamente en 17 con valor 4788. 7n operador de conversi-n de elevaci-n tiene la misma clasi0icaci-n impl5cita o expl5cita ?ue su operador de conversi-n de0inido por el usuario. El t)rmino Pconversi-n de0inida por el usuarioQ se aplica al uso tanto de operadores de conversi-n de0inida por el usuario como a operadores de conversi-n de elevaci-n. $.!.3 E aluacin de con ersiones definidas por el usuario 7na conversi-n de0inida por el usuario convierte un valor de su tipo, denominado tipo de origen, a otro tipo, denominado tipo de destino. 8a evaluaci-n de una conversi-n de0inida por el usuario se centra en descubrir el operador de conversi-n de0inida por el usuario 5s especfico para los tipos de origen y de destino concretos. Esta determinaci-n se divide en varios pasosG Auscar el con$unto de clases y estructuras a partir del cual se consideran los operadores de conversi-n de0inida por el usuario. Este con$unto consta del tipo de origen y sus clases base y el tipo de destino y sus clases base Ocon los supuestos impl5citos de ?ue s-lo las clases y estructuras pueden declarar operadores de0inidos por el usuario y de ?ue los tipos no de clase no tienen clases baseR. 'ara este procedimiento, si el

12$

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

tipo de origen o el de destino es un tipo ?ue acepta valores 4788 On lla-le-t#peR, se usa su tipo subyacente en su lugar. & partir del con$unto de tipos, determinar ?u) operadores de conversi-n de0inida por el usuario o de elevaci-n son aplicables. 'ara ?ue un operador de conversi-n sea aplicable, debe ser posible reali1ar una conversi-n est(ndar O[#.3R del tipo de origen al tipo de operando del operador, y debe ser posible reali1ar una conversi-n est(ndar del tipo del resultado del operador al tipo de destino. & partir del con$unto de operadores de0inidos por el usuario ?ue puedan aplicarse, determinar ?u) operador es el m(s espec50ico sin ninguna ambigIedad. En t)rminos generales, el operador m(s espec50ico es a?u)l cuyo tipo de operando es el Pm(s pr-ximoQ al tipo de origen y cuyo tipo de resultado es el Pm(s pr-ximoQ al tipo de destino. .e pre0ieren los operadores de conversi-n de0inida por el usuario a los operadores de conversi-n de elevaci-n. En las pr-ximas secciones se de0inen las reglas exactas para establecer el operador de conversi-n de0inido por el usuario m(s espec50ico.

7na ve1 identi0icado un operador de conversi-n de0inido por el usuario m(s espec50ico, la e$ecuci-n de la conversi-n de0inida por el usuario implica =asta tres pasosG 'rimero, si se re?uiere, reali1ar una conversi-n est(ndar del tipo de origen al tipo de operando del operador de conversi-n de0inida por el usuario o de elevaci-n. 2espu)s, invocar al operador de conversi-n de0inida por el usuario o de elevaci-n para ?ue realice la conversi-n. 'or Hltimo, si se re?uiere, reali1ar una conversi-n est(ndar del tipo del resultado del operador de conversi-n de0inida por el usuario o de elevaci-n al tipo de destino.

8a evaluaci-n de una conversi-n de0inida por el usuario nunca necesita m(s de un operador de conversi-n de0inida por el usuario o de elevaci-n. Esto es, una conversi-n del tipo S al tipo 1 nunca e$ecuta en primer lugar una conversi-n de0inida por el usuario de S a I y despu)s una conversi-n de0inida por el usuario de I a 1. En las pr-ximas secciones se o0recen las de0iniciones exactas de la evaluaci-n de conversiones impl5citas o expl5citas de0inidas por el usuario. En las de0iniciones se usan los siguientes t)rminosG .i existe una conversi-n impl5cita est(ndar O[#.3.1R de un tipo ' a un tipo :, y si ni ' ni : are son tipos de inter0a1 Ointerface-t#pesR, entonces se dice ?ue ' est( a/arcado por :, y ?ue : a/arca '. El tipo "!e 5s a/arca de un con$unto de tipos es a?u)l ?ue abarca a todos los dem(s tipos del con$unto. .i ninguno de los tipos abarca a todos los dem(s, entonces el con$unto no tiene tipo ?ue m(s abarca. En t)rminos m(s intuitivos, el tipo ?ue m(s abarca es el PmayorQ del con$unto, el tipo al ?ue pueden convertirse impl5citamente todos los dem(s tipos. El tipo 5s a/arcado de un con$unto de tipos es a?u)l al ?ue abarcan todos los dem(s tipos del con$unto. .i ninguno de los tipos es abarcado por todos los dem(s, entonces el con$unto no tiene un tipo m(s abarcado. En t)rminos m(s intuitivos, el tipo m(s abarcado es el PmenorQ del con$unto, a?u)l ?ue puede convertirse impl5citamente a todos los dem(s tipos.

$.!.! %on ersiones e"pl2citas definidas por el usuario 7na conversi-n impl5cita de0inida por el usuario del tipo S al tipo 1 se procesa como sigueG 2eterminar los tipos S3 y 13. .i S o 1 son tipos ?ue aceptan valores 4788, S3 y 13 =acen re0erencia a sus tipos subyacentes, en caso contrario S3 y 13 son iguales ?ue S y 1 respectivamente. .e busca un con$unto de tipos, 6, a partir del cual se consideran los operadores de conversi-n de0inida por el usuario. Este con$unto est( 0ormado por S3 Osi S3 es una clase o una estructuraR, las clases base de S3 Osi S3 es una claseR y 13 Osi 13 es una clase o una estructuraR.

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

12"

Especificacin del lenguaje C#

.e busca el con$unto de operadores de conversi-n de0inida por el usuario o de elevaci-n aplicables, ;. Este con$unto est( 0ormado por los operadores de0inidos por el usuario y operadores de conversi-n impl5cita de elevaci-n declarados por las clases o estructuras en 6 ?ue reali1an la conversi-n de un tipo ?ue abarca S a un tipo abarcado por 1. .i ; est( vac5a, la conversi-n no estar( de0inida y se producir( un error en tiempo de e$ecuci-n. .e busca el tipo de origen m(s espec50ico, SI, de los operadores de ;G o o .i uno de los operadores de ; se convierte desde S, entonces SI es S. 2e lo contrario, SI es el tipo m(s abarcado del con$unto combinado de tipos de origen de los operadores de ;. .i no se puede encontrar exactamente el tipo m(s abarcado, la conversi-n es ambigua y se genera un error en tiempo de compilaci-n. .i uno de los operadores de ; se convierte a 1, entonces 1I es 1. 2e lo contrario, 1I es el tipo ?ue m(s abarca del con$unto combinado de tipos de destino de los operadores de ;. .i no se puede encontrar exactamente el tipo ?ue m(s abarca, la conversi-n es ambigua y se genera un error en tiempo de compilaci-n. .i ; contiene exactamente un operador de conversi-n de0inida por el usuario ?ue convierte de SI a 1I, )ste es el operador de conversi-n m(s espec50ico. 2e lo contrario, si ; contiene exactamente un operador de conversi-n de elevaci-n ?ue reali1a la conversi-n de SI a 1I, )ste es el operador de conversi-n m(s espec50ico. 2e lo contrario, la conversi-n es ambigua y se genera un error en tiempo de compilaci-n. .i S no es SI, se reali1a una conversi-n impl5cita est(ndar de S a SI. El operador de conversi-n m(s espec50ico se invoca para reali1ar la conversi-n de SI a 1I. .i 1I no es 1, se reali1a una conversi-n impl5cita est(ndar de 1I a 1.

.e busca el tipo de destino m(s espec50ico, 1I, de los operadores de ;G o o

.e buscar el operador de conversi-n m(s espec50icoG o o o

'or Hltimo, se aplica la conversi-nG o o o

$.!.# %on ersiones e"pl2citas definidas por el usuario 7na conversi-n expl5cita de0inida por el usuario del tipo S al tipo 1 se procesa como sigueG 2eterminar los tipos S3 y 13. .i S o 1 son tipos ?ue aceptan valores 4788, S3 y 13 =acen re0erencia a sus tipos subyacentes, en caso contrario S3 y 13 son iguales ?ue S y 1 respectivamente. .e busca un con$unto de tipos, 6, a partir del cual se consideran los operadores de conversi-n de0inida por el usuario. Este con$unto consta de S3 Osi S3 es una clase o estructuraR, las clases base de S3 Osi S3 es una claseR, 13 Osi 13 es una clase o estructuraR y las clases base de 13 Osi 13 es una claseR. .e busca el con$unto de operadores de conversi-n de0inida por el usuario o de elevaci-n aplicables, ;. Este con$unto est( 0ormado por los operadores de0inidos por el usuario y los operadores de conversi-n expl5cita de elevaci-n declarados por las clases o estructuras en 6 ?ue reali1an la conversi-n de un tipo abarcado o ?ue abarca S a un tipo abarcado o ?ue abarca 1. .i ; est( vac5a, la conversi-n no estar( de0inida y se producir( un error en tiempo de e$ecuci-n. .e busca el tipo de origen m(s espec50ico, SI, de los operadores de ;G o .i uno de los operadores de ; se convierte desde S, entonces SI es S.

13'

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

2e lo contrario, si uno de los operadores de ; convierte de los tipos ?ue abarca S, entonces SI es el tipo m(s abarcado del con$unto combinado de tipos de origen de estos operadores. .i no se encuentra un tipo m(s abarcado, la conversi-n ser( ambigua y se producir( un error en tiempo de compilaci-n. 2e lo contrario, SI es el tipo ?ue m(s abarca del con$unto combinado de tipos de origen de los operadores de ;. .i no se puede encontrar exactamente el tipo ?ue m(s abarca, la conversi-n es ambigua y se genera un error en tiempo de compilaci-n. .i uno de los operadores de ; se convierte a 1, entonces 1I es 1. 2e lo contrario, si uno de los operadores de ; convierte a los tipos abarcados por 1, entonces 1I es el tipo ?ue m(s abarca del con$unto combinado de tipos de origen de estos operadores. .i no se puede encontrar exactamente el tipo m(s abarcado, la conversi-n es ambigua y se genera un error en tiempo de compilaci-n. 2e lo contrario, 1I es el tipo m(s abarcado del con$unto combinado de tipos de destino de los operadores de ;. .i no se puede encontrar exactamente el tipo m(s abarcado, la conversi-n puede ser ambigua y se genera un error en tiempo de compilaci-n. .i ; contiene exactamente un operador de conversi-n de0inida por el usuario ?ue convierte de SI a 1I, )ste es el operador de conversi-n m(s espec50ico. 2e lo contrario, si ; contiene exactamente un operador de conversi-n de elevaci-n ?ue reali1a la conversi-n de SI a 1I, )ste es el operador de conversi-n m(s espec50ico. 2e lo contrario, la conversi-n es ambigua y se genera un error en tiempo de compilaci-n. .i S no es SI, se reali1a una conversi-n expl5cita est(ndar de S a SI. .e llama al operador de conversi-n m(s espec50ico de0inido por el usuario para convertir de SI a 1I. .i 1I no es 1, se reali1a una conversi-n expl5cita est(ndar de 1I a 1.

.e busca el tipo de destino m(s espec50ico, 1I, de los operadores de ;G o o

.e buscar el operador de conversi-n m(s espec50icoG o o o

'or Hltimo, se aplica la conversi-nG o o o

$.# %on ersiones de funcin annima


7na expresi-n de m)todo an-nimo Oanon#%o s-%ethod-e2pressionR o expresi-n lambda Ola%-da-e2pressionR se clasi0ica como una 0unci-n an-nima O[R. 8a expresi-n no tiene un tipo, pero se puede convertir de manera impl5cita en un tipo de (rbol de expresiones o un tipo delegado compatible. En concreto, un tipo delegado 6 es compatible con una 0unci-n an-nima V siempre ?ueG .i V contiene una 0irma de 0unci-n an-nima Oanon#%o s-f nction-si&nat reR, 6 y V tienen el mismo nHmero de par(metros. .i V no contiene una 0irma de 0unci-n an-nima Oanon#%o s-f nction-si&nat reR, 6 puede no tener ningHn par(metro o tener par(metros de cual?uier tipo siempre y cuando ninguno de ellos tenga el modi0icador de par(metros out. .i V tiene una lista de par(metros escritos expl5citamente, cada par(metro de 6 tiene el mismo tipo y los mismos modi0icadores ?ue el par(metro correspondiente en V. .i V tiene una lista de par(metros escritos impl5citamente, 6 no tiene ningHn par(metro re- u out.

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

131

Especificacin del lenguaje C#

.i 6 tiene un tipo de valor devuelto void y el cuerpo de V es una expresi-n, cuando se da a cada par(metro de V el tipo del par(metro correspondiente en 6, el cuerpo de V es una expresi-n v(lida O9rt [*R ?ue se permitir5a como expresi-n de instrucci-n Ostate%ent-e2pressionR O[8.#R. .i 6 tiene un tipo de valor devuelto void y el cuerpo de V es un blo?ue de instrucciones, cuando se da a cada par(metro de V el tipo del par(metro correspondiente en 6, el cuerpo de V es un blo?ue de instrucci-n v(lido O9rt [*R en el ?ue ninguna instrucci-n return especi0ica una expresi-n. .i 6 tiene un tipo de valor devuelto ?ue no es void y el cuerpo de V es una expresi-n, cuando se da a cada par(metro de V el tipo del par(metro correspondiente en 6, el cuerpo de V es una expresi-n v(lida O9rt [*R ?ue es impl5citamente convertible al tipo de valor devuelto de 6. .i 6 tiene un tipo de valor devuelto ?ue no es void y el cuerpo de V es un blo?ue de instrucciones, cuando se da a cada par(metro de V el tipo del par(metro correspondiente en 6, el cuerpo de V es un blo?ue de instrucci-n v(lido O9rt [8.2R con un punto 0inal ?ue no es alcan1able en el ?ue cada instrucci-n return especi0ica una expresi-n ?ue es impl5citamente convertible al tipo de 6.

7n tipo de (rbol de expresiones )#&ressionD6E es compatible con una 0unci-n an-nima V si el tipo delegado 6 es compatible con V. En el e$emplo siguiente se utili1a un tipo delegado gen)rico VuncD' OE ?ue representa una 0unci-n ?ue toma un argumento del tipo ' y devuelve un valor de tipo OG
delegate O VuncD' OE(' arg);

En las asignaciones
VuncDint intE -2 + # +E # < 2; VuncDint doubleE -8 + # +E # < 2; VuncDdouble intE -9 + # +E # < 2; .. %( .. %( .. )rror

el par(metro y los tipos de valor devuelto de cada 0unci-n an-nima se determinan a partir del tipo de la variable a la ?ue la 0unci-n an-nima se asigna. 8a primera asignaci-n convierte correctamente la 0unci-n an-nima en el tipo delegado VuncDint intE por?ue, cuando se da a # el tipo int, # < 2 es una expresi-n v(lida ?ue es impl5citamente convertible al tipo int. 2el mismo modo, la segunda asignaci-n convierte correctamente la 0unci-n an-nima en el tipo delegado VuncDint doubleE por?ue el resultado de # < 2 Ode tipo intR es impl5citamente convertible al tipo double. .in embargo, la tercera asignaci-n es un error en tiempo de compilaci-n por?ue, cuando se da a # el tipo double, el resultado de # < 2 Ode tipo doubleR no es impl5citamente convertible al tipo int. 8as 0unciones an-nimas pueden in0luenciar la resoluci-n de sobrecargas y participar en la in0erencia de tipos. Consulte la [*.4 para obtener m(s detalles. $.#.1 E aluacin de con ersiones de funcin annima a tipos delegados 8a conversi-n de una 0unci-n an-nima a un tipo delegado genera una instancia de delegado ?ue =ace re0erencia a la 0unci-n an-nima y al con$unto Oposiblemente vac5oR de variables externas capturadas y activas en el momento de la evaluaci-n. .i se invoca el delegado, se e$ecuta el cuerpo de la 0unci-n an-nima. El c-digo del cuerpo se e$ecuta con el con$unto de variables externas capturadas al ?ue el delegado =ace re0erencia. 8a lista de invocaci-n de un delegado producida desde una 0unci-n an-nima contiene una sola entrada. 4o se especi0ican el ob$eto y el m)todo de destino exactos del delegado. En concreto, no se especi0ica si el ob$eto de destino del delegado es null, el valor t"is del miembro de 0unci-n envolvente o algHn otro ob$eto.

132

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

8as conversiones de 0unciones an-nimas de sem(nticas id)nticas con el mismo con$unto Oposiblemente vac5oR de instancias de variables externas capturadas a los mismos tipos delegados pueden devolver Oaun?ue no es obligatorioR la misma instancia de delegado. En este contexto, sem(ntica id)ntica =ace re0erencia a ?ue la e$ecuci-n de 0unciones an-nimas generar( en todos los casos los mismos e0ectos si se dan los mismos argumentos. Esta regla permite optimi1ar c-digo como el siguiente.
delegate double Vunction(double #); class 1est { static double45 '&&ly(double45 a Vunction -) { double45 result + ne, double4a.Lengt"5; -or (int i + 3; i D a.Lengt"; i<<) result4i5 + -(a4i5); return result; ! static void V(double45 a double45 b) { a + '&&ly(a (double #) +E Mat".Sin(#)); b + '&&ly(b (double y) +E Mat".Sin(y)); ... ! !

'uesto ?ue los dos delegados de 0unci-n an-nima tienen el mismo con$unto Ovac5oR de variables externas capturadas y puesto ?ue las 0unciones an-nimas son sem(nticamente id)nticas, el compilador puede tener delegados ?ue =agan re0erencia al mismo m)todo de destino. 2e =ec=o, el compilador puede devolver la misma instancia de delegado de ambas expresiones de 0unci-n an-nima. $.#.2 E aluacin de con ersiones de funcin annima a tipos delegados de )rbol de e"presiones 8a conversi-n de una 0unci-n an-nima a un tipo de (rbol de expresiones produce un (rbol de expresiones O[4.#R. %(s concretamente, la evaluaci-n de la conversi-n de 0unci-n an-nima conduce a la construcci-n de una estructura de ob$etos ?ue representa la estructura de la 0unci-n an-nima en s5. 8a estructura precisa del (rbol de expresiones, as5 como el proceso exacto de su creaci-n se de0inen en otro lugar. $.#.3 Ejemplo de implementacin En esta secci-n se describe una posible implementaci-n de conversiones de 0unciones an-nimas en t)rminos de otras construcciones del lengua$e C#. 8a implementaci-n a?u5 descrita se basa en los mismos principios utili1ados por el compilador de %icroso0t C#, pero no es una implementaci-n obligatoria ni tampoco la Hnica posible. .-lo se mencionan brevemente los (rboles de expresiones, ya ?ue su sem(ntica exacta est( 0uera del (mbito de este documento. En el resto de esta secci-n se proporcionan varios e$emplos de c-digo ?ue incluye 0unciones an-nimas con di0erentes caracter5sticas. En cada uno de los e$emplos se proporciona la traducci-n correspondiente al c-digo ?ue s-lo utili1a otras construcciones est(ndar del lengua$e C#. En los e$emplos, se asume ?ue el identi0icador 6 representa el siguiente tipo delegadoG
&ublic delegate void 6();

8a estructura m(s sencilla de una 0unci-n an-nima es la ?ue no captura variables externasG
class 1est { static void V() { 6 d + () +E { Console.WriteLine("test"); !; ! !

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

133

Especificacin del lenguaje C#

Esto se puede traducir en una creaci-n de instancias de delegado ?ue =ace re0erencia a un m)todo est(tico generado por compilador en el ?ue se sitHa la 0unci-n an-nimaG
class 1est { static void V() { 6 d + ne, 6(\\Met"od2); ! static void \\Met"od2() { Console.WriteLine("test"); ! !

En el siguiente e$emplo, la 0unci-n an-nima =ace re0erencia a miembros de instancia de t"isG


class 1est { int #; void V() { 6 d + () +E { Console.WriteLine(#); !; ! !

.e puede traducir en un m)todo de instancia generado por compilador ?ue contiene el c-digo de la 0unci-n an-nimaG
class 1est { int #; void V() { 6 d + ne, 6(\\Met"od2); ! void \\Met"od2() { Console.WriteLine(#); ! !

En este e$emplo, la 0unci-n an-nima captura una variable localG


class 1est { void V() { int y + 289; 6 d + () +E { Console.WriteLine(y); !; ! !

&=ora, el per5odo de duraci-n de la variable local se debe extender al menos al per5odo de duraci-n del delegado de la 0unci-n an-nima. Esto se puede lograr PactivandoQ la variable local en un campo de una clase generada por compilador. Entonces, la creaci-n de instancias de la variable local O[*.14.4.2R corresponde a la creaci-n de una instancia de la clase generada por compilador y el acceso a la variable local corresponde al acceso a un campo en la instancia de la clase generada por compilador. 8a 0unci-n an-nima se convierte en un m)todo de instancias de la clase generada por compiladorG
class 1est { void V() { \\Locals2 \\locals2 + ne, \\Locals2(); \\locals2.y + 289; 6 d + ne, 6(\\locals2.\\Met"od2); !

13#

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases class \\Locals2 { &ublic int y; &ublic void \\Met"od2() { Console.WriteLine(y); ! ! !

:inalmente, la siguiente 0unci-n an-nima captura t"is as5 como dos variables locales con di0erentes per5odos de duraci-nG
class 1est { int #; void V() { int y + 289; -or (int i + 3; i D 23; i<<) { int ? + i > 8; 6 d + () +E { Console.WriteLine(# < y < ?); !; ! ! !

&?u5 se crea una clase generada por compilador para cada blo?ue de instrucciones en los ?ue se capturan valores locales para ?ue los valores locales de blo?ues di0erentes tengan per5odos de duraci-n independientes. 7na instancia de \\Locals8, la clase generada por compilador para el blo?ue interior de instrucciones, contiene la variable local ? y un campo ?ue =ace re0erencia a una instancia de \\Locals2. 7na instancia de \\Locals2, la clase generada por compilador para el blo?ue exterior de instrucciones, contiene la variable local y y un campo ?ue =ace re0erencia a t"is del miembro de 0unci-n envolvente. Con estas estructuras de datos es posible alcan1ar todas las variables externas capturadas mediante una instancia de \\Local8 y el c-digo de la 0unci-n an-nima se puede implementar como un m)todo de una instancia de dic=a clase.
class 1est { void V() { \\Locals2 \\locals2 + ne, \\Locals2(); \\locals2.\\t"is + t"is; \\locals2.y + 289; -or (int i + 3; i D 23; i<<) { \\Locals8 \\locals8 + ne, \\Locals8(); \\locals8.\\locals2 + \\locals2; \\locals8.? + i > 8; 6 d + ne, 6(\\locals8.\\Met"od2); ! ! class \\Locals2 { &ublic 1est \\t"is; &ublic int y; ! class \\Locals8 { &ublic \\Locals2 \\locals2; &ublic int ?; &ublic void \\Met"od2() { Console.WriteLine(\\locals2.\\t"is.# < \\locals2.y < ?); ! ! !

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

13!

Especificacin del lenguaje C#

8a misma t)cnica aplicada a?u5 para capturar variables locales tambi)n se puede utili1ar a la =ora de convertir 0unciones an-nimas a (rboles de expresionesG las re0erencias a los ob$etos generados por el compilador se pueden almacenar en el (rbol de expresiones, y el acceso a las variables locales se puede representar como acceso a campos en esos ob$etos. 8a venta$a de este m)todo es ?ue permite ?ue las variables locales de Pelevaci-nQ sean compartidas entre (rboles de expresiones y delegados.

$.$ %on ersiones de grupo de m*todos


Existe una conversi-n impl5cita O[#.1R desde un grupo de m)todos O[*.1R a un tipo delegado compatible. 2ado un tipo delegado 6 y una expresi-n ) clasi0icada como un grupo de m)todos, existe una conversi-n impl5cita de ) a 6 si ) contiene al menos un m)todo aplicable en su estructura normal O[R a una lista de argumentos construidos por el uso de tipos de par(metro y modi0icadores de 6, tal como se describe a continuaci-n. 8a aplicaci-n en tiempo de compilaci-n de una conversi-n desde un grupo de m)todos ) a un tipo delegado 6 se describe a continuaci-n. Tenga en cuenta ?ue la existencia de una conversi-n impl5cita de ) a 6 no garanti1a ?ue la aplicaci-n en tiempo de compilaci-n de la conversi-n se reali1ar( sin errores. .e selecciona un Hnico m)todo M, correspondiente a una invocaci-n de m)todo O[*. . .1R con la estructura )('), con las siguientes modi0icacionesG o 8a lista de argumentos ' es una lista de expresiones, cada una clasi0icada con una variable y con el tipo y el modi0icador Ore- u outR del par(metro correspondiente en la lista de par(metros 0ormales Ofor%alpara%eter-listR de 6. 8os m)todos de candidatos considerados s-lo son los ?ue se aplican en su estructura normal O[*.4.3.1R, no los ?ue se aplican s-lo en su estructura expandida.

.i el algoritmo de [*. . .1 genera un error, se produce un error en tiempo de compilaci-n. 2e lo contrario, el algoritmo genera un m)todo individual me$or M con el mismo nHmero de par(metros ?ue 6 y se considera ?ue existe conversi-n. El m)todo M seleccionado debe ser compatible O[R con el tipo delegado 6 o, de lo contrario, se generar( un error en tiempo de compilaci-n. .i el m)todo seleccionado M es un m)todo de instancia, la expresi-n de instancia asociada a ) determina el ob$eto de destino del delegado. .i el m)todo seleccionado M es un m)todo de extensi-n ?ue se denota mediante un acceso a miembros en una expresi-n de instancia, esa expresi-n de instancia determina el ob$eto de destino del delegado. El resultado de la conversi-n es un valor del tipo 6, un delegado reci)n creado ?ue =ace re0erencia al m)todo seleccionado y al ob$eto de destino. Tenga en cuenta ?ue este proceso puede conducir a la creaci-n de un delegado para un m)todo de extensi-n, si el algoritmo de [*. . .1 no logra encontrar un m)todo de instancia pero s5 logra culminar con )xito el procesamiento de la invocaci-n de )(') como una invocaci-n del m)todo de extensi-n O[*. . .2R. &s5, el delegado =a creado capturas del m)todo de extensi-n as5 como su primer argumento.
delegate string 62(object o); delegate object 68(string s); delegate object 69(); delegate string 6J(object o delegate string 6K(int i); &arams object45 a);

En el siguiente e$emplo se demuestran las conversiones de grupo de m)todosG

136

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases class 1est { static string V(object o) {...! static void S() { 62 d2 + V; 68 d8 + V; 69 d9 + V; 6J dJ + V; 6K dK + V; ! ! .. .. .. .. .. %( %( )rror C not a&&licable )rror C not a&&licable in normal -orm )rror C a&&licable but not com&atible

8a asignaci-n a d2 convierte de manera impl5cita el grupo de m)todos V en un valor del tipo 62. 8a asignaci-n a d8 muestra c-mo es posible crear un delegado para un m)todo ?ue tiene menos par(metros derivados OcontravariantesR y m(s tipos de valor devuelto OcovariantesR derivados. 8a asignaci-n a d9 muestra c-mo no existe ninguna conversi-n si el m)todo no es aplicable. 8a asignaci-n a dJ muestra c-mo el m)todo debe ser aplicable en su estructura 0ormal. 8a asignaci-n a dK muestra la manera en ?ue par(metros y tipos de valor devuelto del delegado y del m)todo pueden di0erenciarse s-lo por los tipos de re0erencia. &l igual ?ue ocurre con otras conversiones impl5citas y expl5citas, el operador de conversi-n se puede utili1ar para reali1ar de manera expl5cita una conversi-n de grupo de m)todos. 'or lo tanto, el siguiente e$emploG
object obj + ne, )ventHandler(my6ialog.%(Clic();

se puede escribir de la siguiente manera


object obj + ()ventHandler)my6ialog.%(Clic(;

8os grupos de m)todo pueden in0luenciar la resoluci-n de sobrecargas y participar en la in0erencia de tipos. Consulte la [*.4 para obtener m(s detalles. 8a evaluaci-n en tiempo de e$ecuci-n de una conversi-n de grupo de m)todos se reali1a de la siguiente 0ormaG .i el m)todo seleccionado en tiempo de compilaci-n es un m)todo de instancia, o es un m)todo de extensi-n al ?ue se tiene acceso como m)todo de instancia, el ob$eto de destino del delegado se determina a partir de la expresi-n de instancia asociada con )G o o .e evalHa la expresi-n de instancia. .i esta evaluaci-n da lugar a una excepci-n, no se e$ecutan nuevos pasos. .i la expresi-n de instancia es de un tipo de re0erencia Oreference-t#peR, el valor calculado por la expresi-n de instancia es el ob$eto de destino. .i el ob$eto de destino es null, se inicia una excepci-n System.NullOe-erence)#ce&tion y no se e$ecutan m(s pasos. .i la expresi-n de instancia es de un tipo de valor Oval e-t#peR, se reali1a una operaci-n boxing O[4.3.1R para convertir el valor en un ob$eto, ?ue pasa a ser el ob$eto de destino.

2e lo contrario, el m)todo seleccionado es parte de una llamada a m)todo est(tico, y el ob$eto de destino del delegado es null. .e asigna una nueva instancia del tipo delegado 6. .i no =ay memoria disponible su0iciente para asignar la nueva instancia, se inicia una excepci-n System.%ut%-Memory)#ce&tion y no se e$ecutan m(s pasos. .e iniciali1a la nueva instancia de delegado con una re0erencia al m)todo ?ue se determin- en tiempo de compilaci-n y una re0erencia al ob$eto de destino antes calculado.

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

13(

Especificacin del lenguaje C#

+. E"presiones
7na expresi-n es una secuencia de operadores y operandos. En este cap5tulo se de0inen la sintaxis, el orden de evaluaci-n de los operandos y los operadores, as5 como el signi0icado de las expresiones.

+.1 %lasificaciones de e"presin


7na expresi-n se puede clasi0icar comoG 7n valor. Todos los valores tienen asociado un tipo. 7na variable. Todas variables tienen un tipo asociado, esto es, el tipo declarado de la variable. 7n espacio de nombres. 7na expresi-n con su clasi0icaci-n s-lo puede aparecer como el miembro i1?uierdo de un acceso a miembro O%e%-er-accessR O[*. .4R. En cual?uier otro contexto, una expresi-n ?ue se clasi0ica como un espacio de nombres produce un error en tiempo de compilaci-n. Tipo. 7na expresi-n con esta clasi0icaci-n s-lo puede aparecer como el lado i1?uierdo de un acceso a miembro O%e%-er-accessR O[*. .4R, o como un operando para el operador as O[*.+.11R, el operador is O[*.+.1"R o el operador ty&eo- O[*. .11R. En cual?uier otro contexto, una expresi-n ?ue se clasi0ica como un tipo produce un error en tiempo de compilaci-n. 7n grupo de m)todos, ?ue es un con$unto de m)todos sobrecargados producidos por una bHs?ueda de miembros O[*.3R. 7n grupo de m)todos puede tener asociada una expresi-n de instancia y una lista de argumentos de tipo asociados. Cuando se invoca un m)todo de instancia, el resultado de la evaluaci-n de la expresi-n de instancia se convierte en la instancia representada por t"is O[*. .*R. .e permite un grupo de m)todos en una expresi-n de invocaci-n Oinvocation-e2pressionR O[*. . R, una expresi-n de creaci-n de delegados Odele&ate-creation-e2pressionR O[*. .1". R y como la parte i1?uierda de un operador is, y se puede convertir impl5citamente en un tipo delegado compatible O[#.#R. En cual?uier otro contexto, una expresi-n ?ue se clasi0ica como un grupo de m)todos produce un error en tiempo de compilaci-n. 7n literal 4788. 7na expresi-n con esta clasi0icaci-n se puede convertir de manera impl5cita en un tipo de re0erencia o un tipo ?ue acepta valores 4788. 7na 0unci-n an-nima. 7na expresi-n con esta clasi0icaci-n se puede convertir de manera impl5cita en un tipo delegado compatible o un tipo de (rbol de expresiones. 7n acceso de propiedad. Todos los accesos de propiedades tienen un tipo asociado, esto es, el tipo declarado de la propiedad. &dem(s, un acceso a propiedad puede tener asociada una expresi-n de instancia. .i se llama a un descriptor de acceso Oel blo?ue get o setR de un acceso a propiedad de una instancia, el resultado de la evaluaci-n de la expresi-n de instancia se convierte en la instancia representada por t"is O[*. .*R. 7n acceso a evento. Todos los accesos de evento tienen un tipo asociado, el tipo declarado del evento. &dem(s, un acceso de evento puede tener asociada una expresi-n de instancia. 7n acceso a evento puede aparecer como el operando i1?uierdo de los operadores <+ y =+ O[*.1#.3R. En cual?uier otro contexto, una expresi-n ?ue se clasi0ica como un acceso a evento produce un error en tiempo de compilaci-n. 7n acceso a indi1ador. Todos los accesos a indi1adores tienen un tipo asociado, el tipo declarado del indi1ador. &dem(s, un acceso a indi1ador tiene asociadas una expresi-n de instancia y una lista de argumentos. .i se llama a un descriptor de acceso Oel blo?ue get o setR de un indi1ador, el resultado de la

13$

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

evaluaci-n de la expresi-n de instancia pasa a ser la instancia representada por t"is O[*. .*R, y el resultado de la evaluaci-n de la lista de argumentos se convierte en la lista de par(metros de la invocaci-n. 4ada. Esto ocurre cuando la expresi-n es una invocaci-n de un m)todo con el tipo de valor devuelto void. 7na expresi-n clasi0icada como nada s-lo es v(lida en el contexto de una expresi-n de instrucci-n Ostate%ent-e2pressionR O[8.#R.

El resultado 0inal de una expresi-n nunca es un espacio de nombres, un tipo, un grupo de m)todos o un acceso de evento. En lugar de ello, como se =a mencionado antes, estas categor5as de expresiones son construcciones intermedias ?ue s-lo est(n permitidas en determinados contextos. 7n acceso a propiedad o un acceso a indi1ador siempre se reclasi0ican como un valor mediante una llamada del descriptor de acceso get O&et-accessorR o del descriptor de acceso set Oset-accessorR. El descriptor de acceso concreto viene determinado por el contexto del acceso a propiedad o del acceso a indi1adorG si el acceso es el destino de una asignaci-n, se llama al descriptor de acceso set Oset-accessorR para asignar un nuevo valor O[*.1#.1R. En otro caso, se invoca el descriptor de acceso get O&et-accessorR para obtener el valor actual O[*.1.1R. +.1.1 Valores de e"presiones 8a mayor5a de las construcciones ?ue involucran una expresi-n re?uieren en de0initiva ?ue la expresi-n denote un valor. En estos casos, si la expresi-n real denota un espacio de nombres, un tipo, un grupo de m)todos o nada, se produce un error en tiempo de compilaci-n. 4o obstante, si la expresi-n denota un acceso a propiedad, un acceso a indi1ador o una variable, el valor de la propiedad, el indi1ador o la variable se sustituyen de 0orma impl5citaG El valor de una variable es sencillamente el valor almacenado en la ubicaci-n de almacenamiento ?ue ella misma identi0ica. 7na variable debe considerarse asignada de0initivamente O[ .3R para poder obtener su valor o, de lo contrario, se produce un error de tiempo de compilaci-n. El valor de una expresi-n de acceso a propiedad se obtiene mediante una llamada al descriptor de acceso get O&et-accessorR de la propiedad. .i la propiedad no tiene un descriptor de acceso get O&et-accessorR, se produce un error durante la compilaci-n. En caso contrario, se reali1a una llamada a un miembro de 0unci-n O[*.4.4R y el resultado de la llamada pasa a ser el valor de la expresi-n de acceso a propiedad. El valor de una expresi-n de acceso a indi1ador se obtiene mediante una llamada al descriptor de acceso get O&et-accessorR del indi1ador. .i el indi1ador no tiene un descriptor de acceso get O&et-accessorR, se produce un error durante la compilaci-n. En caso contrario, se reali1a una llamada a un miembro de 0unci-n O[*.4.4R con la lista de argumentos asociada a la expresi-n de acceso al indi1ador, y el resultado de la llamada se convierte en el valor de la expresi-n de acceso al indi1ador.

+.2 ,peradores
8as expresiones se construyen a partir de operandos y operadores. 8os operadores de una expresi-n indican ?u) operaciones se aplican a los operandos. Entre los e$emplos de operadores se incluyen <, =, >, . y ne,. .on e$emplos de operandos los literales, campos, variables locales y expresiones. Existen tres tipos de operadoresG /peradores unarios. 8os operadores unarios tienen un operando y utili1an la notaci-n de pre0i$o Ocomo C#R o de post0i$o Ocomo #<<R. /peradores binarios. 8os operadores binarios tienen dos operandos y utili1an una notaci-n in0i$a Opor e$emplo, # < yR. /perador ternario. .-lo existe un operador ternario, 7/, tiene tres operandos y utili1a notaci-n in0i$a Oc7 #/ yR.

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

13"

Especificacin del lenguaje C#

El orden de evaluaci-n de los operadores de una expresi-n est( determinado por la prioridad y asociatividad de los operadores O[*.2.1R. 8os operandos de una expresi-n se evalHan de i1?uierda a derec=a. 'or e$emplo, en V(i) < S(i<<) > H(i), se llama al m)todo V con el valor antiguo de i, despu)s se llama al m)todo S con el valor antiguo de i y, por Hltimo, se llama al m)todo H con el valor nuevo de i. Esto es aparte y no est( relacionado con la prioridad de los operadores. &lgunos operadores no se pueden so/recargar. 8a sobrecarga de operadores permite utili1ar implementaciones de operadores de0inidas por el usuario en operaciones en las ?ue al menos uno de los operandos es de un tipo estructura o clase de0inido por el usuario O[*.2.2R. +.2.1 (rioridad y asociati idad de los operadores Cuando una expresi-n contiene varios operadores, la prioridad de los operadores controla el orden de evaluaci-n de los operadores individuales. 'or e$emplo, la expresi-n # < y > ? se evalHa como # < (y > ?) por?ue el operador > tiene prioridad sobre el operador binario <. 8a prioridad de un operador est( determinada por la de0inici-n de su producci-n gramatical asociada. 'or e$emplo, una expresi-n aditiva Oadditive-e2pressionR consta de una secuencia de expresiones multiplicativas O% ltiplicative-e2pressionsR separadas por los operadores < o =, lo ?ue da a estos operadores una menor prioridad ?ue a >, . y B. En la tabla siguiente se resumen todos los operadores, en orden de prioridad de mayor a menorG 3eccin *. *.# *.* *.* *.8 *.+ *.+ *.1" *.1" *.1" *.11 *.11 *.12 *.13 *.1#, *.14 Categor0a 'rincipal 7nario %ultiplicativo .umatorio 2espla1amiento Comprobaci-n de tipos y relacionales !gualdad &42 l-gico N/; l-gico /; l-gico &42 condicional /; condicional 7so combinado de 4ull Condicional &signaci-n y expresi-n lambda 7peradores
#.y < > < DD D ++ F G H FF HH 77 7/ + +E >+ .+ B+ <+ =+ DD+ EE+ F+ G+ H+ = . = EE E @+ D+ E+ is as -(#) @ B A a4#5 <<# #<< ==# #== (1)# ne, unc"ec(ed delegate ty&eode-ault c"ec(ed

1#'

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

Cuando un operando se encuentra entre dos operadores con igual grado de prioridad, la asociatividad de los operadores controla el orden en ?ue se e$ecutan las operaciones. & excepci-n de los operadores de asignaci-n, todos los operadores binarios son asociativos por la i-"!ierda, lo ?ue signi0ica ?ue las operaciones se reali1an de i1?uierda a derec=a. 'or e$emplo, # < y < ? se evalHa como (# < y) < ?. 8os operadores de asignaci-n y el operador condicional O7/R son asociativos por la derecha, lo ?ue signi0ica ?ue las operaciones se e$ecutan de derec=a a i1?uierda. 'or e$emplo, # + y + ? se evalHa como # + (y + ?).

8a precedencia y asociatividad pueden controlarse mediante el uso de par)ntesis. 'or e$emplo, # < y > ? primero multiplica y por ? y despu)s suma el resultado a #, pero (# < y) > ? primero suma # e y, y despu)s multiplica el resultado por ?. +.2.2 4obrecarga de operadores Todos los operadores unarios y binarios tienen implementaciones prede0inidas ?ue est(n disponibles autom(ticamente en cual?uier expresi-n. &dem(s de las implementaciones prede0inidas, pueden introducirse implementaciones de0inidas por el usuario si se incluyen declaraciones o&erator en las clases y estructuras O[1".1"R. 8as implementaciones de operador de0inidas por el usuario siempre tienen precedencia sobre las implementaciones de operador prede0inidasG s-lo se consideran las implementaciones de operador prede0inidas cuando no existen implementaciones de operador de0inidas por el usuario ?ue puedan aplicarse, como se explica en [*.2.3 y [*.2.4. 8os operadores !narios so/recarga/les sonG
< = @ A << == true -alse

&un?ue true y -alse no se utili1an expl5citamente en las expresiones Opor lo ?ue no se incluyen en la tabla de prioridades de [*.2.1R, se consideran operadores por?ue se los llama en varios contextos de expresi-nG expresiones booleanas O[*.1+R y expresiones ?ue implican el condicional O[*.13R y los operadores l-gicos condicionales O[*.11R. 8os operadores /inarios so/recarga/les sonG
< = > . B F H G DD EE ++ @+ E D E+ D+

.-lo los operadores mencionados pueden sobrecargarse. En concreto, no es posible sobrecargar accesos a miembros, llamadas a m)todos o los operadores +, FF, HH, 77, 7/, +E, c"ec(ed, unc"ec(ed, ne,, ty&eo-, de-ault, as e is. Cuando se sobrecarga un operador binario, el operador correspondiente de asignaci-n, si lo =ay, tambi)n se sobrecarga de modo impl5cito. 'or e$emplo, una sobrecarga del operador > tambi)n es una sobrecarga del operador >+. Esta categor5a se explica con m(s detalle en la secci-n [*.1#.2. 2ebe tenerse en cuenta ?ue el propio operador de asignaci-n O+R no se puede sobrecargar. 7na asignaci-n siempre reali1a una simple copia bit a bit de un valor en una variable. 8as operaciones de conversi-n de tipo, como (1)#, se sobrecargan proporcionando conversiones de0inidas por el usuario O[#.4R. El acceso a elementos, del tipo a4#5, no se considera un operador sobrecargable. En lugar de ello, se acepta la indi1aci-n de0inida por el usuario mediante indi1adores O[1".+R. En las expresiones, las re0erencias a los operadores se reali1an mediante la notaci-n de operadores y, en las declaraciones, las re0erencias a los operadores se reali1an mediante la notaci-n 0uncional. En la tabla siguiente se muestra la relaci-n entre las notaciones de operador y 0uncional para los operadores unarios y binarios. En la primera entrada, op denota cual?uier operador de pre0i$o unario sobrecargable. En la segunda entrada, op denota

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

1#1

Especificacin del lenguaje C#

los operadores de su0i$o unarios << y ==. En la primera entrada, op denota cual?uier operador binario sobrecargable. 4otacin de operador op #
# op # op y

4otacin funcional
o&erator op(#) o&erator op(#) o&erator op(# y)

8as declaraciones de operador de0inidas por el usuario siempre re?uieren ?ue por lo menos uno de los par(metros sea del tipo de la clase o estructura ?ue contiene la declaraci-n del operador. 'or lo tanto, no es posible ?ue un operador de0inido por el usuario tenga la misma 0irma ?ue un operador prede0inido. 8as declaraciones de operador de0inidas por el usuario no pueden modi0icar la sintaxis, precedencia o asociatividad de un operador. 'or e$emplo, el operador . siempre es un operador binario, siempre tiene el nivel de precedencia especi0icado en la [*.2.1 y siempre es asociativo por la i1?uierda. &un?ue es posible ?ue un operador de0inido por el usuario realice cual?uier c(lculo ?ue le interese, no se recomiendan las implementaciones ?ue generan resultados distintos de los ?ue intuitivamente pueden esperarse. 'or e$emplo, una implementaci-n de o&erator ++ debe comparar la igualdad de los dos operandos y devolver un resultado bool apropiado. 8as descripciones de los operadores individuales desde la [*. a la [*.11 especi0ican las implementaciones prede0inidas de los operadores y cual?uier regla adicional aplicable a cada operador. En las descripciones se utili1an los t)rminos resol!ci,n de so/recarga de operador !nario, resol!ci,n de so/recarga de operador /inario y pro oci,n n! 6rica, cuyas de0iniciones se encuentran en las siguientes secciones. +.2.3 9esolucin de sobrecarga de operador unario 7na operaci-n con la estructura op # o # op, donde op es un operador unario sobrecargable, y # es una expresi-n de tipo I, se procesa como sigueG El con$unto de operadores candidatos de0inidos por el usuario suministrados por I para la operaci-n o&erator op(#) se determina aplicando las reglas de la [*.2. . .i el con$unto de operadores candidatos de0inidos por el usuario no est( vac5o, se convierte en el con$unto de operadores candidatos para la operaci-n. 2e lo contrario, las implementaciones del o&erator op unario prede0inidas, incluidos los 0ormatos de elevaci-n, se convierten en el con$unto de operadores candidatos para la operaci-n. 8as implementaciones prede0inidas de un operador dado se especi0ican en la descripci-n del operador O[*. y [*.#R. 8as reglas de resoluci-n de las sobrecargas de [*.4.3 se aplican al con$unto de operadores candidatos para seleccionar el me$or operador con respecto a la lista de argumentos (#), y este operador es el resultado del proceso de resoluci-n de las sobrecargas. .i la resoluci-n de las sobrecargas no puede seleccionar un operador Hnico id-neo, se producir( un error en tiempo de compilaci-n.

+.2.! 9esolucin de sobrecarga de operador binario 7na operaci-n con la estructura # op y, donde op es un operador binario sobrecargable, # es una expresi-n de tipo I e y es una expresi-n de tipo `, se procesa como sigueG .e determina el con$unto de operadores candidatos de0inidos por el usuario suministrado por I e ` para la operaci-n o&erator op(# y). El con$unto consta de la uni-n de los operadores candidatos suministrados por I y los operadores candidatos suministrados por `, cada uno de los cuales se determina mediante las

1#2

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

reglas de [*.2. . .i I e ` son del mismo tipo, o si I e ` se derivan de un tipo base comHn, los operadores candidatos compartidos s-lo se producen una ve1 en el con$unto combinado. .i el con$unto de operadores candidatos de0inidos por el usuario no est( vac5o, se convierte en el con$unto de operadores candidatos para la operaci-n. 2e lo contrario, las implementaciones del o&erator op binario prede0inidas, incluidos los 0ormatos de elevaci-n, se convierten en el con$unto de operadores candidatos para la operaci-n. 8as implementaciones prede0inidas de un operador dado se especi0ican en la descripci-n del operador O[*.* a [*.11R. 8as reglas de resoluci-n de las sobrecargas de [*.4.3 se aplican al con$unto de operadores candidatos para seleccionar el me$or operador con respecto a la lista de argumentos (# y), y este operador es el resultado del proceso de resoluci-n de las sobrecargas. .i la resoluci-n de las sobrecargas no puede seleccionar un operador Hnico id-neo, se producir( un error en tiempo de compilaci-n.

+.2.# ,peradores candidatos definidos por el usuario 2ados un tipo 1 y una operaci-n o&erator op('), donde op es un operador sobrecargable y ' es una lista de argumentos, el con$unto de operadores candidatos de0inidos por el usuario suministrado por 1 para el o&erator op(') se determina como sigueG 2eterminar el tipo 13. .i 1 es un tipo ?ue acepta valores 4788, 13 es su tipo subyacente, de lo contrario 13 es igual a 1. 'ara todas las declaraciones de o&erator op en 13 y todas los 0ormatos de elevaci-n de dic=os operadores, si por lo menos un operador es aplicable O[R con respecto a la lista de argumentos ', entonces el con$unto de operadores candidatos consta de todos los operadores aplicables en 13. 2e lo contrario, si 13 es object, el con$unto de operadores candidatos est( vac5o. En otros casos, el con$unto de operadores candidatos suministrado por 13 es el con$unto de operadores candidatos suministrado por la clase base directa de 13, o la clase base e0ectiva de 13 si 13 es un tipo de par(metro.

+.2.$ (romociones num*ricas 7na promoci-n num)rica consiste en reali1ar de 0orma autom(tica determinadas conversiones impl5citas de los operandos de los operadores num)ricos unarios y binarios prede0inidos. 8a promoci-n num)rica no es un mecanismo exclusivo, sino m(s bien un e0ecto de la aplicaci-n de la resoluci-n de las sobrecargas a los operadores prede0inidos. 8a promoci-n num)rica en concreto no a0ecta a la evaluaci-n de los operadores de0inidos por el usuario, aun?ue dic=os operadores puedan implementarse de manera ?ue presenten e0ectos similares. Como e$emplo de promoci-n num)rica, consideremos las implementaciones prede0inidas del operador binario >G
int o&erator >(int # int y); uint o&erator >(uint # uint y); long o&erator >(long # long y); ulong o&erator >(ulong # ulong y); -loat o&erator >(-loat # -loat y); double o&erator >(double # double y); decimal o&erator >(decimal # decimal y);

Cuando se aplican las reglas de resoluci-n de las sobrecargas O[*.4.3R a este con$unto de operadores, el e0ecto ?ue se produce es la selecci-n del primero de los operadores para el cual existen conversiones impl5citas de los tipos de los operandos. 'or e$emplo, para la operaci-n b > s, donde b es un byte y s es s"ort, la resoluci-n de las sobrecargas selecciona o&erator >(int int) como el me$or operador. 2e esta 0orma, el e0ecto producido es ?ue b y s se convierten a int, y el tipo del resultado es int. 2e modo similar, para la operaci-n i
1#3

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Especificacin del lenguaje C# > d, donde i es un int y d es double, la resoluci-n de sobrecargas selecciona o&erator >(double double) como el me$or operador.

#.2.6.1 Promociones numricas unarias 7na promoci-n num)rica unaria se produce para los operandos de los operadores unarios prede0inidos <, C y A. 7na promoci-n num)rica unaria sencillamente es la conversi-n de operandos de tipo sbyte, byte, s"ort, us"ort o c"ar al tipo int. &simismo, para el operador unario C, la promoci-n num)rica unaria convierte los operandos del tipo uint al tipo long. #.2.6.2 Promociones numricas binarias 8a promoci-n num)rica binaria se produce para los operandos de los operadores binarios prede0inidos <, C, >, ., B, F, H, G, ++, @+, E, D, E+ y D+. 8a promoci-n num)rica binaria convierte impl5citamente los dos operandos a un tipo comHn ?ue, en caso de los operadores no relacionales, tambi)n se convierte en el tipo del resultado de la operaci-n. 7na promoci-n num)rica binaria consiste en aplicar las reglas siguientes, en el orden en ?ue se exponen a?u5G .i uno de los operandos es de tipo decimal, el otro se convierte al tipo decimal o se produce un error en tiempo de compilaci-n si el otro operando es de tipo -loat o double. / bien, si uno de los operandos es de tipo double, el otro se convierte al tipo double. / bien, si uno de los operandos es de tipo -loat, el otro se convierte al tipo -loat. / bien, si uno de los operandos es de tipo ulong, el otro se convierte al tipo ulong o se produce un error en tiempo de compilaci-n si el otro operando es de tipo sbyte, s"ort int o long. / bien, si uno de los operandos es de tipo long, el otro se convierte al tipo long. / bien, si uno de los operandos es de tipo uint y el otro es de tipo sbyte, s"ort o int, los dos operandos se convierten al tipo long. / bien, si uno de los operandos es de tipo uint, el otro se convierte al tipo uint. / bien, los dos operandos se convierten al tipo int.

T)ngase en cuenta ?ue la primera regla no permite las operaciones ?ue me1clan el tipo decimal con los tipos double y -loat. 8a regla se basa en ?ue no =ay conversiones impl5citas entre el tipo decimal y los tipos double y -loat. Tambi)n debe tenerse en cuenta ?ue un operando no puede ser de tipo ulong si el otro es de un tipo integral con signo. El motivo es ?ue no existe un tipo integral ?ue pueda representar la gama completa de ulong as5 como los tipos integrales con signo. En los dos casos anteriores, puede utili1arse una expresi-n de conversi-n de tipos para convertir de 0orma expl5cita uno de los operandos a un tipo ?ue sea compatible con el otro. En el e$emplo
decimal 'dd*ercent(decimal # double &ercent) { return # > (2.3 < &ercent . 233.3); !

se produce un error de tiempo de compilaci-n por?ue un decimal no puede multiplicarse por un double. El error se resuelve mediante la conversi-n expl5cita del segundo operando a decimal, de la manera siguienteG
decimal 'dd*ercent(decimal # double &ercent) { return # > (decimal)(2.3 < &ercent . 233.3); !

1##

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

+.2.+ ,peradores de ele acin 8os operadores de elevaci,n permiten utili1ar operadores prede0inidos y de0inidos por el usuario ?ue 0uncionan en tipos de valor ?ue no aceptan valores 4788 con estructuras ?ue aceptan valores 4788 de dic=os tipos. 8os operadores de elevaci-n se construyen a partir de operadores prede0inidos y de0inidos por el usuario ?ue cumplen ciertos re?uisitos como se describe a continuaci-nG 'ara los operadores unarios
< << = == @ A

existe un 0ormato de elevaci-n de un operador si el operando y los tipos de resultado son tipos de valor ?ue no aceptan valores 4788. El 0ormato de elevaci-n se construye agregando un modi0icador 7 Hnico al operando y a los tipos de resultado. El operador de elevaci-n genera un valor 4788 si el operando es 4788. 2e lo contrario, el operador de elevaci-n desa$usta el operando, aplica el operador subyacente y a$usta el resultado. 'ara los operadores binarios
< = > . B F H G DD EE

existe un 0ormato de elevaci-n si el operando y los tipos de resultado son todos tipos de valor ?ue no aceptan valores 4788. El 0ormato de elevaci-n se construye agregando un modi0icador 7 Hnico a cada operando y al tipo de resultado. El operador de elevaci-n genera un valor 4788 si uno o varios operandos son 4788 Ouna de las excepciones son los operadores F y H del tipo bool7 como se describe en la secci-n [*.1".3R. 2e lo contrario, el operador de elevaci-n desa$usta los operandos, aplica el operador subyacente y a$usta el resultado. 'ara los operadores de igualdad
++ @+

existe un 0ormato de elevaci-n si los tipos de operando son tipos de valor ?ue no aceptan valores 4788 y si el tipo de resultado es bool. El 0ormato de elevaci-n se construye agregando un modi0icador 7 Hnico a cada tipo de operando. El operador de elevaci-n considera ?ue dos valores 4788 son iguales y ?ue un valor 4788 no es igual a un valor ?ue no es 4788. .i ninguno de los operandos es 4788, el operador de elevaci-n desa$usta los operandos y aplica el operador subyacente para generar el resultado bool. 'ara los operadores relacionales
D E D+ E+

existe un 0ormato de elevaci-n si los tipos de operando son tipos de valor ?ue no aceptan valores 4788 y si el tipo de resultado es bool. El 0ormato de elevaci-n se construye agregando un modi0icador 7 Hnico a cada tipo de operando. El operador de elevaci-n genera el valor -alse si uno o ambos operandos es 4788. 2e lo contrario, el operador de elevaci-n desa$usta los operandos y aplica el operador subyacente para generar el resultado bool.

+.3 <=s;ueda de miembros


7na bHs?ueda de miembros es el proceso por el cual se determina el signi0icado de un nombre en el contexto de un tipo. 7na bHs?ueda de miembros puede ocurrir como parte de la evaluaci-n de un nombre simple Osi%plena%eR O[*. .2R o un acceso a miembro O%e%-er-accessR O[*. .4R en una expresi-n. .i se produce un acceso a miembros O%e%-er-accessR o un nombre simple Osi%ple-na%eR como la expresi-n simple Osi%ple-e2pressionR de una expresi-n de invocaci-n Oinvocation-e2pressionR O[*. . .1R, se dice ?ue el miembro se =a invocado. .i un miembro es un m)todo o evento, o si es una constante, campo o propiedad de un tipo delegado O[1 R, se dice ?ue el miembro es invoca-le.

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

1#!

Especificacin del lenguaje C#

8a bHs?ueda de miembros no s-lo tiene en cuenta el nombre de un miembro, sino ?ue tambi)n considera el nHmero de par(metros de tipo ?ue el miembro tiene independientemente de su accesibilidad. 'ara la bHs?ueda de miembros, los m)todos gen)ricos y los tipos gen)ricos anidados tienen el nHmero de par(metros de tipo indicado en sus respectivas declaraciones y el resto de los miembros no tienen ningHn par(metro tipo. 7na bHs?ueda de miembros de un nombre N con par(metros de tipo a en un tipo 1 se procesa como sigueG En primer lugar, se determina un con$unto de miembros accesibles denominado NG o .i 1 es un par(metro de tipo, el con$unto es la uni-n de con$untos de miembros accesibles denominados N en cada uno de los tipos especi0icados como una restricci-n principal o secundaria O[1".1. R para 1, $unto con el con$unto de miembros accesibles denominado N en object. 2e lo contrario, el con$unto est( 0ormado por todos los miembros accesibles O[3. R denominados N en 1, incluidos los miembros =eredados y los miembros accesibles denominados N en object. .i 1 es un tipo construido, el con$unto de miembros se obtiene sustituyendo los argumentos de tipo como se describe en [1".3.2. .e excluyen del con$unto los miembros ?ue incluyen un modi0icador override.

& continuaci-n, si a es cero, se ?uitan todos los tipos anidados cuyas declaraciones incluyan par(metros de tipo. .i a no es cero, se ?uitan todos los miembros con un nHmero di0erente de par(metros de tipo. Tenga en cuenta ?ue cuando a es cero, no se ?uitan los m)todos ?ue tienen par(metros de tipo puesto ?ue el proceso de in0erencia de tipos O[*.4.2R puede in0erir los argumentos de tipo. & continuaci-n, si el miembro es invocado, se ?uitan del con$unto todos los miembros no invocables. & continuaci-n, se ?uitan del con$unto los miembros ?ue est(n ocultos por otros miembros. 'or cada miembro S.M del con$unto, donde S es el tipo en el ?ue se declara el miembro M, se aplican las siguientes reglasG o o .i M es un miembro de constante, campo, propiedad, evento, tipo o enumeraci-n, entonces se ?uitan del con$unto todos los miembros declarados en un tipo base de S. .i M es una declaraci-n de tipo, entonces todos los miembros ?ue no sean declaraciones en un tipo base de S se ?uitan del con$unto, se eliminar(n todas las declaraciones de tipo con el mismo nHmero de par(metros de tipo ?ue M declarados en un tipo base de S. .i M es un m)todo, se ?uitar(n del con$unto todos los miembros ?ue no son m)todos declarados en un tipo base de S.

& continuaci-n, se ?uitan del con$unto los miembros de inter0a1 ocultos por miembros de clase. Este paso s-lo tiene e0ecto si 1 es un par(metro de tipo y 1 tiene una clase base e0ectiva di0erente de object y un con$unto de inter0aces e0ectivas ?ue no est)n vac5as O[1".1. R. 'or cada miembro S.M del con$unto, donde S es el tipo en el ?ue se declara el miembro M, se aplican las siguientes reglas si S es una declaraci-n de clase di0erente de objectG o o .i M es un miembro de constante, campo, propiedad, evento, miembro de enumeraci-n o declaraci-n de tipo, se ?uitan del con$unto todos los miembros declarados en una declaraci-n de inter0a1. .i M es un m)todo, entonces todos los miembros ?ue no son m)todos declarados en una declaraci-n de inter0a1 se ?uitan del con$unto, as5 como todos los m)todos con la misma 0irma ?ue M declarados en una declaraci-n de inter0a1. .i el con$unto est( 0ormado por un solo miembro ?ue no es un m)todo, entonces este miembro es el resultado de la bHs?ueda.

'or Hltimo, una ve1 ?uitados los miembros ocultos, se determina el resultado de la bHs?uedaG o

1#6

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

o o

/ bien, si el con$unto s-lo contiene m)todos, entonces este grupo de m)todos es el resultado de la bHs?ueda. 2e lo contrario, la bHs?ueda es ambigua y se genera un error en tiempo de compilaci-n.

'ara bHs?uedas de miembros en tipos ?ue no sean inter0aces ni par(metros de tipo, y bHs?uedas de miembros en inter0aces ?ue sean estrictamente de =erencia simple Ocada inter0a1 en la cadena de la =erencia tienen exactamente cero o una inter0a1 base directaR, el e0ecto de las reglas de bHs?ueda es sencillamente ?ue los miembros derivados ocultan a los miembros base del mismo nombre o la misma 0irma. Este tipo de bHs?uedas de =erencia simple nunca son ambiguas. 8as ambigIedades ?ue pueden surgir de las bHs?uedas de miembros en inter0aces de =erencia mHltiple se describen en la [13.2. . +.3.1 Tipos base 'ara los 0ines de bHs?ueda de miembros, se considera ?ue un tipo 1 tiene los siguientes tipos baseG .i 1 es object, entonces 1 no tiene tipo base. .i 1 es un tipo enum Oen %-t#peR, los tipos base de 1 son los tipos de clase System.)num, System.Ualue1y&e y object. .i 1 es un tipo struct Ostr ct-t#peR, los tipos base de 1 son los tipos de clase System.Ualue1y&e y object. .i 1 es un tipo de clase Oclass-t#peR, los tipos base de 1 son las clases base de 1, incluido el tipo de clase object. .i 1 es un tipo de inter0a1 Ointerface-t#peR, los tipos base de 1 son las inter0aces base de 1 y el tipo de clase object. .i 1 es un tipo de matri1 Oarra#-t#peR, los tipos base de 1 son los tipos de clase System.'rray y object. .i 1 es un tipo delegado Odele&ate-t#peR, los tipos base de 1 son los tipos de clase System.6elegate y object.

+.! &iembros de funcin


8os miembros de 0unci-n son miembros ?ue contienen instrucciones e$ecutables. .iempre son miembros de tipos y no pueden ser miembros de espacios de nombres. C# de0ine las siguientes categor5as de miembros de 0unci-nG %)todos 'ropiedades Eventos !ndi1adores /peradores de0inidos por el usuario Constructores de instancia Constructores static 2estructores

Excepto para los destructores y los constructores est(ticos O?ue no se pueden invocar de manera expl5citaR, las instrucciones contenidas en miembros de 0unci-n se e$ecutan mediante invocaciones de miembros de 0unci-n. 8a sintaxis concreta de la programaci-n de invocaciones de miembros de 0unci-n depende de la categor5a del miembro concreto.

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

1#(

Especificacin del lenguaje C#

8a lista de argumentos O[*.4.1R de la invocaci-n de un miembro de 0unci-n proporciona valores reales o re0erencias de variable a los par(metros del miembro de 0unci-n. 8as llamadas de m)todos, indi1adores, operadores y constructores de instancia utili1an la resoluci-n de sobrecargas para determinar a ?u) miembro de un con$unto candidato de miembros de 0unci-n se debe llamar. Este proceso se describe en [*.4.3. 7na ve1 identi0icado un miembro de 0unci-n concreto en tiempo de compilaci-n, posiblemente mediante resoluci-n de sobrecargas, el proceso exacto de invocar el miembro de 0unci-n en tiempo de e$ecuci-n se explica en [*.4.4. En la tabla siguiente se resume el procesamiento ?ue tiene lugar en las construcciones ?ue implican las seis categor5as de miembros de 0unci-n, ?ue se puede invocar expl5citamente. En la tabla, e, #, y y value indican expresiones clasi0icadas como variables o valores, 1 indica una expresi-n clasi0icada como un tipo, V es el nombre simple de un m)todo y * es el nombre simple de una propiedad. Construccin !nvocaci-n de m)todo Eje)plo
V(# y)

+escripcin .e aplica la resoluci-n de sobrecargas para seleccionar el me$or m)todo V de la clase o estructura contenedora. .e llama al m)todo con la lista de argumentos (# y). .i el m)todo no es static, la expresi-n de instancia es t"is. .e aplica la resoluci-n de sobrecargas para seleccionar el me$or m)todo V de la clase o estructura 1. .e produce un error en tiempo de compilaci-n si el m)todo no es static. .e llama al m)todo con la lista de argumentos (# y). .e aplica la resoluci-n de sobrecargas para seleccionar el me$or m)todo V de la clase, estructura o inter0a1 dada por el tipo de e. .e produce un error en tiempo de compilaci-n si el m)todo es static. .e llama al m)todo con la expresi-n de instancia e y la lista de argumentos (# y). .e invoca al descriptor de acceso get de la propiedad * en la clase o estructura contenedora. .e produce un error en tiempo de compilaci-n si * es de s-lo escritura. .i * no es static, la expresi-n de instancia es t"is. .e invoca al descriptor de acceso set de la propiedad * en la clase o estructura contenedora con la lista de argumentos (value). .e produce un error en tiempo de compilaci-n si * es de s-lo lectura. .i * no es static, la expresi-n de instancia es t"is. .e invoca al descriptor de acceso get de la propiedad * en la clase o estructura 1. .e produce un error en tiempo de compilaci-n si * no es static o si es de s-lo escritura. .e invoca al descriptor de acceso set de la propiedad * en la clase o estructura 1 con la lista de argumentos (value). .e produce un error en tiempo de compilaci-n si * no es static o si es de s-lo lectura.

1.V(# y)

e.V(# y)

&cceso a la propiedad

* + value

1.*

1.* + value

1#$

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

Construccin

Eje)plo
e.*

+escripcin .e invoca al descriptor de acceso get de la propiedad * en la clase, estructura o inter0a1 dada por el tipo de e con la expresi-n de instancia e. .e produce un error en tiempo de compilaci-n si * es static o si es de s-lo escritura. .e invoca el descriptor de acceso set de la propiedad * en la clase, estructura o inter0a1 dada por el tipo de e con la expresi-n de instancia e y la lista de argumentos (value). .e produce un error en tiempo de compilaci-n si * es static o si es de s-lo lectura. .e invoca al descriptor de acceso add del evento ) en la clase o estructura contenedora. .i ) no es static, la expresi-n de instancia es t"is. .e invoca al descriptor de acceso remove del evento ) en la clase o estructura contenedora. .i ) no es static, la expresi-n de instancia es t"is. .e invoca al descriptor de acceso add del evento ) en la clase o estructura 1. .i ) no es est(tico, se produce un error en tiempo de compilaci-n. .e invoca al descriptor de acceso remove del evento ) en la clase o estructura 1. .i ) no es est(tico, se produce un error en tiempo de compilaci-n. .e invoca al descriptor de acceso add del evento ) en la clase, estructura o inter0a1 dada por el tipo de e con la expresi-n de instancia e. .i ) es est(tico, se produce un error en tiempo de compilaci-n. .e invoca al descriptor de acceso remove del evento ) en la clase, estructura o inter0a1 dada por el tipo de e con la expresi-n de instancia e. .i ) es est(tico, se produce un error en tiempo de compilaci-n. 8a resoluci-n de sobrecarga se aplica para seleccionar el me$or indi1ador de la clase, estructura o inter0a1 dada por el tipo de e. El descriptor de acceso get del indi1ador se invoca con la expresi-n de instancia e y la lista de argumentos (# y). .e produce un error en tiempo de compilaci-n si el indi1ador es de s-lo escritura. 8a resoluci-n de sobrecarga se aplica para seleccionar el me$or indi1ador de la clase, estructura o inter0a1 dada por el tipo de e. El descriptor de acceso set del indi1ador se invoca con la expresi-n de instancia e y la lista de argumentos (# y value). .e produce un error en tiempo de compilaci-n si el indi1ador es de s-lo lectura.

e.* + value

&cceso a evento

) <+ value

) =+ value

1.) <+ value

1.) =+ value

e.) <+ value

e.) =+ value

&cceso al indi1ador

e4# y5

e4# y5 + value

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

1#"

Especificacin del lenguaje C#

Construccin !nvocaci-n de operador

Eje)plo
=#

+escripcin .e aplica la resoluci-n de sobrecargas para seleccionar el me$or operador unario de la clase, estructura o inter0a1 dada por el tipo de #. .e invoca al operador seleccionado con la lista de argumentos (#). .e aplica la resoluci-n de sobrecargas, para seleccionar el me$or operador binario de las clases o estructuras dadas por los tipos de x e y. El operador seleccionado se invoca con la lista de argumentos (# y). 8a resoluci-n de sobrecarga se aplica para seleccionar el me$or constructor de la clase o estructura 1. .e invoca al constructor de instancias con la lista de argumentos (# y).

#<y

!nvocaci-n de constructores de instancias

ne, 1(# y)

+.!.1 6istas de argumentos Toda invocaci-n de delegado y miembro de 0unci-n incluye una lista de argumentos ?ue proporciona los valores reales o las re0erencias de variable de los par(metros del miembro de 0unci-n. 8a sintaxis para especi0icar la lista de argumentos de una invocaci-n de miembro de 0unci-n depende de la categor5a del miembro de 0unci-nG 'ara los constructores de instancia, m)todos y delegados, los argumentos se especi0ican como una lista de argumentos Oar& %ent-listR, como se explica a continuaci-n. 'ara las propiedades, la lista de argumentos est( vac5a cuando se llama al descriptor de acceso get, y est( 0ormada por la expresi-n especi0icada como el operando derec=o del operador de asignaci-n cuando se invoca el descriptor de acceso set. 'ara los eventos, la lista de argumentos est( 0ormada por la expresi-n especi0icada como el operando derec=o del operador <+ o =+. 'ara los indi1adores, la lista de argumentos est( 0ormada por las expresiones especi0icadas entre los corc=etes del acceso a indi1ador. Cuando se invoca el descriptor de acceso set, la lista de argumentos incluye adem(s la expresi-n especi0icada como el operando derec=o del operador de asignaci-n. 'ara los operadores de0inidos por el usuario, la lista de argumentos est( 0ormada por el operando Hnico del operador unario o los dos operandos del operador binario.

8os argumentos de propiedades O[1".*R, eventos O[1".8R y operadores de0inidos por el usuario O[1".1"R siempre se pasan como par(metros de valor O[1".#.1.1R. 8os argumentos de indi1adores O[1".+R siempre se pasan como par(metros de valor O[1".#.1.1R o matrices de par(metros O[1".#.1.4R. 8os par(metros de re0erencia y de salida no se aceptan para estas categor5as de miembros de 0unci-n. 8os argumentos de llamadas a constructores de instancia, m)todos o delegados se especi0ican como una lista de argumentos Oar& %ent-listRG ar& %ent-list1 ar& %ent ar& %ent-list

ar& %ent

ar& %ent1 e2pression re- varia-le-reference out varia-le-reference

1!'

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

7na lista de argumentos Oar& %ent-listR consta de uno o m(s argumentos Oar& %entsR, separados por comas. Cada argumento puede tomar una de las siguientes 0ormasG 7na expresi-n Oe2pressionR, para indicar ?ue el argumento se pasa como un par(metro de valor O[1".#.1.1R. 8a palabra clave re- seguida por una re0erencia a variable Ovaria-le-referenceR O[ .4R, para indicar ?ue el argumento se pasa como un par(metro de re0erencia O[1".#.1.2R. 7na variable debe estar asignada de manera de0initiva O[ .3R antes de ?ue se pueda pasar como par(metro de re0erencia. 8a palabra clave out seguida por una re0erencia a variable Ovaria-le-referenceR O[ .4R, para indicar ?ue el argumento se pasa como un par(metro de salida O[1".#.1.3R. 7na variable se considera asignada de manera de0initiva O[ .3R despu)s de una llamada a miembro de 0unci-n en la ?ue la variable se pasa como un par(metro de salida.

2urante el procesamiento de una invocaci-n de miembro de 0unci-n O[*.4.4R en tiempo de e$ecuci-n, las re0erencias de expresiones o de variables de una lista de argumentos se evalHan por orden, de i1?uierda a derec=a, como sigueG 'ara un par(metro de valor, se evalHa la expresi-n del argumento y se reali1a una conversi-n impl5cita O[#.1R al tipo de par(metro correspondiente. El valor resultante pasa a ser el valor inicial del par(metro de valor en la invocaci-n del miembro de 0unci-n. 'ara un par(metro de re0erencia o de salida, se evalHa la re0erencia de variable, mientras ?ue la ubicaci-n de almacenamiento resultante pasa a ser la ubicaci-n de almacenamiento, representada por el par(metro de la invocaci-n del miembro de 0unci-n. .i la re0erencia de variable dada como par(metro de re0erencia o de salida es un elemento de matri1 de tipo de re0erencia Oreference-t#peR, se lleva a cabo una comprobaci-n en tiempo de e$ecuci-n para garanti1ar ?ue el tipo de elemento de la matri1 es id)ntico al tipo del par(metro. .i esta comprobaci-n produce un error, se inicia una excepci-n System.'rray1y&eMismatc")#ce&tion.

8os m)todos, indi1adores y constructores de instancia pueden declarar su par(metro situado m(s a la derec=a como una matri1 de par(metros O[1".#.1.4R. Estos miembros de 0unci-n se invocan en su 0orma normal o en su 0orma expandida, dependiendo de lo ?ue sea aplicable O[*.4.3.1RG .i se invoca un miembro de 0unci-n con una matri1 de par(metros en su 0orma normal, el argumento pasado por la matri1 de par(metros debe ser una expresi-n Hnica de un tipo ?ue sea impl5citamente convertible O[#.1R al tipo de la matri1 de par(metros. En este caso, la matri1 de par(metros actHa exactamente como un par(metro de valor. .i se invoca un miembro de 0unci-n con una matri1 de par(metros en su 0orma expandida, la invocaci-n debe especi0icar cero o m(s argumentos para la matri1 de par(metros, donde cada argumento es una expresi-n de un tipo impl5citamente convertible O[#.1R al tipo de los elementos de la matri1 de par(metros. En este caso, la invocaci-n crea una instancia del tipo de la matri1 de par(metros con una longitud correspondiente al nHmero de argumentos, iniciali1a los elementos de la instancia de matri1 con los valores de los argumentos especi0icados y utili1a la instancia de matri1 reci)n creada como argumento real.

8as expresiones de una lista de argumentos siempre se evalHan en el orden en ?ue est(n escritas. 'or lo tanto, el siguiente e$emploG
class 1est { static void V(int # int y int ?) { System.Console.WriteLine("# + {3! ! static void Main() { int i + 3; V(i<< i<< i<<); ! !

y + {2!

? + {8!"

?);

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

1!1

Especificacin del lenguaje C#

produce el resultado
# + 3 y + 2 ? + 8

8as reglas de covarian1a matricial O[12. R permiten ?ue un valor de un tipo de matri1 '45 se trate como una re0erencia a una instancia de un tipo matricial :45, siempre ?ue exista una conversi-n impl5cita de re0erencias de : a '. 2ebido a estas reglas, si se pasa un elemento de matri1 de un tipo de re0erencia Oreference-t#peR como un par(metro de re0erencia o de resultado, se lleva a cabo una comprobaci-n en tiempo de e$ecuci-n para garanti1ar ?ue el tipo de elemento de la matri1 es id?ntico al tipo del par(metro. En el e$emplo
class 1est { static void V(re- object #) {...! static void Main() { object45 a + ne, object4235; object45 b + ne, string4235; V(re- a435); .. %( V(re- b425); .. 'rray1y&eMismatc")#ce&tion ! !

la segunda invocaci-n de V causa una excepci-n System.'rray1y&eMismatc")#ce&tion, puesto ?ue el tipo del elemento de b es string y no object. Cuando se llama a un miembro de 0unci-n con una matri1 de par(metros en su 0orma expandida, la invocaci-n se trata exactamente como si se =ubiera insertado una expresi-n de creaci-n de matri1 con un iniciali1ador de matri1 O[*. .1".4R alrededor de los par(metros expandidos. 'or e$emplo, dada la declaraci-n
void V(int # V(23 V(23 V(23 V(23 V(23 V(23 int y &arams object45 args);

las invocaciones siguientes de la 0orma expandida del m)todo


83); 83 93 J3); 83 2 ""ello" 83 83 83 9.3);

se corresponden exactamente con


ne, object45 {!); ne, object45 {93 J3!); ne, object45 {2 ""ello" 9.3!);

En particular, debe tenerse en cuenta ?ue si se pasan cero argumentos como matri1 de par(metros, se crea una matri1 vac5a. +.!.2 Inferencia de tipos Cuando se llama a un m)todo gen)rico sin especi0icar argumentos de tipo, una inferencia de tipos procesa los intentos para deducir los argumentos de tipo para la llamada. 8a presencia de la in0erencia de tipo permite utili1ar una sintaxis m(s adecuada para llamar a un m)todo gen)rico y permite ?ue el programador no especi0i?ue in0ormaci-n de tipo redundante. 'or e$emplo, dada la declaraci-n de m)todoG
class C"ooser { static Oandom rand + ne, Oandom(); &ublic static 1 C"ooseD1E(1 -irst 1 second) { return (rand.Ne#t(8) ++ 3)7 -irst/ second; ! !

es posible invocar el m)todo C"oose sin especi0icar expl5citamente un argumento de tipoG

1!2

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases int i + C"ooser.C"oose(K 829); "bar"); .. Calls C"ooseDintE .. Calls C"ooseDstringE

string s + C"ooser.C"oose("-oo"

%ediante la in0erencia de tipos, los argumentos de tipo int y string se determinan desde los argumentos al m)todo. 8a in0erencia de tipo tiene lugar como parte del proceso en tiempo de compilaci-n de una invocaci-n de m)todo O[*. . .1R y tiene lugar antes del paso de resoluci-n de sobrecarga de la invocaci-n. Cuando se especi0ica un grupo de m)todos concreto en una invocaci-n del m)todo y no se especi0ican argumentos como parte de esta invocaci-n, se aplica la in0erencia de tipo para cada m)todo gen)rico del grupo de m)todos. .i la in0erencia de tipo es correcta, los argumentos de tipo se utili1an para determinar los tipos de argumentos para la resoluci-n de sobrecarga subsiguiente. .i la resoluci-n de sobrecarga selecciona un m)todo gen)rico como el ?ue se va a invocar, los argumentos de tipo ?ue se deducen se utili1an como argumentos de tipo reales para la invocaci-n. .i no se puede reali1ar la in0erencia de tipo para un m)todo concreto, dic=o m)todo no participa en la resoluci-n de sobrecarga. &un?ue se genere un error en la in0erencia de tipo, esto no provocar( un error en tiempo de compilaci-n. .in embargo, en ocasiones esto lleva a un error en tiempo de compilaci-n cuando la resoluci-n de sobrecarga no puede encontrar ningHn m)todo aplicable. .i el nHmero de argumentos suministrados es di0erente del nHmero de par(metros del m)todo, la deducci-n genera inmediatamente un error. En caso contrario, se asume ?ue el m)todo gen)rico tiene la siguiente 0irmaG
1r MDI2bInE(12 #2 b 1m #m)

Con una llamada a m)todo ?ue tiene la estructura M()2 b)m) la tarea de la in0erencia de tipos es buscar argumentos de tipo Hnico S2bSn para cada uno de los par(metros de tipo I2bIn con el 0in de ?ue la llamada MDS2bSnE()2b)m) sea v(lida. 2urante el proceso de in0erencia, cada par(metro de tipo Ii se 0i$a Ofi2edR a un tipo determinado Si o ?ueda sin 0i$ar O nfi2edR con un con$unto asociado de l5mites O-o ndsR. Cada uno de los l5mites es algHn tipo 1. !nicialmente cada variable de tipo Ii est( sin 0i$ar y tiene un con$unto vac5o de l5mites. 8a in0erencia de tipos tiene lugar en 0ases. En cada 0ase se intentar( in0erir argumentos de tipo para m(s variables de tipo basados en los =alla1gos de la 0ase anterior. En la primera 0ase se reali1an algunas in0erencias iniciales de l5mites, mientras ?ue en la segunda 0ase se 0i$an variables de tipo a tipos espec50icos y se in0ieren m(s l5mites. Es posible ?ue la segunda 0ase se tenga ?ue repetir varias veces. 8ota1 la in0erencia de tipos tiene lugar no s-lo cuando se llama a un m)todo gen)rico. 8a in0erencia de tipos para la conversi-n de grupos de m)todos se describe en la secci-n [ y c-mo buscar el me$or tipo comHn de un con$unto de expresiones se describe en la secci-n [. #.4.2.1 *a primera 3ase 'ara cada uno de los argumentos de m)todo )iG .i )i es una 0unci-n an-nima, se reali1a una inferencia e2pl*cita de tipo de par,%etro O[R desde )i a 1i En caso contrario, se reali1a una inferencia de tipos de res ltado O[R desde )i a 1i

#.4.2.2 *a se"unda 3ase. 8a segunda 0ase se reali1a de la siguiente 0ormaG Todas las variables de tipo sin fi>ar Ii ?ue no dependen de O[*.4.2. R ninguna Ij se 0i$an O[*.4.2.1"R. .i no existen variables de este tipo, todas las variables de tipo sin fi>ar Ii se fi>an, y para ellas se cumplen las siguientes condicionesG o o Hay al menos una variable de tipo Ij ?ue depende de Ii
Ii tiene un con$unto vac5o de l5mites

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

1!3

Especificacin del lenguaje C#

.i no existieran variables de este tipo y =ubiera variables de tipo sin fi>ar, no se producir5a correctamente la in0erencia de tipos. En caso contrario, si no =ubiera ninguna otra variable de tipo sin fi>ar, la in0erencia de tipos se producir5a correctamente. En caso contrario, para todos los argumentos )i con el tipo de par(metro correspondiente 1i donde los tipos de res ltado O[*.4.2.4R contienen variables de tipo sin fi>ar Ij pero los tipos de entrada O[*.4.2.3R no, se produce una inferencia de tipos de res ltado O[*.4.2.#R desde )i a 1i. & continuaci-n, se repite la segunda 0ase.

#.4.2.3 :ipos de entrada. .i ) es un grupo de m)todos o una 0unci-n an-nima con asignaci-n de tipo impl5cita y 1 es un tipo delegado o tipo de (rbol de expresiones, entonces todos los tipos de par(metro de 1 son tipos de entrada de ) con el tipo 1. #.4.2.4 :ipos de resultado. .i ) es un grupo de m)todos o una 0unci-n an-nima y 1 es un tipo delegado o tipo de (rbol de expresiones, entonces el tipo de resultado de 1 es un tipo de entrada de ) con el tipo 1. #.4.2. (ependencia 7na variable de tipo sin fi>ar Ii depende directa%ente de una variable de tipo sin fi>ar Ij si para algHn argumento )( con el tipo 1( Ij se produce un tipo de entrada de )( con el tipo 1( y Ii tiene lugar en un tipo de res ltado de )( con el tipo 1(.
Ij depende de Ii si Ij depende directa%ente de Ii o si Ii depende directa%ente de I( y I( depende de Ij. &s5,

Pdepende deQ es el cierre transitivo, ?ue no re0lexivo de Pdepende directa%ente deQ. #.4.2.6 $n3erencias de tipo de resultado 7na inferencia de tipos de res ltado se reali1a desde una expresi-n ) a un tipo 1 de la siguiente 0ormaG .i ) es una 0unci-n an-nima con el tipo de resultado in0erido ; O[*.4.2.11R y 1 es un tipo delegado o tipo de (rbol de expresiones con un tipo de resultado 1b, entonces se reali1a una inferencia de l*%ite inferior O[*.4.2.+R desde ; a 1b. En caso contrario, si ) es un grupo de m)todos y 1 es un tipo delegado o tipo de (rbol de expresiones con tipos de par(metro 12b1( y el tipo de resultado 1b, y la resoluci-n de sobrecarga de ) con los tipos 12b1( genera un Hnico m)todo con el tipo de resultado ;, entonces se reali1a una inferencia de l*%ite inferior desde ; a 1b. En caso contrario, si ) es una expresi-n con el tipo ;, entonces se reali1a una in0erencia de l5mite in0erior desde ; a 1. En caso contrario, no se reali1a ninguna in0erencia.

#.4.2.# $n3erencias e2plCcitas de tipo de parmetro 7na in0erencia expl5cita de tipo de par(metro se reali1a a partir de una expresi-n ) a un tipo 1 de la siguiente 0ormaG .i ) es una 0unci-n an-nima con asignaci-n de tipo expl5cita ?ue tiene tipos de par(metro ;2b;( y 1 es el tipo delegado o tipo de (rbol de expresiones con tipos de par(metro U2bU(, entonces para cada ;i se reali1a una in0erencia exacta O[R desde ;i al Ui correspondiente.

1!#

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

#.4.2.+ $n3erencias e2actas 7na in0erencia exacta desde un tipo ; a un tipo U se reali1a de la siguiente maneraG .i U es una de las variables de tipo sin fi>ar Ii, entonces ; se agrega al con$unto de l5mites para Ii. En caso contrario, si ; es un tipo de matri1 ;e4b5 y U es un tipo de matri1 Ue4b5 del mismo rango, se reali1a la inferencia e2acta desde ;e a Ue. En caso contrario, si U es un tipo construido CDU2bU(E y ; es un tipo construido CD;2b;(E, se reali1a la inferencia e2acta para cada ;i al Ui correspondiente. En caso contrario, no se reali1a ninguna in0erencia.

#.4.2.5 $n3erencias de lCmite in3erior 7na inferencia de l*%ite inferior desde un tipo ; a un tipo U se reali1a de la siguiente maneraG .i U es una de las variables de tipo sin fi>ar Ii, entonces ; se agrega al con$unto de l5mites para Ii. En caso contrario, si ; es un tipo de matri1 ;e4b5 y U es un tipo de matri1 Ue4b5 del mismo rango, o si ; es un tipo de matri1 unidimensional ;e45 y U es $)numerableDUeE, $CollectionDUeE o $ListDUeE entonces o o .i ;e es un tipo de re0erencia, se reali1a una inferencia de l*%ite inferior desde ;e a Ue En caso contrario, se reali1a una inferencia e2acta desde ;e a Ue

En caso contrario, si U es un tipo construido CDU2bU(E y =ay un con$unto Hnico de tipos CD;2b;(E tal ?ue existe una conversi-n est(ndar impl5cita desde ; a CD;2b;(E, entonces se reali1a una inferencia e2acta desde cada ;i al Ui correspondiente. En caso contrario, no se reali1a ninguna in0erencia.

#.4.2.17 6i=ar tipos 7na variable de tipo sin fi>ar Ii con un con$unto de l5mites se 0i$a Ofi2edR de la siguiente 0ormaG El con$unto de tipos de candidatos ;j se inicia como con$unto de todos los tipos en el con$unto de l5mites para Ii. & continuaci-n, se examina cada l5mite para IiG para cada l5mite ; de Ii se ?uitan todos los tipos ;j para los ?ue no =ay una conversi-n impl5cita est(ndar desde ; en el con$unto de candidatos. .i entre los tipos de candidatos restantes ;j =ay un tipo Hnico U desde el ?ue =ay una conversi-n impl5cita est(ndar para todos los dem(s tipos de candidatos, entonces Ii se 0i$a en U. En caso contrario, la in0erencia de tipos no se reali1a correctamente.

#.4.2.11 :ipo de resultado in3erido El tipo de res!ltado inferido de una 0unci-n an-nima V se utili1a durante la in0erencia de tipos y la resoluci-n de sobrecargas. El tipo de resultado in0erido s-lo se puede determinar para una 0unci-n an-nima cuando se conocen todos los tipos de resultados, ya sea por?ue se dan expl5citamente, a trav)s de una conversi-n de 0unci-n an-nima, o in0eridos durante una in0erencia de tipos en una invocaci-n de m)todo gen)rico envolvente. El tipo de resultado in0erido se determina como sigueG .i el cuerpo de V es una expresi-n Oe2pressionR, el tipo de resultado in0erido de V es el tipo de esa expresi-n.

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

1!!

Especificacin del lenguaje C#

.i el cuerpo de V es un blo?ue O-loc3R y el con$unto de expresiones en las instrucciones return del blo?ue tiene un tipo comHn me$or 1 O[R, el tipo de resultado in0erido de V es 1. En caso contrario, no se puede in0erir un tipo de resultado para ).

Como e$emplo de in0erencia de tipos con 0unciones an-nimas, considere el m)todo de extensi-n Select declarado en la clase System.LinQ.)numerableG
names&ace System.LinQ { &ublic static class )numerable { &ublic static $)numerableD1OesultE SelectD1Source 1OesultE( t"is $)numerableD1SourceE source VuncD1Source 1OesultE selector) { -oreac" (1Source element in source) yield return selector(element); ! ! !

&sumiendo ?ue el espacio de nombres System.LinQ se import- mediante una cl(usula using, y dada una clase Customer con una propiedad Name de tipo string, el m)todo Select se puede usar para seleccionar los nombres de una lista de clientes Oc sto%ersRG
ListDCustomerE customers + SetCustomerList(); $)numerableDstringE names + customers.Select(c +E c.Name);

8a invocaci-n del m)todo de extensi-n O[*. . .2R de Select se procesa reescribiendo la invocaci-n para una invocaci-n de m)todo est(ticoG
$)numerableDstringE names + )numerable.Select(customers c +E c.Name);

2ado ?ue los argumentos de tipo no se especi0icaron expl5citamente, la in0erencia de tipos se utili1a para in0erir los argumentos de tipo. En primer lugar, el argumento customers se relaciona con el par(metro source, in0iriendo 1 para ?ue sea Customer. & continuaci-n, mediante el proceso de la inter0a1 de tipo de la 0unci-n an-nima, se da a c el tipo Customer, y la expresi-n c.Name se relaciona con el tipo de resultado del par(metro selector, in0iriendo S para ?ue sea string. &s5, la invocaci-n es e?uivalente a
SeQuence.SelectDCustomer stringE(customers (Customer c) +E c.Name)

y el resultado es el tipo $)numerableDstringE. El siguiente e$emplo demuestra c-mo una in0erencia de tipo de la 0unci-n an-nima permite ?ue la in0ormaci-n de tipo P0luyaQ entre los argumentos de una invocaci-n de m)todo gen)rico. 2ado el m)todoG
static P VDI ` PE(I value return -8(-2(value)); ! VuncDI `E -2 VuncD` PE -8) {

Escriba la in0erencia de tipos para la invocaci-nG


double seconds + V("2/2K/93" s +E 1imeS&an.*arse(s) t +E t.1otalSeconds);

se procesa como sigueG en primer lugar, el argumento "2/2K/93" se relaciona con el par(metro value, in0iriendo I para ?ue sea string. & continuaci-n, el par(metro de la primera 0unci-n an-nima, s, se da al tipo in0erido string, y la expresi-n 1imeS&an.*arse(s) se relaciona con el tipo de resultado de -2, in0iriendo ` para ?ue sea System.1imeS&an. 'or Hltimo, el par(metro de la segunda 0unci-n an-nima, t, se da al tipo in0erido System.1imeS&an, y la expresi-n t.1otalSeconds se relaciona con el tipo de resultado de -8, in0iriendo P para ?ue sea double. &s5, el resultado de la invocaci-n es de tipo double.

1!6

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

#.4.2.12 $n3erencia de tipos para la conversin de "rupos de mtodos 2e manera similar a las llamadas de m)todos gen)ricos, la in0erencia de tipos se debe aplicar tambi)n cuando un grupo de m)todos M ?ue contiene un m)todo gen)rico se convierte a un tipo delegado 6 determinado (c#.#). 2ado un m)todo
1r MDI2bInE(12 #2 b 1m #m)

y el grupo de m)todos M ?ue se est( asignado al tipo delegado 6, la tarea de la in0erencia de tipos consiste en buscar los argumentos de tipo S2bSn para ?ue la expresi-nG
MDS2bSnE

pasa a ser compatible O[1 .1R con 6. & di0erencia del algoritmo de in0erencia de tipos para llamadas de m)todos gen)ricos, en este caso s-lo =ay tipos de argumentos, no e2presiones de argumentos. En particular, no =ay 0unciones an-nimas y por lo tanto no =ay necesidad de varias 0ases de in0erencia. En lugar de eso, todas las Ii se consideran sin fi>ar y se reali1a una inferencia de nivel inferior desde cada tipo de argumento ;j de 6 al tipo de par(metro correspondiente 1j de M. .i para alguna de las Ii no se encuentra un l5mite, la in0erencia de tipos no se reali1ar( correctamente. En caso contrario, todas las Ii se fi>an en las Si correspondientes, ?ue son el resultado de la in0erencia de tipos. #.4.2.13 8uscar el me=or tipo comDn de un con=unto de e2presiones En algunos casos, un tipo comHn necesita in0erirse para un con$unto de expresiones. En particular, los tipos de elementos de las matrices con asignaci-n de tipo impl5cita y los tipos de resultado de 0unciones an-nimas con cuerpos de blo?ue O-loc3R se encuentra de esta manera. 2e 0orma intuitiva, dado un con$unto de expresiones )2b)m esta in0erencia deber5a ser e?uivalente a la llamada de un m)todo
1r MDIE(I #2 b I #m)

con )i como argumentos. %(s concretamente, la in0erencia se inicia con una variable de tipo sin fi>ar I. 8as inferencias de tipos de res ltados se reali1an desde cada )i a I. 'or Hltimo, I se 0i$a Ofi2edR y, si es correcto, el tipo resultante S es el tipo comHn resultante para las expresiones. .i el tipo S existe, las excepciones no tienen el me$or tipo comHn. +.!.3 9esolucin de sobrecargas 8a resoluci-n de sobrecargas es un mecanismo del tiempo de compilaci-n ?ue selecciona el me$or miembro de 0unci-n ?ue puede invocarse dados una lista de argumentos y un con$unto de miembros de 0unci-n candidatos. 8a resoluci-n de sobrecargas selecciona el miembro de 0unci-n al ?ue se invoca en los contextos siguientes Hnicos en C#G !nvocaci-n de un m)todo con nombre en una expresi-n de invocaci-n Oinvocation-e2pressionR O[R. !nvocaci-n de un constructor de instancia con nombre en una expresi-n de creaci-n de ob$eto Oo->ectcreation-e2pressionR O[*. .1".1R. !nvocaci-n de un descriptor de acceso a indi1ador mediante un acceso a elementos Oele%ent-accessR O[*. .#R. 8lamada de un operador prede0inido o de0inido por el usuario al ?ue se =ace re0erencia en una expresi-n O[*.2.3 y [*.2.4R.

Cada uno de estos contextos de0ine el con$unto de miembros de 0unci-n candidatos y la lista de argumentos a su propia manera, segHn se describe detalladamente en las secciones anteriormente citadas. 'or e$emplo, el

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

1!(

Especificacin del lenguaje C#

con$unto de candidatos para una invocaci-n a un m)todo no incluye m)todos marcados con override O[*.3R y los m)todos de una clase base no son candidatos si ningHn m)todo de una clase derivada es aplicable O[*. . .1R. 7na ve1 identi0icados los miembros de 0unci-n candidatos y la lista de argumentos, la selecci-n del me$or miembro de 0unci-n es la misma en todos los casosG 2ado el con$unto de miembros de 0unci-n candidatos aplicables, se locali1a el me$or miembro de 0unci-n del con$unto. .i el con$unto s-lo contiene un miembro de 0unci-n, )se es el me$or miembro. / bien, el me$or miembro de 0unci-n es a?u)l ?ue es me$or ?ue todos los dem(s miembros de 0unci-n con respecto a la lista de argumentos dada, a condici-n de ?ue cada miembro de 0unci-n se compare con todos los dem(s miembros aplicando las reglas de la [*.4.3.2. .i no =ay exactamente un miembro de 0unci-n me$or ?ue todos los dem(s, la llamada de un miembro de 0unci-n es ambigua y se produce un error durante la compilaci-n. ie /ro de f!nci,n aplica/le y

En las secciones siguientes se de0ine el signi0icado exacto de los t)rminos e1or ie /ro de f!nci,n. #.4.3.1 Miembro de 3uncin aplicable

.e dice ?ue un miembro de 0unci-n es un ie /ro de f!nci,n aplica/le con respecto a una lista de argumentos ' si todas las condiciones siguientes son verdaderasG El nHmero de argumentos de ' es id)ntico al nHmero de par(metros de la declaraci-n del miembro de 0unci-n. 'ara cada argumento de ', el modo de pasar los par(metros del argumento Oes decir, value, re- u outR es id)ntico al modo de pasar los par(metros del par(metro correspondiente, yG o o para un par(metro de valor o una matri1 de par(metros, existe una conversi-n impl5cita O[R del argumento al tipo del par(metro correspondiente, o para un par(metro re- u out, el tipo del argumento es id)ntico al tipo del par(metro correspondiente Odespu)s de todo, un par(metro re- u out es un alias para el argumento ?ue se pasaR.

'ara un miembro de 0unci-n ?ue incluye una matri1 de par(metros, si el miembro es aplicable por las reglas anteriores, se dice ?ue es aplicable en su for a nor al. .i un miembro de 0unci-n ?ue incluye una matri1 de par(metros no es aplicable en su 0orma normal, el miembro puede ser aplicable en su for a e.pandidaG 8a 0orma expandida se construye mediante el reempla1o de la matri1 de par(metros en la declaraci-n del miembro de 0unci-n con cero o m(s par(metros de valor del tipo de los elementos de la matri1 de par(metros, de 0orma ?ue el nHmero de argumentos de la lista de argumentos ' coincida con el nHmero total de par(metros. .i ' tiene menos argumentos ?ue el nHmero de par(metros de tipo 0i$ado de la declaraci-n del miembro de 0unci-n, la 0orma expandida del miembro de 0unci-n no puede construirse y, por lo tanto, no es aplicable. / bien, la 0orma expandida es aplicable si, para cada argumento de ', el modo de pasar los par(metros del argumento es id)ntico al modo de pasar los par(metros del par(metro correspondiente, y o o para un par(metro de valores 0i$ados o par(metro de valores creados por la expansi-n, existe una conversi-n impl5cita O[#.1R del tipo del argumento al tipo del par(metro correspondiente, o para un par(metro re- u out, el tipo del argumento es id)ntico al tipo del par(metro correspondiente.

#.4.3.2 Me=or miembro de 3uncin 2ada una lista de argumentos ' con un con$unto de expresiones de argumento d )2, )8, ..., )N e y dos miembros de 0unci-n aplicables M* y M^ con los tipos de par(metro d *2, *8, ..., *N e y d ^2, ^8, ..., ^N e, M* se de0ine como un e1or ie /ro de f!nci,n ?ue M^ si
1!$
Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

para cada argumento, la conversi-n impl5cita de )I a ^I no es me$or ?ue la conversi-n impl5cita de )I a *I, y por lo menos para un argumento, la conversi-n de )I a *I es me$or ?ue la conversi-n de )I a ^I.

Cuando se reali1a esta evaluaci-n, si M* o M^ es aplicable en su 0orma expandida, entonces *I o ^I =ace re0erencia a un par(metro en la 0orma expandida de la lista de par(metros. .i las secuencias de tipo de par(metros, {*2, *8, f, *N! y {^2, ^8, f, ^N! son id)nticas, se aplican las siguientes reglas de desempate, por orden, con el 0in de determinar el me$or miembro de 0unci-n. .i M* es un m)todo no gen)rico y M^ es un m)todo gen)rico, M* es me$or ?ue M^. 2e lo contrario, si M* es aplicable en su estructura normal y M^ tiene una matri1 &arams y s-lo es aplicable en su 0orma expandida, M* es me$or ?ue M^. 2e lo contrario, si M* tiene menos par(metros declarados ?ue M^, M* es me$or ?ue M^. Esto puede ocurrir si ambos m)todos tienen matrices &arams y s-lo son aplicables en sus 0ormas expandidas. 2e lo contrario, si M* tiene m(s tipos de par(metro espec50icos ?ue M^, M* es me$or ?ue M^. {O2, O8, f, ON! y {S2, S8, f, SN! representar(n los tipos de par(metros no expandidos y para los ?ue no se crearon instancias de M* y M^. 8os tipos de par(metro de M* son m(s espec50icos ?ue los de M^ si, para cada par(metro, OI no es menos espec50ico ?ue SI y, para al menos un par(metro, OI es m(s espec50ico ?ue SIG o o 7n par(metro de tipo es menos espec50ico ?ue un par(metro ?ue no es de tipo. 2e manera recursiva, un tipo construido es m(s espec50ico ?ue otro tipo construido Ocon el mismo nHmero de argumentos de tipoR si al menos un argumento de tipo es m(s espec50ico y no =ay argumentos de tipo menos espec50icos ?ue el argumento de tipo correspondiente. 7n tipo de matri1 es m(s espec50ico ?ue otro tipo de matri1 Ocon el mismo nHmero de dimensionesR si el tipo de elemento del primero es m(s espec50ico ?ue el tipo de elemento del segundo.

En caso contrario, si un miembro es un operador de no elevaci-n y el otro es un operador de elevaci-n, el de no elevaci-n es me$or. En caso contrario, ningHn miembro de 0unci-n es me$or.

#.4.3.3 Me=or conversin de e2presiones 2ada una conversi-n impl5cita C2 ?ue convierte de una expresi-n ) a un tipo 12, y una conversi-n impl5cita C8 ?ue convierte de una expresi-n ) a un tipo 18, C2 es una conversi,n e1or ?ue C8 si 12 y 18 son tipos di0erentes y al menos se cumple una de las condiciones siguientesG
)2 tiene un tipo S y la conversi-n desde S a 12 es me$or ?ue la conversi-n desde S a 18. ) es una 0unci-n an-nima, 12 y 18 son tipos delegados o tipos de (rbol de expresiones con listas de par(metros id)nticos, y existe un tipo de resultado in0erido I para ) en el contexto de esa lista de par(metros

O[*.4.2.11R, y se cumple una de las condiciones siguientesG


12 tiene un tipo de resultado `2 y 18 tiene el tipo de resultado `8, y la conversi-n desde I a `2 es me$or ?ue la conversi-n desde S a `8 12 tiene un tipo de resultado ` y 18 devuelve valores void

#.4.3.4 Me=or conversin de tipos 2ada una conversi-n impl5cita C2 ?ue convierte de un tipo S a un tipo 12, y una conversi-n C8 ?ue convierte de un tipo S a un tipo 18, C2 es una conversi,n e1or ?ue C8 si 12 y 18 son tipos di0erentes y se cumple al menos una de las condiciones siguientesG

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

1!"

Especificacin del lenguaje C#

S es 12

Existe una conversi-n impl5cita desde 12 a 18 y no =ay una conversi-n impl5cita desde 18 a 12
12 es un tipo integral con signo y 18 es un tipo integral sin signo. ConcretamenteG

o o o o

12 es sbyte y 18 es byte, us"ort, uint o ulong 12 es s"ort y 18 es us"ort, uint o ulong 12 es int y 18 es uint o ulong 12 es long y 18 es ulong

Tenga en cuenta ?ue as5 se puede de0inir una conversi-n para ?ue sea me$or incluso cuando no =aya ninguna conversi-n impl5cita de0inida. 2e este modo, por e$emplo la conversi-n de la expresi-n X a s"ort es me$or ?ue la conversi-n de X a us"ort, por?ue una conversi-n de cual?uier tipo a s"ort es me$or ?ue una conversi-n a us"ort. #.4.3. !obrecar"a en clases "enricas 8as 0irmas declaradas deben ser Hnicas, pero es posible ?ue al sustituir argumentos de tipo se generen 0irmas id)nticas. En estos casos, y gracias a las reglas de desempate de la resoluci-n de sobrecarga antes mencionada, se escoge el miembro m(s especi0ico. En los siguientes e$emplos se muestran sobrecargas v(lidas y no v(lidas segHn dic=a reglaG
inter-ace $2D1E {...! inter-ace $8D1E {...! class S2D;E { int V2(; u); int V2(int i); void V8($2D;E a); void V8($8D;E a); ! class S8D; UE { void V9(; u void V9(U v

.. %verload resulotion -or SDintE.V2 .. ,ill &ic( non=generic .. Ualid overload

U v); ; u);

.. Ualid but overload resolution -or .. S8Dint intE.V9 ,ill -ail .. Ualid but overload resolution -or .. S8D$2DintE intE.VJ ,ill -ail .. Ualid overload .. valid overload

void VJ(; u $2DUE v); void VJ($2DUE v ; u); void VK(; u2 void VK(U v2 $2DUE v8); ; u8);

void VX(re- ; u); void VX(out U v); !

+.!.! In ocacin de miembros de funcin En esta secci-n se explica el proceso ?ue tiene lugar en tiempo de e$ecuci-n para invocar un miembro de 0unci-n concreto. .e supone ?ue un proceso de tiempo de compilaci-n ya =a determinado el miembro concreto ?ue se invoca, posiblemente por la aplicaci-n de la resoluci-n de sobrecargas a un con$unto de miembros de 0unci-n candidatos. 'ara la descripci-n del proceso de invocaci-n, los miembros de 0unci-n se dividen en dos categor5asG

16'

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

%iembros de 0unci-n est(ticos. .on constructores de instancia, m)todos est(ticos, descriptores de acceso a propiedad est(ticos y operadores de0inidos por el usuario. 8os miembros de 0unci-n est(ticos siempre son no virtuales. %iembros de 0unci-n de instancia. .on m)todos de instancia, descriptores de acceso a propiedad de instancia y descriptores de acceso a indi1ador. 8os miembros de 0unci-n de instancia son virtuales o no virtuales, y siempre se les llama en una instancia concreta. 8a instancia se calcula mediante una expresi-n de instancia, y ?ueda accesible dentro del miembro de 0unci-n como t"is O[*. .*R.

El procesamiento en tiempo de e$ecuci-n de una invocaci-n de miembro de 0unci-n re?uiere los pasos siguientes, donde M es el miembro de 0unci-n y, si M es un miembro de instancia, ) es la expresi-n de instanciaG .i M es un miembro de 0unci-n est(ticoG o o o o 8a lista de argumentos se evalHa segHn lo descrito en [*.4.1. .e invoca M. .e evalHa ). .i esta evaluaci-n da lugar a una excepci-n, no se e$ecutan nuevos pasos. .i ) no se clasi0ica como variable, se crea una variable local temporal con el estilo de ) y el valor de ) se asigna a esa variable. Entonces ) se vuelve a clasi0icar como re0erencia para esa variable local temporal. 8a variable temporal est( accesible como t"is dentro de M, pero no de otra 0orma. 'or lo tanto, solamente si ) es una variable verdadera es posible ?ue el proceso llamante observe los cambios ?ue M e0ectHa en t"is. 8a lista de argumentos se evalHa segHn lo descrito en [*.4.1. .e invoca M. 8a variable a ?ue =ace re0erencia ) pasa a ser la variable a ?ue =ace re0erencia t"is. .e evalHa ). .i esta evaluaci-n da lugar a una excepci-n, no se e$ecutan nuevos pasos. 8a lista de argumentos se evalHa segHn lo descrito en [*.4.1. .i el tipo de ) es un tipo de valor Oval e-t#peR, se reali1a una conversi-n boxing O[4.3.1R para convertir ) al tipo object, y ) se considera de tipo object en los pasos siguientes. En este caso, M s-lo podr5a ser un miembro de System.%bject. .e comprueba la valide1 del valor de ). .i el valor de ) es null, se inicia una excepci-n System.NullOe-erence)#ce&tion y no se e$ecutan nuevos pasos. 8a implementaci-n del miembro de 0unci-n ?ue se va a invocar se determina de la siguiente 0ormaG .i el tipo de tiempo de compilaci-n de ) es una inter0a1, el miembro de 0unci-n ?ue =ay ?ue invocar es la implementaci-n de M ?ue proporciona el tipo de tiempo de e$ecuci-n de la instancia a la ?ue =ace re0erencia ). Este miembro de 0unci-n se determina aplicando las reglas de asignaci-n de inter0aces O[13.4.4R para determinar la implementaci-n de M proporcionada por el tipo en tiempo de e$ecuci-n de la instancia a la ?ue =ace re0erencia ). 2e lo contrario, si M es un miembro de 0unci-n virtual, el miembro de 0unci-n ?ue =ay ?ue invocar es la implementaci-n de M ?ue proporciona el tipo de tiempo de e$ecuci-n de la instancia a la ?ue =ace re0erencia ) Este miembro de 0unci-n se determina aplicando las reglas para determinar la implementaci-n m(s derivada O[1".#.3R de M relativa al tipo en tiempo de e$ecuci-n de la instancia a la ?ue =ace re0erencia ).

.i M es un miembro de 0unci-n de instancia declarado en un tipo de valor Oval e-t#peRG

o o o o o

.i M es un miembro de 0unci-n de instancia declarado en un tipo de re0erencia Oreference-t#peRG

o o

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

161

Especificacin del lenguaje C#

2e lo contrario, M ser( un miembro de 0unci-n no virtual y el miembro de 0unci-n ?ue =abr( ?ue invocar ser( el propio M.

.e invoca la implementaci-n del miembro de 0unci-n determinada en el paso anterior. El ob$eto al ?ue =ace re0erencia ) se convierte en el ob$eto al ?ue =ace re0erencia t"is.

#.4.4.1 $nvocaciones en instancias de conversin bo2in" 7n miembro de 0unci-n implementado en un tipo de valor Oval e-t#peR puede invocarse mediante una instancia de conversi-n boxing del tipo de valor en las situaciones siguientesG .i el miembro de 0unci-n es un override de un m)todo =eredado del tipo object y se invoca mediante una expresi-n de instancia de tipo object. .i el miembro de 0unci-n es una implementaci-n de un miembro de 0unci-n de inter0a1 y se invoca mediante una expresi-n de instancia de un tipo de inter0a1 Ointerface-t#peR. .i se invoca el miembro de 0unci-n a trav)s de un delegado.

En estas situaciones, se considera ?ue la instancia convertida mediante boxing contiene una variable de tipo de valor Oval e-t#peR, y esta variable se convierte en la variable a la ?ue se =ace re0erencia con t"is dentro de la invocaci-n del miembro de 0unci-n. Esto, concretamente, signi0ica ?ue cuando se invoca un miembro de 0unci-n en una instancia convertida mediante boxing, el miembro de 0unci-n puede modi0icar el valor contenido en dic=a instancia.

+.# E"presiones primarias


8as expresiones primarias incluyen las 0ormas m(s simples de las expresiones. pri%ar#-e2pression1 pri%ar#-no-arra#-creation-e2pression arra#-creation-e2pression pri%ar#-no-arra#-creation-e2pression1 literal si%ple-na%e parenthesi0ed-e2pression %e%-er-access invocation-e2pression ele%ent-access this-access -ase-access post-incre%ent-e2pression post-decre%ent-e2pression o->ect-creation-e2pression dele&ate-creation-e2pression anon#%o s-o->ect-creation-e2pression t#peof-e2pression chec3ed-e2pression nchec3ed-e2pression defa lt-val e-e2pression anon#%o s-%ethod-e2pression 8as expresiones primarias se dividen en expresiones de creaci-n de matrices Oarra#-creation-e2pressionsR y expresiones primarias sin creaci-n de matrices Opri%ar#-no-arra#-creation-e2pressionsR. .i las expresiones de

162

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

creaci-n de matrices se tratan de esta manera, en lugar de enumerarlas $unto con todas las 0ormas de expresiones simples, se permite ?ue la gram(tica des=abilite potencialmente c-digos con0usos comoG
object o + ne, int495425;

?ue, de otra manera, podr5a interpretarse como


object o + (ne, int495)425;

+.#.1 6iterales 7na expresi-n primaria Opri%ar#-e2pressionR compuesta por un literal OliteralR O[2.4.4R se clasi0ica como un valor. +.#.2 1ombres sencillos 7n nombre simple Osi%ple-na%eR est( 0ormado por un identi0icadorV opcionalmente le sigue una lista de argumentos de tipoG si%ple-na%e1 identifier t#pe-ar& %ent-listopt 7n nombre simple Osi%ple-na%eR tiene la estructura $ o la estructura $D'2 ... 'aE, donde $ es un solo identi0icador y D'2 ... 'aE una lista de argumentos de tipo Ot#pe-ar& %ent-listR opcionales. .i no se especi0ica ninguna lista de argumentos de tipo Ot#pe-ar& %ent-listR, se considera ?ue a es cero. El nombre simple Osi%ple-na%eR se evalHa y clasi0ica como sigueG .i a es cero y el nombre simple Osi%ple-na%eR aparece dentro de un blo?ue O-loc3R y si el espacio de declaraci-n de variables locales O[3.3R del blo?ue O-loc3R Oo de un blo?ue contenedorR contiene una variable local, un par(metro o una constante con el nombre $, el nombre simple Osi%ple-na%eR =ace re0erencia a dic=o par(metro, constante o variable local y se clasi0ica como una variable o un valor. .i a es cero y el nombre simple Osi%ple-na%eR aparece dentro del cuerpo de una declaraci-n de m)todo gen)rico y si dic=a declaraci-n incluye un par(metro de tipo con el nombre $, el nombre simple Osi%plena%eR =ace re0erencia a dic=o par(metro de tipo. 2e lo contrario, para cada tipo de instancia 1 O[1".3.1R, empe1ando por el tipo de instancia de la declaraci-n de tipo envolvente inmediata y continuando con el tipo de instancia de cada clase envolvente o declaraci-n de estructura Osi las =ubieraRG o o .i a es cero y la declaraci-n de 1 incluye un par(metro de tipo con el nombre $, el nombre simple Osi%ple-na%eR =ace re0erencia a dic=o par(metro de tipo. 2e lo contrario, si la bHs?ueda de un miembro O[*.3R de $ en 1 con argumentos de tipo a da un resultadoG .i 1 es el tipo de instancia de la clase envolvente o del tipo struct inmediato y la bHs?ueda identi0ica uno o m(s m)todos, el resultado es un grupo de m)todos con una expresi-n de instancia asociada de t"is. .i se especi0ic- una lista de argumentos de tipo, se utili1a para llamar a un m)todo gen)rico O[*. . .1R. 2e lo contrario, si 1 es el tipo de instancia de la clase envolvente o del tipo struct inmediato, si la bHs?ueda identi0ica un miembro de instancia, y si la re0erencia ocurre dentro del blo?ue O-loc3R de un constructor de instancia, un m)todo de instancia o un descriptor de acceso a instancia, el resultado es el mismo ?ue un acceso a miembros O[R de la 0orma t"is.$. Esto s-lo puede ocurrir cuando a es cero.

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

163

Especificacin del lenguaje C#

2e lo contrario, el resultado es el mismo ?ue un acceso a miembros O[*. .4R con la estructura 1.$ o 1.$D'2 ... 'aE. En este caso, se produce un error durante la compilaci-n si el nombre simple Osi%ple-na%eR =ace re0erencia a un miembro de instancia.

2e lo contrario, para cada espacio de nombres N, empe1ando por el espacio de nombres en el ?ue se produce el nombre simple Osi%ple-na%eR, continuando por cada uno de los espacios de nombres envolventes Osi los =ubieraR y terminando por el espacio de nombres global, se ir(n evaluando los siguientes pasos =asta ?ue se localice una entidadG o .i a es cero e $ es el nombre de un espacio de nombres en NG .i la ubicaci-n donde tiene lugar el nombre simple Osi%ple-na%eR tiene una declaraci-n de espacio de nombres para N y la declaraci-n de espacio de nombres contiene una directiva de alias extern Oe2tern-alias-directiveR o una directiva de alias using O sin&-alias-directiveR ?ue asocia el nombre $ con un nombre de espacio de nombres o de tipo, el nombre simple Osi%ple-na%eR es ambiguo y se genera un error en tiempo de compilaci-n. 2e lo contrario, el nombre simple Osi%ple-na%eR =ace re0erencia al espacio de nombres denominado $ en N. .i a es cero y la ubicaci-n donde tiene lugar el nombre simple Osi%ple-na%eR tiene una declaraci-n de espacio de nombres para N y la declaraci-n de espacio de nombres contiene una directiva de alias extern Oe2tern-alias-directiveR o una directiva de alias using O sin&-alias-directiveR ?ue asocia el nombre $ con un nombre de espacio de nombres o de tipo, el nombre simple Osi%ple-na%eR es ambiguo y se genera un error en tiempo de compilaci-n. 2e lo contrario, el nombre de espacio de nombres o de tipo Ona%espace-or-t#pe-na%eR =ace re0erencia al tipo construido con los argumentos de tipo dados.

2e lo contrario, si N contiene un tipo accesible con un nombre $ y par(metros de tipo aG

2e lo contrario, si la ubicaci-n donde tiene lugar el nombre simple Osi%ple-na%eR tiene lugar en una declaraci-n de espacio de nombres para NG .i a es cero y la declaraci-n de espacio de nombres contiene una directiva de alias extern Oe2ternalias-directiveR o una directiva de alias using O sin&-alias-directiveR ?ue asocia el nombre $ a un espacio de nombres o tipo importado, entonces el nombre simple Osi%ple-na%eR =ace re0erencia a dic=o espacio de nombres o tipo. 2e lo contrario, si los espacios de nombres importados por las directivas using de espacio de nombres O sin&-na%espace-directivesR de la declaraci-n del espacio de nombres contienen exactamente un Hnico tipo con el nombre $ y par(metros de tipo a, entonces el nombre simple Osi%ple-na%eR =ace re0erencia al tipo construido con los argumentos de tipo dados. 2e lo contrario, si los espacios de nombres importados por las directivas using de espacio de nombres O sin&-na%espace-directivesR de la declaraci-n del espacio de nombres contienen m(s de un tipo con el nombre $ y par(metros de tipo a, entonces el nombre simple Osi%ple-na%eR ser( ambiguo y se producir( un error.

Tenga en cuenta ?ue este paso es paralelo al paso correspondiente en el procesamiento de un nombre de espacio de nombres o de tipo Ona%espace-or-t#pe-na%eR O[3.8R. 2e lo contrario, el nombre simple Osi%ple-na%eR no est( de0inido y se produce un error en tiempo de compilaci-n.

16#

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

#. .2.1 !i"ni3icado invariable en blo0ues 'or cada repetici-n de un identi0icador dado como un nombre simple Osi%ple-na%eR en una expresi-n o declarador, dentro del espacio de declaraci-n de la variable local O[3.3R ?ue envuelve inmediatamente a dic=a repetici-n, todas las dem(s repeticiones del mismo identi0icador como nombre simple Osi%ple-na%eR en una expresi-n o declarador debe =acer re0erencia a la misma entidad. Esta regla asegura ?ue el signi0icado de un nombre siempre es el mismo dentro de un blo?ue, blo?ue s9itc=, instrucci-n 0orB, 0oreac=B o usingB, o 0unci-n an-nima determinada. En el e$emplo
class 1est { double #; void V(bool b) { # + 2.3; i- (b) { int #; # + 2; ! ! !

se produce un error durante la compilaci-n por?ue # =ace re0erencia a varias entidades dentro del blo?ue externo Ocuya extensi-n incluye el blo?ue anidado de la instrucci-n i-R. 'or el contrario, el e$emploG
class 1est { double #; void V(bool b) { i- (b) { # + 2.3; ! else { int #; # + 2; ! ! !

est( permitido por?ue el nombre # nunca se utili1a en el blo?ue externo. 2ebe tenerse en cuenta ?ue la regla del signi0icado invariable s-lo se aplica a los nombres simples. Es per0ectamente v(lido ?ue el mismo identi0icador tenga un signi0icado como nombre simple y otro distinto como operando derec=o de un acceso a miembros O[*. .4R. 'or e$emploG
struct *oint { int # y; &ublic *oint(int # t"is.# + #; t"is.y + y; ! ! int y) {

El e$emplo anterior ilustra un modelo comHn de uso de los nombres de campos como nombres de par(metros en un constructor de instancia. En el e$emplo, los nombres simples # e y =acen re0erencia a los par(metros, pero ello no impide ?ue expresiones de acceso a miembros como t"is.# y t"is.y obtengan acceso a los campos.

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

16!

Especificacin del lenguaje C#

+.#.3 E"presiones entre par*ntesis 7na expresi-n entre par)ntesis Oparenthesi0ed-e2pressionR consiste en una expresi-n Oe2pressionR encerrada entre par)ntesis. parenthesi0ed-e2pression1 ( e2pression ) 7na expresi-n entre par)ntesis Oparenthesi0ed-e2pressionR se evalHa mediante la evaluaci-n de la expresi-n Oe2pressionR contenida entre los par)ntesis. .i la expresi-n Oe2pressionR entre par)ntesis denota un espacio de nombres, un tipo o un grupo de m)todos, se produce un error durante la compilaci-n. 2e lo contrario, el resultado de la expresi-n entre par)ntesis Oparenthesi0ed-e2pressionR es el resultado de la evaluaci-n de la expresi-n Oe2pressionR contenida. +.#.! 'cceso a miembros 7n acceso a miembro O%e%-er-accessR consiste en una expresi-n primaria Opri%ar#-e2pressionR, un tipo prede0inido Opredefined-t#peR o un miembro de alias completo O6 alified-alias-%e%-erR seguido por un s5mbolo Oto6enR P.Q y, despu)s, por un identi0icador OidentifierRV opcionalmente, a este Hltimo puede seguirle una lista de argumentos de tipo Ot#pe-ar& %ent-listR. %e%-er-access1 pri%ar#-e2pression . identifier t#pe-ar& %ent-listopt predefined-t#pe . identifier t#pe-ar& %ent-listopt 6 alified-alias-%e%-er . identificador predefined-t#pe1
bool object

no de
c"ar s"ort decimal string double uint -loat ulong int us"ort long

byte sbyte

8a producci-n de miembros alias completos O6 alified-alias-%e%-erR se de0ine en la secci-n [+.*. 7n acceso a miembro O%e%-er-accessR tiene la estructura ).$ o la estructura ).$D'2 ... 'aE, donde ) es una expresi-n primaria, $ es un solo identi0icador y D'2 ... 'aE una lista de argumentos de tipo Ot#pe-ar& %entlistR opcional. .i no se especi0ica ninguna lista de argumentos de tipo Ot#pe-ar& %ent-listR, se considera ?ue a es cero. El acceso a miembro O%e%-er-accessR se evalHa y clasi0ica como sigueG .i a es cero y ) es un espacio de nombres y ) contiene un espacio de nombres anidado con el nombre $, el resultado es dic=o espacio de nombres. 2e lo contrario, si ) es un espacio de nombres y ) contiene un tipo accesible con el nombre $ y par(metros de tipo a, el resultado es el tipo construido con los argumentos de tipo dados. .i ) es un tipo prede0inido Opredefined-t#peR o una expresi-n primaria Opri%ar#-e2pressionR clasi0icada como un tipo, si ) no es un par(metro de tipo y si una bHs?ueda de miembros O[*.3R de $ en ) con par(metros de tipo a produce una coincidencia, entonces ).$ se evalHa y clasi0ica como sigueG o o .i $ identi0ica un tipo, el resultado es el tipo construido con los argumentos de tipo dados. .i $ identi0ica uno o varios m)todos, entonces el resultado es un grupo de m)todos sin una expresi-n de instancia asociada. .i se especi0ic- una lista de argumentos de tipo, se utili1a para llamar a un m)todo gen)rico O[*. . .1R. .i $ identi0ica una propiedad static, entonces el resultado es un acceso a propiedad sin una expresi-n de instancia asociada. .i $ identi0ica un campo staticG

o o

166

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

.i el campo es readonly y la re0erencia ocurre 0uera del constructor est(tico de la clase o estructura donde est( declarado el campo, entonces el resultado es un valor, concretamente, el valor del campo est(tico $ de ). En caso contrario, el resultado es una variable, en concreto, el campo est(tico $ en ). .i la re0erencia ocurre dentro de la clase o estructura donde est( declarado el evento, y )ste se =a declarado sin declaraciones de descriptor de acceso a evento Oevent-accessor-declarationsR O[1".8R, entonces ).$ se procesa exactamente como si $ 0uera un campo est(tico. / bien, el resultado es un acceso a evento sin una expresi-n de instancia asociada.

.i $ identi0ica un evento staticG

o o o

.i $ identi0ica una constante, entonces el resultado es un valor, en concreto el valor de la constante. .i $ identi0ica un miembro de enumeraci-n, entonces el resultado es un valor, a saber, el valor de dic=o miembro de enumeraci-n. 2e lo contrario, ).$ ser( una re0erencia de miembro no v(lida y se producir( un error en tiempo de compilaci-n.

.i ) es un acceso a propiedad, un acceso a indi1ador, una variable o un valor, cuyo tipo es 1, y una bHs?ueda de miembros O[R de $ en 1 con argumentos de tipo a produce una coincidencia, entonces ).$ se evalHa y clasi0ica como sigueG o o En primer lugar, si ) es un acceso a propiedad o a indi1ador, entonces se obtiene el valor del acceso a propiedad o a indi1ador O[*.1.1R y ) se reclasi0ica como un valor. .i $ identi0ica uno o varios m)todos, entonces el resultado es un grupo de m)todos con una expresi-n de instancia asociada de ). .i se especi0ic- una lista de argumentos de tipo, se utili1a para llamar a un m)todo gen)rico O[*. . .1R. .i $ identi0ica una propiedad de instancia, entonces el resultado es un acceso a propiedad con una expresi-n de instancia asociada de ). .i 1 es un tipo de clase Oclass-t#peR e $ identi0ica un campo de instancia de dic=o tipo de claseG .i el valor de ) es null, se inicia una excepci-n System.NullOe-erence)#ce&tion. 2e lo contrario, si el campo es readonly y la re0erencia ocurre 0uera de un constructor de instancia de la clase donde est( declarado el campo, entonces el resultado es un valor, concretamente, el valor del campo $ en el ob$eto al ?ue =ace re0erencia ). 2e lo contrario, el resultado es una variable, en concreto, el campo $ en el ob$eto al ?ue =ace re0erencia ). .i ) es un valor o si el campo es readonly y la re0erencia ocurre 0uera de un constructor de instancia de la estructura donde est( declarado el campo, entonces el resultado es un valor, concretamente, el valor del campo $ en la instancia de estructura dada por ). / bien, el resultado es una variable, en concreto, el campo $ en la instancia de estructura dada por ).

o o

.i 1 es un tipo struct Ostr ct-t#peR e $ identi0ica un campo de instancia de dic=o tipoG

.i $ identi0ica un evento de instanciaG

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

16(

Especificacin del lenguaje C#

.i la re0erencia ocurre dentro de la clase o estructura donde est( declarado el evento, y )ste se =a declarado sin declaraciones de descriptor de acceso a evento Oevent-accessor-declarationsR O[1".8R, entonces ).$ se procesa exactamente como si $ 0uera un campo de instancia. 2e lo contrario, el resultado es un acceso a evento con una expresi-n de instancia asociada de ).

En caso contrario, se reali1a un intento de procesar ).$ como una invocaci-n del m)todo de extensi-n O[*. . .2R. .i esto da error, ).$ ser( una re0erencia de miembro no v(lida y se producir( un error en tiempo de compilaci-n.

#. .4.1 Eombres simples y nombres de tipos idnticos En un acceso a miembros con la estructura ).$, si ) es un solo identi0icador y el signi0icado de ) como nombre simple Osi%ple-na%eR O[*. .2R es una constante, un campo, una propiedad, una variable local o un par(metro del mismo tipo ?ue el signi0icado de ) como nombre de tipo Ot#pe-na%eR O[3.8R, entonces se permiten los dos posibles signi0icados de ). 8os dos posibles signi0icados de ).$ nunca son ambiguos, puesto ?ue $ necesariamente tiene ?ue ser un miembro del tipo ) en los dos casos. Es decir, la regla sencillamente permite el acceso a los miembros est(ticos y tipos anidados de ) donde, de otra 0orma, se =abr5a producido un error en tiempo de compilaci-n. 'or e$emploG
struct Color { &ublic static readonly Color W"ite + ne, Color(...); &ublic static readonly Color :lac( + ne, Color(...); &ublic Color Com&lement() {...! ! class ' { &ublic Color Color; void V() { Color + Color.:lac(; Color + Color.Com&lement(); ! static void S() { Color c + Color.W"ite; ! !

.. Vield Color o- ty&e Color .. Oe-erences Color.:lac( static member .. $nvo(es Com&lement() on Color -ield

.. Oe-erences Color.W"ite static member

2entro de la clase ', estas repeticiones del identi0icador Color ?ue =acen re0erencia al tipo Color est(n subrayadas, y las ?ue =acen re0erencia al campo Color no. #. .4.2 Fmbi"Gedades "ramaticales 8as producciones para nombre simple Osi%ple-na%eR O[*. .2R y acceso a miembro O%e%-er-accessR O[*. .4R pueden dar lugar a ambigIedades en la gram(tica de las expresiones. 'or e$emplo, la instrucci-nG
V(SD' :E(M));

se puede interpretar como una llamada a V con dos argumentos, S D ' y : E (M). Tambi)n se puede interpretar como una llamada a V con un argumento, ?ue es una llamada a un m)todo gen)rico S con dos argumentos de tipo y un argumento normal. .i se puede anali1ar Oen contextoR una secuencia de s5mbolos como un nombre simple Osi%ple-na%eR O[*. .2R, un acceso a miembro O%e%-er-accessR O[*. .4R o un acceso a miembros de puntero Opointer-%e%-er-accessR O[18. .2R ?ue termine con una lista de argumentos de tipo Ot#pe-ar& %ent-listR O[4.4.1R, se examinar( el s5mbolo Oto6enR ?ue aparece inmediatamente despu)s del s5mbolo Oto6enR de cierre E. .i se trata de
( ) 5 ! / ; . 7 ++ @+

16$

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

8a lista de argumentos de tipo Ot#pe-ar& %ent-listR se retiene como parte del nombre simple Osi%ple-na%eR, del acceso a miembro O%e%-er-accessR o del acceso a miembro de puntero Opointer-%e%-er-accessR y se descarta cual?uier otro an(lisis posible de la secuencia de s5mbolos Oto6enR. 2e lo contrario, lista de argumentos de tipo Ot#pe-ar& %ent-listR no se considera parte del nombre simple Osi%ple-na%eR, del acceso a miembro O%e%-eraccessR o del acceso a miembro de puntero Opointer-%e%-er-accessR incluso si no =ay otro an(lisis posible de la secuencia de s5mbolos Oto6enR. Tenga en cuenta ?ue estas reglas no se aplican al anali1ar una lista de argumentos de tipo Ot#pe-ar& %ent-listR en un espacio de nombres o de tipo na%espace-or-t#pe-na%eR O[3.8R. 8a instrucci-n
V(SD' :E(M));

se interpretar(, de acuerdo con esta regla, como una llamada a V con un argumento, ?ue es una llamada a un m)todo gen)rico S con dos argumentos de tipo y un argumento normal. Cada una de las instrucciones
V(S D ' V(S D ' : E M); : EE M);

se interpretar(n como una llamada a V con dos argumentos. 8a instrucci-n


# + V D ' E <y;

se interpretar( como un operador menor ?ue, mayor ?ue y unario de signo m(s, como si la instrucci-n se =ubiese escrito # + (V D ') E (<y), en lugar de como un nombre simple Osi%ple-na%eR con una lista de argumentos de tipo Ot#pe-ar& %ent-listR seguida de un operador binario de signo m(s. En la instrucci-n
# + y is CD1E < ?;

los s5mbolos Oto6enR CD1E se interpretan como un nombre de espacio de nombres o de tipo Ona%espace-or-t#pena%eR con una lista de argumentos de tipo Ot#pe-ar& %ent-listR. +.#.# E"presiones de in ocacin 7na expresi-n de invocaci-n o llamada Oinvocation-e2pressionR se utili1a para llamar a un m)todo. invocation-e2pression1 pri%ar#-e2pression ( ar& %ent-listopt ) 8a expresi-n primaria Opri%ar#-e2pressionR de una expresi-n de invocaci-n Oinvocation-e2pressionR debe ser un grupo de m)todos o un valor de un tipo delegado Odele&ate-t#peR. .i la expresi-n primaria Opri%ar#-e2pressionR es un grupo de m)todos, la expresi-n de invocaci-n Oinvocation-e2pressionR es una invocaci-n de m)todo O[R. .i la expresi-n primaria Opri%ar#-e2pressionR es un valor de un tipo delegado Odele&ate-t#peR, la expresi-n de invocaci-n Oinvocation-e2pressionR es una invocaci-n de delegado O[R. .i la expresi-n primaria Opri%ar#e2pressionR no es un grupo de m)todos ni un valor de un tipo delegado Odele&ate-t#peR, se produce un error en tiempo de compilaci-n. 8a lista de argumentos Oar& %ent-listR opcional O[*.4.1R proporciona valores o re0erencias de variables para los par(metros del m)todo. El resultado de evaluar una expresi-n de invocaci-n Oinvocation-e2pressionR se clasi0ica como sigueG .i la expresi-n de invocaci-n Oinvocation-e2pressionR invoca un m)todo o un delegado ?ue devuelve void, el resultado es nada. 7na expresi-n ?ue se clasi0ica como nada s-lo est( permitida en el contexto de una expresi-n de instrucci-n Ostate%ent-e2pressionR O[8.#R o como el cuerpo de una expresi-n lambda Ola%-dae2pressionR O[*.14R. En caso contrario, el resultado es un valor del tipo ?ue devuelve el m)todo o el delegado.

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

16"

Especificacin del lenguaje C#

#. . .1 $nvocaciones de mtodo 'ara una invocaci-n de m)todo, la expresi-n primaria Opri%ar#-e2pressionR de la expresi-n de invocaci-n Oinvocation-e2pressionR debe ser un grupo de m)todos. El grupo de m)todos identi0ica el m)todo ?ue se invoca o el con$unto de m)todos sobrecargados entre los cuales se elige un m)todo concreto para invocar. En el Hltimo caso, la determinaci-n del m)todo concreto ?ue se invoca se basa en el contexto suministrado por los tipos de los argumentos de lista de argumentos Oar& %ent-listR. El procesamiento en tiempo de compilaci-n de una invocaci-n de m)todo con la estructura M('), donde M es un grupo de m)todos O?ue posiblemente incluya una lista de argumentos de tipo gt#pe-ar& %ent-listhR y ' es una lista de argumentos Oar& %ent-listR opcional, se compone de los siguientes pasosG .e construye el con$unto de m)todos candidatos para la invocaci-n del m)todo. 'ara cada m)todo V asociado con el grupo de m)todos MG o .i V es un m)todo no gen)rico, V es un candidato cuandoG o
M no tiene una lista de argumentos de tipo y V es aplicable en lo ?ue concierne a ' O[*.4.3.1R.

.i V es un m)todo gen)rico y M no tiene una lista de argumentos de tipo, V es un candidato cuandoG 8a in0erencia de tipo O[*.4.2R se reali1a correctamente, deduciendo una lista de argumentos de tipo para la llamada y 7na ve1 in0eridos, los argumentos de tipo se sustituyen por los par(metros de tipo del m)todo correspondientes, todos los tipos construidos en la lista de par(metros de V cumplen sus restricciones O[4.4.4R y la lista de par(metros de V es aplicable en lo ?ue concierne a ' O[*.4.3.1R.
V tiene el mismo nHmero de par(metros de tipo del m)todo ?ue el suministrado en la lista de

.i V es un m)todo gen)rico y M incluye una lista de argumentos de tipo, V es un candidato cuandoG argumentos de tipo y 8os argumentos de tipo se sustituyen por los par(metros de tipo del m)todo correspondientes, todos los tipos construidos en la lista de par(metros de V cumplen sus restricciones O[4.4.4R y la lista de par(metros de V es aplicable en lo ?ue concierne a ' O[*.4.3.1R.

El con$unto de m)todos candidatos se limita a m)todos procedentes de los tipos m(s derivadosG para cada m)todo C.V del con$unto, donde C es el tipo en el ?ue se declara el m)todo V, se ?uitan del con$unto todos los m)todos declarados en un tipo base de C. .i C es un tipo de clase di0erente de object, se ?uitan del con$unto todos los m)todos declarados en un tipo de inter0a1. OEsta Hltima regla s-lo tiene e0ecto cuando el grupo de m)todos es el resultado de una bHs?ueda de miembros en un par(metro de tipo con una clase base e0ectiva di0erente de ob$ect y un con$unto de inter0aces e0ectivas ?ue no est)n vac5as.R .i el con$unto resultante de m)todos candidatos est( vac5o, no se reali1an los pasos siguientes, y en lugar de eso se reali1a un intento de procesar la invocaci-n como una invocaci-n del m)todo de extensi-n O[*. . .2R. .i esto da error, signi0ica ?ue no existen m)todos aplicables, y se produce un error durante la compilaci-n. El me$or m)todo del con$unto de m)todos candidatos se identi0ica mediante las reglas de resoluci-n de sobrecargas de [*.4.3. .i no puede identi0icarse un m)todo individual me$or, la invocaci-n del m)todo es ambigua, y se produce un error durante la compilaci-n. &l reali1ar la resoluci-n de sobrecarga, se tienen en cuenta los par(metros de un m)todo gen)rico despu)s de sustituir los argumentos de tipo Osuministrados o in0eridosR para los par(metros de tipo del m)todo correspondientes. .e reali1a la validaci-n 0inal del m)todo me$or elegidoG

1('

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

El m)todo se valida en el contexto del grupo de m)todosG si el me$or m)todo es un m)todo est(tico, el grupo de m)todos debe =aberse obtenido de un nombre simple Osi%ple-na%eR o de un acceso a miembro O%e%-er-accessR mediante un tipo. .i el m)todo me$or es un m)todo de instancia, el grupo de m)todos debe =aberse obtenido de un nombre simple Osi%ple-na%eR, de un acceso a miembro O%e%-er-accessR a trav)s de una variable o un valor, o de un acceso a base O-ase-accessR. .i no se cumple ninguna de estas dos condiciones, se producir( un error de compilaci-n. .i el m)todo me$or es un m)todo gen)rico, los argumentos de tipo Osuministrados o in0eridosR se cote$an con las restricciones O[4.4.4R declaradas en el m)todo gen)rico. .i un argumento de tipo no satis0ace las restricciones correspondientes del par(metro de tipo, se generar( un error en tiempo de compilaci-n.

7na ve1 seleccionado un m)todo y validado en tiempo de compilaci-n por los pasos anteriores, se procesa la invocaci-n real en tiempo de e$ecuci-n con0orme a las reglas de invocaci-n de un miembro de 0unci-n explicadas en [*.4.4. El e0ecto intuitivo de las reglas de resoluci-n explicadas es como sigueG para locali1ar el m)todo concreto invocado por una invocaci-n de m)todo, se empie1a con el tipo indicado por la invocaci-n del m)todo y se continHa en la cadena de la =erencia =asta encontrar por lo menos una declaraci-n de m)todo aplicable, accesible y no de invalidaci-n. 2espu)s, se lleva a cabo la in0erencia de tipos y la resoluci-n de sobrecargas en el con$unto de m)todos aplicables, accesibles y de no invalidaci-n declarados en dic=o tipo y se invoca el m)todo seleccionado por este procedimiento. .i no se encuentra ningHn m)todo, pruebe en su lugar a procesar la invocaci-n como una invocaci-n del m)todo de extensi-n. #. . .2 $nvocaciones del mtodo de e2tensin En una invocaci-n de m)todo O[*. . .1R una de las estructurasG e2pr . identificador ( ) e2pr . identificador ( ar&s ) e2pr . identificador D t#pear&s E ( ) e2pr . identificador D t#pear&s E ( ar&s ) si el procesamiento normal de la invocaci-n no encuentra m)todos aplicables, se reali1a un intento de procesar la estructura como una invocaci-n del m)todo de extensi-n. El ob$etivo es buscar el me$or nombre de tipo Ot#pena%eR C, para ?ue se produ1ca la invocaci-n del m)todo est(tico correspondienteG
C . identificador ( e2pr ) C . identificador ( e2pr

ar&s ) ar&s )

C . identificador D t#pear&s E ( e2pr ) C . identificador D t#pear&s E ( e2pr

7n m)todo de extensi-n Ci.Mj es candidato siG


Ci es una clase no gen)rica y no anidada

El nombre de Mj es identifier
Mj es accesible y aplicable cuando se aplica a los argumentos como un m)todo est(tico tal y como se

muestra anteriormente Existe una conversi-n de identidad, de re0erencia o boxing impl5cita desde e2pr al tipo del primer par(metro de Mj.

8a bHs?ueda de C se reali1a de la siguiente 0ormaG

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

1(1

Especificacin del lenguaje C#

Empe1ando por la declaraci-n del espacio de nombres envolvente m(s cercana, siguiendo por cada declaraci-n de espacio de nombres envolvente, y terminando por la unidad de compilaci-n contenedora, se reali1an sucesivos intentos de encontrar un con$unto de candidatos para los m)todos de extensi-nG o .i el espacio de nombres o la unidad de compilaci-n dada contiene directamente declaraciones de tipo no gen)rico Ci con m)todos de extensi-n candidatos Mj, el con$unto de dic=os m)todos de extensi-n es el con$unto candidato. .i los espacios de nombres importado usando directivas de espacio de nombres en el espacio de nombres o la unidad de compilaci-n dada contienen directamente declaraciones de tipo no gen)rico Ci con m)todos de extensi-n candidatos Mj, el con$unto de dic=os m)todos de extensi-n es el con$unto candidato.

.i no se encuentra ningHn con$unto de candidatos en la unidad de compilaci-n o la declaraci-n de espacios de nombres envolventes, se produce un error durante la compilaci-n. En caso contrario, se aplica la resoluci-n de sobrecargas en el con$unto de candidatos tal como se describe en la secci-n O[*.4.3R. .i no se encuentra un m)todo individual me$or, se produce un error en tiempo de compilaci-n.
C es el tipo dentro del ?ue se encuentra declarado el me$or m)todo como un m)todo de extensi-n.

Cuando se utili1a C como destino, la llamada a m)todo se procesa como una invocaci-n de m)todo est(tico O[*.4.4R.

8as reglas anteriores signi0ican ?ue los m)todos de instancia tienen prioridad sobre los m)todos de extensi-n, ?ue los m)todos de extensi-n disponibles en declaraciones de espacios de nombres internos tienen prioridad sobre los m)todos de extensi-n disponibles en las declaraciones de espacios de nombres externos, y ?ue los m)todos de extensi-n declarados directamente en un espacio de nombres tienen prioridad sobre los importados dentro del mismo espacio de nombres con una directiva using de espacio de nombres. 'or e$emploG
&ublic static class ) { &ublic static void V(t"is object obj &ublic static void V(t"is object obj ! class ' { ! class : { &ublic void V(int i) { ! ! class C { &ublic void V(object obj) { ! ! class I { static void 1est(' a : b C c) { a.V(2); .. ).V(object a.V(""ello"); .. ).V(object b.V(2); b.V(""ello"); c.V(2); c.V(""ello"); ! ! .. :.V(int) .. ).V(object .. C.V(object) .. C.V(object) int i) { ! string s) { !

int) string) string)

1(2

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

En el e$emplo, el m)todo de : tiene prioridad sobre el primer m)todo de extensi-n, y el m)todo de C tiene prioridad sobre ambos m)todos de extensi-n.
&ublic static class C { &ublic static void V(t"is int i) { Console.WriteLine("C.V({3!)" &ublic static void S(t"is int i) { Console.WriteLine("C.S({3!)" &ublic static void H(t"is int i) { Console.WriteLine("C.H({3!)" ! i); ! i); ! i); !

names&ace N2 { &ublic static class 6 { &ublic static void V(t"is int i) { Console.WriteLine("6.V({3!)" &ublic static void S(t"is int i) { Console.WriteLine("6.S({3!)" ! ! names&ace N8 { using N2; &ublic static class ) { &ublic static void V(t"is int i) { Console.WriteLine(").V({3!)" ! class 1est { static void Main(string45 args) { 2.V(); 8.S(); 9.H(); ! ! !

i); ! i); !

i); !

El resultado de este e$emplo esG


).V(2) 6.S(8) C.H(9) 6.S tiene prioridad sobre C.S, y ).V tiene prioridad sobre ambos, 6.V y C.V.

#. . .3 $nvocaciones de dele"ados 'ara una invocaci-n de delegado, la expresi-n primaria Opri%ar#-e2pressionR de la expresi-n de invocaci-n Oinvocation-e2pressionR debe ser un valor de un tipo delegado Odele&ate-t#peR. &dem(s, considerando ?ue el tipo delegado Odele&ate-t#peR debe ser un miembro de 0unci-n con la misma lista de par(metros ?ue el tipo delegado Odele&ate-t#peR, )ste debe ser aplicable O[*.4.3.1R con respecto a la lista de argumentos Oar& %ent-listR de expresi-n de invocaci-n Oinvocation-e2pressionR. El procesamiento en tiempo de e$ecuci-n de una invocaci-n de delegado con la estructura 6('), donde 6 es una expresi-n primaria Opri%ar#-e2pressionR de un tipo delegado y ' es una lista de argumentos Oar& %ent-listR opcional, se compone de los siguientes pasosG .e evalHa 6. .i esta evaluaci-n da lugar a una excepci-n, no se e$ecutan nuevos pasos. .e comprueba la valide1 del valor de 6. .i el valor de 6 es null, se inicia una excepci-n System.NullOe-erence)#ce&tion y no se e$ecutan nuevos pasos.

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

1(3

Especificacin del lenguaje C#

En otro caso, 6 es una re0erencia a una instancia de delegado. 8as llamadas a miembros de 0unci-n O[*.4.4R se reali1an en cada una de las entidades invocables de la lista de llamadas del delegado. En el caso de las entidades invocables y ?ue constan de una instancia y de un m)todo de instancia, la instancia para la invocaci-n es la contenida en la entidad a la ?ue se puede llamar.

+.#.$ 'cceso a elementos> 7n acceso a elementos Oele%ent-accessR consta de una expresi-n primaria sin creaci-n de matrices Opri%ar#-noarra#-creation-e2pressionR, seguida de un to6en P4Q, una lista de expresiones Oe2pression-listR y un to6en P5Q. 7na lista de expresiones Oe2pression-listR consta de una o m(s expresiones Oe2pressionsR, separadas por comas. ele%ent-access1 pri%ar#-no-arra#-creation-e2pression 4 e2pression-list 5 e2pression-list1 e2pression e2pression-list

e2pression

.i la expresi-n primaria sin creaci-n de matrices Opri%ar#-no-arra#-creation-e2pressionR de un acceso a elementos Oele%ent-accessR es un valor de tipo matricial Oarra#-t#peR, el acceso a elementos Oele%ent-accessR es un acceso a matri1 O[*. .#.1R. 2e lo contrario, la expresi-n primaria sin creaci-n de matrices Opri%ar#-no-arra#creation-e2pressionR debe ser una variable o un valor de un tipo de clase, estructura o inter0a1 ?ue tenga uno o m(s miembros indi1adores, en cuyo caso el acceso a elementos Oele%ent-accessR es un acceso a indi1ador O[*. .#.2R. #. .6.1 Fcceso a matrices 'ara un acceso a matrices, la expresi-n primaria sin creaci-n de matrices Opri%ar#-no-arra#-creatione2pressionR del acceso a elementos Oele%ent-accessR debe ser un valor de tipo matricial Oarra#-t#peR. El nHmero de expresiones de la lista de expresiones Oe2pression-listR debe ser el mismo ?ue el rango del tipo matricial Oarra#-t#peR, y cada expresi-n debe ser de tipo int, uint, long, ulong o de un tipo ?ue pueda convertirse de 0orma impl5cita a uno o m(s de estos tipos. El resultado de la evaluaci-n de un acceso a matri1 es una variable del tipo de elementos de la matri1, es decir, el elemento de matri1 seleccionado por los valores de las expresiones en la lista de expresiones Oe2pression-listR. El procesamiento en tiempo de e$ecuci-n de un acceso a matri1 con la estructura *4'5 Odonde * es una expresi-n primaria sin creaci-n de matrices Opri%ar#-no-arra#-creation-e2pressionR de un tipo matricial Oarra#t#peR y ' es una lista de expresiones Oe2pression-listR se compone de los siguientes pasosG .e evalHa *. .i esta evaluaci-n da lugar a una excepci-n, no se e$ecutan nuevos pasos. 8as expresiones de 5ndice de la lista de expresiones Oe2pression-listR se evalHan por orden, de i1?uierda a derec=a. 2espu)s de la evaluaci-n de cada expresi-n de 5ndice, se reali1a una conversi-n impl5cita O[#.1R a uno de los tipos siguientesG int, uint, long, ulong. .e elige el primer tipo de esta lista para el cual existe una conversi-n impl5cita. 'or e$emplo, si la expresi-n de 5ndice es de tipo s"ort, se lleva a cabo una conversi-n impl5cita a int, puesto ?ue son posibles conversiones impl5citas de s"ort a int y de s"ort a long. .i la evaluaci-n de una expresi-n de 5ndice o de la conversi-n impl5cita posterior causa una excepci-n, no se evalHan otras expresiones de 5ndice y no se e$ecutan nuevos pasos. .e comprueba la valide1 del valor de *. .i el valor de * es null, se inicia una excepci-n System.NullOe-erence)#ce&tion y no se e$ecutan nuevos pasos. .e compara otra ve1 el valor de cada expresi-n de lista de expresiones Oe2pression-listR con los l5mites reales de cada dimensi-n de la instancia matricial a ?ue =ace re0erencia *. .i uno o m(s valores no est(n

1(#

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

comprendidos en el intervalo, se inicia una excepci-n System.$nde#%ut%-Oange)#ce&tion y no se e$ecutan nuevos pasos. .e calcula la ubicaci-n del elemento de matri1 dada por la expresi-n o expresiones de 5ndice, ?ue pasa a ser el resultado del acceso a matri1.

#. .6.2 Fcceso al indi%ador 'ara un acceso a indi1ador, la expresi-n primaria sin creaci-n de matrices Opri%ar#-no-arra#-creatione2pressionR del acceso a elementos Oele%ent-accessR debe ser una variable o un valor de un tipo de clase, estructura o inter0a1, y este tipo debe implementar uno o m(s indi1adores ?ue sean aplicables con respecto a la lista de expresiones Oe2pression-listR del acceso a elementos Oele%ent-accessR. El procesamiento en tiempo de compilaci-n de un acceso a indi1ador de la 0orma *4'5, donde * es una expresi-n primaria sin creaci-n de matrices Opri%ar#-no-arra#-creation-e2pressionR de un tipo 1 de clase, estructura o inter0a1, y ' es una lista de expresiones Oe2pression-listR, se compone de los siguientes pasosG .e construye el con$unto de indi1adores suministrados por 1. El con$unto est( 0ormado por todos los indi1adores declarados en 1 o un tipo base de 1 ?ue no son declaraciones override y est(n accesibles en el contexto actual O[3. R. El con$unto se reduce a a?uellos indi1adores ?ue sean aplicables y no est)n ocultos por otros indi1adores. 8as reglas siguientes se aplican a todos los indi1adores S.$ del con$unto, donde S es el tipo en el ?ue se declara el indi1ador $G o o o .i $ no es aplicable con respecto a ' O[*.4.3.1R, entonces $ se ?uita del con$unto. .i $ es aplicable con respecto a ' O[*.4.3.1R, entonces todos los indi1adores declarados en un tipo base de S se ?uitan del con$unto. .i $ es aplicable con respecto a ' O[*.4.3.1R y S es un tipo de clase distinto de object, todos los indi1adores declarados en una inter0a1 se ?uitan del con$unto.

.i el con$unto resultante de indi1adores candidatos est( vac5o, entonces no existen indi1adores aplicables, y se produce un error durante la compilaci-n. El me$or indi1ador del con$unto de indi1adores candidatos se identi0ica mediante las reglas de resoluci-n de sobrecargas de [*.4.3. .i no puede identi0icarse un indi1ador individual me$or, el acceso a indi1ador es ambiguo y se produce un error durante la compilaci-n. 8as expresiones de 5ndice de la lista de expresiones Oe2pression-listR se evalHan por orden, de i1?uierda a derec=a. El resultado de procesar el acceso a indi1ador es una expresi-n clasi0icada como un acceso a indi1ador. 8a expresi-n de acceso a indi1ador =ace re0erencia al indi1ador determinado en el paso anterior, y tiene una expresi-n de instancia asociada de * y una lista de argumentos asociada de '.

2ependiendo del contexto en ?ue se utilice, un acceso a indi1ador provoca la invocaci-n del descriptor de acceso get O&et-accessorR o del descriptor de acceso set Oset-accessorR del indi1ador. .i el acceso a indi1ador es el destino de una asignaci-n, se invoca el descriptor de acceso set Oset-accessorR para asignar un nuevo valor O[*.1#.1R. En todos los dem(s casos, se invoca el descriptor de acceso a get O&et-accessorR para obtener el valor actual O[*.1.1R. +.#.+ 'cceso a t?is 7n acceso a t=is Othis-accessR consta de la palabra reservada t"is. this-access1
t"is

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

1(!

Especificacin del lenguaje C#

El acceso a t=is Othis-accessR s-lo se permite en el blo?ue O-loc3R de un constructor de instancia, un m)todo de instancia o un descriptor de acceso a una instancia. Tiene uno de los siguientes signi0icadosG Cuando se utili1a t"is en una expresi-n primaria Opri%ar#-e2pressionR dentro de un constructor de instancia de una clase, )sta se clasi0ica como un valor. El tipo del valor es el tipo de instancia O[1".3.1R de la clase dentro de la cual ocurre la utili1aci-n y el valor es una re0erencia al ob$eto ?ue se construye. Cuando se utili1a t"is en una expresi-n primaria Opri%ar#-e2pressionR dentro de un m)todo de instancia o de un descriptor de acceso a instancia de una clase, )sta se clasi0ica como un valor. El tipo del valor es el tipo de instancia O[1".3.1R de la clase dentro de la cual ocurre la utili1aci-n, y el valor es una re0erencia al ob$eto para el cual se invoca el m)todo o el descriptor de acceso. Cuando se utili1a t"is en una expresi-n primaria Opri%ar#-e2pressionR dentro de un constructor de instancia de una estructura, )sta se clasi0ica como una variable. El tipo de la variable es el tipo de instancia O[1".3.1R de la estructura dentro de la cual ocurre la utili1aci-n y la variable representa la estructura ?ue se construye. 8a variable t"is de un constructor de instancia de una estructura se comporta exactamente igual ?ue un par(metro out del tipo structV esto signi0ica concretamente ?ue la variable debe estar asignada de0initivamente en todas las rutas de e$ecuci-n del constructor de instancia. Cuando se utili1a t"is en una expresi-n primaria Opri%ar#-e2pressionR dentro de un m)todo de instancia o un descriptor de acceso a instancia de una estructura, )sta se clasi0ica como una variable. El tipo de la variable es el tipo de instancia O[1".3.1R de la estructura donde se da el uso. o .i el m)todo o el descriptor de acceso no es un iterador O[1".14R, la variable t"is representa la estructura para la ?ue se invoca el m)todo o el descriptor de acceso, y se comporta exactamente igual ?ue el par(metro re- del tipo struct. .i el m)todo o el descriptor de acceso no es un iterador, la variable t"is representa una copia de la estructura para la ?ue se invoca el m)todo o el descriptor de acceso, y se comporta exactamente igual ?ue el par(metro de valor del tipo struct.

El uso de t"is en una expresi-n primaria Opri%ar#-e2pressionR dentro de un contexto distinto de los mencionados anteriormente, produce un error en tiempo de compilaci-n. En particular, no es posible =acer re0erencia a t"is en un m)todo est(tico, en un descriptor de acceso a una propiedad est(tica o en un iniciali1ador de variable Ovaria-le-initiali0erR de una declaraci-n de campo. +.#.- 'cceso a bases 7n acceso a base O-ase-accessR est( 0ormado por la palabra reservada base seguida de un s5mbolo Oto6enR P.Q y un identi0icador, o de una lista de expresiones Oe2pression-listR encerrada entre corc=etesG -ase-access1
base . identificador base 4 e2pression-list 5

7n acceso a base O-ase-accessR permite obtener acceso a miembros de clase base ?ue est(n ocultos por miembros de nombres similares en la clase o estructura actuales. El acceso a base O-ase-accessR s-lo se permite en el blo?ue O-loc3R de un constructor de instancia, un m)todo de instancia o un descriptor de acceso a una instancia. .i base.$ ocurre en una clase o una estructura, $ debe denotar un miembro de la clase base de dic=a clase o estructura. 2e igual manera, si base4)5 ocurre en una clase, debe existir un indi1ador aplicable en la clase base. En tiempo de compilaci-n, las expresiones de acceso a base O-ase-accessR con la estructura base.$ y base4)5 se evalHan exactamente igual ?ue si se escribieran ((:)t"is).$ y ((:)t"is)4)5, donde : es la clase base de la clase o estructura en ?ue tiene lugar la construcci-n. 'or lo tanto, base.$ y base4)5 corresponden a t"is.$ y t"is4)5, con la excepci-n de ?ue t"is se considera como una instancia de la clase base.

1(6

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

Cuando un acceso a base O-ase-accessR =ace re0erencia a un miembro de 0unci-n virtual Oun m)todo, una propiedad o un indi1adorR, cambia la 0unci-n ?ue se debe invocar en tiempo de e$ecuci-n O[*.4.4R. El miembro de 0unci-n ?ue se invoca se determina buscando la implementaci-n m(s derivada O[1".#.3R del miembro de 0unci-n con respecto a : Oen lugar de la relativa al tipo de tiempo de e$ecuci-n de t"is, como ser5a normal en un acceso distinto del acceso a baseR. 'or lo tanto, dentro de un override de un miembro de 0unci-n virtual, un acceso a base O-ase-accessR puede utili1arse para llamar a la implementaci-n =eredada del miembro de 0unci-n. .i el miembro de 0unci-n al ?ue =ace re0erencia un acceso a base O-ase-accessR es abstracto, se producir( un error en tiempo de compilaci-n. +.#.. ,peradores postfijos de incremento y decremento post-incre%ent-e2pression1 pri%ar#-e2pression << post-decre%ent-e2pression1 pri%ar#-e2pression == El operando de una operaci-n de su0i$o de incremento o decremento debe ser una expresi-n clasi0icada como una variable, un acceso a propiedad o un acceso a indi1ador. El resultado de la operaci-n es un valor del mismo tipo ?ue el operando. .i el operando de una operaci-n de post0i$o de incremento o decremento es una propiedad o un acceso a indi1ador, la propiedad o el indi1ador debe tener tanto un descriptor de acceso get como set. .i no es )ste el caso, se produce un error en tiempo de compilaci-n. 8a resoluci-n de sobrecargas de operadores unarios O[*.2.3R se aplica para seleccionar una implementaci-n de operador concreta. Existen operadores prede0inidos << y == para los tipos siguientesG sbyte, byte, s"ort, us"ort, int, uint, long, ulong, c"ar, -loat, double, decimal y cual?uier tipo enum. 8os operadores prede0inidos << devuelven el valor generado al sumar 1 al operando y los operadores prede0inidos == devuelven el valor generado al restarle 1. En un contexto c"ec(ed, si el resultado de esta suma o resta se encuentra 0uera del intervalo del tipo del resultado y el tipo del resultado es un tipo integral o enum, se inicia una excepci-n System.%ver-lo,)#ce&tion. El procesamiento en tiempo de e$ecuci-n de una operaci-n de post0i$o de incremento o decremento de la 0orma #<< o #== consta de los pasos siguientesG .i # se clasi0ica como una variableG o o o o o o .e evalHa # para producir la variable. .e guarda el valor de #. .e invoca el operador seleccionado con el valor guardado de # como argumento. El valor devuelto por el operador se almacena en la ubicaci-n dada por la evaluaci-n de #. El valor guardado de # es el resultado de la operaci-n. .e evalHa la expresi-n de instancia Osi # no es staticR y la lista de argumentos Osi # es un acceso a indi1adorR asociada con #, y el resultado se utili1a en las posteriores invocaciones de descriptor de acceso get y set. .e invoca el descriptor de acceso get de # y se guarda el valor devuelto. .e invoca el operador seleccionado con el valor guardado de # como argumento.

.i # se clasi0ica como una propiedad o un acceso a indi1adorG

o o

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

1((

Especificacin del lenguaje C#

o o

.e invoca el descriptor de acceso set de # con el valor devuelto por el operador como su argumento value. El valor guardado de # es el resultado de la operaci-n.

8os operadores << y == admiten la notaci-n de pre0i$os O[*.#. R. El resultado de #<< o #== es el valor de # antes de la operaci-n, mientras ?ue el resultado de <<# o ==# es el valor de # desp ?s de la operaci-n. En uno u otro caso, # tiene el mismo valor despu)s de la operaci-n. 7na implementaci-n de o&erator << u o&erator == puede invocarse mediante la notaci-n de post0i$o o pre0i$o. 4o es posible contar con implementaciones de operador independientes para las dos notaciones. +.#.10 El operador ne@ El operador ne, se utili1a para crear nuevas instancias de tipos. Existen tres 0ormas de expresiones ne,G 8as expresiones de creaci-n de ob$etos se utili1an para crear nuevas instancias de tipos de clase y tipos de valor. Expresiones de creaci-n de matrices, ?ue se utili1an para crear nuevas instancias de tipos de matri1. Expresiones de creaci-n de delegados, ?ue se utili1an para crear nuevas instancias de tipos delegados.

El operador ne, implica la creaci-n de una instancia de un tipo, pero no necesariamente la asignaci-n din(mica de memoria. En concreto, las instancias de tipos de valor no re?uieren m(s memoria ?ue las variables en las ?ue residen, por lo ?ue no se llevan a cabo asignaciones din(micas cuando se usa ne, para crear instancias de tipos de valor. #. .17.1 &2presiones de creacin de ob=etos 7na expresi-n de creaci-n de ob$etos Oo->ect-creation-e2pressionR se utili1a para crear una nueva instancia de un tipo de clase Oclass-t#peR o un tipo de valor Oval e-t#peR. o->ect-creation-e2pression1 ne, t#pe ( ar& %ent-listopt ) o->ect-or-collection-initiali0eropt ne, t#pe o->ect-or-collection-initiali0er o->ect-or-collection-initiali0er1 o->ect-initiali0er collection-initiali0er El tipo Ot#peR de una expresi-n de creaci-n de ob$etos Oo->ect-creation-e2pressionR debe ser un tipo de clase Oclass-t#peR, un tipo de valor Oval e-t#peR o un tipo de par(metro Ot#pe-para%eterR. El tipo Ot#peR no puede ser un tipo de clase Oclass-t#peR abstract. 8a lista de argumentos Oar& %ent-listR opcional O[*.4.1R s-lo est( permitida si el tipo Ot#peR es un tipo de clase Oclass-t#peR o un tipo struct Ostr ct-t#peR. 7na expresi-n de creaci-n de ob$etos puede omitir la lista de argumentos de constructores y los par)ntesis de cierre siempre ?ue incluya un iniciali1ador de ob$eto o de colecci-n. /mitir la lista de argumentos de constructores y los par)ntesis de cierre es e?uivalente a especi0icar una lista de argumentos vac5a. El procesamiento de una expresi-n de creaci-n de ob$etos ?ue incluye un iniciali1ador de ob$eto o de colecci-n consiste en procesar primero el constructor de instancias y, a continuaci-n, el miembro de las iniciali1aciones de elemento especi0icadas por el iniciali1ador de ob$eto O[*. .1".2R o el iniciali1ador de colecci-n O[*. .1".3R.

1($

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

El procesamiento en tiempo de compilaci-n de una expresi-n de creaci-n de ob$etos Oo->ect-creatione2pressionR de la 0orma ne, 1('), donde 1 es un tipo de clase Oclass-t#peR o un tipo de valor Oval e-t#peR y ' es una lista de argumentos Oar& %ent-listR opcional, se compone de los siguientes pasosG .i 1 es un tipo de valor Oval e-t#peR y ' no est( presenteG o 8a expresi-n de creaci-n de ob$etos Oo->ect-creation-e2pressionR es una invocaci-n de constructor predeterminado. El resultado de la expresi-n de creaci-n de ob$etos Oo->ect-creation-e2pressionR es un valor de tipo 1, en concreto, el valor predeterminado de 1 segHn se de0ine en [4.1.1. .i no se =a especi0icado ninguna restricci-n de tipo ni de constructor O[1".1. R para 1, se produce un error durante la compilaci-n. El resultado de la expresi-n de creaci-n de ob$etos Oo->ect-creation-e2pressionR es un valor del tipo en tiempo de e$ecuci-n al ?ue est( enla1ado el par(metro de tipo, en concreto el resultado de invocar el constructor predeterminado de dic=o tipo. El tipo en tiempo de e$ecuci-n puede ser un tipo de re0erencia o un tipo de valor. .i 1 es un tipo de clase Oclass-t#peR abstract, se produce un error en tiempo de compilaci-n. 8os constructores de instancia ?ue se invoca se determina con las reglas de resoluci-n de sobrecargas de [*.4.3. El con$unto de constructores de instancia candidatos est( 0ormado por todos los constructores de instancia accesibles declarados en 1, ?ue son aplicables con respecto a ' O[*.4.3.1R. .i el con$unto de constructores de instancia candidatos est( vac5o o no es posible identi0icar un solo constructor de instancia id-neo, se produce un error en tiempo de compilaci-n. El resultado de la expresi-n de creaci-n de ob$etos Oo->ect-creation-e2pressionR es un valor de tipo 1, en concreto, el valor generado al invocar el constructor de instancia determinado en el paso anterior.

En caso contrario, si 1 es un par(metro de tipo Ot#pe-para%eterR y ' no est( presenteG o o

En caso contrario, si 1 es un tipo de clase Oclass-t#peR o un tipo struct Ostr ct-t#peRG o o

2e lo contrario, la expresi-n de creaci-n de ob$etos Oo->ect-creation-e2pressionR no es v(lida y se produce un error durante la compilaci-n.

El procesamiento en tiempo de compilaci-n de una expresi-n de creaci-n de ob$etos Oo->ect-creatione2pressionR con la estructura ne, 1('), donde 1 es un tipo de clase Oclass-t#peR o un tipo struct Ostr ct-t#peR y ' es una lista de argumentos Oar& %ent-listR opcional, se compone de los siguientes pasosG .i 1 es un tipo de clase Oclass-t#peRG o .e asigna una nueva instancia de la clase 1. .i no =ay memoria disponible su0iciente para asignar la nueva instancia, se inicia una excepci-n System.%ut%-Memory)#ce&tion y no se e$ecutan m(s pasos. Todos los campos de la nueva instancia se iniciali1an con sus valores predeterminados O[ .2R. 8os constructores de instancia se invoca con0orme a las reglas de invocaci-n de un miembro de 0unci-n O[*.4.4R. .e pasa autom(ticamente al constructor de instancia una re0erencia a la instancia reci)n asignada y se posibilita el acceso a dic=a instancia como t"is desde el constructor. .e crea una instancia de tipo 1 mediante la asignaci-n de una variable local temporal. 2ado ?ue se re?uiere un constructor de instancia de un tipo struct Ostr ct-t#peR para asignar de0initivamente un valor a cada campo de la instancia ?ue se crea, no es necesaria una iniciali1aci-n de la variable temporal.

o o

.i 1 es un tipo struct Ostr ct-t#peRG o

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

1("

Especificacin del lenguaje C#

8os constructores de instancia se invoca con0orme a las reglas de invocaci-n de un miembro de 0unci-n O[*.4.4R. .e pasa autom(ticamente al constructor de instancia una re0erencia a la instancia reci)n asignada y se posibilita el acceso a dic=a instancia como t"is desde el constructor.

#. .17.2 $niciali%adores de ob=eto 7n iniciali-ador de o/1eto especi0ica valores para cero o m(s campos o propiedades de un ob$eto. o->ect-initiali0er1 { %e%-er-initiali0er-listopt ! { %e%-er-initiali0er-list ! %e%-er-initiali0er-list1 %e%-er-initiali0er %e%-er-initiali0er-list

%e%-er-initiali0er

%e%-er-initiali0er1 identifier @ initiali0er-val e initiali0er-val e1 e2pression o->ect-or-collection-initiali0er 7n iniciali1ador de ob$eto se compone de una secuencia de iniciali1adores de miembro, ?ue 0iguran entre los to6ens P{Q y P!Q y separados por comas. Cada iniciali1ador de miembro debe nombrar una propiedad o campo accesible del ob$eto ?ue se iniciali1a, seguido por un signo igual y una expresi-n o un iniciali1ador de ob$eto o colecci-n. Es un error ?ue un iniciali1ador de ob$eto incluya m(s de un iniciali1ador de miembro para la misma propiedad o campo. 4o es posible ?ue un iniciali1ador de ob$eto =aga re0erencia a un ob$eto reci)n creado ?ue se est( iniciali1ando. 7n iniciali1ador de miembro ?ue especi0ica una expresi-n despu)s de un signo igual se procesa igual ?ue una asignaci-n O[*.1#.1R al campo o propiedad. 7n iniciali1ador de miembro ?ue especi0ica un iniciali1ador de ob$eto despu)s de un signo igual es un iniciali-ador de o/1eto anidado, es decir una iniciali1aci-n de un ob$eto incrustado. En lugar de asignar un nuevo valor al campo o propiedad, las asignaciones de un iniciali1ador de ob$eto anidado se tratan como asignaciones a miembros del campo o propiedad. 8os iniciali1adores de ob$etos anidados no se pueden aplicar a propiedades con un tipo de valor, o a campos de s-lo lectura con un tipo de valor. 7n iniciali1ador de miembro ?ue especi0ica un iniciali1ador de colecci-n despu)s de un signo igual es una iniciali1aci-n de una colecci-n incrustada. En lugar de asignar una nueva colecci-n al campo o propiedad, los elementos dados en un iniciali1ador se agregan a la colecci-n re0erenciada por el campo o propiedad. El campo o la propiedad deben ser un tipo de colecci-n ?ue cumpla los re?uisitos especi0icados en la secci-n [*. .1".3. 8a siguiente clase representa un punto con dos coordenadasG
&ublic class *oint { int # y; &ublic int I { get { return #; ! set { # + value; ! ! &ublic int ` { get { return y; ! set { y + value; ! ! !

7na instancia de *oint se puede crear e iniciali1ar de la siguiente 0ormaG


*oint a + ne, *oint { I + 3 ` + 2 !;

?ue tiene el mismo e0ecto ?ue

1$'

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases *oint \\a.I \\a.` *oint \\a + ne, *oint(); + 3; + 2; a + \\a;

donde \\a es una variable temporal inaccesible e invisible en caso contrario. 8a siguiente clase representa un rect(ngulo creado a partir de dos puntosG
&ublic class Oectangle { *oint &2 &8; &ublic *oint *2 { get { return &2; ! set { &2 + value; ! ! &ublic *oint *8 { get { return &8; ! set { &8 + value; ! ! !

7na instancia de Oectangle se puede crear e iniciali1ar de la siguiente 0ormaG


Oectangle r + ne, Oectangle { *2 + ne, *oint { I + 3 ` + 2 ! *8 + ne, *oint { I + 8 ` + 9 ! !;

?ue tiene el mismo e0ecto ?ue


Oectangle \\r + ne, Oectangle(); *oint \\&2 + ne, *oint(); \\&2.I + 3; \\&2.` + 2; \\r.*2 + \\&2; *oint \\&8 + ne, *oint(); \\&8.I + 8; \\&8.` + 9; \\r.*8 + \\&8; Oectangle r + \\r;

donde \\r, \\&2 y \\&8 son variables temporales ?ue, en caso contrario, son inaccesibles e invisibles. .i el constructor de Oectangle asigna las dos instancias *oint incrustadas
&ublic class Oectangle { *oint &2 + ne, *oint(); *oint &8 + ne, *oint(); &ublic *oint *2 { get { return &2; ! ! &ublic *oint *8 { get { return &8; ! ! !

el siguiente constructor se puede utili1ar para iniciali1ar las instancias *oint incrustadas en lugar de asignar nuevas instanciasG
Oectangle r + ne, Oectangle { *2 + { I + 3 ` + 2 ! *8 + { I + 8 ` + 9 ! !;

?ue tiene el mismo e0ecto ?ue


Oectangle \\r + ne, Oectangle(); \\r.*2.I + 3; \\r.*2.` + 2; \\r.*8.I + 8; \\r.*8.` + 9; Oectangle r + \\r;

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

1$1

Especificacin del lenguaje C#

#. .17.3 $niciali%adores de coleccin 7n iniciali1ador de colecci-n especi0ica los elementos de una colecci-n. collection-initiali0er1 { ele%ent-initiali0er-list ! { ele%ent-initiali0er-list ! ele%ent-initiali0er-list1 ele%ent-initiali0er ele%ent-initiali0er-list ele%ent-initiali0er1 non-assi&n%ent-e2pression { e2pression-list ! 7n iniciali1ador de colecci-n se compone de una secuencia de iniciali1adores de elemento, ?ue 0iguran entre los to6ens P{Q y P!Q y separados por comas. Cada iniciali1ador de elemento especi0ica un elemento ?ue se va a agregar al ob$eto de colecci-n ?ue se iniciali1a, y se compone de una lista de expresiones entre los to6ens { y ! y separadas por comas. 7n iniciali1ador de elemento de una sola expresi-n se puede escribir sin corc=etes, pero en ese caso no puede ser una expresi-n de asignaci-n, con el 0in de evitar ambigIedad con los iniciali1adores de miembro. 8a producci-n de expresiones de no asignaci-n Onon-assi&n%ent-e2pressionR se de0ine en la secci-n [*.1*. & continuaci-n, se muestra un e$emplo de una expresi-n de creaci-n de ob$eto ?ue incluye un iniciali1ador de colecci-nG
ListDintE digits + ne, ListDintE { 3 2 8 9 J K X M Y L !;

ele%ent-initiali0er

El ob$eto de colecci-n al ?ue se aplica un iniciali1ador de colecci-n debe ser un tipo ?ue implemente System.Collections.$)numerable o se producir( un error durante la compilaci-n. 'ara cada elemento especi0icado en orden, el iniciali1ador de colecci-n invoca un m)todo 'dd en el ob$eto de destino con la lista de expresiones del iniciali1ador de elemento como lista de argumentos, aplicando una resoluci-n de sobrecarga normal para cada invocaci-n. 'or tanto, el ob$eto de colecci-n debe contener un m)todo 'dd aplicable para cada iniciali1ador de elemento. 8a siguiente clase representa un contacto con un nombre y una lista de nHmeros de tel)0onoG
&ublic class Contact { string name; ListDstringE &"oneNumbers + ne, ListDstringE(); &ublic string Name { get { return name; ! set { name + value; ! ! &ublic ListDstringE *"oneNumbers { get { return &"oneNumbers; ! ! ! ListDContactE se puede crear e iniciali1ar de la siguiente 0ormaG var contacts + ne, ListDContactE { ne, Contact { Name + "C"ris Smit"" *"oneNumbers + { "83X=KKK=3232" "J8K=YY8=Y3Y3" ! ! ne, Contact { Name + ":ob Harris" *"oneNumbers + { "XK3=KKK=32LL" ! ! !;

?ue tiene el mismo e0ecto ?ue

1$2

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases var \\clist + ne, ListDContactE(); Contact \\c2 + ne, Contact(); \\c2.Name + "C"ris Smit""; \\c2.*"oneNumbers.'dd("83X=KKK=3232"); \\c2.*"oneNumbers.'dd("J8K=YY8=Y3Y3"); \\clist.'dd(\\c2); Contact \\c8 + ne, Contact(); \\c8.Name + ":ob Harris"; \\c8.*"oneNumbers.'dd("XK3=KKK=32LL"); \\clist.'dd(\\c8); var contacts + \\clist;

donde \\clist

\\c2 y \\c8 son variables temporales ?ue, en caso contrario, son inaccesibles e invisibles.

#. .17.4 &2presiones de creacin de matrices 'ara crear una nueva instancia de un tipo matricial Oarra#-t#peR, se utili1a una expresi-n de creaci-n de matrices Oarra#-creation-e2pressionR. arra#-creation-e2pression1 ne, non-arra#-t#pe 4 e2pression-list 5 ran3-specifiersopt arra#-initiali0eropt ne, arra#-t#pe arra#-initiali0er ne, ran3-specifier arra#-initiali0er 7na expresi-n de creaci-n de matrices de la primera 0orma asigna una instancia de matri1 del tipo ?ue se obtiene al eliminar cada una de las expresiones individuales de la lista de expresiones. 'or e$emplo, la expresi-n de creaci-n de matrices ne, int423 835 produce una instancia de matri1 de tipo int4 5, y la expresi-n ne, int42354 5 produce una matri1 de tipo int454 5. Cada expresi-n de la lista de expresiones debe ser de tipo int, uint, long o ulong, o bien de un tipo ?ue pueda convertirse impl5citamente a uno o m(s de estos tipos. El valor de cada expresi-n determina la longitud de la dimensi-n correspondiente en la instancia de matri1 reci)n asignada. 2ado ?ue la longitud de la dimensi-n de matri1 no puede ser negativa, si existe una expresi-n constante Oconstant-e2pressionR con un valor negativo en la lista de expresiones, se producir( un error en tiempo de compilaci-n. Excepto en un contexto no seguro O[18.1R, la 0orma de las matrices no se especi0ica. .i una expresi-n de creaci-n de matri1 de la primera 0orma incluye un iniciali1ador de matri1, cada expresi-n de la lista de expresiones debe ser una constante, y las longitudes de rango y dimensi-n especi0icadas por la lista de expresiones deben coincidir con las del iniciali1ador. En una expresi-n de creaci-n de matrices de la segunda o tercera 0orma, el rango del tipo de matri1 especi0icado o el especi0icador de rango debe coincidir con el del iniciali1ador. 8as longitudes de las dimensiones individuales se in0ieren del nHmero de elementos en cada uno de los niveles de anidamiento correspondientes del iniciali1ador de matri1. 'or lo tanto, la expresi-n
ne, int4 5 {{3 ne, int49 2! {8 2! 9! {8 {J 9! K!! {J K!!

se corresponde exactamente con


85 {{3

7na expresi-n de creaci-n de matrices de la tercera 0orma se conoce como e.presi,n de creaci,n de atrices con asignaci,n de tipo i plcita. Es similar a la segunda 0orma, excepto en ?ue el tipo de elemento de la matri1 no se da expl5citamente, sino ?ue se determina como el me$or tipo comHn O[*.4.2.13R del con$unto de expresiones del iniciali1ador de matri1. 'ara una matri1 multidimensional, es decir, una donde el especi0icador de rango Oran3-specifierR contiene al menos una coma, este con$unto comprende todas las expresiones Oe2pressionsR encontradas en los iniciali1adores de matrices Oarra#-initiali0ersR anidados. 8os iniciali1adores de matrices se describen m(s detalladamente en [12.#.

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

1$3

Especificacin del lenguaje C#

El resultado de evaluar una expresi-n de creaci-n de matrices se clasi0ica como un valor, concretamente como una re0erencia a la instancia de matri1 reci)n asignada. El procesamiento en tiempo de e$ecuci-n de una expresi-n de creaci-n de matrices consta de los siguientes pasosG 8as expresiones de longitud de dimensi-n de la lista de expresiones Oe2pression-listR se evalHan por orden, de i1?uierda a derec=a. 2espu)s de la evaluaci-n de cada expresi-n, se reali1a una conversi-n impl5cita O[#.1R a uno de los tipos siguientesG int, uint, long, ulong. .e elige el primer tipo de esta lista para el cual existe una conversi-n impl5cita. .i la evaluaci-n de una expresi-n o de la conversi-n impl5cita posterior causa una excepci-n, no se evalHan otras expresiones y no se e$ecutan nuevos pasos. 8os valores calculados para las longitudes de dimensi-n se validan como sigue. .i uno o m(s valores son menores ?ue cero, se inicia una excepci-n System.%ver-lo,)#ce&tion y no se e$ecutan nuevos pasos. .e asigna una instancia de matri1 con las longitudes de dimensi-n dadas. .i no =ay memoria disponible su0iciente para asignar la nueva instancia, se inicia una excepci-n System.%ut%-Memory)#ce&tion y no se e$ecutan m(s pasos. Todos los elementos de la nueva instancia de matri1 se iniciali1an con sus valores predeterminados O[ .2R. .i la expresi-n de creaci-n de matri1 contiene un iniciali1ador de matri1, entonces se evalHan las expresiones del iniciali1ador y se asignan a sus elemento de matri1 correspondientes. 8as evaluaciones y asignaciones se llevan a cabo en el orden en ?ue est(n escritas las expresiones en el iniciali1ador de matri1, es decir, los elementos se iniciali1an en orden de 5ndice creciente, empe1ando por la dimensi-n situada m(s a la derec=a. .i la evaluaci-n de una expresi-n dada o la posterior asignaci-n al elemento de matri1 correspondiente causa una excepci-n, no se iniciali1an m(s elementos Oy los elementos restantes conservan sus valores predeterminadosR.

7na expresi-n de creaci-n de matri1 permite crear una instancia de una matri1 con elementos de un tipo de matri1, pero los elementos de una matri1 como )sta deben iniciali1arse de 0orma manual. 'or e$emplo, la instrucci-n
int4545 a + ne, int4233545;

crea una matri1 de una dimensi-n con 1"" elementos de tipo int45. El valor inicial de cada elemento es null. 7na misma expresi-n de creaci-n de matrices no puede crear tambi)n instancias de las submatrices, y la instrucci-n
int4545 a + ne, int423354K5; .. )rror

da como resultado un error en tiempo de compilaci-n. 8a creaci-n de instancias de las submatrices debe reali1arse de 0orma manual, como en
int4545 a + ne, int4233545; -or (int i + 3; i D 233; i<<) a4i5 + ne, int4K5;

Cuando una matri1 de matrices tiene 0orma PrectangularQ, es decir, cuando todas las submatrices tienen la misma longitud, es m(s e0ica1 utili1ar una matri1 de varias dimensiones. En el e$emplo anterior, la creaci-n de instancias de la matri1 de matrices crea 1"1 ob$etos, una matri1 externa y 1"" submatrices. 'or el contrario,
int4 5 + ne, int4233 K5;

s-lo crea un ob$eto, una matri1 de dos dimensiones, y reali1a la asignaci-n mediante una sola instrucci-n. & continuaci-n se muestran e$emplos de expresiones de creaci-n de matrices con asignaci-n de tipo impl5cita.
var a + ne,45 { 2 var b + ne,45 { 2 var d + ne,45 { 2 23 2.K "one" 233 8 2333 !; 8.K !; null ! 8 { ",orld" "@" ! !; "t,o" !; .. int45 .. double45 .. string4 5 .. )rror

var c + ne,4 5 { { ""ello"

1$#

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

8a Hltima expresi-n origina un error durante la compilaci-n por?ue ni int ni string son impl5citamente convertibles entre s5, de modo ?ue no =ay un me$or tipo comHn. En este caso se debe utili1ar una expresi-n de creaci-n de matrices con asignaci-n de tipo impl5cita, por e$emplo, especi0icando el tipo para ?ue sea object45. &lternativamente, uno de los elementos se puede convertir a un tipo base comHn, ?ue entonces pasar5a a ser el tipo de elemento in0erido. 8as expresiones de creaci-n de matrices con asignaci-n de tipo impl5cita se pueden combinar con iniciali1adores de ob$etos an-nimos O[*. .1".#R para crear estructuras de datos con asignaci-n de tipo an-nima. 'or e$emploG
var contacts + ne,45 { ne, { Name + "C"ris Smit"" *"oneNumbers + ne,45 { "83X=KKK=3232" "J8K=YY8=Y3Y3" ! ! ne, { Name + ":ob Harris" *"oneNumbers + ne,45 { "XK3=KKK=32LL" ! ! !;

#. .17. &2presiones de creacin de dele"ados 7na expresi-n de creaci-n de delegados Odele&ate-creation-e2pressionR se usa para crear una nueva instancia de un tipo delegado Odele&ate-t#peR. dele&ate-creation-e2pression1 ne, dele&ate-t#pe ( e2pression ) El argumento de una expresi-n de creaci-n de delegados debe ser un grupo de m)todos, una 0unci-n an-nima o un valor de un tipo delegado Odele&ate-t#peR. .i el argumento es un con$unto de m)todos, identi0ica el m)todo y, en el caso de un m)todo de instancia, el ob$eto para el ?ue se crea un delegado. .i el argumento es una 0unci-n an-nima de0ine los par(metros y el cuerpo del m)todo para el destino del delegado. .i el argumento es un valor de un tipo delegado Odele&ate-t#peR, identi0ica una instancia de delegado del ?ue se va crear una copia. El procesamiento en tiempo de compilaci-n de una expresi-n de creaci-n de delegados Odele&ate-creatione2pressionR con la estructura ne, 6()), donde 6 es un tipo delegado Odele&ate-t#peR y ) es una expresi-n Oe2pressionR, se compone de los siguientes pasosG .i ) es un grupo de m)todos, la expresi-n de creaci-n de delegados se procesa de la misma manera ?ue una conversi-n de grupo de m)todos O[R de ) a 6. .i ) es una 0unci-n an-nima, la expresi-n de creaci-n de delegados se procesa de la misma manera ?ue una conversi-n de 0unci-n an-nima O[#. R de ) a 6. .i ) es un valor de un tipo delegado, ) debe ser compatible O[R con 6, y el resultado es una re0erencia a un delegado reci)n creado del tipo 6 ?ue =ace re0erencia a la misma lista de invocaci-n ?ue ). .i ) no es compatible con 6, se produce un error en tiempo de compilaci-n.

El procesamiento en tiempo de e$ecuci-n de una expresi-n de creaci-n de delegados Odele&ate-creatione2pressionR con la estructura ne, 6()), donde 6 es un tipo delegado Odele&ate-t#peR y ) es una expresi-n Oe2pressionR, se compone de los siguientes pasosG .i ) es un grupo de m)todos, la expresi-n de creaci-n de delegados se evalHa como una conversi-n de grupo de m)todos O[#.#R de ) a 6. .i ) es una 0unci-n an-nima, la expresi-n de creaci-n de delegados se evalHa como una conversi-n de 0unci-n an-nima O[#. R de ) a 6. .i ) es un valor de un tipo delegado Odele&ate-t#peRG

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

1$!

Especificacin del lenguaje C#

o o o

.e evalHa ). .i esta evaluaci-n da lugar a una excepci-n, no se e$ecutan nuevos pasos. .i el valor de ) es null, se inicia una excepci-n System.NullOe-erence)#ce&tion y no se e$ecutan nuevos pasos. .e asigna una nueva instancia del tipo delegado 6. .i no =ay memoria disponible su0iciente para asignar la nueva instancia, se inicia una excepci-n System.%ut%-Memory)#ce&tion y no se e$ecutan m(s pasos. .e iniciali1a la nueva instancia de delegado con la misma lista de invocaciones ?ue la instancia de delegado proporcionada por ).

8a lista de invocaciones de un delegado se determina cuando se iniciali1a el delegado y permanece constante durante toda la vigencia del delegado. 2ic=o de otra 0ormaG no se podr(n cambiar las entidades de destino invocables de un delegado una ve1 =aya sido creado el delegado. .i se combinan dos delegados o se ?uita uno de otro O[1 .1R, se produce un nuevo delegadoV no se cambia el contenido de ningHn delegado existente. 4o es posible crear un delegado ?ue =aga re0erencia a una propiedad, un indi1ador, un operador de0inido por el usuario, un constructor de instancia, un destructor o un constructor est(tico. Como se =a explicado antes, cuando se crea un delegado a partir de un grupo de m)todos, la lista de par(metros 0ormales y el tipo de valor devuelto del delegado determinan cu(l de los m)todos sobrecargados se debe seleccionar. En el e$emplo
delegate double 6oubleVunc(double #); class ' { 6oubleVunc - + ne, 6oubleVunc(SQuare); static -loat SQuare(-loat #) { return # > #; ! static double SQuare(double #) { return # > #; ! !

el campo '.- se iniciali1a con un delegado ?ue =ace re0erencia al segundo m)todo SQuare debido a ?ue ese m)todo coincide exactamente con la lista de par(metros 0ormales y el tipo de valor devuelto de 6oubleVunc. .i no =ubiera existido el segundo m)todo SQuare, se =abr5a producido un error de compilaci-n. #. .17.6 &2presiones de creacin de ob=etos annimos 7na expresi-n de creaci-n de ob$etos an-nimos Oanon#%o s-o->ect-creation-e2pressionR se utili1a para crear un ob$eto de un tipo an-nimo. anon#%o s-o->ect-creation-e2pression1 ne, anon#%o s-o->ect-initiali0er anon#%o s-o->ect-initiali0er1 { %e%-er-declarator-listopt ! { %e%-er-declarator-list ! %e%-er-declarator-list1 %e%-er-declarator %e%-er-declarator-list

%e%-er-declarator

1$6

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

%e%-er-declarator1 si%ple-na%e %e%-er-access -ase-access identifier @ e2pression 7n iniciali1ador de ob$eto an-nimo declara un tipo an-nimo y devuelve una instancia de ese tipo. 7n tipo an-nimo es un tipo de clase sin nombre ?ue =ereda directamente de object. 8os miembros de un tipo an-nimo son una secuencia de propiedades de s-lo lectura in0eridas del iniciali1ador de ob$etos an-nimos utili1ado para crear una instancia del tipo. Espec50icamente, un iniciali1ador de ob$eto an-nimo con la estructura
ne,

p1 + e1

p2 + e2

A pn + en

declara un tipo an-nimo con la estructura


class \\'nonymous2 { &rivate readonly B1 f1 ; &rivate readonly B2 f2 ;

A
&rivate readonly Bn fn ; &ublic \\'nonymous2(B1 a1 B2 a2 A Bn an) { f1 + a1 ; f2 + a2 ;

A fn + an ;

&ublic B1 p1 { get { return f1 ; ! ! &ublic B2 p2 { get { return f2 ; ! !

A
&ublic Bn pn { get { return fn ; ! ! &ublic override bool )Quals(object o) { b ! &ublic override int SetHas"Code() { b ! !

donde cada B2 es el tipo de expresi-n e2.correspondiente. 8a expresi-n utili1ada en un declarador de miembro O%e%-er-declaratorR debe tener un tipo. 'or tanto, es un error en tiempo de compilaci-n ?ue una expresi-n de un declarador de miembro O%e%-er-declaratorR sea nula o una 0unci-n an-nima. Tambi)n se trata de un error en tiempo de compilaci-n ?ue la expresi-n tenga un tipo no seguro. El compilador genera autom(ticamente el nombre de un tipo an-nimo y no se puede =acer re0erencia a )ste en un texto del programa. 2entro del mismo programa, dos iniciali1adores de ob$etos an-nimos ?ue especi0i?uen una secuencia de propiedades con los mismos nombres y tipos en tiempo de compilaci-n en el mismo orden producir(n instancias del mismo tipo an-nimo. En el e$emplo
var &2 + ne, { Name + "La,nmo,er" *rice + JLK.33 !; var &8 + ne, { Name + "S"ovel" *rice + 8X.LK !; &2 + &8;

la asignaci-n en la Hltima l5nea se permite por?ue &2 y &8 son del mismo tipo an-nimo.

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

1$(

Especificacin del lenguaje C#

8os m)todos )Quals y SetHas"code en tipos an-nimos invalidan los m)todos =eredados de object, y se de0inen en t)rminos de )Quals y SetHas"code de las propiedades, para ?ue las dos instancias del mismo tipo an-nimo sean iguales si y s-lo si todas sus propiedades son iguales. 7n declarador de miembro se puede abreviar como un nombre simple O[*. .2R, un acceso a miembro O[*. .4R o un acceso a base O[*. .8R. Es lo ?ue se denomina iniciali-ador de proyecci,n y es la 0orma abreviada de una declaraci-n de asignaci-n para una propiedad con el mismo nombre. Concretamente, los declaradores de miembros con la estructura identificador identifer + identificador e2pr . identificador identificador + e2pr . identificador son precisamente e?uivalentes a los siguientes, respectivamenteG 'or tanto, en un iniciali1ador de proyecci-n el identi0icador OidentifierR selecciona tanto el valor como el campo o propiedad para el ?ue el valor se asigna. !ntuitivamente, un iniciali1ador de proyecci-n proyecta no s-lo un valor, sino tambi)n el nombre de ese valor. +.#.11 ,perador typeof El operador ty&eo- se utili1a para obtener el ob$eto System.1y&e para un tipo. t#peof-e2pression1 ty&eo- ( t#pe ) ty&eo- ( n-o nd-t#pe-na%e )
ty&eo- ( void )

n-o nd-t#pe-na%e1 identifier &eneric-di%ension-specifieropt identifier // identifier &eneric-di%ension-specifieropt n-o nd-t#pe-na%e . identifier &eneric-di%ension-specifieropt &eneric-di%ension-specifier1 D co%%asopt E co%%as1 co%%as 8a primera 0orma de expresi-n typeo0 Ot#peof-e2pressionR consta de una palabra clave ty&eo- seguida de un tipo Ot#peR entre par)ntesis. El resultado de una expresi-n de esta 0orma es el ob$eto System.1y&e del tipo indicado. .-lo existe un ob$eto System.1y&e para cual?uier tipo dado. 8o ?ue implica ?ue, para el tipo 1, ty&eo-(1) ++ ty&eo-(1) siempre ser( true. 8a segunda 0orma de la expresi-n typeo0 Ot#peof-e2pressionR consta de una palabra clave ty&eo- seguida de un nombre de tipo sin enla1ar O n-o nd-t#pe-na%eR entre par)ntesis. 7n nombre de tipo sin enla1ar O n-o nd-t#pena%eR es muy similar a un nombre de tipo Ot#pe-na%eR O[3.8R excepto en ?ue un nombre de tipo sin enla1ar O n-o nd-t#pe-na%eR contiene especi0icadores de dimensi-n gen)ricos O&eneric-di%ension-specifiersR donde un nombre de tipo Ot#pe-na%eR contiene listas de argumentos de tipo Ot#pe-ar& %ent-listsR. Cuando el operando de una expresi-n typeo0 Ot#peof-e2pressionR es una secuencia de s5mbolos Oto6enR ?ue cumple con la gram(tica del nombre de tipo sin enla1ar O n-o nd-t#pe-na%eR y del nombre de tipo Ot#pe-na%eR, principalmente cuando no contiene un especi0icador de dimensi-n gen)rico O&eneric-di%ension-specifierR ni una lista de argumentos de tipo Ot#pe-ar& %ent-listR, se considera ?ue la secuencia de s5mbolos es un nombre de tipo Ot#pe-na%eR. El signi0icado de un nombre de tipo sin enla1ar O n-o nd-t#pe-na%eR se determina como sigueG Convertir la secuencia de s5mbolos Oto6enR en un nombre de tipo Ot#pe-na%eR al reempla1ar cada especi0icador de dimensi-n gen)rico O&eneric-di%ension-specifierR por una lista de argumentos de tipo

1$$

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

Ot#pe-ar& %ent-listR con el mismo nHmero de comas y la palabra clave object ?ue cada argumento de tipo Ot#pe-ar& %entR. Evaluar el nombre de tipo Ot#pe-na%eR resultante, al mismo tiempo ?ue se omiten todas las restricciones de los par(metros de tipo. El nombre de tipo sin enla1ar O n-o nd-t#pe-na%eR se resuelve como un tipo gen)rico sin enla1ar asociado al tipo construido resultante O[4.4.3R.

El resultado de la expresi-n typeo0 Ot#peof-e2pressionR es el ob$eto System.1y&e para el tipo gen)rico sin enla1ar resultante. 8a tercera 0orma de la expresi-n typeo0 Ot#peof-e2pressionR consta de una palabra clave ty&eo- seguida de una palabra clave void entre par)ntesis. El resultado de una expresi-n con esta estructura es el ob$eto System.1y&e ?ue representa la ausencia de un tipo. El ob$eto del tipo devuelto por ty&eo-(void) es exclusivo del ob$eto del tipo devuelto por cual?uier tipo. Este ob$eto de tipo especial es Htil en las bibliotecas de clases ?ue permiten la re0lexi-n en m)todos del lengua$e, donde dic=os m)todos desean tener un medio para representar el tipo de valor devuelto de cual?uier m)todo, incluidos los m)todos void, con una instancia de System.1y&e. El operador ty&eo- se puede utili1ar en un par(metro de tipo. El resultado es el ob$eto System.1y&e para el tipo en tiempo de e$ecuci-n enla1ado al par(metro de tipo. El operador ty&eo- tambi)n se puede utili1ar en un tipo construido o en un tipo gen)rico no sin enla1ar O[4.4.3R. El ob$eto System.1y&e para el tipo gen)rico sin enla1ar no es el mismo ?ue el ob$eto System.1y&e del tipo de instancia. El tipo de instancia siempre es un tipo construido cerrado en tiempo de e$ecuci-n, por?ue el ob$eto depende de los argumentos de tipo en tiempo de e$ecuci-n ?ue se est(n utili1ando, mientras ?ue el tipo gen)rico sin enla1ar no tiene argumentos de tipo. En el e$emplo
using System; class ID1E { &ublic static void *rint1y&es() { 1y&e45 t + { ty&eo-(int) ty&eo-(System.$nt98) ty&eo-(string) ty&eo-(double45) ty&eo-(void) ty&eo-(1) ty&eo-(ID1E) ty&eo-(IDID1EE) ty&eo-(IDE) !; -or (int i + 3; i D t.Lengt"; i<<) { Console.WriteLine(t4i5); ! ! ! class 1est { static void Main() { IDintE.*rint1y&es(); ! !

produce el resultadoG

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

1$"

Especificacin del lenguaje C# System.$nt98 System.$nt98 System.String System.6ouble45 System.Uoid System.$nt98 Id24System.$nt985 Id24Id24System.$nt9855 Id2415

2ebe tenerse en cuenta ?ue int y System.$nt98 son el mismo tipo. Tambi)n ?ue el resultado de ty&eo-(IDE) no depende del argumento de tipo, pero el resultado de ty&eo-(ID1E) s5. +.#.12 6os operadores c?ec3ed y unc?ec3ed 8os operadores c"ec(ed y unc"ec(ed se utili1an con el 0in de controlar el conte.to de co pro/aci,n de des/orda iento para conversiones y operaciones aritm)ticas de tipo integral. chec3ed-e2pression1 c"ec(ed ( e2pression ) nchec3ed-e2pression1 unc"ec(ed ( e2pression ) El operador c"ec(ed evalHa la expresi-n contenida en un contexto comprobado Oc=ec6edR, y el operador unc"ec(ed evalHa la expresi-n contenida en un contexto no comprobado Ounc=ec6edR. 7na expresi-n c=ec6ed Ochec3ed-e2pressionR o una expresi-n unc=ec6ed O nchec3ed-e2pressionR se corresponde exactamente con una expresi-n entre par)ntesis Oparenthesi0ed-e2pressionR O[*. .3R, excepto por?ue la expresi-n contenida se evalHa en el contexto de comprobaci-n de desbordamiento dado. El contexto de comprobaci-n de desbordamiento tambi)n puede controlarse mediante instrucciones c"ec(ed y unc"ec(ed O[8.11R. 8as siguientes operaciones resultan a0ectadas por el contexto de comprobaci-n de desbordamiento establecido por los operadores e instrucciones c"ec(ed y unc"ec(edG 8os operadores unarios prede0inidos << y == O[*. .+ y [*.#. R, cuando el operando es de un tipo integral. El operador unario prede0inido = O[*.#.2R, cuando el operando es de un tipo integral. 8os operadores binarios prede0inidos <, =, > y . O[*.*R, cuando los dos operandos son de tipo integral. 8as conversiones expl5citas num)ricas O[#.2.1R de un tipo integral a otro, o de -loat o double a un tipo integral.

Cuando una de las operaciones anteriores produce un resultado demasiado grande para representarlo en el tipo de destino, el contexto en ?ue se e$ecuta la operaci-n controla el comportamiento resultanteG En un contexto c"ec(ed, si la operaci-n es una expresi-n constante O[*.18R, se produce un error en tiempo de compilaci-n. / bien, si la operaci-n se reali1a en tiempo de e$ecuci-n, se inicia una excepci-n System.%ver-lo,)#ce&tion. En un contexto unc"ec(ed, el resultado se trunca, descart(ndose cual?uier bit de orden superior ?ue no ?uepa en el tipo de destino.

'ara expresiones no constantes Oexpresiones ?ue se evalHan en tiempo de e$ecuci-nR no incluidas por operadores o instrucciones c"ec(ed o unc"ec(ed, el contexto de comprobaci-n de desbordamiento predeterminado es unc"ec(ed salvo ?ue 0actores externos Ocomo la con0iguraci-n de opciones del compilador y del entorno de e$ecuci-nR llamen a la evaluaci-n c"ec(ed.

1"'

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

'ara expresiones constantes Oexpresiones ?ue pueden evaluarse completamente en tiempo de compilaci-nR, el contexto de comprobaci-n de desbordamiento predeterminado siempre es c"ec(ed. .alvo ?ue una expresi-n constante se colo?ue expl5citamente en un contexto unc"ec(ed, los desbordamientos ?ue ocurren durante la evaluaci-n en tiempo de compilaci-n de la expresi-n siempre causan errores de tiempo de compilaci-n. El cuerpo de una 0unci-n an-nima no se ve a0ectado por los contextos c"ec(ed o unc"ec(ed en los ?ue ocurre la 0unci-n an-nima. En el e$emplo
class 1est { static readonly int # + 2333333; static readonly int y + 2333333; static int V() { return c"ec(ed(# > y); ! static int S() { return unc"ec(ed(# > y); ! static int H() { return # > y; ! ! .. 1"ro,s %ver-lo,)#ce&tion

.. Oeturns =M8M9MLLXY

.. 6e&ends on de-ault

no se noti0ican errores de tiempo de compilaci-n puesto ?ue ninguna de las expresiones puede evaluarse en tiempo de compilaci-n. En tiempo de e$ecuci-n, el m)todo V inicia una excepci-n System.%ver-lo,)#ce&tion y el m)todo S devuelve W*2*3*++#8 Olos 32 bits menores del resultado 0uera de intervaloR. El comportamiento del m)todo H depende del contexto de comprobaci-n de desbordamiento predeterminado de la compilaci-n, pero es el mismo ?ue V o el mismo ?ue S. En el e$emplo
class 1est { const int # + 2333333; const int y + 2333333; static int V() { return c"ec(ed(# > y); ! static int S() { return unc"ec(ed(# > y); ! static int H() { return # > y; ! ! .. Com&ile error over-lo,

.. Oeturns =M8M9MLLXY

.. Com&ile error

over-lo,

los desbordamientos ?ue se producen durante la evaluaci-n de las expresiones constantes en V y H causan la noti0icaci-n de errores en tiempo de compilaci-n, puesto ?ue las expresiones se evalHan en un contexto c"ec(ed. Tambi)n se produce un desbordamiento cuando se evalHa la expresi-n constante en S, si bien, al tener lugar la evaluaci-n en un contexto unc"ec(ed, dic=o desbordamiento no se noti0ica. 8os operadores c"ec(ed y unc"ec(ed solamente a0ectan al contexto de comprobaci-n de desbordamiento para a?uellas operaciones ?ue est(n contenidas textualmente en los to6ens P(Q y P)Q. 8os operadores no tienen ningHn e0ecto sobre los miembros de 0unci-n ?ue se invocan como consecuencia de la evaluaci-n de la expresi-n contenida. En el e$emplo

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

1"1

Especificacin del lenguaje C# class 1est { static int Multi&ly(int # return # > y; !

int y) {

static int V() { return c"ec(ed(Multi&ly(2333333 ! !

2333333));

el uso de c"ec(ed en V no a0ecta a la evaluaci-n de # > y en Multi&ly y, por lo tanto, # > y se evalHa en el contexto de comprobaci-n de desbordamiento predeterminado. El operador unc"ec(ed es pr(ctico cuando se escriben constantes de los tipos integrales con signo en notaci-n =exadecimal. 'or e$emploG
class 1est { &ublic const int 'll:its + unc"ec(ed((int)3#VVVVVVVV); &ublic const int Hig":it + unc"ec(ed((int)3#Y3333333); !

8as dos constantes =exadecimales anteriores son de tipo uint. 2ado ?ue las constantes est(n 0uera del intervalo de int, sin el operador unc"ec(ed, las conversiones al tipo int producir5an errores en tiempo de compilaci-n. 8as instrucciones y operadores c"ec(ed y unc"ec(ed permiten a los programadores controlar algunos aspectos de determinados c(lculos num)ricos. 4o obstante, el comportamiento de algunos operadores num)ricos depende de los tipos de datos de sus operandos. 'or e$emplo, la multiplicaci-n de dos decimales siempre genera una excepci-n por desbordamiento, incl so en una construcci-n unc"ec(ed expl5cita. 2e igual manera, la multiplicaci-n de dos tipos de punto 0lotante nunca genera una excepci-n por desbordamiento, incl so en una construcci-n c"ec(ed expl5cita. &simismo, otros operadores n nca resultan a0ectados por el modo de comprobaci-n, ya sea predeterminado o expl5cito. +.#.13 E"presiones de alor predeterminadas 7na expresi-n de valor predeterminada se utili1a para obtener el valor predeterminado O[ .2R de un tipo. 3eneralmente, una expresi-n de valor predeterminada se utili1a para par(metros de tipo puesto ?ue es posible ?ue no se detecte si el par(metro de tipo es un tipo de valor o un tipo de re0erencia. O4o existe una conversi-n del literal null al par(metro de tipo a menos ?ue )ste sea un tipo de re0erencia.R defa lt-val e-e2pression1 de-ault ( t#pe ) .i el tipo Ot#peR de una expresi-n de valor predeterminada Odefa lt-val e-e2pressionR se evalHa como un tipo de re0erencia en tiempo de e$ecuci-n, null se convierte en dic=o tipo como resultado. .i el tipo Ot#peR de una expresi-n de valor predeterminada Odefa lt-val e-e2pressionR se evalHa como un tipo de valor en tiempo de e$ecuci-n, se obtiene el valor predeterminado del tipo de valor Oval e-t#peR como resultado O[4.1.2R. 7na expresi-n de valor predeterminada Odefa lt-val e-e2pressionR es una expresi-n constante O[*.18R si el tipo es un tipo de re0erencia o un par(metro de tipo ?ue es un tipo de re0erencia O[1".1. R. &dem(s, una expresi-n de valor predeterminada Odefa lt-val e-e2pressionR es una expresi-n constante si el tipo es uno de los tipos de valor siguientesG sbyte, byte, s"ort, us"ort, int, uint, long, ulong, c"ar, -loat, double, decimal, bool o cual?uier tipo de enumeraci-n. +.#.1! E"presiones de m*todos annimos 7na expresi-n de m)todo an-nimo Oanon#%o s-%ethod-e2pressionR es uno de los dos m)todos ?ue existen para de0inir una 0unci-n an-nima. Este tema se describe con m(s detalle en la secci-n [*.14.

1"2

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

+.$ ,peradores unarios


8os operadores <, =, @, A, <<, ==, y los operadores de conversi-n de tipos se denominan operadores unarios. nar#-e2pression1 pri%ar#-e2pression < nar#-e2pression = nar#-e2pression @ nar#-e2pression A nar#-e2pression pre-incre%ent-e2pression pre-decre%ent-e2pression cast-e2pression +.$.1 ,perador unario de signo m)s 'ara una operaci-n con la 0orma <#, se aplica la resoluci-n de sobrecargas de operadores unarios O[*.2.3R con el 0in de seleccionar una implementaci-n de operador concreta. El operando se convierte al tipo de par(metro del operador seleccionado, y el tipo del resultado es el tipo de valor devuelto del operador. 8os operadores de signo m(s unarios prede0inidos sonG
int o&erator <(int #); uint o&erator <(uint #); long o&erator <(long #); ulong o&erator <(ulong #); -loat o&erator <(-loat #); double o&erator <(double #); decimal o&erator <(decimal #);

'ara cada uno de estos operadores, el resultado es sencillamente el valor del operando. +.$.2 ,perador unario de signo menos 'ara una operaci-n con la 0orma C#, se aplica la resoluci-n de sobrecargas de operadores unarios O[*.2.3R con el 0in de seleccionar una implementaci-n de operador concreta. El operando se convierte al tipo de par(metro del operador seleccionado, y el tipo del resultado es el tipo de valor devuelto del operador. 8os operadores de negaci-n prede0inidos sonG 4egaci-n enteraG
int o&erator C(int #); long o&erator C(long #);

El resultado se calcula restando # de cero. .i el valor de # es el valor menor representable del tipo de operando OY231 para int o Y2#3 para long), la negaci-n matem(tica de # no se puede representar en este tipo de operando. .i esto ocurre dentro de un contexto c"ec(ed, se inicia una excepci-n System.%ver-lo,)#ce&tionV si ocurre dentro de un contexto unc"ec(ed, el resultado es el valor del operando y no se in0orma del desbordamiento. .i el operando del operador de negaci-n es de tipo uint, se convierte al tipo long y el tipo del resultado es long. 7na excepci-n es la regla ?ue permite escribir el valor int Y214*483#48 OY231R como un literal entero decimal O[2.4.4.2R. .i el operando del operador de negaci-n es de tipo ulong, se produce un error durante la compilaci-n. 7na excepci-n es la regla ?ue permite escribir el valor long Y+2233*2"3#8 4** 8"8 OY2#3R como un literal entero decimal O[2.4.4.2R. 4egaci-n de punto 0lotanteG

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

1"3

Especificacin del lenguaje C# -loat o&erator C(-loat #); double o&erator C(double #);

El resultado es el valor de # con su signo invertido. .i # es 4a4, el resultado es tambi)n 4a4. 4egaci-n decimalG
decimal o&erator C(decimal #);

El resultado se calcula restando # de cero. 8a negaci-n decimal e?uivale a usar el operador unario de signo menos del tipo System.6ecimal. +.$.3 ,perador de negacin lgica 'ara una operaci-n con la 0orma @#, se aplica la resoluci-n de sobrecargas de operadores unarios O[*.2.3R para seleccionar una implementaci-n de operador concreta. El operando se convierte al tipo de par(metro del operador seleccionado, y el tipo del resultado es el tipo de valor devuelto del operador. .olamente existe un operador de negaci-n l-gica prede0inidoG
bool o&erator @(bool #);

Este operador calcula la negaci-n l-gica del operandoG si )ste es true, el resultado es -alse. .i el operando es -alse, el resultado es true. +.$.! ,perador de complemento de bit a bit 'ara una operaci-n con la 0orma A#, se aplica la resoluci-n de sobrecargas de operadores unarios O[*.2.3R para seleccionar una implementaci-n de operador concreta. El operando se convierte al tipo de par(metro del operador seleccionado, y el tipo del resultado es el tipo de valor devuelto del operador. 8os operadores de complemento de bit a bit prede0inidos sonG
int o&erator A(int #); uint o&erator A(uint #); long o&erator A(long #); ulong o&erator A(ulong #);

'ara cada uno de estos operadores, el resultado de la operaci-n es el complemento de bit a bit de #. Todos los tipos de enumeraci-n ) proporcionan impl5citamente el siguiente operador de complemento de bit a bitG
) o&erator A() #);

El resultado de evaluar A#, donde # es una expresi-n de un tipo de enumeraci-n ) con un tipo subyacente ;, es exactamente el mismo ?ue el de evaluar OER(A(;)#). +.$.# ,peradores prefijos de incremento y decremento pre-incre%ent-e2pression1 << nar#-e2pression pre-decre%ent-e2pression1 == nar#-e2pression El operando de una operaci-n de pre0i$o de incremento o decremento debe ser una expresi-n clasi0icada como un variable, un acceso a propiedad o un acceso a indi1ador. El resultado de la operaci-n es un valor del mismo tipo ?ue el operando. .i el operando de una operaci-n de pre0i$o de incremento o decremento es una propiedad o un acceso a indi1ador, la propiedad o el indi1ador debe tener tanto un descriptor de acceso get como set. .i no es )ste el caso, se produce un error en tiempo de compilaci-n.

1"#

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

8a resoluci-n de sobrecargas de operadores unarios O[*.2.3R se aplica para seleccionar una implementaci-n de operador concreta. Existen operadores prede0inidos << y == para los tipos siguientesG sbyte, byte, s"ort, us"ort, int, uint, long, ulong, c"ar, -loat, double, decimal y cual?uier tipo enum. 8os operadores prede0inidos << devuelven el valor generado al sumar 1 al operando, y los operadores prede0inidos == devuelven el valor generado al restarle 1. En un contexto c"ec(ed, si el resultado de esta suma o resta se encuentra 0uera del intervalo del tipo del resultado y el tipo del resultado es un tipo integral o enum, se inicia una excepci-n System.%ver-lo,)#ce&tion. El procesamiento en tiempo de e$ecuci-n de una operaci-n de pre0i$o de incremento o decremento de la 0orma < <# o ==# consta de los pasos siguientesG .i # se clasi0ica como una variableG o o o o o .e evalHa # para producir la variable. .e invoca el operador seleccionado con el valor de # como argumento. El valor devuelto por el operador se almacena en la ubicaci-n dada por la evaluaci-n de #. El valor devuelto por el operador es el resultado de la operaci-n. .e evalHa la expresi-n de instancia Osi # no es staticR y la lista de argumentos Osi # es un acceso a indi1adorR asociada con #, y el resultado se utili1a en las posteriores invocaciones de descriptor de acceso get y set. .e invoca el descriptor de acceso get de #. .e invoca el operador seleccionado con el valor devuelto por el descriptor de acceso get como argumento. .e invoca el descriptor de acceso set de # con el valor devuelto por el operador como su argumento value. El valor devuelto por el operador es el resultado de la operaci-n.

.i # se clasi0ica como una propiedad o un acceso a indi1adorG

o o o o

8os operadores << y == admiten la notaci-n de post0i$os O[*. .+R. El resultado de #<< o #== es el valor de # antes de la operaci-n, mientras ?ue el resultado de <<# o ==# es el valor de # desp ?s de la operaci-n. En uno u otro caso, # tiene el mismo valor despu)s de la operaci-n. 7na implementaci-n de o&erator << u o&erator == puede invocarse mediante la notaci-n de post0i$o o pre0i$o. 4o es posible contar con implementaciones de operador independientes para las dos notaciones. +.$.$ E"presiones de con ersin 7na expresi-n de conversi-n de tipos Ocast-e2pressionR se usa para convertir expl5citamente una expresi-n a un tipo dado. cast-e2pression1 ( t#pe ) nar#-e2pression 7na expresi-n de conversi-n cast Ocast-e2pressionR de la 0orma (1)), donde 1 es un tipo Ot#peR y ) es una expresi-n unaria O nar#-e2pressionR, reali1a una conversi-n expl5cita O[#.2R del valor de ) al tipo 1. .i no existe una conversi-n expl5cita de ) a 1, se produce un error durante la compilaci-n. En caso contrario, el resultado es el valor producido por la conversi-n expl5cita. El resultado siempre se clasi0ica como un valor, aun?ue ) denote una variable.

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

1"!

Especificacin del lenguaje C#

8a gram(tica de una expresi-n de conversi-n de tipos Ocast-e2pressionR produce algunas ambigIedades sint(cticas. 'or e$emplo, la expresi-n (#)Cy podr5a interpretarse como una expresi-n de conversi-n de tipos Ocast-e2pressionR Ouna conversi-n del tipo Cy al tipo #R o como una expresi-n aditiva Oadditive-e2pressionR combinada con una expresi-n entre par)ntesis Oparenthesi0ed-e2pressionR O?ue calcula el valor de # C yR. 'ara resolver las ambigIedades de las expresiones de conversi-n de tipos Ocast-e2pressionR, existe la siguiente reglaG una secuencia de uno o m(s s5mbolos Oto3ensR O[2.3.3R encerrados entre par)ntesis se considera el inicio de una expresi-n de conversi-n de tipos Ocast-e2pressionR s-lo si al menos uno de los siguientes supuestos es ciertoG 8a secuencia de to6ens es correcta gramaticalmente para un tipo Ot#peR, pero no para una expresi-n Oe2pressionR. 8a secuencia de to6ens es correcta gramaticalmente para un tipo Ot#peR, y el s5mbolo ?ue sigue inmediatamente al par)ntesis de cierre es el to6en PAQ, P@Q o P(Q, un identi0icador OidentifierR O[2.4.1R, un literal OliteralR O[2.4.4R o cual?uier palabra clave O3e#wordR O[2.4.3R excepto as e is.

El t)rmino Pgramaticalmente correctaQ signi0ica ?ue la secuencia de s5mbolos Oto6ensR debe a$ustarse a la producci-n gramatical particular de esta clase de expresiones. En concreto, no se considera al signi0icado real de sus identi0icadores constituyentes. 'or e$emplo, si # e y son identi0icadores, entonces #.y es correcta gramaticalmente para un tipo, aun?ue #.y no denote realmente un tipo. 2e la regla de eliminaci-n de ambigIedades se deduce ?ue, si # e y son identi0icadores, (#)y, (#)(y) y (#)(=y) son expresiones de conversi-n de tipos Ocast-e2pressionsR, pero no as5 (#)=y, aun?ue # identi0i?ue un tipo. 4o obstante, si # es una palabra clave ?ue identi0ica un tipo prede0inido Ocomo intR, las cuatro 0ormas son expresiones de conversi-n de tipos Ocast-e2pressionsR Opor?ue esta palabra clave nunca podr5a ser una expresi-n por s5 mismaR.

+.+ ,peradores aritm*ticos


8os operadores >, ., B, < y C se denominan operadores aritm)ticos. % ltiplicative-e2pression1 nar#-e2pression % ltiplicative-e2pression > % ltiplicative-e2pression . % ltiplicative-e2pression B

nar#-e2pression nar#-e2pression nar#-e2pression

additive-e2pression1 % ltiplicative-e2pression additive-e2pression < % ltiplicative-e2pression additive-e2pression C % ltiplicative-e2pression +.+.1 ,perador de multiplicacin 'ara una operaci-n con la 0orma # > y, se aplica la resoluci-n de sobrecargas de operadores binarios O[*.2.4R para seleccionar una implementaci-n de operador concreta. 8os operandos se convierten a los tipos de par(metro del operador seleccionado, y el tipo del resultado es el tipo de valor devuelto por el operador. & continuaci-n se enumeran los operadores de multiplicaci-n prede0inidos. Todos los operadores calculan el producto de # e y. %ultiplicaci-n de enterosG
int o&erator >(int # int y); uint o&erator >(uint # uint y); long o&erator >(long # long y); ulong o&erator >(ulong # ulong y);

1"6

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

En un contexto c"ec(ed, si el producto est( 0uera del intervalo del tipo del resultado, se inicia una excepci-n System.%ver-lo,)#ce&tion. En un contexto unc"ec(ed, no se noti0ican los desbordamientos y se descarta cual?uier bit signi0icativo de nivel superior del resultado ?ue est) 0uera del intervalo del tipo de resultado. %ultiplicaci-n de nHmeros de punto 0lotanteG
-loat o&erator >(-loat # -loat y); double o&erator >(double # double y);

El producto se calcula segHn las reglas de aritm)tica !EEE * 4. 8a tabla siguiente muestra los resultados de todas las posibles combinaciones de valores 0initos distintos de cero, ceros, in0initos y 4a4. En la tabla, # e y son valores 0initos positivos. ? es el resultado de # > y. .i el resultado es demasiado grande para el tipo de destino, ? es in0inito. .i el resultado es demasiado pe?ueUo para el tipo de destino, ? es cero.
<y <# C# <3 C3 <e Ce NaN <? C? <3 C3 <e Ce NaN Cy C? <? C3 <3 Ce <e NaN <3 <3 C3 <3 C3 NaN NaN NaN C3 C3 <3 C3 <3 NaN NaN NaN <e <e Ce NaN NaN <e Ce NaN Ce Ce <e NaN NaN Ce <e NaN NaN NaN NaN NaN NaN NaN NaN NaN

%ultiplicaci-n de nHmeros decimalesG


decimal o&erator >(decimal # decimal y);

.i el valor resultante es demasiado grande para representarlo en 0ormato decimal, se inicia una excepci-n System.%ver-lo,)#ce&tion. .i el valor resultante es demasiado pe?ueUo para representarlo en 0ormato decimal, el resultado es cero. 8a escala del resultado, antes de cual?uier redondeo, es la suma de las escalas de los dos operandos. 8a multiplicaci-n de decimales e?uivale al uso del operador de multiplicaci-n de tipo System.6ecimal. +.+.2 ,perador de di isin 'ara una operaci-n con la 0orma # . y, se aplica la resoluci-n de sobrecargas de operadores binarios O[*.2.4R para seleccionar una implementaci-n de operador concreta. 8os operandos se convierten a los tipos de par(metro del operador seleccionado, y el tipo del resultado es el tipo de valor devuelto por el operador. & continuaci-n se enumeran los operadores de divisi-n prede0inidos. Todos los operadores calculan el cociente de # e y. 2ivisi-n de nHmeros enterosG
int o&erator .(int # int y); uint o&erator .(uint # uint y); long o&erator .(long # long y); ulong o&erator .(ulong # ulong y);

.i el valor del operando derec=o es cero, se inicia una excepci-n System.6ivide:yPero)#ce&tion. 8a divisi-n redondea el resultado =acia cero, y el valor absoluto del resultado es el entero mayor posible ?ue sea menor ?ue el valor absoluto del cociente de los dos operandos. El resultado es cero o positivo cuando los dos operandos tienen el mismo signo, y cero o negativo si los dos operandos tienen signos opuestos.

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

1"(

Especificacin del lenguaje C#

.i el operando i1?uierdo es el int o long representable menor y el derec=o es C2, se produce un desbordamiento. En un contexto c"ec(ed, esto =ace ?ue se produ1ca una excepci-n System.'rit"metic)#ce&tion Oo una subclase de la mismaR. En un contexto unc"ec(ed, la implementaci-n de0ine si se inicia una excepci-n System.'rit"metic)#ce&tion Oo una subclase de la mismaR o no se in0orma del desbordamiento, siendo el valor resultante el del operando i1?uierdo. 2ivisi-n de nHmeros de punto 0lotanteG
-loat o&erator .(-loat # -loat y); double o&erator .(double # double y);

El cociente se calcula segHn las reglas de aritm)tica !EEE * 4. 8a tabla siguiente muestra los resultados de todas las posibles combinaciones de valores 0initos distintos de cero, ceros, in0initos y 4a4. En la tabla, # e y son valores 0initos positivos. ? es el resultado de # . y. .i el resultado es demasiado grande para el tipo de destino, ? es in0inito. .i el resultado es demasiado pe?ueUo para el tipo de destino, ? es cero.
<y <# C# <3 C3 <e Ce NaN <? C? <3 C3 <e Ce NaN Cy C? <? C3 <3 Ce <e NaN <3 <e Ce NaN NaN <e Ce NaN C3 Ce <e NaN NaN Ce <e NaN <e <3 C3 <3 C3 NaN NaN NaN Ce C3 <3 C3 <3 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN

2ivisi-n de nHmeros decimalesG


decimal o&erator .(decimal # decimal y);

.i el valor del operando derec=o es cero, se inicia una excepci-n System.6ivide:yPero)#ce&tion. .i el valor resultante es demasiado grande para representarlo en 0ormato decimal, se inicia una excepci-n System.%ver-lo,)#ce&tion. .i el valor resultante es demasiado pe?ueUo para representarlo en 0ormato decimal, el resultado es cero. 8a escala del resultado ser( la menor escala ?ue conserve un resultado igual al valor decimal representable m(s cercano al aut)ntico valor matem(tico. 8a divisi-n de decimales e?uivale al uso del operador de divisi-n de tipo System.6ecimal. +.+.3 ,perador de resto 'ara una operaci-n con la 0orma # B y, se aplica la resoluci-n de sobrecargas de operadores binarios O[*.2.4R para seleccionar una implementaci-n de operador concreta. 8os operandos se convierten a los tipos de par(metro del operador seleccionado, y el tipo del resultado es el tipo de valor devuelto por el operador. & continuaci-n se enumeran los operadores de resto prede0inidos. Todos los operadores calculan el resto de la divisi-n entre # e y. ;esto de nHmeros enterosG
int o&erator B(int # int y); uint o&erator B(uint # uint y); long o&erator B(long # long y); ulong o&erator B(ulong # ulong y);

El resultado de # B y es el valor producido por # C (# . y) > y. .i y es cero, se produce una excepci-n System.6ivide:yPero)#ce&tion.

1"$

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

.i el operando i1?uierdo es el valor int o long menor y el operando derec=o es =2, se inicia una excepci-n System.%ver-lo,)#ce&tion. En ningHn caso # B y inicia una excepci-n donde # . y no iniciar5a una excepci-n. ;esto de nHmeros de punto 0lotanteG
-loat o&erator B(-loat # -loat y); double o&erator B(double # double y);

8a tabla siguiente muestra los resultados de todas las posibles combinaciones de valores 0initos distintos de cero, ceros, in0initos y 4a4. En la tabla, # e y son valores 0initos positivos. ? es el resultado de # B y, y se calcula como # C n > y, donde n es el mayor entero posible ?ue sea menor o igual a # . y. Este m)todo para calcular el resto es an(logo al utili1ado para los operandos enteros, pero di0iere de la de0inici-n de !EEE * 4 Oen la ?ue n es el entero m(s pr-ximo a # . yR.
<y <# C# <3 C3 <e Ce NaN <? C? <3 C3 NaN NaN NaN Cy <? C? <3 C3 NaN NaN NaN <3 NaN NaN NaN NaN NaN NaN NaN C3 NaN NaN NaN NaN NaN NaN NaN <e # C# <3 C3 NaN NaN NaN Ce # C# <3 C3 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN

;esto de nHmeros decimalesG


decimal o&erator B(decimal # decimal y);

.i el valor del operando derec=o es cero, se inicia una excepci-n System.6ivide:yPero)#ce&tion. 8a escala del resultado, antes de cual?uier redondeo, es la mayor de las escalas de los dos operandosV el signo del resultado, si es distinto de cero, es el mismo ?ue el de #. El resto decimal e?uivale al uso del operador de resto de tipo System.6ecimal. +.+.! ,perador de suma 'ara una operaci-n con la 0orma # < y, se aplica la resoluci-n de sobrecargas de operadores binarios O[*.2.4R para seleccionar una implementaci-n de operador concreta. 8os operandos se convierten a los tipos de par(metro del operador seleccionado, y el tipo del resultado es el tipo de valor devuelto por el operador. & continuaci-n se enumeran los operadores de suma prede0inidos. 'ara tipos num)ricos y de enumeraci-n, los operadores de suma prede0inidos calculan la suma de los dos operandos. Cuando al menos uno de los operandos es de tipo string, los operadores de suma prede0inidos concatenan las representaciones de la cadena de los operandos. .uma de nHmeros enterosG
int o&erator <(int # int y); uint o&erator <(uint # uint y); long o&erator <(long # long y); ulong o&erator <(ulong # ulong y);

En un contexto c"ec(ed, si la suma est( 0uera del intervalo del tipo del resultado, se inicia una excepci-n System.%ver-lo,)#ce&tion. En un contexto unc"ec(ed, no se noti0ican los desbordamientos y se descarta cual?uier bit signi0icativo de nivel superior del resultado ?ue est) 0uera del intervalo del tipo de resultado.

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

1""

Especificacin del lenguaje C#

.uma de nHmeros de punto 0lotanteG


-loat o&erator <(-loat # -loat y); double o&erator <(double # double y);

8a suma se calcula segHn las reglas de aritm)tica !EEE * 4. 8a tabla siguiente muestra los resultados de todas las posibles combinaciones de valores 0initos distintos de cero, ceros, in0initos y 4a4. En la tabla, # e y son valores 0initos distintos de cero y ? es el resultado de # < y. .i # e y tienen la misma magnitud pero signos opuestos, ? es cero positivo. .i # < y es demasiado grande para representarlo en el tipo de destino, ? es un in0inito con el signo de # < y.
y # <3 C3 <e Ce NaN ? y y <e Ce NaN <3 # <3 <3 <e Ce NaN C3 # <3 C3 <e Ce NaN <e <e <e <e <e NaN NaN Ce Ce Ce Ce NaN Ce NaN NaN NaN NaN NaN NaN NaN NaN

.uma de nHmeros decimalesG


decimal o&erator <(decimal # decimal y);

.i el valor resultante es demasiado grande para representarlo en 0ormato decimal, se inicia una excepci-n System.%ver-lo,)#ce&tion. 8a escala del resultado, antes de cual?uier redondeo, es la mayor de las escalas de los dos operandos. 8a suma de decimales e?uivale al uso del operador de suma de tipo System.6ecimal. .uma de enumeraciones. Todos los tipos de enumeraci-n proporcionan de 0orma impl5cita los siguientes operadores prede0inidos, donde ) es el tipo enum y ; es el tipo subyacente de )G
) o&erator <() # ) o&erator <(; # ; y); ) y);

8os operadores se evalHan exactamente como ())((;)# < (;)y). Concatenaci-n de cadenasG
string o&erator <(string # string o&erator <(string # string o&erator <(object # string y); object y); string y);

El operador binario < concatena cadenas cuando uno o los dos operandos son de tipo string. .i un operando de la concatenaci-n de cadenas es null, se sustituye una cadena vac5a. / bien, cual?uier argumento ?ue no sea de cadena se convierte a su representaci-n en 0ormato de cadena mediante la invocaci-n del m)todo virtual 1oString =eredado del tipo object. .i 1oString devuelve null, se sustituye una cadena vac5a.
using System;

2''

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases class 1est { static void Main() { string s + null; Console.WriteLine("s + int i + 2; Console.WriteLine("i + -loat - + 2.8933)<2KV; Console.WriteLine("- + decimal d + 8.L33m; Console.WriteLine("d + ! !

E" < s < "D"); " < i); " < -); " < d);

.. dis&lays s + ED .. dis&lays i + 2 .. dis&lays - + 2.89)<2K .. dis&lays d + 8.L33

El resultado del operador de concatenaci-n de cadenas es una cadena 0ormada por los caracteres del operando i1?uierdo seguidos de los caracteres del operando derec=o. El operador de concatenaci-n de cadenas nunca devuelve un valor null. 'uede iniciarse una excepci-n System.%ut%-Memory)#ce&tion si no =ay su0iciente memoria libre para asignar la cadena resultante. Combinaci-n de delegados. Todos los tipos delegados proporcionan impl5citamente el siguiente operador prede0inido, donde 6 es el tipo delegadoG
6 o&erator <(6 # 6 y);

El operador binario < reali1a la combinaci-n de delegados cuando los dos operandos son de un tipo delegado 6. O.i los operandos tienen tipos de delegado distintos, se produce un error en tiempo de compilaci-n.R .i el primer operando es null, el resultado de la operaci-n es el valor del segundo operando Oaun?ue este operando tambi)n sea nullR. En caso contrario, si el segundo operando es null, el resultado de la operaci-n es el valor del primer operando. / bien, el resultado de la operaci-n es una nueva instancia de delegado ?ue, cuando se invoca, llama al primer operando y despu)s al segundo. 'ara obtener e$emplos de combinaci-n de delegados, vea [*.*. y [1 .4. 'uesto ?ue System.6elegate no es un tipo delegado, no tiene o&erator <. +.+.# ,perador de resta 'ara una operaci-n con la 0orma # C y, se aplica la resoluci-n de sobrecargas de operadores binarios O[*.2.4R para seleccionar una implementaci-n de operador concreta. 8os operandos se convierten a los tipos de par(metro del operador seleccionado, y el tipo del resultado es el tipo de valor devuelto por el operador. & continuaci-n se enumeran los operadores de resta prede0inidos. Todos los operadores restan y de #. ;esta de enterosG
int o&erator C (int # int y); uint o&erator C (uint # uint y); long o&erator C (long # long y); ulong o&erator C (ulong # ulong y);

En un contexto c"ec(ed, si la di0erencia est( 0uera del intervalo del tipo del resultado, se inicia una excepci-n System.%ver-lo,)#ce&tion. En un contexto unc"ec(ed, no se noti0ican los desbordamientos y se descarta cual?uier bit signi0icativo de nivel superior del resultado ?ue est) 0uera del intervalo del tipo de resultado. ;esta de nHmeros de punto 0lotanteG
-loat o&erator C (-loat # -loat y); double o&erator C (double # double y);

8a di0erencia se calcula segHn las reglas de aritm)tica !EEE * 4. 8a tabla siguiente muestra los resultados de todas las posibles combinaciones de valores 0initos distintos de cero, ceros, in0initos y 4a4. En la tabla, # e y son valores 0initos distintos de cero y ? es el resultado de # C y. .i # e y son iguales, ? es cero

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

2'1

Especificacin del lenguaje C#

positivo. .i # C y es demasiado grande para representarlo en el tipo de destino, ? es un in0inito con el signo de # C y.
y # <3 C3 <e Ce NaN ? Cy Cy <e Ce NaN <3 # <3 C3 <e Ce NaN C3 # <3 <3 <e Ce NaN <e Ce Ce Ce NaN Ce NaN Ce <e <e <e <e NaN NaN NaN NaN NaN NaN NaN NaN NaN

;esta de nHmeros decimalesG


decimal o&erator C (decimal # decimal y);

.i el valor resultante es demasiado grande para representarlo en 0ormato decimal, se inicia una excepci-n System.%ver-lo,)#ce&tion. 8a escala del resultado, antes de cual?uier redondeo, es la mayor de las escalas de los dos operandos. 8a resta de decimales e?uivale al uso del operador de resta de tipo System.6ecimal. ;esta de enumeraciones. Todos los tipos de enumeraci-n proporcionan de 0orma impl5cita el siguiente operador prede0inido, donde ) es el tipo enum y ; es el tipo subyacente de )G
; o&erator C () # ) y);

Este operador se evalHa exactamente como (;)((;)# C (;)y). Es decir, el operador calcula la di0erencia entre los valores ordinales de # e y, y el tipo del resultado es el tipo subyacente de la enumeraci-n.
) o&erator C () # ; y);

Este operador se evalHa exactamente como ())((;)# C y). Es decir, el operador resta un valor del tipo subyacente de la enumeraci-n, ?ue produce un valor de la enumeraci-n. Eliminaci-n de delegados. Todos los tipos delegados proporcionan impl5citamente el siguiente operador prede0inido, donde 6 es el tipo delegadoG
6 o&erator C (6 # 6 y);

El operador binario < reali1a la eliminaci-n de delegados cuando los dos operandos son de un tipo delegado 6. .i los operandos tienen tipos de delegado distintos, se produce un error en tiempo de compilaci-n. .i el primer operando es null, el resultado de la operaci-n tambi)n es null. En caso contrario, si el segundo operando es null, el resultado de la operaci-n es el valor del primer operando. 2e lo contrario, ambos operandos representan listas de invocaciones O[1 .1R ?ue tienen una o m(s entradas, y el resultado es una nueva lista de invocaciones ?ue se compone de la lista del primer operando con las entradas del segundo operando ?uitadas de ella, siempre ?ue la lista del segundo operando sea una sublista apropiada contigua al primero. O'ara determinar la igualdad de la sublista, las entradas correspondientes se comparan en cuanto al operador de igualdad del delegado O[*.+.8R.R En caso contrario, el resultado es el valor del operando i1?uierdo. En el proceso no se modi0ica la lista de ninguno de los operandos. .i la lista del segundo operando coincide con varias sublistas de entradas contiguas de la lista del primero, se ?uita la sublista coincidente situada m(s a la derec=a de las entradas contiguas. .i la eliminaci-n produce una lista vac5a, el resultado es null. 'or e$emploG
delegate void 6(int #);

2'2

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases class C { &ublic static void M2(int i) { .> b >. ! &ublic static void M8(int i) { .> b >. ! ! class 1est { static void Main() { 6 cd2 + ne, 6(C.M2); 6 cd8 + ne, 6(C.M8); 6 cd9 + cd2 < cd8 < cd8 < cd2; cd9 =+ cd2; cd9 + cd2 < cd8 < cd8 < cd2; cd9 =+ cd2 < cd8; cd9 + cd2 < cd8 < cd8 < cd2; cd9 =+ cd8 < cd8; cd9 + cd2 < cd8 < cd8 < cd2; cd9 =+ cd8 < cd2; cd9 + cd2 < cd8 < cd8 < cd2; cd9 =+ cd2 < cd2; ! !

.. M2 < M8 < M8 < M2 .. +E M2 < M8 < M8 .. M2 < M8 < M8 < M2 .. +E M8 < M2 .. M2 < M8 < M8 < M2 .. +E M2 < M2 .. M2 < M8 < M8 < M2 .. +E M2 < M8 .. M2 < M8 < M8 < M2 .. +E M2 < M8 < M8 < M2

+.- ,peradores de despla8amiento


8os operadores DD y EE permiten reali1ar operaciones de despla1amiento de bits. shift-e2pression1 additive-e2pression shift-e2pression DD additive-e2pression shift-e2pression ri&ht-shift additive-e2pression 'ara una operaci-n con la 0orma # DD count o # EE count, se aplica la resoluci-n de sobrecargas de operadores binarios O[*.2.4R con el 0in de seleccionar una implementaci-n de operador concreta. 8os operandos se convierten a los tipos de par(metro del operador seleccionado, y el tipo del resultado es el tipo de valor devuelto por el operador. Cuando se declara un operador de despla1amiento sobrecargado, el tipo del primer operando siempre debe ser la clase o estructura ?ue contiene su declaraci-n, mientras ?ue el tipo del segundo operando siempre debe ser int. & continuaci-n se enumeran los operadores de despla1amiento prede0inidos. 2espla1amiento a la i1?uierdaG
int o&erator DD(int # int count); uint o&erator DD(uint # int count); long o&erator DD(long # int count); ulong o&erator DD(ulong # int count);

El operador DD despla1a # a la i1?uierda el nHmero de bits calculados como se explica a continuaci-n. 8os bits de orden superior no comprendidos en el intervalo del tipo de resultado de # no se tienen en cuenta, los bits restantes se despla1an a la i1?uierda y las posiciones vac5as de los bits de orden in0erior se establecen en cero.

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

2'3

Especificacin del lenguaje C#

2espla1amiento a la derec=aG
int o&erator EE(int # int count); uint o&erator EE(uint # int count); long o&erator EE(long # int count); ulong o&erator EE(ulong # int count);

El operador EE despla1a # a la derec=a el nHmero de bits calculados como se explica a continuaci-n. .i # es de tipo int o long, los bits de orden in0erior de # no se tienen en cuenta, los bits restantes se despla1an a la derec=a y las posiciones vac5as de los bits de orden superior se establecen en cero si # no es negativo, y en uno si # es negativo. .i # es de tipo uint o ulong, los bits de orden in0erior de # no se tienen en cuenta, los bits restantes se despla1an a la derec=a y las posiciones vac5as de los bits de orden superior se establecen en cero. 'ara los operadores prede0inidos, el nHmero de bits del despla1amiento se calcula como se explica a continuaci-nG .i el tipo de # es int o uint, el valor del despla1amiento viene dado por los cinco bits de orden in0erior de count. Es decir, el recuento del despla1amiento se calcula a partir de count F 3#2V. .i el tipo de # es long o ulong, el valor del despla1amiento viene dado por los seis bits de orden in0erior de count. Es decir, el recuento del despla1amiento se calcula a partir de count F 3#9V.

.i el valor del despla1amiento resultante es cero, los operadores de despla1amiento sencillamente devuelven el valor de #. 8as operaciones de despla1amiento nunca causan desbordamientos y producen el mismo resultado en los contextos c"ec(ed y unc"ec(ed. .i el operando i1?uierdo del operador EE es de un tipo integral con signo, el operador reali1a un despla1amiento arit%?tico a la derec=a, en el cual el valor del bit m(s signi0icativo Oel bit de signoR del operando se propaga a las posiciones vac5as de los bits de orden superior. .i el operando i1?uierdo del operador EE es de un tipo integral sin signo, el operador reali1a un despla1amiento l/&ico a la derec=a, en el cual las posiciones vac5as de los bits de orden superior siempre se establecen en cero. 'ara reali1ar la operaci-n opuesta de la in0erida a partir del tipo del operando, pueden utili1arse conversiones expl5citas. 'or e$emplo, si # es una variable de tipo int, la operaci-n unc"ec(ed((int)((uint)# EE y)) reali1a un despla1amiento l-gico a la derec=a de #.

+.. ,peradores de comprobacin de tipos y relacionales


8os operadores ++, @+, D, E, D+, E+, is y as se denominan operadores relacionales y de comprobaci-n de tipos. relational-e2pression1 shift-e2pression relational-e2pression relational-e2pression relational-e2pression relational-e2pression relational-e2pression relational-e2pression

D shift-e2pression E shift-e2pression D+ shift-e2pression E+ shift-e2pression is t#pe as t#pe

e6 alit#-e2pression1 relational-e2pression e6 alit#-e2pression ++ relational-e2pression e6 alit#-e2pression @+ relational-e2pression El operador is se describe en [*.+.1", y el operador as en [*.+.11.

2'#

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

8os operadores ++, @+, D, E, D+ y E+ son operadores de co paraci,n. 'ara una operaci-n con la 0orma # op y, donde op es un operador de comparaci-n, se aplica la resoluci-n de sobrecargas de operadores binarios O[R para seleccionar una implementaci-n de operador concreta. 8os operandos se convierten a los tipos de par(metro del operador seleccionado, y el tipo del resultado es el tipo de valor devuelto por el operador. 8os operadores de comparaci-n prede0inidos se describen en las siguientes secciones. Todos los operadores de comparaci-n prede0inidos devuelven un resultado de tipo bool, como se muestra en la tabla siguiente. 7peracin
# ++ y # @+ y #Dy #Ey # D+ y # E+ y

/esultado
true si # es igual a y, -alse en los dem(s casos true si # no es igual a y, -alse en los dem(s casos true si # es menor ?ue y, -alse en los dem(s casos true si # es mayor ?ue y, -alse en los dem(s casos true si # es menor o igual ?ue y, -alse en los dem(s casos true si # es mayor o igual ?ue y, -alse en los dem(s casos

+...1 ,peradores de comparacin de enteros 8os operadores de comparaci-n de enteros prede0inidos sonG
bool bool bool bool bool bool bool bool bool bool bool bool bool bool bool bool bool bool bool bool bool bool bool bool o&erator o&erator o&erator o&erator o&erator o&erator o&erator o&erator o&erator o&erator o&erator o&erator o&erator o&erator o&erator o&erator o&erator o&erator o&erator o&erator o&erator o&erator o&erator o&erator ++(int # int y); ++(uint # uint y); ++(long # long y); ++(ulong # ulong y); @+(int # int y); @+(uint # uint y); @+(long # long y); @+(ulong # ulong y); D(int # int y); D(uint # uint y); D(long # long y); D(ulong # ulong y); E(int # int y); E(uint # uint y); E(long # long y); E(ulong # ulong y); D+(int # int y); D+(uint # uint y); D+(long # long y); D+(ulong # ulong y); E+(int # int y); E+(uint # uint y); E+(long # long y); E+(ulong # ulong y);

Todos estos operadores comparan los valores num)ricos de los dos operandos enteros y devuelven un valor bool ?ue indica si la relaci-n concreta es true o -alse.

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

2'!

Especificacin del lenguaje C#

+...2 ,peradores de comparacin de punto flotante 8os operadores de comparaci-n de punto 0lotante prede0inidos sonG
bool o&erator ++(-loat # -loat y); bool o&erator ++(double # double y); bool o&erator @+(-loat # -loat y); bool o&erator @+(double # double y); bool o&erator D(-loat # -loat y); bool o&erator D(double # double y); bool o&erator E(-loat # -loat y); bool o&erator E(double # double y); bool o&erator D+(-loat # -loat y); bool o&erator D+(double # double y); bool o&erator E+(-loat # -loat y); bool o&erator E+(double # double y);

8os operadores comparan los operandos segHn las reglas del est(ndar !EEE * 4G .i uno de los operandos es 4a4, el resultado es -alse para todos los operadores excepto @+, cuyo resultado es true. 'ara dos operandos cuales?uiera, # @+ y siempre produce el mismo resultado ?ue @(# ++ y). 4o obstante, si uno o los dos operandos son 4a4, los operadores D, E, D+ y E+ no prod cen el mismo resultado ?ue la negaci-n l-gica del operador opuesto. 'or e$emplo, si # o y es 4a4, entonces # D y es -alse, pero @ (# E+ y) es true. .i ninguno de los operandos es 4a4, los operadores comparan los valores de los dos operandos de punto 0lotante con respecto al orden
Ce D Cma# D ... D Cmin D C3.3 ++ <3.3 D <min D ... D <ma# D <e

donde min y ma# son los valores 0initos positivos m(ximo y m5nimo ?ue pueden representarse en el 0ormato de punto 0lotante. .on e0ectos notables de este ordenG o o o El cero negativo y el positivo se consideran iguales. 7n in0inito negativo se considera menor ?ue todos los dem(s valores, pero igual ?ue otro in0inito negativo. 7n in0inito positivo se considera mayor ?ue todos los dem(s valores, pero igual ?ue otro in0inito positivo.

+...3 ,peradores de comparacin decimales 8os operadores de comparaci-n de decimales prede0inidos sonG
bool o&erator ++(decimal # bool o&erator @+(decimal # bool o&erator D(decimal # bool o&erator E(decimal # bool o&erator D+(decimal # bool o&erator E+(decimal # decimal y); decimal y); decimal y); decimal y); decimal y); decimal y);

Todos estos operadores comparan los valores num)ricos de los dos operandos decimales y devuelven un valor bool ?ue indica si la relaci-n concreta es true o -alse. Cada comparaci-n de decimales e?uivale al uso del operador relacional o de igualdad correspondiente de tipo System.6ecimal.

2'6

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

+...! ,peradores de igualdad booleanos 8os operadores de igualdad booleanos prede0inidos sonG
bool o&erator ++(bool # bool o&erator @+(bool # bool y); bool y);

El resultado de ++ es true si tanto # como y son true o si tanto # como y son -alse. 2e lo contrario, el resultado es -alse. El resultado de @+ es -alse si tanto # como y son true o si tanto # como y son -alse. 2e lo contrario, el resultado es true. .i los operandos son de tipo bool, el operador @+ produce el mismo resultado ?ue G. +...# ,peradores de comparacin de tipo de enumeracin Todos los tipos de enumeraci-n proporcionan impl5citamente los siguientes operadores de comparaci-n prede0inidosG
bool o&erator ++() # bool o&erator @+() # bool o&erator D() # bool o&erator E() # bool o&erator D+() # bool o&erator E+() # ) y); ) y); ) y); ) y); ) y); ) y);

El resultado de evaluar # op y, donde # e y son expresiones de un tipo de enumeraci-n ) con un tipo subyacente ;, y op es uno de los operadores de comparaci-n, es exactamente el mismo ?ue el de evaluar ((;)#) op ((;)y). Esto es lo mismo ?ue decir ?ue los operadores de comparaci-n de tipo de enumeraci-n sencillamente comparan los valores subyacentes integrales de los dos operandos. +...$ ,peradores de igualdad de tipos de referencia 8os operadores de igualdad de tipos de re0erencia prede0inidos sonG
bool o&erator ++(object # bool o&erator @+(object # object y); object y);

8os operadores devuelven el resultado de comparar la igualdad o desigualdad de las dos re0erencias. 2ado ?ue los operadores de igualdad de tipos de re0erencia prede0inidos aceptan operandos de tipo object, se aplican a todos los tipos ?ue no declaran miembros aplicables o&erator ++ y o&erator @+. & la inversa, cual?uier operador de igualdad aplicable de0inido por el usuario oculta los operadores de igualdad prede0inidos de tipos de re0erencia. 8os operadores de igualdad de tipos de re0erencia prede0inidos re?uieren uno de los siguientes puntosG bue los dos operandos sean valores de tipo de re0erencia Oreference-t#peR o el literal null. &dem(s, re?uieren ?ue exista una conversi-n impl5cita est(ndar O[#.3.1R del tipo de uno de los operandos al tipo del otro operando. bue un operando sea un valor de tipo 1 donde 1 es un par(metro de tipo Ot#pe-para%eterR y el otro operando sea el literal null. &dem(s, 1 no debe tener la restricci-n de tipo de valor.

& menos ?ue una de estas dos condiciones sean verdaderas, se producir( un error de compilaci-n. .on implicaciones notables de estas reglasG 'roduce un error durante la compilaci-n utili1ar los operadores de igualdad de tipos de re0erencia prede0inidos para comparar dos re0erencias de las ?ue se sabe ?ue son di0erentes en tiempo de compilaci-n.

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

2'(

Especificacin del lenguaje C#

'or e$emplo, si los tipos de los operandos en tiempo de compilaci-n 0ueran dos tipos de clases ' y :, y si ni ' ni : se derivaran del otro, no ser5a posible ?ue los operandos =icieran re0erencia al mismo ob$eto. 'or lo tanto, la operaci-n se considera un error de compilaci-n. 8os operadores de igualdad de tipos de re0erencia prede0inidos no permiten la comparaci-n de operandos de tipo de valor. 'or lo tanto, salvo ?ue un tipo struct declare sus propios operadores de igualdad, no es posible comparar valores de ese tipo struct. 8os operadores de igualdad de tipos de re0erencia prede0inidos nunca causan operaciones boxing para sus operandos. 4o tendr5a sentido reali1ar este tipo de operaciones boxing, puesto ?ue las re0erencias a las instancias convertidas mediante boxing reci)n asignadas di0erir5an necesariamente de todas las dem(s re0erencias. .i un operando de un tipo 1 de par(metro de tipo se compara con null, y el tipo en tiempo de e$ecuci-n de 1 es un tipo de valor, el resultado de la comparaci-n es -alse.
class CD1E { void V(1 #) { i- (# ++ null) t"ro, ne, 'rgumentNull)#ce&tion(); ... ! !

En el siguiente e$emplo se comprueba si un argumento de un tipo de par(metro de tipo sin restricciones es null.

8a construcci-n # ++ null se permite aun?ue 1 represente un tipo de valor y el resultado se de0ina simplemente como -alse cuando 1 es un tipo de valor. 'ara una operaci-n con la 0orma # ++ y o # @+ y, si existe un o&erator ++ u o&erator @+ aplicable, las reglas de resoluci-n de sobrecargas de operador O[R seleccionan este operador en lugar del operador de igualdad de tipos de re0erencia prede0inido. 4o obstante, siempre es posible seleccionar el operador de igualdad de tipos de re0erencia prede0inido mediante la conversi-n expl5cita de uno o los dos operandos al tipo object. En el e$emplo
using System; class 1est { static void Main() { string s + "1est"; string t + string.Co&y(s); Console.WriteLine(s ++ t); Console.WriteLine((object)s ++ t); Console.WriteLine(s ++ (object)t); Console.WriteLine((object)s ++ (object)t); ! !

produce el resultado
1rue Valse Valse Valse

8as variables s y t =acen re0erencia a las dos instancias Hnicas de string ?ue contienen los mismos caracteres. 8a primera comparaci-n produce 1rue a causa de la selecci-n del operador de igualdad de cadenas prede0inido O[*.+.*R cuando los dos operandos son de tipo string. Todas las comparaciones restantes producen Valse a causa de la selecci-n del operador de igualdad de tipos de re0erencia prede0inido cuando uno o los dos operandos son de tipo object.

2'$

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

T)ngase en cuenta ?ue la t)cnica anterior no tiene sentido para los tipos de valor. En el e$emplo
class 1est { static void Main() { int i + 289; int j + 289; System.Console.WriteLine((object)i ++ (object)j); ! !

produce Valse por?ue las conversiones de tipos crean re0erencias a dos instancias distintas de valores int convertidos mediante boxing. +...+ ,peradores de igualdad de cadenas 8os operadores de igualdad de cadenas prede0inidos sonG
bool o&erator ++(string # bool o&erator @+(string # string y); string y);

2os valores string se consideran iguales cuando una de las siguientes condiciones es verdaderaG 8os dos valores son null. 8os dos valores son re0erencias no nulas a instancias de cadenas ?ue tienen una longitud id)ntica y caracteres id)nticos en cada posici-n de car(cter.

8os operadores de igualdad de cadenas comparan valores de cadenas y no referencias a cadenas. Cuando dos instancias de cadena distintas contienen exactamente la misma secuencia de caracteres, los valores de las cadenas son iguales, pero las re0erencias son di0erentes. Como se explica en la [*.+.#, los operadores de igualdad de tipos de re0erencia sirve para comparar re0erencias de cadenas en lugar de valores de cadenas. +...- ,peradores de igualdad de delegados Todos los tipos delegados proporcionan impl5citamente los siguientes operadores de comparaci-n prede0inidosG
bool o&erator ++(System.6elegate # bool o&erator @+(System.6elegate # System.6elegate y); System.6elegate y);

2os instancias de delegados se consideran iguales en los siguientes casosG .i una de las instancias de delegado es null, son iguales si y solamente si las dos son null. .i los dos delegados tienen un tipo en tiempo de e$ecuci-n di0erente, no ser(n nunca iguales. .i ambas instancias de delegado tienen una lista de invocaciones O[1 .1R, dic=as instancias son iguales si y solamente si sus listas de invocaciones tienen la misma longitud, y cada entrada de la lista de invocaciones de una es igual a la entrada correspondiente Ocomo se de0ine a continuaci-nR, por orden, de la lista de invocaciones de la otra. .i dos entradas de las listas de invocaciones =acen re0erencia al mismo m)todo est(tico, entonces las entradas se consideran iguales. .i dos entradas de las listas de invocaciones =acen re0erencia al mismo m)todo no est(tico en el mismo ob$eto de destino Otal como de0inen los operadores de igualdad de re0erenciaR, se considera ?ue las entradas son iguales.

8as entradas de las listas de invocaciones deben cumplir las siguientes reglasG

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

2'"

Especificacin del lenguaje C#

8as entradas de las listas de invocaci-n generadas en la evaluaci-n de expresiones de 0unciones an-nimas Oanon#%o s-f nction-e2pressionsR de sem(ntica id)ntica con el mismo con$unto Oposiblemente vac5oR de instancias de variables externas capturadas pueden ser iguales Oaun?ue no es obligatorioR.

+.... ,peradores de igualdad y 1566 8os operadores ++ y Ei permiten ?ue un operando sea un valor de un tipo ?ue acepta valores 4788 y el otro el literal null, incluso si no existe un operador prede0inido ni de0inido por el usuario Oen 0ormato de elevaci-n o de no elevaci-nR para la operaci-n. 'ara una operaci-n con las estructuras
# ++ null null ++ # # @+ null null @+ #

donde # es una expresi-n de un tipo ?ue acepta valores 4788, si la resoluci-n de sobrecargas de operadores O[*.2.4R no encuentra un operador aplicable, el resultado se calcula a partir de la propiedad HasUalue de #. En concreto, las primeras dos estructuras se traducen como @#.HasUalue y las Hltimas dos estructuras se traducen como #.HasUalue. +...10 ,perador Is El operador is se utili1a para comprobar din(micamente si el tipo en tiempo de e$ecuci-n de un ob$eto es compatible con un tipo dado. El resultado de la operaci-n ) is 1, donde ) es una expresi-n y 1 es un tipo, es un valor booleano ?ue indica si ) puede convertirse de 0orma satis0actoria al tipo 1 mediante una conversi-n de re0erencias, una conversi-n boxing o una conversi-n unboxing. 8a operaci-n se evalHa de la siguiente manera, una ve1 sustituidos los argumentos de tipo por todos los par(metros de tipoG .i ) es una 0unci-n an-nima, se produce un error durante la compilaci-n .i ) es un grupo de m)todos o el literal null, o si el tipo de ) es un tipo de re0erencia o un tipo ?ue acepta valores 4788 y el valor de ) es null, el resultado es 0alse. 2e lo contrario, 6 representa el tipo din(mico de ) de la siguiente maneraG o o o o .i el tipo de ) es un tipo de re0erencia, 6 es el tipo en tiempo de e$ecuci-n de la instancia a la ?ue ) =ace re0erencia. .i el tipo de ) es un tipo ?ue acepta valores 4788, 6 es el tipo subyacente del tipo ?ue acepta valores 4788. .i el tipo de ) es un tipo de valor ?ue no acepta valores 4788, 6 es el tipo de ). .i 1 es un tipo de re0erencia, el resultado es true si 6 y 1 son el mismo tipo, si 6 es un tipo de re0erencia y existe una conversi-n de re0erencia impl5cita de 6 a 1 o si 6 es un tipo de valor y existe una conversi-n boxing de 6 a 1. .i 1 es un tipo ?ue acepta valores 4788, el resultado es true si 6 es el tipo subyacente de 1. .i 1 es un tipo de valor ?ue no acepta valores 4788, el resultado es true si 6 y 1 son el mismo tipo. 2e lo contrario, el resultado es -alse.

El resultado de la operaci-n depende de 6 y 1 de la siguiente maneraG

o o o

Tenga en cuenta ?ue el operador is no tiene en cuenta las conversiones de0inidas por el usuario. +...11 ,perador 's El operador as permite convertir expl5citamente un valor a un tipo de re0erencia dado mediante una conversi-n de re0erencia o tipo ?ue acepta valores 4788. & di0erencia de una expresi-n de conversi-n de tipos O[*.#.#R, el

21'

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

operador as nunca inicia una excepci-n. En lugar de ello, si la conversi-n indicada no es posible, el valor resultante es null. En una operaci-n con la estructura ) as 1, ) debe ser una expresi-n y 1 debe ser un tipo de re0erencia, un par(metro de tipo conocido como un tipo de re0erencia o un tipo ?ue acepta valores 4788. &l menos una de las siguientes a0irmaciones debe ser trueV de lo contrario, se genera un error en tiempo de compilaci-nG Existe una conversi-n de identidad O[#.1.1R, una conversi-n impl5cita ?ue acepta valores null, O[#.1.4R, una conversi-n de re0erencia impl5cita O[#.1.#R, una conversi-n boxing O[#.1.*R, una conversi-n expl5cita ?ue acepta valores nullO[#.2.3R una conversi-n de re0erencia O[#.2.4R o una conversi-n unboxing O[#.2. R desde ) a 1. El tipo de ) o 1 es un tipo abierto.
) es el literal null. ) is 1 7 (1)()) / (1)null

8a operaci-n ) as 1 genera el mismo resultado ?ue salvo ?ue ) s-lo se evalHa una ve1. .e puede esperar ?ue el compilador optimice ) as 1 para reali1ar como m(ximo una comprobaci-n de tipo din(mico por oposici-n a las dos comprobaciones de tipo din(mico implicadas por la expansi-n anterior.

Tenga en cuenta ?ue algunas conversiones, como las de0inidas por el usuario, no son posibles con el operador as y deben reali1arse mediante expresiones de conversi-n de tipos OcastR. En el e$emplo
class I { &ublic string V(object o) { return o as string; .. %a ! string is a re-erence ty&e

&ublic 1 SD1E(object o) ,"ere 1/ 'ttribute { return o as 1; .. %( 1 "as a class constraint ! &ublic ; HD;E(object o) { return o as ;; ! ! .. )rror ; is unconstrained

el par(metro de tipo 1 de S es un tipo de re0erencia, por?ue tiene la restricci-n de clase. .in embargo, el par(metro de tipo ; de H no lo esV por lo tanto, no se permite el uso del operador as en H.

+.10 ,peradores lgicos


8os operadores F, G y H se denominan operadores l-gicos. and-e2pression1 e6 alit#-e2pression and-e2pression F e6 alit#-e2pression e2cl sive-or-e2pression1 and-e2pression e2cl sive-or-e2pression G and-e2pression incl sive-or-e2pression1 e2cl sive-or-e2pression incl sive-or-e2pression H e2cl sive-or-e2pression

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

211

Especificacin del lenguaje C#

'ara una operaci-n con la 0orma # op y, donde op es uno de los operadores l-gicos, se aplica la resoluci-n de sobrecargas de operadores binarios O[R para seleccionar una implementaci-n de operador concreta. 8os operandos se convierten a los tipos de par(metro del operador seleccionado, y el tipo del resultado es el tipo de valor devuelto por el operador. 8os operadores l-gicos prede0inidos se describen en las siguientes secciones. +.10.1 ,peradores lgicos enteros 8os operadores l-gicos enteros prede0inidos sonG
int o&erator F(int # int y); uint o&erator F(uint # uint y); long o&erator F(long # long y); ulong o&erator F(ulong # ulong y); int o&erator H(int # int y); uint o&erator H(uint # uint y); long o&erator H(long # long y); ulong o&erator H(ulong # ulong y); int o&erator G(int # int y); uint o&erator G(uint # uint y); long o&erator G(long # long y); ulong o&erator G(ulong # ulong y);

El operador F calcula la operaci-n l-gica 'N6 bit a bit de los dos operandos, el operador H calcula la operaci-n l-gica %O bit a bit de los dos operandos y el operador G calcula la operaci-n l-gica %O exclusivo bit a bit de los dos operandos. 8os desbordamientos no son posibles en estas operaciones. +.10.2 ,peradores lgicos de enumeracin Todo tipo de enumeraci-n ) proporciona impl5citamente los siguientes operadores l-gicos prede0inidosG
) o&erator F() # ) o&erator H() # ) o&erator G() # ) y); ) y); ) y);

El resultado de evaluar # op y, donde # e y son expresiones de un tipo de enumeraci-n ) con un tipo subyacente ;, y op es uno de los operadores l-gicos, es exactamente el mismo ?ue el de evaluar OER((;)# op (;)y). Esto es lo mismo ?ue decir ?ue los operadores l-gicos de tipo de enumeraci-n sencillamente e$ecutan la operaci-n l-gica en el tipo subyacente de los dos operandos. +.10.3 ,peradores lgicos booleanos 8os operadores l-gicos booleanos prede0inidos sonG
bool o&erator F(bool # bool o&erator H(bool # bool o&erator G(bool # bool y); bool y); bool y);

El resultado de # F y es true si tanto # como y son true. 2e lo contrario, el resultado es -alse. El resultado de # H y es true si # o y es true. 2e lo contrario, el resultado es -alse. El resultado de # G y es true si # es true e y es -alse, o si # es -alse e y es true. 2e lo contrario, el resultado es -alse. .i los operandos son de tipo bool, el operador G calcula el mismo resultado ?ue el operador @+.

212

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

+.10.! ,peradores lgicos booleanos ;ue aceptan alores 1566 El tipo booleano bool7 ?ue acepta valores 4788 puede representar tres valores, true, -alse y null, y es conceptualmente similar al tipo de tres valores utili1ado por expresiones booleanas en .b8. 'ara asegurarse de ?ue los resultados generados por los operadores F y H para los operandos bool7 son co=erentes con la l-gica de tres valores de .b8 se proporcionan los siguientes operadores prede0inidosG
bool7 o&erator F(bool7 # bool7 o&erator H(bool7 # bool7 y); bool7 y);

En la siguiente tabla se enumeran los resultados generados por estos operadores para todas las combinaciones de los valores true, -alse y null.
# true true true -alse -alse -alse null null null y true -alse null true -alse null true -alse null # F y true -alse null -alse -alse -alse null -alse null # H y true true true true -alse null true null null

+.11 ,peradores lgicos condicionales


8os operadores FF y HH se denominan operadores l-gicos condicionales. Tambi)n se conocen como operadores l-gicos de evaluaci-n PcortocircuitadaQ. conditional-and-e2pression1 incl sive-or-e2pression conditional-and-e2pression FF incl sive-or-e2pression conditional-or-e2pression1 conditional-and-e2pression conditional-or-e2pression HH conditional-and-e2pression 8os operadores FF y HH son versiones condicionales de los operadores F y HG 8a operaci-n # FF y corresponde a la operaci-n # F y, excepto ?ue y se evalHa solamente si # no es -alse. 8a operaci-n # HH y corresponde a la operaci-n # H y, excepto ?ue y se evalHa solamente si # no es true.

7na operaci-n de la 0orma # FF y o # HH y se procesa mediante la aplicaci-n de la resoluci-n de sobrecargas O[*.2.4R como si la operaci-n estuviera escrita como # F y o # H y. Entonces, .i la resoluci-n de sobrecargas no encuentra un solo operador me$or o selecciona uno de los operadores l-gicos enteros prede0inidos, se produce un error durante la compilaci-n. En caso contrario, si el operador seleccionado es uno de los operadores l-gicos booleanos prede0inidos O[*.1".3R u operadores l-gicos booleanos ?ue aceptan valores 4788 O[*.1".4R, la operaci-n se procesa como se explica en la secci-n [*.11.1.

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

213

Especificacin del lenguaje C#

/ bien, el operador seleccionado es un operador de0inido por el usuario y la operaci-n se procesa como se explica en [*.11.2.

4o es posible sobrecargar directamente los operadores l-gicos condicionales. 4o obstante, dado ?ue los operadores l-gicos condicionales se evalHan en t)rminos de los operadores l-gicos regulares, las sobrecargas de )stos, con algunas restricciones, tambi)n se consideran sobrecargas de los operadores l-gicos condicionales. Esta categor5a se explica con m(s detalle en la secci-n [*.11.2. +.11.1 ,peradores lgicos condicionales booleanos .i los operandos de FF o HH son de tipo bool, o si los operandos son de tipos ?ue no de0inen un o&erator F o un o&erator H aplicable, pero s5 de0inen conversiones impl5citas a bool, la operaci-n se procesa como sigueG 8a operaci-n # FF y se evalHa como # 7 y / -alse. En otras palabras, primero se evalHa # y se convierte al tipo bool. 2espu)s, si # es true, y se evalHa y se convierte al tipo bool, y se convierte en el resultado de la operaci-n. 2e lo contrario, el resultado de la operaci-n es -alse. 8a operaci-n # HH y se evalHa como # 7 true / y. En otras palabras, primero se evalHa # y se convierte al tipo bool. 2espu)s, si el valor de # es true, el resultado de la operaci-n es true. / bien, y se evalHa y se convierte al tipo bool, y pasa a ser el resultado de la operaci-n.

+.11.2 ,peradores lgicos condicionales definidos por el usuario .i los operandos de FF o de HH son de tipos ?ue declaran un operador o&erator F o un operador o&erator H aplicable de0inidos por el usuario, las dos siguientes declaraciones deben ser verdaderas, donde 1 es el tipo en ?ue se declara el operador seleccionadoG El tipo del valor devuelto y el tipo de todos los par(metros del operador seleccionado debe ser 1. Es decir, el operador debe calcular el 'N6 l-gico o el %O l-gico de los dos operandos de tipo 1, y debe devolver un resultado de tipo 1.
1 debe contener declaraciones de o&erator true y o&erator -alse.

.i alguno de estos re?uisitos no se satis0ace, se produce un error de compilaci-n. / bien, la operaci-n FF o HH se evalHa mediante la combinaci-n de operadores o&erator true u o&erator -alse de0inidos por el usuario con el operador seleccionado de0inido por el usuarioG 8a operaci-n # FF y se evalHa como 1.-alse(#) 7 # / 1.F(# y), donde 1.-alse(#) es una invocaci-n del elemento o&erator -alse declarado en 1, y 1.F(# y) es una invocaci-n del elemento o&erator F seleccionado. En otras palabras, # es el primero en evaluarse y se invoca o&erator -alse en el resultado para averiguar si # es de0initivamente 0alse. 2espu)s, si # es de0initivamente 0alse, el resultado de la operaci-n es el valor previamente calculado para #. 2e lo contrario, se evalHa y y se invoca el operador o&erator F seleccionado en el valor previamente calculado para # y el valor calculado para y, a 0in de producir el resultado de la operaci-n. 8a operaci-n # HH y se evalHa como 1.true(#) 7 # / 1.H(# y), donde 1.true(#) es una invocaci-n del elemento o&erator true declarado en 1, y 1.H(# y) es una invocaci-n del elemento o&erator H seleccionado. En otras palabras, # es el primero en evaluarse y se invoca o&erator true en el resultado para averiguar si # es de0initivamente true. 2espu)s, si # es de0initivamente true, el resultado de la operaci-n es el valor previamente calculado para #. 2e lo contrario, se evalHa y y se invoca el operador o&erator H seleccionado en el valor previamente calculado para # y el valor calculado para y, a 0in de producir el resultado de la operaci-n.

En cual?uiera de estas operaciones, la expresi-n dada por # se evalHa una sola ve1, y la expresi-n dada por y no se evalHa o bien se evalHa exactamente una ve1. 'ara obtener un e$emplo de un tipo ?ue implementa o&erator true y o&erator -alse, vea [11.4.2.
21#

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

+.12 El operador de uso combinado de 1566


El operador 77 se denomina operador de uso combinado de 4788. n ll-coalescin&-e2pression1 conditional-or-e2pression conditional-or-e2pression 77 n ll-coalescin&-e2pression 7na expresi-n de uso combinado de 4788 con la estructura a 77 b re?uiere ?ue a sea un tipo ?ue acepta valores 4788 o un tipo de re0erencia. .i a no es 4788, el resultado de a 77 b es aV de lo contrario, el resultado es b. 8a operaci-n evalHa b s-lo si a es 4788. El operador de uso combinado de 4788 es asociativo por la derec=a, lo ?ue signi0ica ?ue las operaciones se agrupan de derec=a a i1?uierda. 'or e$emplo, una expresi-n con la 0orma a 77 b 77 c se evalHa como a 77 (b 77 c). En t)rminos generales, una expresi-n con la estructura )2 77 )8 77 ... 77 )N devuelve el primero de los operandos ?ue no es 4788 o ?ue lo es si todos son 4788. El tipo de expresi-n a 77 b depende de ?u) conversiones impl5citas est(n disponibles entre los tipos de operandos. En orden de pre0erencia, el tipo de a 77 b es '3, ', o :, donde ' es el tipo de a, : es el tipo de b Osiempre ?ue b tenga un tipoR, y '3 es el tipo subyacente de ' si ' es un tipo ?ue acepta valores 4788, o, en caso contrario, '. En concreto, a 77 b se procesa de la siguiente maneraG .i ' no es un tipo ?ue acepta valores 4788 o un tipo de re0erencia, se genera un error en tiempo de compilaci-n. .i ' es un tipo ?ue acepta valores 4788 y existe una conversi-n impl5cita de b a '3, el tipo de resultado es '3. En tiempo de e$ecuci-n, a se evalHa en primer lugar. .i a no es 4788, a se desa$usta en el tipo '3y )ste se convierte en el resultado. 2e lo contrario, b se evalHa y se convierte al tipo '3y )ste se convierte en el resultado. 2e lo contrario, si existe una conversi-n impl5cita de b a ', el tipo de resultado es '. En tiempo de e$ecuci-n, a se evalHa primero. .i a no es 4788, a se convierte en el resultado. 2e lo contrario, b se evalHa y se convierte al tipo ' y )ste se convierte en el resultado. 2e lo contrario, si b tiene un tipo : existe una conversi-n impl5cita de '3 a :, el tipo de resultado es :. En tiempo de e$ecuci-n, a se evalHa primero. .i a no es 4788, a se desa$usta en el tipo '3 Oa menos ?ue ' y '3 sean del mismo tipoR y se convierte en tipo : y )ste se convierte en el resultado. 2e lo contrario, b se evalHa y se convierte en el resultado. 2e lo contrario, a y b son incompatibles y se genera un error en tiempo de compilaci-n.

+.13 ,perador condicional


El operador 7/ se denomina operador condicional. & veces tambi)n se le denomina operador ternario. conditional-e2pression1 n ll-coalescin&-e2pression n ll-coalescin&-e2pression 7 e2pression / e2pression 7na expresi-n condicional con la estructura b 7 # / y evalHa en primer lugar la condici-n b. 2espu)s, si el valor de b es true, se evalHa # y pasa a ser el resultado de la operaci-n. 2e lo contrario, se evalHa y, ?ue se convierte en el resultado de la operaci-n. 7na expresi-n condicional nunca evalHa # e y. El operador condicional es asociativo por la derec=a, lo ?ue signi0ica ?ue las operaciones se agrupan de derec=a a i1?uierda. 'or e$emplo, una expresi-n con la 0orma a 7 b / c 7 d / e se evalHa como a 7 b / (c 7 d / e).

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

21!

Especificacin del lenguaje C#

El primer operando del operador 7/ debe ser una expresi-n de un tipo ?ue pueda convertirse impl5citamente a bool o una expresi-n de un tipo ?ue implemente o&erator true. .i no se cumple ninguna de estas dos condiciones, se producir( un error de compilaci-n. El segundo y tercer operandos del operador 7/ controlan el tipo de la expresi-n condicional. .upongamos ?ue I e ` sean los tipos del segundo y tercer operandos. EntoncesG .i I e ` son del mismo tipo, entonces )ste es el tipo de la expresi-n condicional. / bien, si existe una conversi-n impl5cita O[#.1R de I a `, pero no de ` a I, entonces ` es el tipo de la expresi-n condicional. / bien, si existe una conversi-n impl5cita O[#.1R de ` a I, pero no de I a `, entonces I es el tipo de la expresi-n condicional. En caso contrario, no puede determinarse una expresi-n y se produce un error de compilaci-n.

El procesamiento en tiempo de e$ecuci-n de una expresi-n condicional con la estructura b 7 # / y consta de los siguientes pasosG En primer lugar, se evalHa b y se determina el valor bool de bG o o .i existe una conversi-n impl5cita del tipo de b a bool, se e$ecuta dic=a conversi-n para generar un valor bool. 2e lo contrario, se invoca el o&erator true de0inido por el tipo de b para generar un valor bool.

.i el valor bool producido por el paso anterior es true, entonces se evalHa # y se convierte al tipo de la expresi-n condicional, ?ue pasa a ser el resultado de la expresi-n condicional. / bien, y se evalHa y se convierte al tipo de la expresi-n condicional, y pasa a ser el resultado de dic=a de expresi-n.

+.1! E"presiones de funciones annimas


7na f!nci,n an,ni a es una expresi-n ?ue representa una de0inici-n de m)todo Pen l5neaQ. 7na 0unci-n an-nima no tiene un valor de por s5, pero se puede convertir en un tipo de (rbol de expresiones o un tipo delegado compatible. 8a evaluaci-n de una conversi-n de 0unci-n an-nima depende del tipo de destino de la conversi-n. .i es un tipo delegado, la conversi-n se evalHa para un valor delegado ?ue =ace re0erencia al m)todo en el ?ue se de0ine la 0unci-n an-nima. .i es un tipo de (rbol de expresiones, la conversi-n se evalHa para un (rbol de expresiones ?ue representa la estructura del m)todo como una estructura de ob$etos. 'or motivos =ist-ricos =ay dos tipos sint(cticos de 0unciones an-nimas, las expresiones lambda Ola%-dae2pressionsR y las expresiones de m)todos an-nimos Oanon#%o s-%ethod-e2pressionsR. En casi todos los casos, las expresiones lambda Ola%-da-e2pressionsR son m(s concisas y expresivas ?ue las expresiones de m)todos an-nimos Oanon#%o s-%ethod-e2pressionsR, ?ue siguen presentes en el lengua$e para mantener la compatibilidad con versiones anteriores. la%-da-e2pression1 anon#%o s-f nction-si&nat re +E anon#%o s-f nction--od# anon#%o s-%ethod-e2pression1 delegate e2plicit-anon#%o s-f nction-si&nat reopt -loc3 anon#%o s-f nction-si&nat re1 e2plicit-anon#%o s-f nction-si&nat re i%plicit-anon#%o s-f nction-si&nat re

216

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

e2plicit-anon#%o s-f nction-si&nat re1 ( e2plicit-anon#%o s-f nction-para%eter-listopt ) e2plicit-anon#%o s-f nction-para%eter-list e2plicit-anon#%o s-f nction-para%eter e2plicit-anon#%o s-f nction-para%eter-list

e2plicit-anon#%o s-f nction-para%eter

e2plicit-anon#%o s-f nction-para%eter1 anon#%o s-f nction-para%eter-%odifieropt t#pe identifier anon#%o s-f nction-para%eter-%odifier1
reout

i%plicit-anon#%o s-f nction-si&nat re1 ( i%plicit-anon#%o s-f nction-para%eter-listopt ) i%plicit-anon#%o s-f nction-para%eter i%plicit-anon#%o s-f nction-para%eter-list i%plicit-anon#%o s-f nction-para%eter i%plicit-anon#%o s-f nction-para%eter-list i%plicit-anon#%o s-f nction-para%eter1 identificador anon#%o s-f nction--od#1 e2pression -loc3 El operador +E tiene la misma prioridad ?ue la asignaci-n O+R y es asociativo por la derec=a. 8os par(metros de una 0unci-n an-nima con la estructura de una expresi-n lambda Ola%-da-e2pressionR pueden tener asignaci-n de tipo impl5cita o expl5cita. En una lista de par(metros con asignaci-n de tipo expl5cita, el tipo de cada par(metro se indica de manera expl5cita. En una lista de par(metros con asignaci-n de tipo impl5cita, los tipos de los par(metros se in0ieren del contexto en el ?ue tiene lugar la 0unci-n an-nima. Concretamente, cuando la 0unci-n an-nima se convierte a un tipo delegado compatible o un tipo de (rbol de expresiones, ese tipo proporciona los tipos de par(metros O[#. R. En una 0unci-n an-nima con un solo par(metro con asignaci-n de tipo impl5cita, los par)ntesis de la lista de par(metros se pueden omitir. En otras palabras, una 0unci-n an-nima con la 0orma
( para% ) +E e2pr

i%plicit-anon#%o s-f nction-para%eter

se puede abreviar a para% +E e2pr 8a lista de par(metros de una 0unci-n an-nima con la 0orma de una expresi-n de m)todo an-nimo Oanon#%o s%ethod-e2pressionR es opcional. 8os par(metros deben tener asignaci-n de tipo expl5cita, en caso de tener tipo. .i no, la 0unci-n an-nima es convertible a un delegado con cual?uier lista de par(metros ?ue no contenga par(metros out. & continuaci-n, se muestran algunos e$emplos de 0unciones an-nimasG
# +E # < 2 # +E { return # < 2; ! (int #) +E # < 2 (int #) +E { return # < 2; ! (# y) +E # > y .. $m&licitly ty&ed .. $m&licitly ty&ed .. )#&licitly ty&ed .. )#&licitly ty&ed e#&ression body statement body e#&ression body statement body

.. Multi&le &arameters

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

21(

Especificacin del lenguaje C# () +E Console.WriteLine() delegate (int #) { return # < 2; ! delegate { return 2 < 2; ! .. No &arameters .. 'nonymous met"od e#&ression .. *arameter list omitted

El comportamiento de las expresiones lambda Ola%-da-e2pressionsR y las expresiones de m)todos an-nimos Oanon#%o s-%ethod-e2pressionsR es igual excepto en los siguientes puntosG 8as expresiones de m)todos an-nimos Oanon#%o s-%ethod-e2pressionsR permiten ?ue una lista de par(metros se omita por completo, lo ?ue tiene como resultado la convertibilidad a tipos delegados de cual?uier lista de par(metros de valor. 8as expresiones lambda Ola%-da-e2pressionsR permiten ?ue los tipos de par(metros se omitan y sean in0eridos mientras ?ue las expresiones de m)todos an-nimos Oanon#%o s-%ethod-e2pressionsR re?uieren ?ue los tipos de par(metros se indi?uen de manera expl5cita. El cuerpo de una expresi-n lambda Ola%-da-e2pressionR puede ser una expresi-n o un blo?ue de instrucciones mientras ?ue el cuerpo de una expresi-n de m)todos an-nimos Oanon#%o s-%ethode2pressionR debe ser un blo?ue de instrucciones. 2ado ?ue las expresiones lambda Ola%-da-e2pressionsR pueden tener un cuerpo de expresi-n Oe2pressionR, no se puede convertir ninguna expresi-n de m)todos an-nimos Oanon#%o s-%ethod-e2pressionR a un tipo de (rbol de expresiones O[4.#R.

+.1!.1 7irmas de funcin annima 8a 0irma opcional de 0unci-n an-nima Oanon#%o s-f nction-si&nat reR de una 0unci-n an-nima de0ine los nombres y, opcionalmente, los tipos de los par(metros 0ormales para la 0unci-n an-nima. El (mbito de los par(metros de la 0unci-n an-nima es el cuerpo de la 0unci-n an-nima Oanon#%o s-f nction--od#R. O[3.*R Junto con la lista de par(metros Osi la =ayR el cuerpo de m)todo an-nimo constituye un espacio de declaraci-n O[3.3R. 'or tanto, si el nombre de un par(metro de la 0unci-n an-nima coincide con el nombre de una variable local, una constante o un par(metro local cuyo (mbito incluya la expresi-n de m)todos an-nimos Oanon#%o s-%ethode2pressionR o la expresi-n lambda Ola%-da-e2pressionR se produce un error en tiempo de compilaci-n. .i una 0unci-n an-nima tiene una 0irma de 0unci-n an-nima expl5cita Oe2plicit-anon#%o s-f nction-si&nat reR, el con$unto de tipos delegados compatibles y los tipos de (rbol de expresiones se limitan a a?uellos con los mismos tipos de par(metros y modi0icadores en el mismo orden. &l contrario de lo ?ue ocurre con las conversiones de grupo de m)todos O[#.#R, no se admite la contravarian1a de tipos de par(metros de 0unci-n an-nima. .i una 0unci-n an-nima no tiene una 0irma de 0unci-n an-nima Oanon#%o s-f nction-si&nat reR, el con$unto de tipos delegados compatibles y tipos de (rbol de expresiones se limita a a?uellos ?ue no tienen par(metros out. Tenga en cuenta ?ue una 0irma de 0unci-n an-nima Oanon#%o s-f nction-si&nat reR no puede incluir atributos ni una matri1 de par(metros. 4o obstante, una 0irma de 0unci-n an-nima Oanon#%o s-f nction-si&nat reR puede ser compatible con un tipo delegado cuya lista de par(metros contenga una matri1 de par(metros. Tenga en cuenta ?ue una conversi-n a un tipo de (rbol de expresiones, incluso si es compatible, puede no producirse durante la compilaci-n O[4.#R. +.1!.2 %uerpos de funcin annima El cuerpo Oe2pression o -loc3R de una 0unci-n an-nima est( su$eto a las siguientes reglasG .i la 0unci-n an-nima incluye una 0irma, los par(metros especi0icados en la 0irma est(n disponibles en el cuerpo. .i la 0unci-n an-nima no tiene 0irma, se puede convertir en un tipo delegado o un tipo de expresi-n con par(metros O[#. R, pero no se puede obtener acceso a ellos en el cuerpo.

21$

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

Excepto por los par(metros re- u out especi0icados en la 0irma Osi los =ubieraR de la 0unci-n an-nima envolvente m(s cercana, si el cuerpo obtiene acceso a un par(metro re- u out se generar( un error en tiempo de compilaci-n. Cuando el tipo de t"is es un tipo de estructura y el cuerpo obtiene acceso a t"is, se generar( un error en tiempo de compilaci-n. Esta a0irmaci-n es cierta independientemente de si se trata de un acceso expl5cito Ocomo en t"is.#R o impl5cito Ocomo en #, donde # es un miembro de instancia de la estructuraR. Esta regla simplemente pro=5be dic=o acceso y no a0ecta si la bHs?ueda de miembros da como resultado un miembro de la estructura. El cuerpo tiene acceso a las variables externas O[*.14.4R de la 0unci-n an-nima. El acceso de una variable externa =ar( re0erencia a la instancia de la variable activa en el momento de la evaluaci-n de la expresi-n lambda Ola%-da-e2pressionR o la expresi-n de m)todo an-nimo Oanon#%o s-%ethod-e2pressionR O[*.14. R. .i el cuerpo contiene una instrucci-n goto, brea( o continue cuyo destino se encuentra 0uera o dentro del cuerpo de una 0unci-n an-nima contenida, se generar( un error en tiempo de compilaci-n. 7na instrucci-n return del cuerpo devuelve el control desde una invocaci-n de la 0unci-n an-nima envolvente m(s cercana, no desde el miembro de 0unci-n envolvente. 7na expresi-n especi0icada en una instrucci-n return debe ser compatible con el tipo de delegado o un tipo de (rbol de expresiones al ?ue se convierte la expresi-n lambda Ola%-da-e2pressionR o la expresi-n de m)todo an-nimo Oanon#%o s-%ethode2pressionR envolvente m(s cercana O[#. R.

4o se especi0ica expl5citamente si se puede e$ecutar el blo?ue de una 0unci-n an-nima de otra manera ?ue no sea mediante la evaluaci-n y la invocaci-n de la expresi-n lambda Ola%-da-e2pressionR o la expresi-n de m)todo an-nimo Oanon#%o s-%ethod-e2pressionR. En concreto, el compilador puede implementar una 0unci-n an-nima si sinteti1a uno o m(s m)todos o tipos con nombre. 8os nombres de dic=os elementos sinteti1ados deben tener la 0orma reservada para uso del compilador. +.1!.3 9esolucin de sobrecargas 8as 0unciones an-nimas de una lista de argumentos participan en la resoluci-n de sobrecargas y en la in0erencia de tipos. 'ara conocer las reglas exactas vea la secci-n [*.4.2.3. El e0ecto de las 0unciones an-nimas en la resoluci-n de las sobrecargas se ilustra en el siguiente e$emploG
class $temListD1E/ ListD1E { &ublic int Sum(VuncD1 intE selector) { int sum + 3; -oreac" (1 item in t"is) sum <+ selector(item); return sum; ! &ublic double Sum(VuncD1 doubleE selector) { double sum + 3; -oreac" (1 item in t"is) sum <+ selector(item); return sum; ! !

8a clase $temListD1E tiene dos m)todos Sum. Cada uno toma un argumento selector, ?ue extrae el valor ?ue se va a sumar de un elemento de la lista. El valor extra5do puede ser int o double, y la suma resultante es igualmente int o double. 8os m)todos Sum podr5an por e$emplo utili1arse para calcular sumas de una lista de l5neas de datos en un pedido.

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

21"

Especificacin del lenguaje C# class 6etail { &ublic int ;nitCount; &ublic double ;nit*rice; ... ! void Com&uteSums() { $temListD6etailE order6etails + Set%rder6etails(...); int total;nits + order6etails.Sum(d +E d.;nitCount); double order1otal + order6etails.Sum(d +E d.;nit*rice > d.;nitCount); ... !

En la primera invocaci-n de order6etails.Sum, ambos m)todos Sum son aplicables por?ue la 0unci-n an-nima d +E d.;nitCount es compatible tanto con VuncD6etail intE como con VuncD6etail doubleE. .in embargo, la resoluci-n de sobrecargas elige el primer m)todo Sum por?ue la conversi-n a VuncD6etail intE es me$or ?ue la conversi-n a VuncD6etail doubleE. En la segunda invocaci-n de order6etails.Sum, s-lo es aplicable el m)todo Sum por?ue la 0unci-n an-nima d +E d.;nit*rice > d.;nitCount produce un valor de tipo double. 'or tanto, la resoluci-n de sobrecargas elige el segundo m)todo Sum para esa invocaci-n. +.1!.! Variables e"ternas Cual?uier variable local, par(metro de valor o matri1 de par(metros en cuyo (mbito se incluya la expresi-n lambda Ola%-da-e2pressionR o una expresi-n de m)todo an-nimo Oanon#%o s-%ethod-e2pressionR se denomina varia/le e.terna de la expresi-n de 0unci-n an-nima. En un miembro de 0unci-n de instancia de una clase, el valor t"is se considera un par(metro de valor y es una variable externa de cual?uier expresi-n de 0unci-n an-nima contenida dentro del miembro de 0unci-n. #.14.4.1 .ariables e2ternas capturadas Cuando una 0unci-n an-nima =ace re0erencia a una variable externa, se dice ?ue la 0unci-n an-nima capt!r, la variable externa. 2e manera general, la duraci-n de una variable local est( limitada por la e$ecuci-n del blo?ue o de una instrucci-n a la ?ue est( asociada O[ .1.*R. .in embargo, la duraci-n de una variable externa capturada se ampl5a al menos =asta ?ue el delegado o el (rbol de expresiones creado a partir de la 0unci-n an-nima pueda convertirse en una recolecci-n de elementos no utili1ados. En el e$emplo
using System; delegate int 6(); class 1est { static 6 V() { int # + 3; 6 result + () +E <<#; return result; ! static void Main() { 6 d + V(); Console.WriteLine(d()); Console.WriteLine(d()); Console.WriteLine(d()); ! !

22'

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

la 0unci-n an-nima captura la variable local # y el per5odo de duraci-n de # se ampl5a =asta ?ue el delegado devuelto desde V pasa a 0ormar parte de la recolecci-n de elementos no utili1ados O?ue no ocurre =asta el 0inal del programaR. 'uesto ?ue todas las invocaciones de la 0unci-n an-nima operan en la misma instancia ?ue #, el resultado de este e$emplo es el siguienteG
2 8 9

Cuando una 0unci-n an-nima captura una variable local o un par(metro de valor, la variable local o el par(metro ya no se considera una variable de tipo 0i$o O[18.3R, sino una variable m-vil. 'or lo tanto, todo c-digo unsa-e ?ue adopte la direcci-n de una variable externa capturada debe primero utili1ar la instrucci-n -i#ed para 0i$ar la variable. #.14.4.2 Creacin de instancias de variables locales .e considera ?ue se crearon instancias de una variable local cuando la e$ecuci-n entra dentro del (mbito de la variable. 'or e$emplo, cuando se invoca el siguiente m)todo, se crean instancias de la variable local #, ?ue se iniciali1a tres veces, una para cada iteraci-n del bucle.
static void V() { -or (int i + 3; i D 9; i<<) { int # + i > 8 < 2; ... ! !

.in embargo, si la declaraci-n de # se despla1a 0uera del bucle, s-lo se crear( una Hnica instancia de #G
static void V() { int #; -or (int i + 3; i D 9; i<<) { # + i > 8 < 2; ... ! !

Cuando no existe captura, no se puede saber con ?u) 0recuencia exacta se crean instancias de una variable local. 'uesto ?ue los per5odos de creaci-n de instancias son independientes es posible ?ue cada ve1 ?ue se crean instancias se utilice la misma ubicaci-n de almacenamiento. .in embargo, cuando una 0unci-n an-nima captura una variable local, los e0ectos de la creaci-n de instancias son obvios. En el e$emplo
using System; delegate void 6(); class 1est { static 645 V() { 645 result + ne, 6495; -or (int i + 3; i D 9; i<<) { int # + i > 8 < 2; result4i5 + () +E { Console.WriteLine(#); !; ! return result; ! static void Main() { -oreac" (6 d in V()) d(); ! !

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

221

Especificacin del lenguaje C#

se genera el siguiente resultadoG


2 9 K

.in embargo, cuando la declaraci-n de # se traslada 0uera del bucleG


static 645 V() { 645 result + ne, 6495; int #; -or (int i + 3; i D 9; i<<) { # + i > 8 < 2; result4i5 + () +E { Console.WriteLine(#); !; ! return result; !

el resultado esG
K K K

.i un bucle 0or declara una variable de iteraci-n, la propia variable se considera declarada 0uera del bucle. 'or tanto, si el e$emplo cambia para capturar la variable de iteraci-n en s5G
static 645 V() { 645 result + ne, 6495; -or (int i + 3; i D 9; i<<) { result4i5 + () +E { Console.WriteLine(i); !; ! return result; !

s-lo se captura una instancia de la variable de iteraci-n, ?ue produce el resultadoG


9 9 9

8a 0unci-n an-nima puede compartir algunas de las variables capturadas y tener instancias separadas de otras. 'or e$emplo, si V se cambia a
static 645 V() { 645 result + ne, 6495; int # + 3; -or (int i + 3; i D 9; i<<) { int y + 3; result4i5 + () +E { Console.WriteLine("{3! {2!" ! return result; ! 2 2 8 2 9 2

<<#

<<y); !;

los tres delegados capturan la misma instancia de # y di0erentes instancias de y, y el resultado esG

2istintas 0unciones an-nimas pueden capturar la misma instancia de una variable externa. En el siguiente e$emploG
using System; delegate void Setter(int value); delegate int Setter();

222

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases class 1est { static void Main() { int # + 3; Setter s + (int value) +E { # + value; !; Setter g + () +E { return #; !; s(K); Console.WriteLine(g()); s(23); Console.WriteLine(g()); ! !

las dos 0unciones an-nimas capturan la misma instancia de la variable local # y, por lo tanto, se pueden PcomunicarQ a trav)s de dic=a variable. El resultado del e$emplo es el siguienteG
K 23

+.1!.# E"presiones de e aluacin de funciones annimas 7na 0unci-n an-nima V siempre se debe convertir a un tipo delegado 6 o un tipo de (rbol de expresiones ), ya sea directamente o mediante la e$ecuci-n de una expresi-n de creaci-n de delegado ne, 6(V). Esta conversi-n determina el resultado de la 0unci-n an-nima, como se describe en la secci-n [#. .

+.1# E"presiones de consulta


8as e.presiones de cons!lta proporcionan una sintaxis integrada de lengua$es para las consultas ?ue son similares a los lengua$es de consulta $er(r?uicos y relacionales, como .b8 y Nbuery. 6 er#-e2pression1 fro%-cla se 6 er#--od# fro%-cla se1 -rom t#peopt identifier in e2pression 6 er#--od#1 6 er#--od#-cla sesopt select-or-&ro p-cla se 6 er#-contin ationopt 6 er#--od#-cla ses1 6 er#--od#-cla se 6 er#--od#-cla ses 6 er#--od#-cla se 6 er#--od#-cla se1 fro%-cla se let-cla se where-cla se >oin-cla se >oin-into-cla se order-#-cla se let-cla se1 let identifier + e2pression where-cla se1 ,"ere -oolean-e2pression >oin-cla se1 join t#peopt identifier in e2pression on e2pression eQuals e2pression

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

223

Especificacin del lenguaje C#

>oin-into-cla se1 join t#peopt identifier in e2pression on e2pression eQuals e2pression into identifier order-#-cla se1 orderby orderin&s orderin&s1 orderin& orderin&s orderin&1 e2pression

orderin& orderin&-directionopt

orderin&-direction1
ascending descending

select-or-&ro p-cla se1 select-cla se &ro p-cla se select-cla se1


select e2pression

&ro p-cla se1 grou& e2pression by e2pression 6 er#-contin ation1 into identifier 6 er#--od# 7na expresi-n de consulta empie1a con una cl(usula -rom y termina con una cl(usula select o grou&. 8a cl(usula -rom inicial puede ir seguida de cero o m(s cl(usulas -rom, let, ,"ere, join u orderby. Cada cl(usula -rom es un generador ?ue introduce una varia/le de intervalo en los elementos de una sec!encia. Cada cl(usula let introduce una variable de intervalo ?ue representa un valor calculado mediante variables de intervalo anteriores. Cada cl(usula ,"ere es un 0iltro ?ue excluye elementos del resultado. Cada cl(usula join compara las claves especi0icadas de la secuencia de origen con las claves de otra secuencia, dando como resultado pares coincidentes. Cada cl(usula orderby reordena los elementos segHn criterios especi0icados. 8a cl(usula select o grou& 0inal especi0ica la 0orma del resultado en t)rminos de variables de intervalo. 'or Hltimo, una cl(usula into se puede usar para P$untarQ consultas tratando los resultados de una consulta como un generador en una consulta subsiguiente. +.1#.1 'mbigAedad en e"presiones de consulta 8as expresiones de consulta contienen varias Ppalabras clave contextualesQ, es decir, identi0icadores ?ue tienen un signi0icado especial en un contexto dado. Concretamente, se trata de -rom, ,"ere, join, on, eQuals, into, let, orderby, ascending, descending, select, grou& y by. 'ara evitar ambigIedades en las expresiones de consultas originadas por la me1cla en el uso de estos identi0icadores como palabras clave o como nombres comunes, los identi0icadores se consideran palabras clave cuando tienen lugar dentro de una expresi-n de consulta. Con este 0in, una expresi-n de consulta siempre empe1ar( con P-rom identifierQ OP-rom identificadorQR e ir( seguida de un to6en especial excepto P;Q, P+Q o P Q. 'ara poder utili1ar estas palabras como identi0icadores dentro de una expresi-n de consulta, pueden ir pre0i$adas con P[Q O[2.4.2R.

22#

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

+.1#.2 Traduccin de e"presiones de consulta El lengua$e C# no especi0ica la sem(ntica de e$ecuci-n en expresiones de consulta. En lugar de eso, las expresiones de consulta se traducen en invocaciones de m)todos ?ue se ad=ieren al patr-n de expresiones de consulta O[*.1 .3R. Concretamente, las expresiones de consulta se traducen en invocaciones de m)todos denominados W"ere, Select, SelectMany, ]oin, Srou&]oin, %rder:y, %rder:y6escending, 1"en:y, 1"en:y6escending, Srou&:y y Cast. .e espera ?ue estos m)todos tengan tipos de resultados y 0irmas particulares, tal como se describe en la secci-n [. Estos m)todos pueden ser m)todos de instancia del ob$eto sobre el ?ue se reali1a la consulta o m)todos de extensi-n externos al ob$eto, e implementan la e$ecuci-n real de la consulta. 8a traducci-n de expresiones de consulta a invocaciones de m)todo es una asignaci-n sint(ctica ?ue tiene lugar antes de ?ue se produ1ca cual?uier enlace de tipos o resoluci-n de sobrecargas. .e garanti1a ?ue la traducci-n es correcta desde el punto de vista sint(ctico, pero no se garanti1a ?ue produ1ca c-digo de C# correcto desde el punto de vista sem(ntico. 2espu)s de la traducci-n de las expresiones de consulta, las invocaciones de m)todo resultantes se procesan como invocaciones de m)todo comunes, y este procesamiento puede a su ve1 descubrir errores, por e$emplo si los m)todos no existen, si los argumentos tienen tipos err-neos, o si los m)todos son gen)ricos y se produce un error en la inter0a1 de tipos. 7na expresi-n de consulta se procesa aplicando repetidamente las siguientes traducciones =asta ?ue no =ay m(s reducciones posibles. 8as traducciones se enumeran en orden de aplicaci-nG cada secci-n asume ?ue las traducciones de las secciones precedentes se =an reali1ado de manera ex=austiva, y una ve1 agotada, una secci-n no volver( a ser visitada en el procesamiento de la misma expresi-n de consulta. 8a asignaci-n a variables de intervalo no est( permitida en expresiones de consulta. .in embargo, se permite ?ue una implementaci-n de C# no siempre exi$a esta restricci-n por?ue algunas veces no es posible con el es?uema de conversi-n sint(ctico a?u5 presentado. 2eterminadas traducciones insertan variables de intervalo con identificadores transparentes ?ue se denotan mediante >. 8as propiedades especiales de los identi0icadores transparentes se discuten con m(s detalle en la secci-n [*.1 .2.*. #.1 .2.1 Clusulas !elect y 9roupby con continuaciones 7na expresi-n de consulta con una continuaci-n
-rom A into 2 A

se traduce en
-rom 2 in ( -rom A ) A

8as traducciones en las siguientes secciones asumen ?ue las consultas no tienen continuaciones into. El e$emplo
-rom c in customers grou& c by c.Country into g select ne, { Country + g.aey CustCount + g.Count() !

se traduce en
-rom g in -rom c in customers grou& c by c.Country select ne, { Country + g.aey

CustCount + g.Count() !

cuya traducci-n 0inal es

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

22!

Especificacin del lenguaje C# customers. Srou&:y(c +E c.Country). Select(g +E ne, { Country + g.aey

CustCount + g.Count() !)

#.1 .2.2 :ipos de variable de intervalo e2plCcitos 7na cl(usula -rom ?ue especi0ica expl5citamente un tipo de variable de intervalo
-rom B 2 in e

se traduce en
-rom 2 in ( e ) . Cast D B E ( )

7na cl(usula join ?ue especi0ica expl5citamente un tipo de variable de intervalo


join B 2 in e on 31 eQuals 32

se traduce en
join 2 in ( e ) . Cast D B E ( ) on 31 eQuals 32

8as traducciones en las siguientes secciones asumen ?ue las consultas no tienen tipos de variables de intervalo expl5citos. El e$emplo
-rom Customer c in customers ,"ere c.City ++ "London" select c

se traduce en
-rom c in customers.CastDCustomerE() ,"ere c.City ++ "London" select c

cuya traducci-n 0inal es


customers. CastDCustomerE(). W"ere(c +E c.City ++ "London")

8os tipos de variable de intervalo expl5citos son Htiles para reali1ar consultas en colecciones ?ue implementan la inter0a1 $)numerable no gen)rica, pero no la inter0a1 $)numerableD1E gen)rica. En el e$emplo anterior, )ste ser5a el caso si customers 0uera de tipo 'rrayList. #.1 .2.3 &2presiones de consulta de"eneradas 7na expresi-n de consulta con la estructura
-rom 2 in e select 2

se traduce en
( e ) . Select ( 2 +E 2 )

El e$emplo
-rom c in customers select c

se traduce en
customers.Select(c +E c)

226

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

7na expresi-n de consulta degenerada es a?uella ?ue selecciona de manera trivial los elementos del origen. En una 0ase posterior de la traducci-n se ?uitan las consultas degeneradas introducidas por otros pasos de traducci-n reempla1(ndolas por su origen. Es importante, no obstante, asegurar ?ue el resultado de una expresi-n de consulta nunca sea el propio ob$eto de origen, ya ?ue esto revelar5a el tipo y la identidad del origen al cliente de la consulta. 2e este modo, este paso protege las consultas degeneradas escritas directamente en el c-digo de origen llamando a Select en el origen. & partir de ese momento corresponde a los implementadores de Select y los dem(s operadores de consulta garanti1ar ?ue estos m)todos nunca devuelvan el ob$eto de origen en s5. #.1 .2.4 Clusulas 3rom, let, ,-ere, =oin y orderby 7na expresi-n de consulta con una segunda cl(usula -rom seguida de una cl(usula select
-rom 21 in e1 -rom 22 in e2 select v

se traduce en
( e1 ) . SelectMany( 21 +E e2 -rom 21 in e1 -rom 22 in e2 b ( 21

22 ) +E v )

7na expresi-n de consulta con una segunda cl(usula -rom seguida de otra cl(usula ?ue no sea selectG

se traduce en
-rom > in ( e1 ) . SelectMany( 21 +E e2 b ( 21

22 ) +E ne, { 21

22 ! )

7na expresi-n de consulta con una cl(usula let


-rom 2 in e let # + f

A se traduce en
-rom > in ( e ) . Select ( 2 +E ne, { 2 b

# + f ! )

7na expresi-n de consulta con una cl(usula ,"ere


-rom 2 in e ,"ere f

A se traduce en
-rom 2 in ( e ) . W"ere ( 2 +E f ) b

7na expresi-n de consulta con una cl(usula join sin una cl(usula into, y seguida de una cl(usula select
-rom 21 in e1 join 22 in e2 on 31 eQuals 32 select v

se traduce en
( e1 ) . ]oin( e2

21 +E 31

22 +E 32

( 21

22 ) +E v )

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

22(

Especificacin del lenguaje C#

7na expresi-n de consulta con una cl(usula join sin una cl(usula into, y seguida de una cl(usula ?ue no es
select -rom 21 in e1 join 22 in e2 on 31 eQuals 32 b

se traduce en
-rom > in ( e1 ) . ]oin( e2 21 +E 31 22 +E 32 b ( 21

22 ) +E ne, { 21

22 !)

7na expresi-n de consulta con una cl(usula join y una cl(usula into, y seguida de una cl(usula select
-rom 21 in e1 join 22 in e2 on 31 eQuals 32 into & select v

se traduce en
( e1 ) . Srou&]oin( e2 select -rom 21 in e1 join 22 in e2 on 31 eQuals 32 into & b

21 +E 31

22 +E 32

( 21

& ) +E v )

7na expresi-n de consulta con una cl(usula join y una cl(usula into, y seguida de una cl(usula ?ue no es

se traduce en
-rom > in ( e1 ) . Srou&]oin( e2 21 +E 31 22 +E 32 ( 21 b

& ) +E ne, { 21

& !)

7na expresi-n de consulta con una cl(usula orderby


-rom 2 in e orderby 31

32

3n

A se traduce en
-rom 2 in ( e ) . %rder:y ( 2 +E 31 ) . 1"en:y ( 2 +E 32 ) . A . 1"en:y ( 2 +E 3n ) b

.i una cl(usula de tipo order especi0ica un indicador de direcci-n descending, se produce en su lugar una invocaci-n de %rder:y6escending o 1"en:y6escending. 8as siguientes traducciones asumen ?ue no =ay ninguna cl(usula let, ,"ere, join u orderby, y no m(s de una cl(usula -rom inicial en cada expresi-n de consulta. El e$emplo
-rom c in customers -rom o in c.%rders select ne, { c.Name o.%rder$6 o.1otal !

22$

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

se traduce en
customers. SelectMany(c +E c.%rders (c o) +E ne, { c.Name ) o.%rder$6 o.1otal !

El e$emplo
-rom c in customers -rom o in c.%rders orderby o.1otal descending select ne, { c.Name o.%rder$6

o.1otal !

se traduce en
-rom > in customers. SelectMany(c +E c.%rders (c o) +E ne, { c orderby o.1otal descending select ne, { c.Name o.%rder$6 o.1otal ! o !)

cuya traducci-n 0inal es


customers. SelectMany(c +E c.%rders (c o) +E ne, { c o !). %rder:y6escending(# +E #.o.1otal). Select(# +E ne, { #.c.Name #.o.%rder$6 #.o.1otal !)

donde # es un identi0icador generado por el compilador ?ue de otro modo es invisible e inaccesible. El e$emplo
-rom o in orders let t + o.6etails.Sum(d +E d.;nit*rice > d.^uantity) ,"ere t E+ 2333 select ne, { o.%rder$6 1otal + t !

se traduce en
-rom > in orders. Select(o +E ne, { o ,"ere t E+ 2333 select ne, { o.%rder$6 t + o.6etails.Sum(d +E d.;nit*rice > d.^uantity) !) 1otal + t !

cuya traducci-n 0inal es


orders. Select(o +E ne, { o t + o.6etails.Sum(d +E d.;nit*rice > d.^uantity) !). W"ere(# +E #.t E+ 2333). Select(# +E ne, { #.o.%rder$6 1otal + #.t !)

donde # es un identi0icador generado por el compilador ?ue de otro modo es invisible e inaccesible. El e$emplo
-rom c in customers join o in orders on c.Customer$6 eQuals o.Customer$6 select ne, { c.Name o.%rder6ate o.1otal !

se traduce en
customers.]oin(orders c +E c.Customer$6 o +E o.Customer$6 (c o) +E ne, { c.Name o.%rder6ate o.1otal !)

El e$emplo

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

22"

Especificacin del lenguaje C# -rom c in customers join o in orders on c.Customer$6 eQuals o.Customer$6 into co let n + co.Count() ,"ere n E+ 23 select ne, { c.Name %rderCount + n !

se traduce en
-rom > in customers. Srou&]oin(orders c +E c.Customer$6 (c co) +E ne, { c co !) let n + co.Count() ,"ere n E+ 23 select ne, { c.Name %rderCount + n ! o +E o.Customer$6

cuya traducci-n 0inal es


customers. Srou&]oin(orders (c co) +E ne, Select(# +E ne, { W"ere(y +E y.n E+ Select(y +E ne, { c +E c.Customer$6 o +E o.Customer$6 { c co !). # n + #.co.Count() !). 23). y.#.c.Name %rderCount + y.n)

donde # e y son identi0icadores generados por el compilador ?ue de otro modo son invisibles e inaccesibles. El e$emplo
-rom o in orders orderby o.Customer.Name select o o.1otal descending

tiene la traducci-n 0inal


orders. %rder:y(o +E o.Customer.Name). 1"en:y6escending(o +E o.1otal)

#.1 .2. Clusulas !elect 7na expresi-n de consulta con la estructura


-rom 2 in e select v

se traduce en
( e ) . Select ( 2 +E v )

excepto cuando v es el identi0icador 2, la traducci-n es simplemente


( e )

'or e$emploG
-rom c in customers.W"ere(c +E c.City ++ RLondonT) select c

se traduce simplemente en
customers.W"ere(c +E c.City ++ RLondonT)

#.1 .2.6 Clusulas 9roupby 7na expresi-n de consulta con la estructura


-rom 2 in e grou& v by 3

se traduce en

23'

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases ( e ) . Srou&:y ( 2 +E 3

2 +E v )

excepto cuando v es el identi0icador 2, la traducci-n es


( e ) . Srou&:y ( 2 +E 3 )

El e$emplo
-rom c in customers grou& c.Name by c.Country

se traduce en
customers. Srou&:y(c +E c.Country c +E c.Name)

#.1 .2.# $denti3icadores transparentes 2eterminadas traducciones insertan variables de intervalo con identificadores transparentes ?ue se denotan mediante >. 8os identi0icadores transparentes no son una caracter5stica propia del lengua$eV existen s-lo como un paso intermedio en el proceso de traducci-n de expresiones de consulta. Cuando una traducci-n de consulta inserta un identi0icador transparente, los siguientes pasos de traducci-n propagan el identi0icador transparente en 0unciones an-nimas e iniciali1adores de ob$etos an-nimos. En estos contextos, los identi0icadores transparentes tienen el siguiente comportamientoG Cuando un identi0icador transparente tiene lugar como par(metro en una 0unci-n an-nima, los miembros del tipo an-nimo asociado est(n autom(ticamente en el (mbito del cuerpo de la 0unci-n an-nima. Cuando un miembro con un identi0icador transparente est( en el (mbito, los miembros de ese miembro est(n en el (mbito tambi)n. Cuando un identi0icador transparente tiene lugar como un declarador de miembro en un iniciali1ador de ob$eto an-nimo, )ste introduce un miembro con un identi0icador transparente. En los pasos de traducci-n descritos antes, los identi0icadores transparentes siempre se introducen $unto con tipos an-nimos, con la intenci-n de capturar varias variables de intervalo como miembros de un solo ob$eto. .e permite ?ue una implementaci-n de C# utilice un mecanismo di0erente ?ue los tipos an-nimos para agrupar $untas varias variables de intervalo. En la siguiente traducci-n se asume el uso de los tipos an-nimos, y se muestra c-mo se pueden traducir los identi0icadores transparentes.
-rom c in customers -rom o in c.%rders orderby o.1otal descending select ne, { c.Name o.1otal !

El e$emplo

se traduce en
-rom > in customers. SelectMany(c +E c.%rders (c o) +E ne, { c orderby o.1otal descending select ne, { c.Name o.1otal ! o !)

?ue se traduce a su ve1 en


customers. SelectMany(c +E c.%rders (c o) +E ne, { c %rder:y6escending(> +E o.1otal). Select(> +E ne, { c.Name o.1otal !) o !).

?ue, cuando se eliminan los identi0icadores transparentes, e?uivale a

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

231

Especificacin del lenguaje C# customers. SelectMany(c +E c.%rders (c o) +E ne, { c %rder:y6escending(# +E #.o.1otal). Select(# +E ne, { #.c.Name #.o.1otal !)

o !).

donde # es un identi0icador generado por el compilador ?ue de otro modo es invisible e inaccesible. El e$emplo
-rom c join o join d join & select in customers in orders on c.Customer$6 eQuals o.Customer$6 in details on o.%rder$6 eQuals d.%rder$6 in &roducts on d.*roduct$6 eQuals &.*roduct$6 ne, { c.Name o.%rder6ate &.*roductName !

se traduce en
-rom > in customers. ]oin(orders c +E c.Customer$6 o +E o.Customer$6 (c o) +E ne, { c o !) join d in details on o.%rder$6 eQuals d.%rder$6 join & in &roducts on d.*roduct$6 eQuals &.*roduct$6 select ne, { c.Name o.%rder6ate &.*roductName !

?ue a su ve1 se reduce a


customers. ]oin(orders c +E c.Customer$6 o +E o.Customer$6 (c o) +E ne, { c o !). ]oin(details > +E o.%rder$6 d +E d.%rder$6 (> d) +E ne, { > d !). ]oin(&roducts > +E d.*roduct$6 & +E &.*roduct$6 (> &) +E ne, { > & !). Select(> +E ne, { c.Name o.%rder6ate &.*roductName !)

cuya traducci-n 0inal es


customers. ]oin(orders c +E c.Customer$6 o +E o.Customer$6 (c o) +E ne, { c o !). ]oin(details # +E #.o.%rder$6 d +E d.%rder$6 (# d) +E ne, { # d !). ]oin(&roducts y +E y.d.*roduct$6 & +E &.*roduct$6 (y &) +E ne, { y & !). Select(? +E ne, { ?.y.#.c.Name ?.y.#.o.%rder6ate ?.&.*roductName !)

donde #, y y ? son identi0icadores generados por el compilador ?ue de otro modo son invisibles e inaccesibles. +.1#.3 El patrn de e"presiones de consulta El patr,n de e.presiones de cons!lta establece un patr-n de m)todos ?ue los tipos pueden implementar para poder admitir expresiones. 2ado ?ue las expresiones de consulta se traducen en invocaciones de m)todo mediante una asignaci-n sint(ctica, los tipos tienen una 0lexibilidad considerable a la =ora de implementar el patr-n de expresiones de consulta. 'or e$emplo, los m)todos de un patr-n se pueden implementar como m)todos de instancia o como m)todos de extensi-n, por?ue los dos tienen la misma sintaxis de invocaci-n, y los m)todos pueden solicitar delegados o (rboles de expresiones, por?ue las 0unciones an-nimas son convertibles a ambos. 8a 0orma recomendada de un tipo gen)rico CD1E ?ue admite el patr-n de expresiones de consulta se muestra a continuaci-n. El tipo gen)rico se usa para poder ilustrar la relaci-n adecuada entre par(metro y tipos de resultado, pero es posible implementar el patr-n tambi)n para tipos no gen)ricos.
delegate O VuncD12 OE(12 arg2); delegate O VuncD12 18 OE(12 arg2 class C { &ublic CD1E CastD1E(); ! 18 arg8);

232

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases class CD1E / C { &ublic CD1E W"ere(VuncD1 boolE &redicate); &ublic CD;E SelectD;E(VuncD1 ;E selector); &ublic CDUE SelectManyD; UE(VuncD1 CD;EE selector VuncD1 ; UE resultSelector); &ublic CDUE ]oinD; a UE(CD;E inner VuncD1 aE outeraeySelector VuncD; aE inneraeySelector VuncD1 ; UE resultSelector); &ublic CDUE Srou&]oinD; a UE(CD;E inner VuncD1 aE outeraeySelector VuncD; aE inneraeySelector VuncD1 CD;E UE resultSelector); &ublic %D1E %rder:yDaE(VuncD1 aE (eySelector); &ublic %D1E %rder:y6escendingDaE(VuncD1 aE (eySelector); &ublic CDSDa 1EE Srou&:yDaE(VuncD1 aE (eySelector); &ublic CDSDa )EE Srou&:yDa )E(VuncD1 aE (eySelector VuncD1 )E elementSelector); ! class %D1E / CD1E { &ublic %D1E 1"en:yDaE(VuncD1 aE (eySelector); &ublic %D1E 1"en:y6escendingDaE(VuncD1 aE (eySelector); ! class SDa 1E / CD1E { &ublic a aey { get; ! !

8os m)todos anteriores utili1an tipos delegados gen)ricos VuncD12 OE y VuncD12 18 OE, pero igualmente podr5an =aber usado otros tipos delegados o de (rbol de expresiones con las mismas relaciones en par(metro y tipos de resultado. Tenga en cuenta la relaci-n recomendada entre CD1E y %D1E ?ue asegura ?ue los m)todos 1"en:y y 1"en:y6escending est(n disponibles s-lo en el resultado de %rder:y u %rder:y6escending. Tambi)n la 0orma recomendada del resultado de Srou&:y Ouna secuencia de secuenciasR, donde cada secuencia interna tiene una propiedad aey adicional. El espacio de nombres System.LinQ proporciona una implementaci-n del patr-n del operador de consultas para cual?uier tipo ?ue implementa la inter0a1 System.Collections.Seneric.$)numerableD1E.

+.1$ ,peradores de asignacin


8os operadores de asignaci-n se utili1an para asignar un valor nuevo a una variable, propiedad, evento o elemento de indi1ador. assi&n%ent1 nar#-e2pression assi&n%ent-operator e2pression

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

233

Especificacin del lenguaje C#

assi&n%ent-operator1
+ <+ =+ >+ .+ B+ F+ H+ G+ DD+

ri&ht-shift-assi&n%ent El operando i1?uierdo de una asignaci-n debe ser una expresi-n clasi0icada como una variable, un acceso a propiedad, un acceso a indi1ador o un acceso a evento. El operador + se denomina operador de asignaci,n si ple. &signa el valor del operando derec=o a la variable, propiedad o elemento de indi1ador dado por el operando i1?uierdo. El operando de la i1?uierda del operador de asignaci-n simple puede no ser un acceso a evento Oexcepto en las condiciones descritas en [1".8.1R. El operador de asignaci-n simple se explica en [*.1#.1. 8os operadores de asignaci-n distintos del operador + se denominan operadores de asignaci,n co p!estos. 2ic=os operadores e$ecutan la operaci-n indicada en los dos operandos y despu)s asignan el valor resultante a la variable, propiedad o elemento de indi1ador dado por el operando i1?uierdo. 8os operadores de asignaci-n compuesta se explican en [*.1#.2. 8os operadores <+ y =+ con una expresi-n de acceso a eventos como operando i1?uierdo se denominan operadores de asi&naci/n de eventos. 4ingHn otro operador de asignaci-n es v(lido si incluye un acceso a eventos como operando i1?uierdo. 8os operadores de asignaci-n de eventos se explican en [*.1#.3. 8os operadores de asignaci-n son asociativos por la derec=a, lo ?ue signi0ica ?ue las operaciones se agrupan de derec=a a i1?uierda. 'or e$emplo, una expresi-n con la 0orma a + b + c se evalHa como a + (b + c). +.1$.1 'signacin simple El operador + se denomina operador de asignaci-n simple. En una asignaci-n simple, el operando derec=o debe ser una expresi-n de un tipo ?ue pueda convertirse impl5citamente al tipo del operando i1?uierdo. 8a operaci-n asigna el valor del operando derec=o a la variable, propiedad o elemento de indi1ador dado por el operando i1?uierdo. El resultado de una expresi-n de asignaci-n simple es el valor asignado al operando i1?uierdo. El resultado tiene el mismo tipo ?ue el operando i1?uierdo y siempre se clasi0ica como un valor. .i el operando i1?uierdo es una propiedad o un acceso a indi1ador, debe tener un descriptor de acceso set. .i no es )ste el caso, se produce un error en tiempo de compilaci-n. El procesamiento en tiempo de e$ecuci-n de una asignaci-n simple de la 0orma # + y consta de los siguientes pasosG .i # se clasi0ica como una variableG o o o .e evalHa # para producir la variable. .e evalHa y y, si es necesario, se convierte al tipo de # mediante una conversi-n impl5cita O[#.1R. .i la variable dada por # es un elemento de matri1 de un tipo de re0erencia Oreference-t#peR, se lleva a cabo una comprobaci-n en tiempo de e$ecuci-n para garanti1ar ?ue el valor calculado de y es compatible con la instancia de matri1 a la cual pertenece #. 8a comprobaci-n es satis0actoria si y es

23#

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases null o si existe una conversi-n de re0erencia impl5cita O[#.1.#R del tipo real de la instancia a ?ue =ace re0erencia y al tipo del elemento real de la instancia de matri1 ?ue contiene a #. 2e lo contrario, se inicia una excepci-n System.'rray1y&eMismatc")#ce&tion.

El valor resultante de la evaluaci-n y conversi-n de y se almacena en la ubicaci-n dada por la evaluaci-n de #. .e evalHan la expresi-n de instancia Osi # no es staticR y la lista de argumentos Osi # es un acceso a indi1adorR asociadas con #, y el resultado se utili1a en la posterior invocaci-n de descriptor de acceso set. .e evalHa y y, si es necesario, se convierte al tipo de # mediante una conversi-n impl5cita O[#.1R. .e invoca el descriptor de acceso set de # con el valor calculado para y como su argumento value.

.i # se clasi0ica como una propiedad o un acceso a indi1adorG o

o o

8as reglas de covarian1a matricial O[12. R permiten ?ue un valor de un tipo de matri1 '45 se trate como una re0erencia a una instancia de un tipo matricial :45, siempre ?ue exista una conversi-n impl5cita de re0erencias de : a '. 2ebido a estas reglas, la asignaci-n de un tipo de re0erencia Oreference-t#peR a un elemento de matri1 re?uiere una comprobaci-n en tiempo de e$ecuci-n para garanti1ar ?ue el valor asignado es compatible con la instancia de matri1. En el e$emplo
string45 sa + ne, string4235; object45 oa + sa; oa435 + null; oa425 + "Hello"; oa485 + ne, 'rrayList(); .. %( .. %( .. 'rray1y&eMismatc")#ce&tion

la Hltima asignaci-n produce el inicio de la excepci-n System.'rray1y&eMismatc")#ce&tion, debido a ?ue la instancia de 'rrayList no se puede almacenar en un elemento de una cadena string45. Cuando una propiedad o un indi1ador declarado en un tipo struct Ostr ct-t#peR es el destino de una asignaci-n, la expresi-n de instancia asociada al acceso a propiedad o a indi1ador debe estar clasi0icada como una variable. .i la expresi-n de instancia est( clasi0icada como un valor, se produce un error de compilaci-n. Con0orme a la [*. .4, la misma regla tambi)n es aplicable a los campos. 2adas las declaracionesG
struct *oint { int # y; &ublic *oint(int # t"is.# + #; t"is.y + y; ! int y) {

&ublic int I { get { return #; ! set { # + value; ! ! &ublic int ` { get { return y; ! set { y + value; ! ! ! struct Oectangle { *oint a b;

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

23!

Especificacin del lenguaje C# &ublic Oectangle(*oint a t"is.a + a; t"is.b + b; ! &ublic *oint ' { get { return a; ! set { a + value; ! ! &ublic *oint : { get { return b; ! set { b + value; ! ! ! *oint b) {

del e$emploG
*oint & + ne, *oint(); &.I + 233; &.` + 233; Oectangle r + ne, Oectangle(); r.' + ne, *oint(23 23); r.: + &;

las asignaciones a &.I, &.`, r.' y r.: est(n permitidas por?ue & y r son variables. 4o obstante, en el e$emploG
Oectangle r + ne, Oectangle(); r.'.I + 23; r.'.` + 23; r.:.I + 233; r.:.` + 233;

las asignaciones no son v(lidas, puesto ?ue r.' y r.: no son variables. +.1$.2 'signacin compuesta 7na operaci-n con la 0orma # op+ y se procesa mediante la aplicaci-n de la resoluci-n de sobrecargas de operadores binarios O[*.2.4R como si la operaci-n se =ubiera escrito # op y. Entonces, .i el tipo de valor devuelto del operador seleccionado es convertible i%pl*cita%ente al tipo de #, la operaci-n se evalHa como # + # op y, excepto en ?ue # se evalHa una sola ve1. / bien, si el operador seleccionado es un operador prede0inido, si el tipo del valor devuelto del operador seleccionado es convertible e2pl*cita%ente al tipo de #, y si y es convertible i%pl*cita%ente al tipo de #, entonces la operaci-n se evalHa como # + (1)(# op y), donde 1 es el tipo #, excepto en ?ue # se evalHa una sola ve1. / bien, la asignaci-n compuesta no es v(lida y se produce un error en tiempo de compilaci-n.

8a expresi-n Pse evalHa una sola ve1Q implica ?ue, en la evaluaci-n de # op y, el resultado de cual?uier expresi-n ?ue 0orme parte de # se guarda temporalmente y se reutili1a cuando se reali1a la asignaci-n a #. 'or e$emplo, en la asignaci-n '()4:()5 <+ C(), donde ' es un m)todo ?ue devuelve int45, y : y C son m)todos ?ue devuelven int, los m)todos se invocan solamente una ve1, en el orden ', :, C. .i el operando i1?uierdo de una asignaci-n compuesta es un acceso a propiedad o un acceso a indi1ador, la propiedad o el indi1ador debe tener un descriptor de acceso get y un descriptor de acceso set. .i no es )ste el caso, se produce un error en tiempo de compilaci-n. 8a segunda regla mencionada permite ?ue # op+ y se evalHe como # + (1)(# op y) en ciertos contextos. 8a regla existe para permitir utili1ar los operadores prede0inidos como operadores compuestos cuando el operando i1?uierdo es de tipo sbyte, byte, s"ort, us"ort o c"ar. &un?ue los dos argumentos sean de uno de estos

236

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

tipos, los operadores prede0inidos producen un resultado de tipo int, como se explica en [*.2.#.2. 'or lo tanto, sin una conversi-n, no ser5a posible asignar el resultado al operando i1?uierdo. El e0ecto intuitivo de la regla de los operadores prede0inidos es, sencillamente, ?ue # op+ y est( permitido si est(n permitidos # op y, y # + y. En el e$emplo
byte b + 3; c"ar c" + WZ3W; int i + 3; b b b b <+ <+ <+ <+ 2; 2333; i; (byte)i; .. .. .. .. %( )rror )rror %( b + 2333 not &ermitted b + i not &ermitted c" + 2 not &ermitted

c" <+ 2; c" <+ (c"ar)2;

.. )rror .. %(

el motivo intuitivo de cada error es ?ue una asignaci-n simple correspondiente tambi)n =abr5a sido un error. Esto tambi)n signi0ica ?ue las operaciones de asignaci-n compuesta admiten operaciones de elevaci-n. En el e$emplo
int7 i + 3; i <+ 2; .. %(

se utili1a el operador de elevaci-n <(int7 int7). +.1$.3 'signacin de e entos .i el operando i1?uierdo de un operador Si o Bi se clasi0ica como acceso a evento, la expresi-n se evalHa de la siguiente 0ormaG .i existe una expresi-n de instancia del acceso a evento, se evalHa. .e evalHa el operando de la derec=a del operador <+ o =+ y, si 0uera necesario, se convierte al tipo del operando de la i1?uierda mediante una conversi-n impl5cita O[#.1R. 2espu)s de la evaluaci-n y, si es necesario, tambi)n despu)s de la conversi-n, se invoca un descriptor de acceso del evento, con la lista de argumentos 0ormada por el operando derec=o. .i el operador 0uera <+, se invoca el descriptor de acceso addV si el operador 0uera =+, se invoca el descriptor de acceso remove.

7na expresi-n de asignaci-n de evento no produce ningHn valor. 'or tanto, una expresi-n de asignaci-n de eventos s-lo ser( v(lida en el contexto de una expresi-n de instrucci-n Ostate%ent-e2pressionR O[8.#R.

+.1+ E"presin
7na expresi-n Oe2pressionR es una expresi-n de no asignaci-n Onon-assi&n%ent-e2pressionR o una asignaci-n Oassi&n%entR. e2pression1 non-assi&n%ent-e2pression assi&n%ent non-assi&n%ent-e2pression1 conditional-e2pression la%-da-e2pression 6 er#-e2pression

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

23(

Especificacin del lenguaje C#

+.1- E"presiones constantes


7na expresi-n constante Oconstant-e2pressionR es una expresi-n ?ue se puede evaluar totalmente en tiempo de compilaci-n. constant-e2pression1 e2pression 7na expresi-n constante debe ser el literal null o un valor con uno de los siguientes tiposG sbyte, byte, s"ort, us"ort, int, uint, long, ulong, c"ar, -loat, double, decimal, bool, string, o cual?uier tipo de enumeraci-n. .-lo las siguientes construcciones se permiten en expresiones de constantesG 8iterales Oincluido nullR. ;e0erencias a miembros const y tipos de clase y estructura. ;e0erencias a miembros de tipos de enumeraci-n. ;e0erencias a par(metros const o a variables locales .ubexpresiones entre par)ntesis, ?ue son en s5 mismas expresiones constantes. Expresiones de conversi-n, siempre ?ue el tipo de destino sea uno de los antes indicados. Expresiones c"ec(ed y unc"ec(ed Expresiones de valor predeterminadas 8os operadores unarios prede0inidos <, C, @ y A. 8os operadores binarios prede0inidos <, C, >, ., B, DD, EE, F, H, G, FF, HH, ++, @+, D, E, D+ y E+, siempre ?ue todos los operandos sean de uno de los tipos indicados anteriormente. El operador condicional 7/. Conversiones de identidad Conversiones num)ricas Conversiones de enumeraci-n Conversiones de expresi-n constante Conversiones de re0erencia impl5cita y expl5cita, siempre y cuando el origen de las conversiones sea una expresi-n constante ?ue se evalHe como null.

.e permiten las siguientes conversiones en expresiones de constantesG

/tras conversiones, incluidas las conversiones boxing y unboxing, y las conversiones de re0erencia impl5cita de valores distintos de null no se permiten en expresiones constantes. 'or e$emploG
class C { const object i + K; .. error/ bo#ing conversion not &ermitted const object str + R"elloT; .. error/ im&licit re-erence conversion !

la iniciali1aci-n de i es un error por?ue es necesaria una conversi-n boxing. 8a iniciali1aci-n de str es un error por?ue es necesaria una conversi-n de re0erencia impl5cita desde un valor distinto de null. .iempre ?ue una expresi-n cumple los re?uisitos antes mencionados, la expresi-n se evalHa en tiempo de compilaci-n. Esto ocurre as5 aun?ue la expresi-n sea una subBexpresi-n de una expresi-n mayor ?ue contiene construcciones no constantes.

23$

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

8a evaluaci-n en tiempo de compilaci-n de expresiones constantes est( regida por las mismas reglas ?ue la evaluaci-n en tiempo de e$ecuci-n de expresiones no constantes, excepto por?ue donde la evaluaci-n en tiempo de e$ecuci-n iniciar5a una excepci-n, la evaluaci-n en tiempo de compilaci-n causa un error de tiempo de compilaci-n. .alvo ?ue una expresi-n constante se colo?ue expl5citamente en un contexto unc"ec(ed, los desbordamientos ?ue ocurran en las conversiones y operaciones aritm)ticas de tipo integral durante la evaluaci-n en tiempo de compilaci-n de la expresi-n siempre causar(n errores de tiempo de compilaci-n O[*.18R. 8as expresiones constantes ocurren en los contextos ?ue se enumeran a continuaci-n. En estos contextos, se produce un error durante la compilaci-n si una expresi-n no puede evaluarse totalmente en tiempo de compilaci-n. 2eclaraciones de constantes O[1".4R. 2eclaraciones de miembros de enumeraci-n O[14.3R. Eti?uetas case de una instrucci-n s,itc" O[8.*.2R. !nstrucciones goto case O[8.+.3R. 8ongitudes de dimensi-n en una expresi-n de creaci-n de matri1 O[*. .1".4R ?ue incluye un iniciali1ador. &tributos O[1*R.

7na conversi-n impl5cita de expresi-n constante O[#.1.8R permite la conversi-n de una expresi-n constante de tipo int al tipo sbyte, byte, s"ort, us"ort, uint o ulong, siempre ?ue el valor de la expresi-n constante ?uede dentro del intervalo del tipo de destino.

+.1. E"presiones booleanas


7na expresi-n booleana O-oolean-e2pressionR es una expresi-n ?ue devuelve un resultado de tipo boolV ya sea directamente o a trav)s de la aplicaci-n del operador true en ciertos contextos tal y como se especi0ica a continuaci-n. -oolean-e2pression1 e2pression 8a expresi-n condicional ?ue controla una instrucci-n i0 Oif-state%entR O[8.*.1R, instrucci-n 9=ile Owhilestate%entR O[8.8.1R, instrucci-n do Odo-state%entR O[8.8.2R o instrucci-n 0or Ofor-state%entR O[8.8.3R es una expresi-n booleana O-oolean-e2pressionR. 8a expresi-n condicional de control del operador 7/ O[*.13R sigue las mismas reglas ?ue una expresi-n booleana O-oolean-e2pressionR pero, por motivos de prioridad de operadores, se clasi0ica como una expresi-n or condicional Oconditional-or-e2pressionR. 7na expresi-n booleana O-oolean-e2pressionR debe ser de un tipo ?ue pueda convertirse impl5citamente a bool o de un tipo ?ue implemente o&erator true. .i no se satis0ace ninguno de los re?uisitos, se produce un error de compilaci-n. .i una expresi-n booleana es de un tipo ?ue no puede convertirse impl5citamente a bool pero ?ue implementa o&erator true, despu)s de la evaluaci-n de la expresi-n, se llama a la implementaci-n de o&erator true suministrada por ese tipo para generar un valor bool. El tipo struct 6::ool de la secci-n [11.4.2 proporciona un e$emplo de un tipo ?ue implementa o&erator true y o&erator -alse.

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

23"

Especificacin del lenguaje C#

-. Instrucciones
C# proporciona una gran variedad de instrucciones. 8a mayor5a de ellas son conocidas por los programadores de C y CSS. state%ent1 la-eled-state%ent declaration-state%ent e%-edded-state%ent e%-edded-state%ent1 -loc3 e%pt#-state%ent e2pression-state%ent selection-state%ent iteration-state%ent > %p-state%ent tr#-state%ent chec3ed-state%ent nchec3ed-state%ent loc3-state%ent sin&-state%ent #ield-state%ent 8a instrucci-n incrustada Oe%-edded-state%enR sin terminaci-n se utili1a en instrucciones ?ue aparecen dentro de otras instrucciones. El uso de una instrucci-n incrustada Oe%-edded-state%entR en lugar de una instrucci-n Ostate%entR permite ?ue no sea necesario utili1ar instrucciones de declaraci-n y con eti?ueta en dic=os contextos. El e$emplo
void V(bool b) { i- (b) int i + JJ; !

da como resultado un error en tiempo de compilaci-n, ya ?ue una instrucci-n i- re?uiere una instrucci-n incrustada Oe%-edded-state%entR en lugar de una instrucci-n Ostate%entR para su rama i0. .i se admitiera este c-digo, la variable i se declarar5a pero no se utili1ar5a nunca. /bserve, sin embargo, ?ue si coloca la declaraci-n de i en un blo?ue, el e$emplo es v(lido.

-.1 (untos finales y alcance


Toda instrucci-n tiene un p!nto final. 2e manera intuitiva, el punto 0inal de una instrucci-n es la ubicaci-n ?ue sigue a la instrucci-n. 8as reglas para la e$ecuci-n de instrucciones compuestas Oinstrucciones ?ue contienen instrucciones incrustadasR especi0ican las acciones a tomar cuando el control llega al punto 0inal de una instrucci-n incrustada. 'or e$emplo, cuando el control llega al punto 0inal de una instrucci-n dentro de un blo?ue, pasa a la siguiente instrucci-n del blo?ue. .i una instrucci-n tiene posibilidades de e$ecutarse, se dice ?ue la instrucci-n es alcan-a/le. 2e manera inversa, si una instrucci-n no tiene ninguna posibilidad de e$ecutarse, se dice ?ue es una instrucci-n inalcan-a/le.

2#'

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

En el e$emplo
void V() { Console.WriteLine("reac"able"); goto Label; Console.WriteLine("unreac"able"); Label/ Console.WriteLine("reac"able"); !

la segunda llamada a Console.WriteLine es inalcan1able por?ue no =ay posibilidad de ?ue se e$ecute la instrucci-n. .i el compilador determina ?ue existe alguna instrucci-n inalcan1able, emite una advertencia. bue una instrucci-n sea inalcan1able no es un error propiamente dic=o. 'ara determinar si una determinada instrucci-n o punto 0inal es o no alcan1able, el compilador reali1a un an(lisis del 0lu$o del programa de acuerdo con las reglas de alcance de0inidas para cada instrucci-n. El an(lisis de 0lu$o tiene en cuenta los valores de expresiones de constantes O[*.18R ?ue controlan el comportamiento de las instrucciones, pero no considera los posibles valores de expresiones de variables. En otras palabras, en el an(lisis de 0lu$o se considera ?ue una expresi-n de variable de un determinado tipo puede tener cual?uier valor posible de dic=o tipo. En el e$emplo
void V() { const int i + 2; i- (i ++ 8) Console.WriteLine("unreac"able"); !

la expresi-n booleana de la instrucci-n i- es una expresi-n constante por?ue los dos operandos del operador ++ son constantes. 8a expresi-n constante se evalHa en tiempo de compilaci-n y, como devuelve el valor -alse, la llamada a Console.WriteLine se considera inalcan1able. .in embargo, si i se convierte en una variable local
void V() { int i + 2; i- (i ++ 8) Console.WriteLine("reac"able"); !

la invocaci-n a Console.WriteLine se considera alcan1able, aun?ue en realidad no se e$ecutar( nunca. El blo?ue O-loc3R de un miembro de 0unci-n siempre se considera alcan1able. Evaluando sucesivamente las reglas de alcance de cada instrucci-n de un blo?ue, puede determinarse el alcance de una determinada instrucci-n. En el e$emplo
void V(int #) { Console.WriteLine("start"); i- (# D 3) Console.WriteLine("negative"); !

el alcance de la segunda instrucci-n Console.WriteLine se determina de la 0orma siguienteG 8a primera instrucci-n de la expresi-n Console.WriteLine es alcan1able, ya ?ue el blo?ue del m)todo V tambi)n lo es. El punto 0inal de la primera instrucci-n Console.WriteLine es alcan1able por?ue esta instrucci-n tambi)n lo es. 8a instrucci-n i- es alcan1able por?ue el punto 0inal de la primera instrucci-n Console.WriteLine tambi)n lo es.

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

2#1

Especificacin del lenguaje C#

'or Hltimo, como la expresi-n booleana de la instrucci-n i- no tiene el valor constante -alse, la segunda instrucci-n Console.WriteLine es alcan1able.

Existen dos situaciones en las ?ue supone un error en tiempo de compilaci-n ?ue el punto 0inal de una instrucci-n sea alcan1ableG Como la instrucci-n s,itc" no admite ?ue de una secci-n Pse paseQ a la siguiente secci-n, supone un error en tiempo de compilaci-n ?ue el punto 0inal de la lista de instrucciones de una secci-n de s9itc= sea alcan1able. Este error suele producirse cuando 0alta una instrucci-n brea(. Es un error ?ue sea alcan1able el punto 0inal del blo?ue de un miembro de 0unci-n ?ue calcula un valor. Este error suele producirse cuando 0alta una instrucci-n return.

-.2 <lo;ues
7n blo?ue O-loc3R permite escribir varias instrucciones en contextos donde se permite una Hnica instrucci-n. -loc31
{ state%ent-listopt !

7n blo?ue O-loc3R est( 0ormado por una lista de instrucciones Ostate%ent-listR opcional O[8.2.1R, encerrada entre llaves. .i se omite la lista de instrucciones, se dice ?ue el blo?ue es un blo?ue vac5o. 7n blo?ue puede contener instrucciones de declaraci-n O[8. R. El (mbito de una variable o constante local declarada en un blo?ue es el propio blo?ue. 2entro de un blo?ue, el signi0icado de un nombre utili1ado en un contexto de expresi-n siempre debe ser el mismo O[*. .2.1R. 7n blo?ue se e$ecuta de la siguiente 0ormaG .i el blo?ue est( vac5o, el control se trans0iere al punto 0inal del blo?ue. .i no est( vac5o, el control se trans0iere a la lista de instrucciones. Cuando el control alcan1a el punto 0inal de la lista de instrucciones, se trans0iere al punto 0inal del blo?ue.

8a lista de instrucciones de un blo?ue es alcan1able si el propio blo?ue es alcan1able. El punto 0inal de un blo?ue es alcan1able si el blo?ue est( vac5o o si el punto 0inal de la lista de instrucciones es alcan1able. 7n blo?ue O-loc3R ?ue contiene una o m(s instrucciones yield O[8.14R se denomina blo?ue de iteradores. 8os blo?ues de iteradores se utili1an para implementar miembros de 0unci-n como iteradores O[1".14R. & los blo?ues de iteradores se les aplican algunas restricciones adicionalesG .e trata de un error en tiempo de compilaci-n si una instrucci-n return aparece en un blo?ue de iteradores Opero se permiten instrucciones yield returnR. .e trata de un error en tiempo de compilaci-n si un blo?ue de iteradores contiene contexto no seguro O[18.1R. 7n blo?ue de iteradores siempre de0ine un contexto seguro incluso si su declaraci-n est( anidada en un contexto ?ue no lo es.

-.2.1 6istas de instrucciones 7na lista de instr!cciones est( 0ormada por una o varias instrucciones escritas secuencialmente. 8as listas de instrucciones aparecen en blo?ues O-loc3sR O[8.2R y en blo?ues de modi0icadores Oswitch--loc3sR O[8.*.2R. state%ent-list1 state%ent state%ent-list state%ent

2#2

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

Cuando se e$ecuta una lista de instrucciones, se trans0iere el control a la primera instrucci-n. Cuando el control alcan1a el punto 0inal de una instrucci-n, se trans0iere a la siguiente instrucci-n. Cuando el control alcan1a el punto 0inal de la Hltima instrucci-n, se trans0iere al punto 0inal de la lista de instrucciones. 7na instrucci-n ?ue 0orma parte de una lista de instrucciones es alcan1able si se cumple al menos una de las siguientes condicionesG Es la primera instrucci-n y la propia lista de instrucciones es alcan1able. El punto 0inal de la instrucci-n anterior es alcan1able. 8a instrucci-n es una instrucci-n con eti?ueta y la eti?ueta es re0erenciada por una instrucci-n goto alcan1able.

El punto 0inal de una lista de instrucciones es alcan1able si el punto 0inal de la Hltima instrucci-n de la lista es alcan1able.

-.3 Instruccin ac2a


7na instrucci-n vac5a Oe%pt#-state%entR no =ace nada. e%pt#-state%ent1
;

7na instrucci-n vac5a se utili1a cuando no =ay operaciones ?ue reali1ar en un contexto donde se re?uiere una instrucci-n. Cuando se e$ecuta una instrucci-n vac5a, simplemente se trans0iere el control al punto 0inal de la instrucci-n. 'or lo tanto, el punto 0inal de una instrucci-n vac5a es alcan1able si la instrucci-n vac5a es alcan1able. 'uede utili1ar una instrucci-n vac5a cuando escriba una instrucci-n ,"ile sin cuerpoG
bool *rocessMessage() {... void *rocessMessages() { ,"ile (*rocessMessage()) ; !

Tambi)n puede utili1arla para declarar una eti?ueta $usto antes de la llave de cierre P!Q de un blo?ueG
void V() { ... i- (done) goto e#it; ... e#it/ ; !

-.! Instrucciones con eti;ueta


7na instrucci-n con eti?ueta Ola-eled-state%entR permite agregar una eti?ueta por delante de una instrucci-n. 8as instrucciones con eti?ueta se pueden incluir en blo?ues, pero no est(n permitidas como instrucciones incrustadas. la-eled-state%ent1 identifier / state%ent 7na instrucci-n con eti?ueta declara una eti?ueta con el nombre especi0icado en el identi0icador OidentifierR. El (mbito de una eti?ueta es el blo?ue entero en el cual se declara, incluyendo los blo?ues anidados. .e produce un error en tiempo de compilaci-n cuando se de0inen dos eti?uetas con el mismo nombre para ?ue sus (mbitos se solapen.

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

2#3

Especificacin del lenguaje C#

.e puede =acer re0erencia a una eti?ueta desde instrucciones goto O[8.+.3R dentro del (mbito de la eti?ueta. Esto signi0ica ?ue las instrucciones goto pueden trans0erir el control dentro y 0uera de los blo?ues, pero nunca en los blo?ues. 8as eti?uetas tienen su propio espacio de declaraci-n y no inter0ieren con otros identi0icadores. El e$emplo
int V(int #) { i- (# E+ 3) goto #; # + =#; #/ return #; !

es un e$emplo v(lido ?ue utili1a el nombre # como par(metro y como eti?ueta. 7na instrucci-n con eti?ueta se e$ecuta tal y como se e$ecute la instrucci-n ?ue sigue a la eti?ueta. &dem(s de la capacidad de alcance ?ue proporciona el 0lu$o normal de control, una instrucci-n con eti?ueta es alcan1able si una instrucci-n goto alcan1able =ace re0erencia a la eti?ueta. OExcepci-nG si una instrucci-n goto se encuentra dentro de otra try ?ue incluye un blo?ue -inally, la instrucci-n con eti?ueta est( 0uera de try y el extremo del blo?ue -inally no es alcan1able, entonces la instrucci-n con eti?ueta tampoco es alcan1able desde esta instrucci-n gotoR.

-.# Instrucciones de declaracin


7na instrucci-n de declaraci-n Odeclaration-state%entR declara una variable o una constante local. 8as instrucciones de declaraci-n se pueden incluir en blo?ues, pero no est(n permitidas como instrucciones incrustadas. declaration-state%ent1 local-varia-le-declaration ; local-constant-declaration ; -.#.1 /eclaraciones de ariables locales 7na declaraci-n de variable local Olocal-varia-le-declarationR declara una o varias variables locales. local-varia-le-declaration1 local-varia-le-t#pe local-varia-le-declarators local-varia-le-t#pe1 t#pe
var

local-varia-le-declarators1 local-varia-le-declarator local-varia-le-declarators

local-varia-le-declarator

local-varia-le-declarator1 identificador identifier @ local-varia-le-initiali0er local-varia-le-initiali0er1 e2pression arra#-initiali0er El tipo de variable local Olocal-varia-le-t#peR de una declaraci-n de variable local Olocal-varia-le-declarationR especi0ica directamente el tipo de las variables introducidas por la declaraci-n, o indica con la palabra clave var ?ue el tipo se deber5a in0erir bas(ndose en un iniciali1ador. El tipo aparece seguido de una lista de declaradores de variable local Olocal-varia-le-declaratorsR, cada una de las cuales incluye una nueva variable. 7n declarador

2##

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

de variable local Olocal-varia-le-declaratorR est( 0ormado por un identi0icador OidentifierR ?ue da nombre a la variable, ?ue opcionalmente puede ir seguido del s5mbolo Oto6enR P+Q y de un iniciali1ador de variable local Olocal-varia-le-initiali0erR ?ue establece el valor inicial de la variable. Cuando el tipo de variable local Olocal-varia-le-t#peR se especi0ica como var y no =ay ningHn tipo con nombre var en el (mbito, la declaraci-n es una declaraci,n de varia/le local con asignaci,n de tipo i plcita, cuyo tipo se in0iere del tipo de la expresi-n de iniciali1ador asociada. 8as declaraciones de variable local con asignaci-n de tipo impl5cita est(n su$etas a las siguientes restriccionesG 8a declaraci-n de variable local Olocal-varia-le-declarationR no puede incluir varios declaradores de variable local Olocal-varia-le-declaratorsR. El declarador de variable local Olocal-varia-le-declaratorR debe incluir un iniciali1ador de variable local Olocal-varia-le-initiali0erR. El iniciali1ador de variable local Olocal-varia-le-initiali0erR debe ser una expresi-n Oe2pressionR. 8a expresi-n Oe2pressionR del iniciali1ador debe tener un tipo en tiempo de compilaci-n. 8a expresi-n Oe2pressionR del iniciali1ador no puede =acer re0erencia a la variable declarada en s5
var var var var var #; y + ? + u + v + .. .. .. .. .. )rror )rror )rror )rror )rror no initiali?er to in-er ty&e -rom array initiali?er not &ermitted null does not "ave a ty&e anonymous -unctions do not "ave a ty&e initiali?er cannot re-er to variable itsel-

& continuaci-n, se muestran e$emplos de declaraciones de variable local con asignaci-n de tipo impl5citaG
{2 8 9!; null; # +E # < 2; v<<;

'ara obtener el valor de una variable local en una expresi-n se utili1a un nombre simple Osi%ple-na%eR O[*. .2R y, para modi0icarlo, se reali1a una asignaci-n Oassi&n%entR O[*.1#R. 7na variable local debe estar asignada de0initivamente O[ .3R en cada ubicaci-n donde se obtenga su valor. El (mbito de una variable local declarada en una declaraci-n de variable local Olocal-varia-le-declarationR es el blo?ue donde se produce la declaraci-n. .upone un error =acer re0erencia a una variable local en una posici-n textual ?ue precede al declarador de la variable local Olocal-varia-le-declaratorR. 2entro del (mbito de una variable local, supone un error en tiempo de compilaci-n declarar otra variable o constante local con el mismo nombre. 7na declaraci-n de variable local ?ue declara varias variables e?uivale a varias declaraciones de una sola variable con el mismo tipo. 7n iniciali1ador de variable Ovaria-le-initiali0erR en una declaraci-n de variable local es en realidad una instrucci-n de asignaci-n ?ue se inserta inmediatamente despu)s de la declaraci-n. El e$emplo
void V() { int # + 2 ! y ? + # > 8;

es id)ntico a
void V() { int #; # + 2; int y; int ?; ? + # > 8; !

En una declaraci-n de variable local con asignaci-n de tipo impl5cita, se toma el tipo de la variable local ?ue se declara para ?ue sea el mismo tipo de la expresi-n utili1ada para iniciali1ar la variable. 'or e$emploG

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

2#!

Especificacin del lenguaje C# var var var var var i + K; s + "Hello"; d + 2.3; numbers + ne, int45 {2 8 9!; orders + ne, 6ictionaryDint %rderE();

8as declaraciones de variable local con asignaci-n de tipo impl5cita de arriba son precisamente e?uivalentes a las siguientes declaraciones con asignaci-n de tipo expl5citaG
int i + K; string s + "Hello"; double d + 2.3; int45 numbers + ne, int45 {2 8 9!; 6ictionaryDint %rderE orders + ne, 6ictionaryDint %rderE();

-.#.2 /eclaraciones de constantes locales 7na declaraci-n de constante local Olocal-varia-le-declaratorR declara una o varias constantes locales. local-constant-declaration1 const t#pe constant-declarators constant-declarators1 constant-declarator constant-declarators

constant-declarator

constant-declarator1 identifier @ constant-e2pression El tipo Ot#peR de una declaraci-n de constante local Olocal-constant-declarationR especi0ica el tipo de las constantes ?ue se incluyen en la declaraci-n. El tipo viene seguido de una lista de declaradores de constante Oconstant-declaratorsR, cada uno de los cuales incluye una nueva constante. 7n declarador de constante Oconstant-declaratorR consta de un identi0icador OidentifierR ?ue da nombre a la constante, seguido del s5mbolo Oto6enR P+Q y de una expresi-n constante Oconstant-e2pressionR O[*.18R ?ue establece el valor de la constante. El tipo Ot#peR y la e2presi/n constante Oconstant-e2pressionR de una declaraci-n de constante local deben seguir las reglas de declaraci-n de miembros de constantes O[1".4R. 'ara obtener el valor de una constante local en una expresi-n, se utili1a el no%-re si%ple Osi%ple-na%eR O[*. .2R. El (mbito de una constante local es el blo?ue donde se produce la declaraci-n. Es un error =acer re0erencia a una constante local en una posici-n textual anterior a su declarador de constante Oconstant-declaratorR. 2entro del (mbito de una constante local, supone un error en tiempo de compilaci-n declarar otra variable o constante local con el mismo nombre. 7na declaraci-n de constante local ?ue declara varias constantes e?uivale a varias declaraciones de una sola constante con el mismo tipo.

-.$ Instrucciones de e"presiones


7na instrucci-n de expresi-n Oe2pression-state%entR evalHa una expresi-n determinada. El valor calculado por la expresi-n, en el caso de =aber alguno, se descarta. e2pression-state%ent1 state%ent-e2pression ;

2#6

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

state%ent-e2pression1 invocation-e2pression o->ect-creation-e2pression assi&n%ent post-incre%ent-e2pression post-decre%ent-e2pression pre-incre%ent-e2pression pre-decre%ent-e2pression 4o todas las expresiones pueden ser instr cciones. En concreto, expresiones como # < y y # ++ 2, ?ue simplemente calculan un valor Oel cual ser( descartadoR, no se admiten como instrucciones. 8a e$ecuci-n de una instrucci-n de expresi-n Oe2pression-state%entR evalHa la expresi-n ?ue contiene y despu)s trans0iere el control al punto 0inal de la instrucci-n de expresi-n. 'or lo tanto, el punto 0inal de una instrucci-n de expresi-n Oe2pression-state%enR es alcan1able si dic=a instrucci-n tambi)n lo es.

-.+ Instrucciones de seleccin


8as instrucciones de selecci-n Oselection-state%entR seleccionan una de las instrucciones ?ue se van a e$ecutar en 0unci-n del valor de alguna expresi-n. selection-state%ent1 if-state%ent switch-state%ent -.+.1 Instruccin If 8a instrucci-n i- selecciona una instrucci-n ?ue se va a e$ecutar bas(ndose en el valor de una expresi-n booleana. if-state%ent1 i- ( -oolean-e2pression ) e%-edded-state%ent i- ( -oolean-e2pression ) e%-edded-state%ent else e%-edded-state%ent 8a secci-n else se asocia a la instrucci-n i- anterior m(s cercana permitida por la sintaxis. 'or lo tanto, una instrucci-n i- con la estructura
i- (#) i- (y) V(); else S();

e?uivale a
i- (#) { i- (y) { V(); ! else { S(); ! !

7na instrucci-n i- se e$ecuta de la siguiente 0ormaG .e evalHa la e2presi/n -ooleana O-oolean-e2pressionR O[*.1+R. .i la expresi-n booleana devuelve true, el control se trans0iere a la primera instrucci-n incrustada. Cuando el control alcan1a el punto 0inal de dic=a instrucci-n, se trans0iere al punto 0inal de la instrucci-n i-. .i la expresi-n booleana devuelve -alse y existe una secci-n else, el control se trans0iere a la segunda instrucci-n incrustada. Cuando el control alcan1a el punto 0inal de dic=a instrucci-n, se trans0iere al punto 0inal de la instrucci-n i-.

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

2#(

Especificacin del lenguaje C#

.i la expresi-n booleana devuelve -alse y no existe una secci-n else, el control se trans0iere al punto 0inal de la instrucci-n i-.

8a primera instrucci-n incrustada de una instrucci-n i- es alcan1able si la instrucci-n i- es alcan1able y la expresi-n booleana no tiene el valor constante -alse. 8a segunda instrucci-n incrustada de una instrucci-n i-, si existe, es alcan1able si la instrucci-n i- es alcan1able y la expresi-n booleana no tiene el valor constante true. El punto 0inal de una instrucci-n i- es alcan1able si el punto 0inal de al menos una de sus instrucciones incrustadas es alcan1able. &dem(s, el punto 0inal de una instrucci-n i- ?ue no tiene secci-n else es alcan1able si la instrucci-n i- es alcan1able y la expresi-n booleana no tiene el valor constante true. -.+.2 Instruccin 4@itc? 8a instrucci-n s9itc= Oswitch-state%entR selecciona una lista de instrucciones ?ue se van a e$ecutar ?ue tengan asociada una eti?ueta s9itc= Oswitch-la-elR ?ue se corresponda con el valor de la expresi-n s9itc=. switch-state%ent1 s,itc" ( e2pression ) switch--loc3 switch--loc31 { switch-sectionsopt ! switch-sections1 switch-section switch-sections switch-section switch-section1 switch-la-els state%ent-list switch-la-els1 switch-la-el switch-la-els switch-la-el switch-la-el1 case constant-e2pression /
de-ault /

7na instrucci-n s9itc= Oswitch-state%entR est( 0ormada por la palabra clave s,itc", seguida de una expresi-n entre par)ntesis Odenominada expresi-n s9itc=R y de un blo?ue s9itc= Oswitch--loc3R. El blo?ue s9itc= consiste en varias o ninguna secciones de s9itc= Oswitch-sectionsR, encerradas entre llaves. Cada secci/n de switch Oswitch-sectionR est( 0ormada por una o varias eti?uetas de s9itc= Oswitch-la-elsR seguidas de una lista de instrucciones Ostate%ent-listR O[8.2.1R. El tipo aplica/le en una instrucci-n s,itc" est( establecido por la expresi-n s9itc=. .i el tipo de la expresi-n s9itc= es sbyte, byte, s"ort, us"ort, int, uint, long, ulong, bool, c"ar, string o un tipo enum Oen %-t#peR, o si es el tipo ?ue acepta valores null correspondiente a uno de estos tipos, entonces es el tipo aplicable de la instrucci-n s,itc". En caso contrario, debe existir una conversi-n impl5cita de0inida por el usuario O[#.4R del tipo de la expresi-n s9itc= a uno de los posibles tipos aplicablesG sbyte, byte, s"ort, us"ort, int, uint, long, ulong, c"ar, string o un tipo ?ue acepta valores null correspondiente a uno de esos tipos. 2e lo contrario, si no existe tal conversi-n impl5cita o existe m(s de una, se producir( un error en tiempo de compilaci-n.

2#$

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

8a expresi-n constante de cada eti?ueta case debe denotar un valor de tipo convertible impl5citamente O[#.1R al tipo aplicable en la instrucci-n s,itc". .i dos o m(s eti?uetas case de la misma instrucci-n s,itc" especi0ican el mismo valor constante, se producir( un error en tiempo de compilaci-n. 'uede existir como m(ximo una eti?ueta de-ault en una instrucci-n s9itc=. 7na instrucci-n s,itc" se e$ecuta de la siguiente 0ormaG .e evalHa la expresi-n s9itc= y se convierte en el tipo aplicable. .i una de las constantes especi0icadas en una eti?ueta case de una instrucci-n s,itc" es igual al valor de la expresi-n s9itc=, el control se trans0iere a la lista de instrucciones ?ue est(n a continuaci-n de dic=a eti?ueta case. .i ninguna de las constantes especi0icadas en las eti?uetas case de una instrucci-n s,itc" es igual al valor de la expresi-n s9itc= y existe una eti?ueta de-ault, el control se trans0iere a la lista de instrucciones ?ue aparece a continuaci-n de la eti?ueta de-ault. .i ninguna de las constantes especi0icadas en las eti?uetas case de una instrucci-n s,itc" es igual al valor de la expresi-n s9itc= y no existe una eti?ueta de-ault, el control se trans0iere al punto 0inal de la instrucci-n s,itc".

.i el punto 0inal de la lista de instrucciones de una secci-n de s9itc= es alcan1able, se producir( un error en tiempo de compilaci-n. Esto se conoce como regla Psin paso expl5citoQ. El e$emplo
s,itc" (i) { case 3/ CasePero(); brea(; case 2/ Case%ne(); brea(; de-ault/ Case%t"ers(); brea(; !

es v(lido por?ue ninguna secci-n de s9itc= tiene un punto 0inal alcan1able. & di0erencia de C y CSS, la e$ecuci-n de una secci-n s9itc= no permite el Ppaso expl5citoQ a la siguiente secci-n de s9itc=, y el e$emplo
s,itc" (i) { case 3/ CasePero(); case 2/ CasePero%r%ne(); de-ault/ Case'ny(); !

da como resultado un error en tiempo de compilaci-n. 'ara e$ecutar una secci-n de s9itc= despu)s de la e$ecuci-n de otra secci-n de s9itc=, debe utili1ar una instrucci-n goto case o goto de-ault expl5citaG
s,itc" (i) { case 3/ CasePero(); goto case 2; case 2/ CasePero%r%ne(); goto de-ault; de-ault/ Case'ny(); brea(; !

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

2#"

Especificacin del lenguaje C#

7na secci-n s9itc= Oswitch-sectionR admite varias eti?uetas. El e$emplo


s,itc" (i) { case 3/ CasePero(); brea(; case 2/ Case%ne(); brea(; case 8/ de-ault/ Case1,o(); brea(; !

es v(lido. El e$emplo no in0ringe la regla Psin paso expl5citoQ por?ue las eti?uetas case 8/ y de-ault/ 0orman parte de la misma secci-n de s9itc= Oswitch-sectionR. 8a regla Psin paso expl5citoQ evita una clase de errores comunes ?ue se producen en C y CSS cuando se omiten involuntariamente instrucciones brea(. &dem(s, gracias a esta regla, las secciones de s9itc= de una instrucci-n s,itc" se pueden reorgani1ar arbitrariamente sin a0ectar al comportamiento de la instrucci-n. 'or e$emplo, las secciones de la instrucci-n s,itc" anterior se pueden colocar en orden inverso sin modi0icar el comportamiento de la instrucci-nG
s,itc" (i) { de-ault/ Case'ny(); brea(; case 2/ CasePero%r%ne(); goto de-ault; case 3/ CasePero(); goto case 2; !

8a lista de instrucciones de una secci-n de s9itc= termina normalmente con una instrucci-n brea(, goto case o goto de-ault, pero tambi)n se admite cual?uier sintaxis ?ue represente el punto 0inal de la lista de instrucciones en inalcan1able. 'or e$emplo, una instrucci-n ,"ile controlada mediante la expresi-n booleana true nunca alcan1ar( su punto 0inal. !gualmente, una instrucci-n t"ro, o return siempre trans0iere el control a otra parte y nunca alcan1a su punto 0inal. 'or tanto, el siguiente e$emplo es correctoG
s,itc" (i) { case 3/ ,"ile (true) V(); case 2/ t"ro, ne, 'rgument)#ce&tion(); case 8/ return; !

2!'

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

El tipo aplicable en una instrucci-n s,itc" puede ser el tipo string. 'or e$emploG
void 6oCommand(string command) { s,itc" (command.1oLo,er()) { case "run"/ 6oOun(); brea(; case "save"/ 6oSave(); brea(; case "Quit"/ 6o^uit(); brea(; de-ault/ $nvalidCommand(command); brea(; ! !

2e la misma 0orma ?ue los operadores de igualdad O[*.+.*R, la instrucci-n s,itc" distingue mayHsculas de minHsculas y e$ecutar( una determinada secci-n s-lo si la cadena de expresi-n s9itc= coincide exactamente con una constante de eti?ueta case. Cuando el tipo aplicable en una instrucci-n s,itc" es string, se admite el valor null como constante de eti?ueta case. 8as listas de instrucciones Ostate%ent-listsR de blo?ue s9itc= Oswitch--loc3R pueden contener instrucciones de declaraci-n O[8. R. El (mbito de una variable o constante local declarada en un blo?ue s9itc= es el propio blo?ue. 2entro de un blo?ue s9itc=, el signi0icado de un nombre utili1ado en un contexto de expresi-n siempre debe ser el mismo O[*. .2.1R. 8a lista de instrucciones de una secci-n de s9itc= determinada es alcan1able si la instrucci-n s,itc" es alcan1able y se cumple al menos una de las condiciones siguientesG 8a expresi-n s9itc= no es un valor constante. 8a expresi-n s9itc= es un valor de constante ?ue coincide con una eti?ueta case de la secci-n de s9itc=. 8a expresi-n s9itc= es un valor de constante ?ue no coincide con ninguna eti?ueta case y la secci-n de s9itc= contiene la eti?ueta de-ault. 7na instrucci-n goto case o goto de-ault alcan1able =ace re0erencia a una eti?ueta s9itc= de la secci-n. 8a instrucci-n s,itc" contiene una instrucci-n brea( alcan1able ?ue provoca la salida de la instrucci-n s,itc". 8a instrucci-n s,itc" es alcan1able, la expresi-n s9itc= no es un valor constante y no existe eti?ueta de-ault. 8a instrucci-n s,itc" es alcan1able, la expresi-n s9itc= es una constante ?ue no coincide con ninguna eti?ueta case y no existe eti?ueta de-ault.

El punto 0inal de una instrucci-n s,itc" es alcan1able si se cumple al menos una de las siguientes condicionesG

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

2!1

Especificacin del lenguaje C#

-.- Instrucciones de iteracin


8as instrucciones de iteraci-n Oiteration-state%entR e$ecutan repetidas veces una instrucci-n incrustada. iteration-state%ent1 while-state%ent do-state%ent for-state%ent foreach-state%ent -.-.1 Instruccin B?ile 8a instrucci-n ,"ile e$ecuta una instrucci-n incrustada cero o varias veces dependiendo de una condici-n. while-state%ent1 ,"ile ( -oolean-e2pression ) e%-edded-state%ent 7na instrucci-n ,"ile se e$ecuta de la siguiente 0ormaG .e evalHa la e2presi/n -ooleana O-oolean-e2pressionR O[*.1+R. .i la expresi-n booleana devuelve true, el control se trans0iere a la instrucci-n incrustada. Cuando el control alcan1a el punto 0inal de la instrucci-n incrustada Oposiblemente desde la e$ecuci-n de una instrucci-n continueR, se trans0iere al inicio de la instrucci-n ,"ile. .i la expresi-n booleana devuelve -alse, el control se trans0iere al punto 0inal de la instrucci-n ,"ile.

2entro de la instrucci-n incrustada de la instrucci-n ,"ile, puede utili1ar una instrucci-n brea( O[8.+.1R para trans0erir el control al punto 0inal de la instrucci-n ,"ile Oterminando as5 la iteraci-n de la instrucci-n incrustadaR, y una instrucci-n continue O[8.+.2R para trans0erir el control al punto 0inal de la instrucci-n incrustada Ode esta 0orma se reali1ar( otra iteraci-n de la instrucci-n ,"ileR. 8a instrucci-n incrustada de una instrucci-n ,"ile es alcan1able si la instrucci-n ,"ile es alcan1able y la expresi-n booleana no tiene el valor constante -alse. El punto 0inal de una instrucci-n ,"ile es alcan1able si se cumple al menos una de las siguientes condicionesG 8a instrucci-n ,"ile contiene una instrucci-n brea( alcan1able ?ue provoca la salida de la instrucci-n ,"ile. 8a instrucci-n ,"ile es alcan1able y la expresi-n booleana no tiene el valor constante true.

-.-.2 Instruccin /o 8a instrucci-n do e$ecuta una instrucci-n incrustada una o varias veces dependiendo de una condici-n. do-state%ent1 do e%-edded-state%ent ,"ile ( -oolean-e2pression ) ; 7na instrucci-n do se e$ecuta de la siguiente 0ormaG El control se trans0iere a la instrucci-n incrustada. Cuando el control alcan1a el punto 0inal de la instrucci-n incrustada Oposiblemente desde la e$ecuci-n de una instrucci-n continueR, se evalHa la expresi-n booleana O-oolean-e2pressionR O[*.1+R. .i la expresi-n booleana devuelve true, el control se trans0iere al inicio de la instrucci-n do. En caso contrario, el control se trans0iere al punto 0inal de la instrucci-n do.

2entro de la instrucci-n incrustada de la instrucci-n do, puede utili1ar una instrucci-n brea( O[8.+.1R para trans0erir el control al punto 0inal de la instrucci-n do Oterminando as5 la iteraci-n de la instrucci-n incrustadaR, y una instrucci-n continue O[8.+.2R para trans0erir el control al punto 0inal de la instrucci-n incrustada.
2!2
Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

8a instrucci-n incrustada de una instrucci-n do es alcan1able si la instrucci-n do es alcan1able. El punto 0inal de una instrucci-n es alcan1able si se cumple al menos una de las siguientes condicionesG 8a instrucci-n do contiene una instrucci-n brea( alcan1able ?ue provoca la salida de la instrucci-n do. El punto 0inal de la instrucci-n incrustada es alcan1able y la expresi-n booleana no tiene el valor constante true.

-.-.3 Instruccin 7or 8a instrucci-n -or evalHa primero una secuencia de expresiones de iniciali1aci-n y, mientras se cumpla una determinada condici-n, e$ecuta repetidas veces una instrucci-n incrustada y evalHa una secuencia de expresiones de iteraci-n. for-state%ent1 -or ( for-initiali0eropt ; for-conditionopt ; for-iteratoropt ) e%-edded-state%ent for-initiali0er1 local-varia-le-declaration state%ent-e2pression-list for-condition1 -oolean-e2pression for-iterator1 state%ent-e2pression-list state%ent-e2pression-list1 state%ent-e2pression state%ent-e2pression-list

state%ent-e2pression

El iniciali0ador for Ofor-initiali0erR, si existe, es una declaraci-n de variable local Olocal-varia-le-declarationR O[8. .1R o una lista de expresiones de instrucci-n Ostate%ent-e2pressionsR O[8.#R separadas por comas. El (mbito de una variable local declarada por un iniciali1ador 0or Ofor-initiali0erR se inicia en el declarador de variable local Olocal-varia-le-declaratorR y se extiende =asta el 0inal de la instrucci-n incrustada. El (mbito incluye la condici-n 0or Ofor-conditionR y el iterador 0or Ofor-iteratorR. 8a condici-n 0or Ofor-conditionR, si existe, debe ser una expresi-n booleana O-oolean-e2pressionR O[*.1+R. El iterador 0or Ofor-iteratorR, si existe, consiste en una lista de expresiones de instrucci-n Ostate%ente2pressionsR O[8.#R separadas por comas. 7na instrucci-n 0or se e$ecuta de la siguiente 0ormaG .i existe un iniciali1ador 0or Ofor-initiali0erR, se e$ecutan los iniciali1adores de variable o las expresiones de instrucci-n en el orden en el ?ue se =ayan codi0icado. Este paso s-lo se reali1a una ve1. .i existe una condici-n 0or Ofor-conditionR, se evalHa. .i no existe una condici-n 0or Ofor-conditionR, o existe y la evaluaci-n devuelve true, el control se trans0iere a la instrucci-n incrustada. Cuando el control alcan1a el punto 0inal de la instrucci-n incrustada Oposiblemente desde la e$ecuci-n de una instrucci-n continueR, las expresiones del iterador 0or OforiteratorR, si existen, se evalHan en secuencia y, a continuaci-n, se reali1a una nueva iteraci-n empe1ando por la evaluaci-n de la condici-n 0or Ofor-conditionR, como se describe en el paso anterior. .i existe una condici-n 0or Ofor-conditionR y devuelve -alse, el control se trans0iere al punto 0inal de la instrucci-n -or.

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

2!3

Especificacin del lenguaje C#

2entro de la instrucci-n incrustada de una instrucci-n -or, se puede utili1ar una instrucci-n brea( O[8.+.1R para trans0erir el control al punto 0inal de la instrucci-n -or Oterminando as5 la iteraci-n de la instrucci-n incrustadaR, y una instrucci-n continue O[8.+.2R para trans0erir el control al punto 0inal de la instrucci-n incrustada Ode esta manera, se e$ecuta el iterador 0or Ofor-iteratorR y se reali1a otra iteraci-n de la instrucci-n -or, empe1ando por la condici-n 0or Ofor-conditionR. 8a instrucci-n incrustada de una instrucci-n -or es alcan1able si se cumple alguna de las condiciones siguientesG 8a instrucci-n -or es alcan1able y no =ay ninguna condici-n 0or Ofor-conditionR. 8a instrucci-n -or es alcan1able y =ay una condici-n 0or Ofor-conditionR, pero esta Hltima no tiene el valor constante -alse. 8a instrucci-n -or contiene una instrucci-n brea( alcan1able ?ue provoca la salida de la instrucci-n -or. 8a instrucci-n -or es alcan1able y =ay una condici-n 0or Ofor-conditionR, pero esta Hltima no tiene el valor constante true.

El punto 0inal de una instrucci-n -or es alcan1able si se cumple al menos una de las siguientes condicionesG

-.-.! Instruccin 7oreac? 8a instrucci-n -oreac" enumera los elementos de una colecci-n, e$ecutando una instrucci-n incrustada para cada elemento de la colecci-n. foreach-state%ent1 -oreac" ( local-varia-le-t#pe identifier in e2pression ) e%-edded-state%ent El tipo Ot#peR y el identi0icador OidentifierR de una instrucci-n -oreac" declaran la varia/le de iteraci,n de la instrucci-n. .i se da la palabra clave var como tipo de variable local Olocal-varia-le-t#peR, se dice ?ue la variable de iteraci-n es una varia/le de iteraci,n con asignaci,n de tipo i plcita, y se toma su tipo para ?ue sea el tipo de elemento de la instrucci-n -oreac", como se especi0ica a continuaci-n. 8a variable de iteraci-n es una variable local de s-lo lectura con un (mbito ?ue se extiende a lo largo de toda la instrucci-n incrustada. 2urante la e$ecuci-n de una instrucci-n -oreac", la variable de iteraci-n representa el elemento de colecci-n para el ?ue se est( reali1ando la iteraci-n en ese momento. .e producir( un error en tiempo de compilaci-n si la instrucci-n incrustada intenta modi0icar la variable de iteraci-n Opor medio de asignaci-n o utili1ando los operadores << y ==R, o bien si la pasa como un par(metro re- u out. El procesamiento en tiempo de compilaci-n de una instrucci-n 0oreac= determina primero el tipo de colecci,n, el tipo de en! erador y el tipo de ele ento de la expresi-n. Esta determinaci-n se reali1a de la siguiente 0ormaG .i el tipo I de expresi-n Oe2pressionR es un tipo de matri1, =ay una conversi-n impl5cita de I a la inter0a1 System.Collections.$)numerable Oya ?ue System.'rray implementa esta inter0a1R. El tipo de colecci,n es la inter0a1 System.Collections.$)numerable, el tipo de en! erador es la inter0a1 System.Collections.$)numerator y el tipo de ele ento es el tipo de elemento del tipo de matri1 I. En caso contrario, determine si el tipo I tiene un m)todo Set)numerator apropiadoG o ;ealice la bHs?ueda de miembros en el tipo I con el identi0icador Set)numerator y con ningHn argumento de tipo. .i la bHs?ueda de miembros no produce ningHn resultado, o si produce una ambigIedad, o un resultado ?ue no es un grupo de m)todos, compruebe una inter0a1 enumerable como se describe m(s adelante. Es aconse$able ?ue se emita una advertencia si la bHs?ueda de miembros no produce ningHn resultado o si produce resultados pero no son grupos de m)todos. ;ealice la resoluci-n de sobrecargas utili1ando el grupo de m)todos resultante y una lista de argumentos vac5a. .i la resoluci-n de sobrecargas no tiene como resultado m)todos aplicables, si produce una
Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

2!#

Cap0tulo 1' Clases

ambigIedad, o un m)todo individual me$or pero ?ue es est(tico o no pHblico, compruebe una inter0a1 enumerable como se describe m(s adelante. Es aconse$able ?ue se emita una advertencia si la resoluci-n de sobrecargas no produce ningHn m)todo aplicable o si produce resultados pero no son m)todos de instancia pHblica sin ambigIedad. o o .i el tipo de resultado ) del m)todo Set)numerator no es una clase, estructura o tipo de inter0a1, se produce un error y no se reali1an m(s pasos. 8a bHs?ueda de miembros se reali1a en ) con el identi0icador Current y ningHn argumento de tipo. .i la bHs?ueda de miembros no produce ningHn resultado, el resultado es un error, o el resultado no es una propiedad de instancia pHblica ?ue permita la lectura, se produce un error y no se reali1an m(s pasos. 8a bHs?ueda de miembros se reali1a en ) con el identi0icador MoveNe#t y ningHn argumento de tipo. .i la bHs?ueda de miembros no produce ningHn resultado, el resultado es un error, o el resultado no es un grupo de m)todos, se produce un error y no se reali1an m(s pasos. 8a resoluci-n de sobrecargas se reali1a en el grupo de m)todos con una lista de argumentos vac5a. .i la resoluci-n de sobrecargas no tiene como resultado m)todos aplicables, si produce una ambigIedad, o un m)todo individual me$or pero ?ue es est(tico o no pHblico, o su tipo devuelto no es bool, se produce un error y no se reali1an m(s pasos. El tipo de colecci,n es I, el tipo de en! erador es ), y el tipo de ele ento es el tipo de la propiedad Current. .i =ay exactamente un tipo 1 de manera ?ue =ay una conversi-n impl5cita de I a la inter0a1 System.Collections.Seneric.$)numerableD1E, entonces el tipo de colecci,n es esta inter0a1, el tipo en! erador es la inter0a1 System.Collections.Seneric.$)numeratorD1E, y el tipo de ele ento es 1. En caso contrario, si =ay m(s de un tipo 1, se produce un error y no se reali1an m(s pasos. En caso contrario, si =ay una conversi-n impl5cita de I a la inter0a1 System.Collections.$)numerable, entonces el tipo de colecci,n es esta inter0a1, el tipo de n! erador es la inter0a1 System.Collections.$)numerator, y el tipo de ele ento es object. En caso contrario, se produce un error y no se reali1an m(s pasos.

En caso contrario, compruebe una inter0a1 enumerableG o

o o

8os pasos anteriores, si son correctos, producen sin ninguna ambigIedad un tipo de colecci-n C, un tipo de enumerador ) y un tipo de elemento 1. 7na instrucci-n 0oreac= con la estructura
-oreac" (U v in #) e%-edded-state%ent

se expande aG
{ ) e + ((C)(#)).Set)numerator(); try { U v; ,"ile (e.MoveNe#t()) { v + (U)(1)e.Current;

e%-edded-state%ent
! ! -inally { b .. 6is&ose e ! !

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

2!!

Especificacin del lenguaje C#

8a variable e no es visible ni accesible para la expresi-n # o la declaraci-n incrustada o cual?uier otro c-digo 0uente del programa. 8a variable v es de s-lo lectura en la instrucci-n incrustada. .i no =ay una conversi-n expl5cita O[#.2R de 1 Otipo de elementoR a U Otipo de variable local, local-varia-le-t#pe, de la instrucci-n 0oreac=R, se produce un error y no se reali1an m(s pasos. .i # tiene el valor null, se inicia una System.NullOe-erence)#ce&tion en tiempo de e$ecuci-n. .e permite ?ue una implementaci-n implemente una instrucci-n 0oreac= dada de manera di0erente, por e$emplo, por motivos de rendimiento, siempre ?ue el comportamiento sea co=erente con la expansi-n anterior. El cuerpo del blo?ue 0inally se construye de acuerdo con los siguientes pasosG .i =ay una conversi-n impl5cita desde ) a la inter0a1 System.$6is&osable, entonces o .i ) es un tipo de valor ?ue acepta valores null, entonces la cl(usula 0inally se expande =asta el e?uivalente sem(ntico deG
-inally { ((System.$6is&osable)e).6is&ose(); !

2e lo contrario, la cl(usula 0inally se expande =asta el e?uivalente sem(ntico deG


-inally { i- (e @+ null) ((System.$6is&osable)e).6is&ose(); !

excepto si ) es un tipo de valor, o un par(metro de tipo cuya instancia se =a creado para un tipo de valor, entonces la conversi-n de e a System.$6is&osable no producir( una conversi-n boxing. En caso contrario, si ) es un tipo sealed, la cl(usula 0inally se expande a un blo?ue vac5oG
-inally { !

En caso contrario, la cl(usula 0inally se expande aG


-inally { System.$6is&osable d + e as System.$6is&osable; i- (d @+ null) d.6is&ose(); !

8a variable local d no es visible ni accesible para cual?uier c-digo de usuario. En particular, no entra en con0licto con otras variables cuyo (mbito incluya el blo?ue 0inally. El orden en ?ue -oreac" recorre los elementos de una matri1 es el siguienteG en matrices unidimensionales, los elementos se recorren en orden creciente, empe1ando por el 5ndice 3 y acabando por el 5ndice Lengt" C 2. 8os elementos de matrices multidimensionales se recorren de manera ?ue los 5ndices de la dimensi-n del extremo derec=o se incrementan en primer lugar, a continuaci-n la dimensi-n situada inmediatamente a su i1?uierda y as5 sucesivamente =acia la i1?uierda. El c-digo del siguiente e$emplo muestra cada valor de una matri1 bidimensional segHn el orden de los elementosG
using System; class 1est { static void Main() { double4 5 values + { {2.8 8.9 9.J J.K! {K.X X.M M.Y Y.L! !;

2!6

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases -oreac" (double elementUalue in values) Console.Write("{3! " elementUalue); Console.WriteLine(); ! !

El resultado producido es el siguienteG


2.8 8.9 9.J J.K K.X X.M M.Y Y.L

En el e$emplo
int45 numbers + { 2 9 K M L !; -oreac" (var n in numbers) Console.WriteLine(n);

el tipo de n se in0iere ?ue es int, el tipo de elemento de numbers.

-.. Instrucciones Cump


8as instrucciones de salto O> %p-state%entR trans0ieren el control de 0orma incondicional. > %p-state%ent1 -rea3-state%ent contin e-state%ent &oto-state%ent ret rn-state%ent throw-state%ent 8a posici-n a la ?ue trans0iere el control una instrucci-n de salto se denomina destino de la instrucci-n de salto. Cuando se e$ecuta una instrucci-n de salto dentro de un blo?ue y el destino se encuentra 0uera del blo?ue, se dice ?ue la instrucci-n de salto sale del blo?ue. &un?ue una instrucci-n de salto puede trans0erir el control 0uera de un blo?ue, no puede trans0erirlo dentro del blo?ue. 8a e$ecuci-n de las instrucciones de salto se complica cuando intervienen instrucciones try. .i no existen instrucciones try, la instrucci-n de salto trans0iere incondicionalmente el control a su destino. 'ero si existen instrucciones try, la e$ecuci-n es m(s comple$a. .i la instrucci-n de salto sale de uno o varios blo?ues try ?ue llevan asociados blo?ues -inally, el control se trans0iere inicialmente al blo?ue -inally de la instrucci-n try m(s interna. Cuando el control alcan1a el punto 0inal de un blo?ue -inally, el control se trans0iere al blo?ue -inally de la siguiente instrucci-n envolvente try. Este proceso se repite =asta ?ue se e$ecuten los blo?ues -inally de todas las instrucciones try ?ue intervienen. En el e$emplo
using System;

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

2!(

Especificacin del lenguaje C# class 1est { static void Main() { ,"ile (true) { try { try { Console.WriteLine(":e-ore brea("); brea(; ! -inally { Console.WriteLine("$nnermost -inally bloc("); ! ! -inally { Console.WriteLine("%utermost -inally bloc("); ! ! Console.WriteLine("'-ter brea("); ! !

los blo?ues -inally asociados a las dos instrucciones try se e$ecutan antes de trans0erir el control al destino de la instrucci-n de salto. El resultado producido es el siguienteG
:e-ore brea( $nnermost -inally bloc( %utermost -inally bloc( '-ter brea(

-...1 Instruccin <rea3 8a instrucci-n brea( provoca la salida de la instrucci-n envolvente s,itc", ,"ile, do, -or o -oreac" m(s pr-xima. -rea3-state%ent1
brea( ;

El destino de una instrucci-n brea( es el punto 0inal de la instrucci-n envolvente s,itc", ,"ile, do, -or o -oreac" m(s pr-xima. .i la instrucci-n brea( no se encuentra dentro de una instrucci-n s,itc", ,"ile, do, -or o -oreac", se produce un error en tiempo de compilaci-n. Cuando existen varias instrucciones s,itc", ,"ile, do, -or o -oreac" anidadas, la instrucci-n brea( se aplica s-lo a la instrucci-n m(s interna. 'ara trans0erir el control a trav)s de varios niveles de anidamiento, debe utili1ar una instrucci-n goto O[8.+.3R. 7na instrucci-n brea( no puede salir de un blo?ue -inally O[8.1"R. Cuando se e$ecuta una instrucci-n brea( dentro de un blo?ue -inally, el destino de la instrucci-n brea( debe encontrarse dentro del propio blo?ue -inallyV en caso contrario, se producir( un error en tiempo de compilaci-n. 7na instrucci-n brea( se e$ecuta de la siguiente 0ormaG .i la instrucci-n brea( sale de uno o m(s blo?ues try ?ue llevan asociados blo?ues -inally, el control se trans0iere inicialmente al blo?ue -inally de la instrucci-n try m(s interna. Cuando el control alcan1a el punto 0inal de un blo?ue -inally, el control se trans0iere al blo?ue -inally de la siguiente instrucci-n envolvente try. Este proceso se repite =asta ?ue se e$ecuten los blo?ues -inally de todas las instrucciones try ?ue intervienen. El control se trans0iere al destino de la instrucci-n brea(.

2!$

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

Como una instrucci-n brea( trans0iere incondicionalmente el control a otra parte del c-digo, el punto 0inal de una instrucci-n brea( nunca es alcan1able. -...2 Instruccin 4tatement 8a instrucci-n continue inicia una nueva iteraci-n de la instrucci-n envolvente ,"ile, do, -or o -oreac" m(s pr-xima. contin e-state%ent1
continue ;

El destino de una instrucci-n continue es el punto 0inal de la instrucci-n incrustada de la instrucci-n envolvente ,"ile, do, -or o -oreac" m(s pr-xima. .i la instrucci-n continue no se encuentra dentro de una instrucci-n ,"ile, do, -or o -oreac", se produce un error en tiempo de compilaci-n. Cuando existen varias instrucciones ,"ile, do, -or o -oreac" anidadas, la instrucci-n continue se aplica s-lo a la instrucci-n m(s interna. 'ara trans0erir el control a trav)s de varios niveles de anidamiento, debe utili1ar una instrucci-n goto O[8.+.3R. 7na instrucci-n continue no puede salir de un blo?ue -inally O[8.1"R. Cuando se e$ecuta una instrucci-n continue dentro de un blo?ue -inally, el destino de la instrucci-n continue debe encontrarse dentro del propio blo?ue -inallyV en caso contrario, se producir( un error en tiempo de compilaci-n. 7na instrucci-n continue se e$ecuta de la siguiente 0ormaG .i la instrucci-n continue sale de uno o m(s blo?ues try ?ue llevan asociados blo?ues -inally, el control se trans0iere inicialmente al blo?ue -inally de la instrucci-n try m(s interna. Cuando el control alcan1a el punto 0inal de un blo?ue -inally, el control se trans0iere al blo?ue -inally de la siguiente instrucci-n envolvente try. Este proceso se repite =asta ?ue se e$ecuten los blo?ues -inally de todas las instrucciones try ?ue intervienen. El control se trans0iere al destino de la instrucci-n continue.

Como una instrucci-n continue trans0iere incondicionalmente el control a otra parte del c-digo, el punto 0inal de una instrucci-n continue nunca es alcan1able. -...3 Instruccin 0oto 8a instrucci-n goto trans0iere el control a una instrucci-n marcada con una eti?ueta. &oto-state%ent1 goto identifier ; goto case constant-e2pression C
goto de-ault ;

El destino de una instrucci-n de identi0icador OidentifierR goto es la instrucci-n con eti?ueta ?ue lleva el nombre de dic=a eti?ueta. .i no existe una eti?ueta con dic=o nombre en el miembro de 0unci-n actual, o si la instrucci-n goto no se encuentra dentro del (mbito de la eti?ueta, se produce un error en tiempo de compilaci-n. Esta regla permite el uso de una instrucci-n goto para trans0erir el control f era de un (mbito anidado, pero no en un (mbito anidado. En el e$emplo
using System; class 1est { static void Main(string45 args) { string4 5 table + { {"Oed" ":lue" "Sreen"! {"Monday" "Wednesday" "Vriday"! !;

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

2!"

Especificacin del lenguaje C# -oreac" (string str in args) { int ro, colm; -or (ro, + 3; ro, D+ 2; <<ro,) -or (colm + 3; colm D+ 8; <<colm) i- (str ++ table4ro, colm5) goto done; Console.WriteLine("{3! not -ound" continue; done/ Console.WriteLine("Vound {3! at 4{2!54{8!5" ! ! ! str ro, colm); str);

se utili1a una instrucci-n goto para trans0erir el control 0uera de un (mbito anidado. El destino de una instrucci-n goto case es la lista de instrucciones de la instrucci-n s,itc" inmediatamente envolvente O[8.*.2R, ?ue contiene una eti?ueta case con el valor constante dado. .i la instrucci-n goto case no est( dentro de una instrucci-n s,itc", la e2presi/n constante Oconstant-e2pressionR no es convertible impl5citamente O[#.1R al tipo aplicable en la instrucci-n envolvente s,itc" m(s pr-xima, o si dic=a instrucci-n s,itc" no contiene una eti?ueta case con el valor constante dado, se produce un error en tiempo de compilaci-n. El destino de una instrucci-n goto de-ault es la lista de instrucciones de la instrucci-n s,itc" inmediatamente envolvente O[8.*.2R, ?ue contiene una eti?ueta de-ault. .i la instrucci-n goto de-ault no se encuentra dentro de una instrucci-n s,itc" o la instrucci-n envolvente s,itc" m(s pr-xima no contiene una eti?ueta de-ault, se produce un error en tiempo de compilaci-n. 7na instrucci-n goto no puede salir de un blo?ue -inally O[8.1"R. Cuando se e$ecuta una instrucci-n goto dentro de un blo?ue -inally, el destino de la instrucci-n goto debe encontrarse dentro del propio blo?ue -inallyV en caso contrario, se producir( un error en tiempo de compilaci-n. 7na instrucci-n goto se e$ecuta de la siguiente 0ormaG .i la instrucci-n goto sale de uno o m(s blo?ues try ?ue llevan asociados blo?ues -inally, el control se trans0iere inicialmente al blo?ue -inally de la instrucci-n try m(s interna. Cuando el control alcan1a el punto 0inal de un blo?ue -inally, el control se trans0iere al blo?ue -inally de la siguiente instrucci-n envolvente try. Este proceso se repite =asta ?ue se e$ecuten los blo?ues -inally de todas las instrucciones try ?ue intervienen. El control se trans0iere al destino de la instrucci-n goto.

Como una instrucci-n goto trans0iere incondicionalmente el control a otra parte del c-digo, el punto 0inal de una instrucci-n goto nunca es alcan1able. -...! Instruccin 9eturn 8a instrucci-n return devuelve el control al llamador del miembro de 0unci-n en el ?ue aparece la instrucci-n return. ret rn-state%ent1 return e2pressionopt ; 7na instrucci-n return sin expresi-n s-lo puede utili1arse en un miembro de 0unci-n ?ue no calcule un valor, es decir, un m)todo con tipo de valor devuelto void, un descriptor de acceso set de una propiedad o indi1ador, descriptores de acceso add y remove de un evento, un constructor de instancia, un constructor est(tico o un destructor.

26'

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

7na instrucci-n return con expresi-n se puede utili1ar s-lo en un miembro de 0unci-n ?ue calcule un valor, es decir, un m)todo con tipo de valor devuelto ?ue no sea void, el descriptor de acceso get de una propiedad o indi1ador o un operador de0inido por el usuario. 2ebe existir una conversi-n impl5cita O[#.1R del tipo de la expresi-n al tipo de valor devuelto por el miembro de 0unci-n ?ue la contiene. .e produce un error en tiempo de compilaci-n cuando aparece una instrucci-n return en un blo?ue -inally O[8.1"R. 7na instrucci-n return se e$ecuta de la siguiente 0ormaG .i la instrucci-n return especi0ica una expresi-n, se evalHa la expresi-n y el valor devuelto se convierte al tipo de valor devuelto por el miembro de 0unci-n ?ue la contiene mediante una conversi-n impl5cita. El resultado de la conversi-n se convierte en el valor devuelto al llamador. .i la instrucci-n return est( encerrada entre uno o varios blo?ues try ?ue llevan asociados blo?ues -inally, el control se trans0iere inicialmente al blo?ue -inally de la instrucci-n try m(s interna. Cuando el control alcan1a el punto 0inal de un blo?ue -inally, el control se trans0iere al blo?ue -inally de la siguiente instrucci-n envolvente try. Este proceso se repite =asta ?ue se e$ecuten los blo?ues -inally de todas las instrucciones try envolventes. El control se devuelve al llamador del miembro de 0unci-n ?ue lo contiene.

Como una instrucci-n return trans0iere incondicionalmente el control a otra parte del c-digo, el punto 0inal de una instrucci-n return nunca es alcan1able. -...# Instruccin T?ro@ 8a instrucci-n t"ro, inicia una excepci-n. throw-state%ent1 t"ro, e2pressionopt ; 7na instrucci-n t"ro, con expresi-n inicia el valor resultante de evaluar la expresi-n. 8a expresi-n debe denotar un valor del tipo de clase System.)#ce&tion, de un tipo de clase ?ue derive de System.)#ce&tion o de un tipo de par(metro de tipo ?ue tenga System.)#ce&tion Oo una subclase de la mismaR como su clase base e0ectiva. .i la expresi-n evaluada devuelve null, se inicia entonces System.NullOe-erence)#ce&tion. 7na instrucci-n t"ro, sin expresi-n s-lo se puede utili1ar en un blo?ue catc", en cuyo caso esta instrucci-n volver( a iniciar la excepci-n ?ue est) controlando en ese momento el blo?ue catc". Como una instrucci-n t"ro, trans0iere incondicionalmente el control a otra parte del c-digo, el punto 0inal de una instrucci-n t"ro, nunca es alcan1able. Cuando se inicia una excepci-n, el control se trans0iere a la primera cl(usula catc" de una instrucci-n try envolvente ?ue pueda controlar la excepci-n. El proceso ?ue tiene lugar desde el punto de inicio de la excepci-n =asta el punto en ?ue se trans0iere el control a un controlador de excepciones adecuado es conocido con el nombre de propagaci,n de e.cepci,n. 8a propagaci-n de una excepci-n consiste en evaluar repetidamente los siguientes pasos =asta encontrar una cl(usula catc" ?ue coincida con la excepci-n. En esta descripci-n, el p!nto de inicio es la ubicaci-n desde la ?ue se inicia la excepci-n. En el miembro de 0unci-n actual, se examina cada instrucci-n try ?ue envuelve al punto de inicio. .e evalHan los siguientes pasos para cada instrucci-n S, comen1ando con la instrucci-n try m(s interna y terminando con la m(s externaG o .i el blo?ue try de S encierra al punto de inicio y . tiene una o varias cl(usulas catc", se examinan las cl(usulas catc" en orden de aparici-n =asta encontrar un controlador adecuado para la excepci-n. 8a primera cl(usula catc" ?ue especi0i?ue el tipo de excepci-n o un tipo base del tipo de excepci-n se

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

261

Especificacin del lenguaje C#

considera una coincidencia. 7na cl(usula catc" general O[8.1"R es una coincidencia para cual?uier tipo de excepci-n. .i se encuentra una cl(usula catc" coincidente, termina la propagaci-n de excepci-n y se trans0iere el control al blo?ue de la cl(usula catc". o En caso contrario, si el blo?ue try o un blo?ue catc" de S encierra el punto de inicio y S tiene un blo?ue -inally, el control se trans0iere al blo?ue -inally. .i el blo?ue -inally inicia otra excepci-n, 0inali1a el procesamiento de la excepci-n actual. .i no, cuando el control alcan1a el punto 0inal del blo?ue -inally, continHa con el procesamiento de la excepci-n actual.

.i no se encontr- un controlador de excepciones en la llamada del miembro de 0unci-n actual, 0inali1a la llamada al miembro de 0unci-n. 8os pasos anteriores se repiten para el llamador del miembro de 0unci-n con el punto de inicio ?ue corresponda a la instrucci-n desde la ?ue se invoc- al miembro de 0unci-n. .i el procesamiento de la excepci-n 0inali1a todas las llamadas a miembros de 0unci-n del subproceso actual indicando ?ue el subproceso no =a encontrado controlador para la excepci-n, dic=o subproceso 0inali1a. El impacto de esta terminaci-n se de0ine segHn la implementaci-n.

-.10 Instruccin Try


8a instrucci-n try proporciona un mecanismo para capturar las excepciones ?ue ocurren durante la e$ecuci-n de un blo?ue. 8a instrucci-n try permite adem(s especi0icar un blo?ue de c-digo ?ue siempre se e$ecuta cuando el control abandona la instrucci-n try. tr#-state%ent1 try -loc3 catch-cla ses try -loc3 finall#-cla se try -loc3 catch-cla ses finall#-cla se catch-cla ses1 specific-catch-cla ses &eneral-catch-cla seopt specific-catch-cla sesopt &eneral-catch-cla se specific-catch-cla ses1 specific-catch-cla se specific-catch-cla ses specific-catch-cla se specific-catch-cla se1 catc" ( class-t#pe identifieropt ) -loc3 &eneral-catch-cla se1 catc" -loc3 finall#-cla se1
-inally -loc3

Existen tres 0ormas posibles de instrucciones tryG 7n blo?ue try seguido de uno o varios blo?ues catc". 7n blo?ue try seguido de un blo?ue -inally. 7n blo?ue try seguido de uno o varios blo?ues catc" seguidos de un blo?ue -inally.

Cuando una cl(usula catc" especi0ica un tipo de clase Oclass-t#peR, el tipo debe ser System.)#ce&tion, un tipo de clase ?ue derive de System.)#ce&tion o un tipo de par(metro de tipo ?ue tenga System.)#ce&tion Oo una subclase de la mismaR como su clase base e0ectiva. Cuando una cl(usula catc" especi0ica tanto un tipo de clase Oclass-t#peR como un identi0icador OidentifierR, se declara una varia/le de e.cepci,n con el nombre y tipo dados. 8a variable de excepci-n es una variable local

262

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

con un (mbito ?ue se extiende a lo largo de todo el blo?ue catc". 2urante la e$ecuci-n de un blo?ue catc", la variable de excepci-n representa la excepci-n ?ue se est( controlando en ese momento. 2esde el punto de vista de comprobaci-n de asignaci-n de0initiva, la variable de excepci-n se considera asignada de0initivamente en todo su (mbito. .i la cl(usula catc" no incluye el nombre de una variable de excepci-n, no es posible tener acceso al ob$eto de excepci-n en el blo?ue catc". 7na cl(usula catc" general es una cl(usula catc" ?ue no especi0ica el tipo ni la variable de excepci-n. 7na instrucci-n try s-lo puede tener una cl(usula catc" general y, si existe, debe ser la Hltima cl(usula catc". &lgunos lengua$es de programaci-n pueden aceptar excepciones ?ue no son representables como un ob$eto derivado de System.)#ce&tion, aun?ue estas excepciones nunca pueden ser generadas por c-digo C#. 'ara detectar este tipo de excepciones se puede utili1ar una cl(usula catc" general. 'or lo tanto, una cl(usula catc" general es sem(nticamente di0erente de otra ?ue especi0ica el tipo System.)#ce&tion, ya ?ue la primera tambi)n puede detectar excepciones de otros lengua$es. 8as cl(usulas catc" se examinan en orden l)xico con el 0in de encontrar un controlador para la excepci-n. .i una cl(usula catc" especi0ica un tipo ?ue es igual o derivado de un tipo especi0icado en una cl(usula catc" anterior de la misma instrucci-n try, se produce un error en tiempo de compilaci-n. .i no existiera esta restricci-n, ser5a posible escribir cl(usulas catc" inalcan1ables. 2entro de un blo?ue catc", puede utili1ar una instrucci-n t"ro, O[8.+. R sin expresi-n para volver a iniciar la excepci-n ?ue captur- el blo?ue catc". 8as asignaciones a una variable de excepci-n no modi0ican la excepci-n ?ue vuelve a iniciarse. En el e$emplo
using System; class 1est { static void V() { try { S(); ! catc" ()#ce&tion e) { Console.WriteLine(")#ce&tion in V/ " < e.Message); e + ne, )#ce&tion("V"); t"ro,; .. re=t"ro, ! ! static void S() { t"ro, ne, )#ce&tion("S"); ! static void Main() { try { V(); ! catc" ()#ce&tion e) { Console.WriteLine(")#ce&tion in Main/ " < e.Message); ! ! !

el m)todo V captura una excepci-n, escribe in0ormaci-n de diagn-stico en la consola, modi0ica la variable de excepci-n y vuelve a iniciar la excepci-n. 8a excepci-n ?ue se vuelve a iniciar es la excepci-n original, de modo ?ue el resultado producido es el siguienteG
)#ce&tion in V/ S )#ce&tion in Main/ S

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

263

Especificacin del lenguaje C#

.i el primer blo?ue catc= iniciara e en lugar de volver a iniciar la excepci-n actual, el resultado producido ser5a el siguienteG
)#ce&tion in V/ S )#ce&tion in Main/ V

.e produce un error en tiempo de compilaci-n cuando una instrucci-n brea(, continue o goto trans0iere el control 0uera del blo?ue -inally. Cuando ocurre una instrucci-n brea(, continue o goto dentro de un blo?ue -inally, el destino de la instrucci-n debe encontrarse dentro del propio blo?ue -inally. En caso contrario, se producir( un error en tiempo de compilaci-n. Tambi)n se produce un error en tiempo de compilaci-n si una instrucci-n return ocurre dentro de un blo?ue -inally. 7na instrucci-n try se e$ecuta de la siguiente 0ormaG El control se trans0iere al blo?ue try. Cuando el control alcan1a el punto 0inal del blo?ue tryG o o o .i la instrucci-n try tiene un blo?ue -inally, se e$ecuta dic=o blo?ue -inally. El control se trans0iere al punto 0inal de la instrucci-n try. .i existen cl(usulas catc", se examinan en orden de aparici-n para buscar un controlador adecuado para la excepci-n. 8a primera cl(usula catc" ?ue especi0i?ue el tipo de excepci-n o un tipo base del tipo de excepci-n se considera una coincidencia. 7na cl(usula catc" general es una coincidencia para cual?uier tipo de excepci-n. .i se encuentra una cl(usula catc" coincidenteG .i la cl(usula catc" coincidente declara una variable de excepci-n, se asigna el ob$eto de excepci-n a dic=a variable. El control se trans0iere al blo?ue catc" coincidente. Cuando el control alcan1a el punto 0inal del blo?ue catc"G o o o o o .i la instrucci-n try tiene un blo?ue 0inally, se e$ecuta dic=o blo?ue 0inally. El control se trans0iere al punto 0inal de la instrucci-n try. .i la instrucci-n try tiene un blo?ue 0inally, se e$ecuta dic=o blo?ue 0inally. 8a excepci-n se propaga a la siguiente instrucci-n try envolvente.

.i se propaga una excepci-n a la instrucci-n try durante la e$ecuci-n del blo?ue tryG

.i se propaga una excepci-n a la instrucci-n try durante la e$ecuci-n del blo?ue catc"G

.i la instrucci-n try no tiene cl(usulas catc" o si ninguna cl(usula catc" coincide con la excepci-nG .i la instrucci-n try tiene un blo?ue -inally, se e$ecuta dic=o blo?ue -inally. 8a excepci-n se propaga a la siguiente instrucci-n try envolvente.

8as instrucciones de un blo?ue -inally siempre se e$ecutan cuando el control abandona la instrucci-n try. Esto se cumple cuando el control se trans0iere como resultado de una e$ecuci-n normal, de la e$ecuci-n de una instrucci-n brea(, continue, goto o return, o de la propagaci-n de una excepci-n 0uera de la instrucci-n try. .i se vuelve a iniciar una excepci-n durante la e$ecuci-n de un blo?ue -inally, y no se captura dentro del mismo blo?ue -inally, la excepci-n se propaga a la siguiente instrucci-n try envolvente. .i se estaba

26#

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

propagando otra excepci-n anterior, )sta se pierde. El proceso de propagaci-n de una excepci-n se explica con mayor detalle en la descripci-n de la instrucci-n t"ro, O[8.+. R. El blo?ue try de una instrucci-n try es alcan1able si la instrucci-n try es alcan1able. El blo?ue catc" de una instrucci-n try es alcan1able si la instrucci-n try es alcan1able. El blo?ue -inally de una instrucci-n try es alcan1able si la instrucci-n try es alcan1able. El punto 0inal de una instrucci-n try es alcan1able si se cumplen las dos condiciones siguientesG El punto 0inal de un blo?ue try es alcan1able o el punto 0inal de al menos uno de sus blo?ues catc" es alcan1able. .i existe un blo?ue -inally, el punto 0inal del blo?ue -inally es alcan1able.

-.11 Instrucciones %?ec3ed y 5nc?ec3ed


8as instrucciones c"ec(ed y unc"ec(ed se utili1an con el 0in de controlar el conte.to de co pro/aci,n de des/orda iento para operaciones aritm)ticas y conversiones. chec3ed-state%ent1 c"ec(ed -loc3 nchec3ed-state%ent1 unc"ec(ed -loc3 Con la instrucci-n c"ec(ed, todas las expresiones del blo?ue O-loc3R se evalHan en un contexto de comprobaci-n y, con la instrucci-n unc"ec(ed, en un contexto donde no se realicen comprobaciones. 8as instrucciones c"ec(ed y unc"ec(ed son e?uivalentes a los operadores c"ec(ed y unc"ec(ed O[*. .12R, con la excepci-n de ?ue operan con blo?ues en lugar de con expresiones.

-.12 Instruccin 6oc3


8a instrucci-n loc( blo?uea un ob$eto mediante exclusi-n mutua, e$ecuta una instrucci-n y, a continuaci-n, libera el blo?ueo. loc3-state%ent1 loc( ( e2pression ) e%-edded-state%ent 8a expresi-n de una instrucci-n loc( debe denotar un valor de un tipo ?ue sea un tipo de re0erencia Oreferencet#peR. 4unca se reali1a una conversi-n boxing impl5cita O[#.1.*R para la expresi-n de una instrucci-n loc( y, por lo tanto, se produce un error en tiempo de compilaci-n cuando la expresi-n denota un valor de un tipo de valor Oval e-t#peR. 7na instrucci-n loc( con la 0orma
loc( (#) ...

donde # es una expresi-n de tipo de re0erencia Oreference-t#peR, es e?uivalente a


System.1"reading.Monitor.)nter(#); try { ... ! -inally { System.1"reading.Monitor.)#it(#); !

salvo ?ue # s-lo se evalHa una ve1.

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

26!

Especificacin del lenguaje C#

%ientras est) activo un blo?ueo de exclusi-n mutua, el c-digo ?ue est( e$ecut(ndose en el mismo subproceso tambi)n puede obtener y liberar tal blo?ueo. .in embargo, el c-digo ?ue est) e$ecut(ndose en otros subprocesos no puede recibir el blo?ueo =asta ?ue el )ste se libere. .e recomienda no blo?uear ob$etos System.1y&e para sincroni1ar el acceso a datos est(ticos. .e podr5a blo?uear otro c-digo en el mismo tipo, lo ?ue producir5a un interblo?ueo. En su lugar, sincronice el acceso a datos est(ticos blo?ueando un ob$eto est(tico privado. 'or e$emploG
class Cac"e { &rivate static object sync"roni?ation%bject + ne, object(); &ublic static void 'dd(object #) { loc( (Cac"e.sync"roni?ation%bject) { ... ! ! &ublic static void Oemove(object #) { loc( (Cac"e.sync"roni?ation%bject) { ... ! ! !

-.13 Instruccin 5sing


8a instrucci-n using obtiene uno o varios recursos, e$ecuta una instrucci-n y, a continuaci-n, elimina el recurso. sin&-state%ent1
using (

reso rce-ac6 isition ) e%-edded-state%ent

reso rce-ac6 isition1 local-varia-le-declaration e2pression 7n rec!rso es una clase o estructura ?ue implementa System.$6is&osable, ?ue incluye un Hnico m)todo sin par(metros denominado 6is&ose. El c-digo ?ue utili1a un recurso puede llamar a 6is&ose para indicar ?ue ya no lo necesita. .i no llama a 6is&ose, se elimina temporalmente de 0orma autom(tica como consecuencia de la recolecci-n de elementos no utili1ados. .i la ad?uisici-n de recurso Oreso rce-ac6 isitionR se reali1a mediante una declaraci-n de variable local Olocalvaria-le-declarationR, el tipo de esta Hltima debe ser System.$6is&osable o un tipo ?ue pueda ser convertido impl5citamente a System.$6is&osable. .i la ad?uisici-n de recurso Oreso rce-ac6 isitionR se reali1a mediante una expresi-n Oe2pressionR, el tipo de la expresi-n debe ser System.$6is&osable o un tipo ?ue pueda ser convertido impl5citamente a System.$6is&osable. 8as variables locales ?ue se declaran en la ad?uisici-n de recurso Oreso rce-ac6 isitionR son de s-lo lectura y deben incluir un iniciali1ador. .e producir( un error en tiempo de compilaci-n si la instrucci-n incrustada intenta modi0icar estas variables locales Opor medio de asignaci-n o utili1ando los operadores << y ==R o bien si obtiene su direcci-n o las pasa como par(metros re- u out. 7na instrucci-n using se traduce en tres partesG ad?uisici-n, uso y eliminaci-n. El uso de un recurso est( incluido impl5citamente en una instrucci-n try ?ue contiene una cl(usula -inally. 8a cl(usula -inally elimina el recurso. .i se obtiene un recurso null, no se llama a 6is&ose y no se inicia ninguna excepci-n. 7na instrucci-n using de la 0orma
using (Oesource1y&e resource + e#&ression) statement

266

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

corresponde a una de dos posibles expansiones. Cuando Oesource1y&e es un tipo de valor, la expansi-n esG
{ Oesource1y&e resource + e#&ression; try { statement; ! -inally { (($6is&osable)resource).6is&ose(); ! !

En caso contrario, cuando Oesource1y&e es un tipo de re0erencia, la expansi-n esG


{ Oesource1y&e resource + e#&ression; try { statement; ! -inally { i- (resource @+ null) (($6is&osable)resource).6is&ose(); ! !

En ambas expansiones, la variable resource es de s-lo lectura en la instrucci-n incrustada. .e permite ?ue una implementaci-n implemente una instrucci-n using dada de manera di0erente, por e$emplo, por motivos de rendimiento, siempre ?ue el comportamiento sea co=erente con la expansi-n anterior. 7na instrucci-n using de la 0orma
using (e#&ression) statement

tiene las dos mismas posibilidades de expansi-n, pero en este caso Oesource1y&e es impl5citamente el tipo en tiempo de compilaci-n de e#&ression, y la variable resource no es accesible Oni visibleR en la instrucci-n incrustada. Cuando una ad?uisici-n de recurso Oreso rce-ac6 isitionR toma la 0orma de una declaraci-n de variable local Olocal-varia-le-declarationR, es posible ad?uirir mHltiples recursos de un tipo dado. 7na instrucci-n using de la 0orma
using (Oesource1y&e r2 + e2 r8 + e8 ... rN + eN) statement

es per0ectamente e?uivalente a una secuencia de instrucciones using anidadas.


using (Oesource1y&e r2 + e2) using (Oesource1y&e r8 + e8) ... using (Oesource1y&e rN + eN) statement

En el e$emplo siguiente se crea un arc=ivo llamado log.t#t y se escriben dos l5neas de texto en )l. 'osteriormente, se abre el mismo arc=ivo para leerlo y copiar las l5neas de texto ?ue contiene en la consola.
using System; using System.$%; class 1est { static void Main() { using (1e#tWriter , + Vile.Create1e#t("log.t#t")) { ,.WriteLine("1"is is line one"); ,.WriteLine("1"is is line t,o"); !

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

26(

Especificacin del lenguaje C# using (1e#tOeader r + Vile.%&en1e#t("log.t#t")) { string s; ,"ile ((s + r.OeadLine()) @+ null) { Console.WriteLine(s); ! ! ! !

2ado ?ue las clases 1e#tWriter y 1e#tOeader implementan la inter0a1 $6is&osable, en el e$emplo se pueden utili1ar instrucciones using para garanti1ar ?ue el arc=ivo subyacente est) correctamente cerrado despu)s de las operaciones de lectura o escritura.

-.1! 6a instruccin yield


En un blo?ue de iteradores O[8.2R, la instrucci-n yield se utili1a para producir un valor para el ob$eto del enumerador O[1".14.4R o un ob$eto enumerable O[1".14. R de un iterador o para seUalar el 0inal de la iteraci-n. #ield-state%ent1
yield return e2pression ; yield brea( ;
yield no es una palabra reservadaV s-lo ad?uiere un signi0icado especial cuando se utili1a inmediatamente antes de la palabra clave return o brea(. En otros contextos, yield se puede utili1ar como un identi0icador.

Existen varias restricciones ?ue limitan los lugares de uso de la instrucci-n yield como se describe a continuaci-n. 8a instrucci-n yield Oen cual?uiera de sus 0ormasR generar( un error en tiempo de compilaci-n si aparece 0uera de cuerpo del m)todo O%ethod--od#R, un cuerpo de operador Ooperator--od#R o un cuerpo de descriptor de acceso Oaccessor--od#R. 8a instrucci-n yield Oen cual?uiera de sus 0ormasR generar( un error en tiempo de compilaci-n si aparece dentro de una 0unci-n an-nima. 8a instrucci-n yield Oen cual?uiera de sus 0ormasR generar( un error en tiempo de compilaci-n si aparece en la cl(usula -inally de una instrucci-n try. 8a instrucci-n yield return generar( un error en tiempo de compilaci-n si aparece en cual?uier parte dentro de una instrucci-n try con cl(usulas catc".
delegate $)numerableDintE 6(); $)numeratorDintE Set)numerator() { try { yield return 2; .. %( yield brea(; .. %( ! -inally { yield return 8; .. )rror yield brea(; .. )rror !

En el siguiente e$emplo se muestran algunos usos v(lidos y no v(lidos de instrucciones yield.

yield in -inally yield in -inally

26$

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases try { yield yield ! catc" { yield yield !

return 9; brea(; return J; brea(;

.. )rror .. %( .. )rror .. %(

yield return in try...catc"

yield return in try...catc"

6 d + delegate { yield return K; !; ! int MyMet"od() { yield return 2; !

.. )rror

yield in an anonymous -unction

.. )rror

,rong return ty&e -or an iterator bloc(

2ebe existir una conversi-n impl5cita O[#.1R desde el tipo de la expresi-n en la instrucci-n yield return al tipo yield O[1".14.3R del blo?ue de iteradores. 7na instrucci-n yield return se e$ecuta de la siguiente maneraG 8a expresi-n de la instrucci-n se evalHa, se convierte en el tipo yield y se asigna a la propiedad Current del ob$eto del enumerador. .e suspende la e$ecuci-n del blo?ue de iteradores. .i la instrucci-n yield return se encuentra dentro de uno o m(s blo?ues try, los blo?ues -inally asociados no se e$ecutan en este momento. El m)todo MoveNe#t del ob$eto del enumerador devuelve true a su llamador indicando ?ue el ob$eto avan1- correctamente al siguiente valor.

8a siguiente llamada al m)todo MoveNe#t del ob$eto del enumerador reanuda la e$ecuci-n del blo?ue de iteradores desde donde se suspendi- la Hltima ve1. 7na instrucci-n yield brea( se e$ecuta de la siguiente maneraG .i la instrucci-n yield brea( est( rodeada de uno o m(s blo?ues try con blo?ues -inally asociados, el control se trans0iere inicialmente al blo?ue -inally de la instrucci-n try m(s interna. Cuando el control alcan1a el punto 0inal de un blo?ue -inally, el control se trans0iere al blo?ue -inally de la siguiente instrucci-n envolvente try. Este proceso se repite =asta ?ue se e$ecuten los blo?ues -inally de todas las instrucciones try envolventes. El control vuelve al llamador del blo?ue de iteradores. Zste es el m)todo MoveNe#t o el m)todo 6is&ose del ob$eto del enumerador.

'uesto ?ue una instrucci-n yield brea( trans0iere incondicionalmente el control a otra parte, no se puede alcan1ar el punto 0inal de una instrucci-n yield brea(.

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

26"

Especificacin del lenguaje C#

.. Espacio de nombres
8os programas de C# se organi1an utili1ando espacios de nombres. 8os espacios de nombres se utili1an, tanto como sistema de organi1aci-n PinternaQ de un programa, como sistema de organi1aci-n PexternaQV es una 0orma de presentar los elementos de un programa ?ue est(n expuestos a otros programas. 8as directivas using O[+.4R se proporcionan para 0acilitar el uso de los espacios de nombres.

..1 5nidades de compilacin


7na unidad de compilaci-n Oco%pilation- nitR de0ine la estructura completa de un arc=ivo de c-digo 0uente. Consiste en cero o varias directivas using O sin&-directivesR, seguidas de cero o varios atributos globales O&lo-al-attri- tesR, seguidos de cero o varias declaraciones de miembros de espacios de nombres Ona%espace%e%-er-declarationsR. co%pilation- nit1 e2tern-alias-directivesopt sin&-directivesopt &lo-al-attri- tesopt na%espace-%e%-er-declarationsopt 7n programa de C# consiste en una o varias unidades de compilaci-n, cada una de ellas en un arc=ivo de c-digo 0uente independiente. Cuando se compila un programa de C#, todas las unidades de compilaci-n se procesan con$untamente. 'or lo tanto, las unidades de compilaci-n pueden depender unas de otras, posiblemente de 0orma circular. 8as directivas using O sin&-directivesR de una unidad de compilaci-n a0ectan a sus atributos globales y declaraciones de miembros de espacios de nombre Ona%espace-%e%-er-declarationsR, pero no al resto de unidades. 8os atributos globales O&lo-al-attri- tesR O[1*R de una unidad de compilaci-n permiten especi0icar los atributos del m-dulo y del ensamblado de destino. 8os ensamblados y los m-dulos actHan como contenedores 05sicos de tipos. 7n ensamblado puede estar 0ormado por varios m-dulos separados 05sicamente. 8as declaraciones de miembros de espacios de nombre Ona%espace-%e%-er-declarationsR de cada unidad de compilaci-n de un programa contribuyen con miembros a un Hnico espacio de declaraci-n, denominado espacio global de nombres. 'or e$emploG :ile '.csG
class ' {!

:ile :.csG
class : {!

8as dos unidades de compilaci-n contribuyen al espacio global de nombres, en este caso, declarando dos clases con los nombres completos ' y :. Como las dos unidades de compilaci-n contribuyen al mismo espacio de declaraci-n, si cada una contiene una declaraci-n de miembro con el mismo nombre se producir( un error.

..2 /eclaraciones de espacio de nombres


7na declaraci-n de espacio de nombres Ona%espace-declarationR consiste en la palabra clave names&ace seguida de un nombre y de un cuerpo y, opcionalmente, de un punto y coma.

2('

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

na%espace-declaration1 names&ace 6 alified-identifier na%espace--od# ;opt 6 alified-identifier1 identificador 6 alified-identifier . identificador na%espace--od#1 { e2tern-alias-directivesopt sin&-directivesopt na%espace-%e%-er-declarationsopt !

7na declaraci-n de espacio de nombres Ona%espace-declarationR puede ocurrir como declaraci-n de alto nivel de una unidad de compilaci-n Oco%pilation- nitR o como declaraci-n de miembro dentro de otra declaraci-n de espacio de nombres. Cuando una declaraci-n de espacio de nombres Ona%espace-declarationR ocurre como declaraci-n de alto nivel de una unidad de compilaci-n Oco%pilation- nitR, el espacio de nombres se convierte en miembro del espacio global de nombres. Cuando una declaraci-n de espacio de nombres ocurre dentro de otra declaraci-n de espacio de nombres, el espacio de nombres m(s interno se convierte en miembro del espacio de nombres externo. En ambos casos, el nombre del espacio de nombres debe ser Hnico dentro del espacio de nombres ?ue lo contiene. 8os espacios de nombres son &ublic impl5citamente y la declaraci-n de un espacio de nombres no puede incluir modi0icadores de acceso. 2entro del cuerpo de espacio de nombres Ona%espace--od#R, las directivas using O sin&-directivesR opcionales importan los nombres de otros espacios de nombres y tipos, permitiendo ?ue se =aga re0erencia a los mismos directamente y no a trav)s de nombres completos. 8as declaraciones de miembros de espacios de nombres Ona%espace-%e%-er-declarationsR opcionales contribuyen con miembros al espacio de declaraci-n del espacio de nombres. /bserve ?ue todas las directivas using O sin&-directivesR deben aparecer antes de cual?uier declaraci-n de miembro. El identi0icador completo O6 alified-identifierR de una declaraci-n de espacio de nombres Ona%espacedeclarationR puede ser un Hnico identi0icador o una secuencia de identi0icadores separados por s5mbolos Oto6enR P.Q. Esta Hltima 0orma permite ?ue un programa de0ina un espacio de nombres anidado sin anidar l)xicamente varias declaraciones de espacio de nombres. 'or e$emplo,
names&ace N2.N8 { class ' {! class : {! !

e?uivale sem(nticamente a
names&ace N2 { names&ace N8 { class ' {! class : {! ! !

8os espacios de nombres tienen extremo abierto, y dos declaraciones de espacio de nombres con el mismo nombre completo contribuyen al mismo espacio de declaraci-n O[3.3R. En el e$emplo
names&ace N2.N8 { class ' {! !

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

2(1

Especificacin del lenguaje C# names&ace N2.N8 { class : {! !

las dos declaraciones de espacios de nombres anteriores contribuyen al mismo espacio de declaraci-n, en este caso declarando dos clases con los nombres completos N2.N8.' y N2.N8.:. Como las dos declaraciones contribuyen al mismo espacio de declaraci-n, si cada una contiene una declaraci-n de miembro con el mismo nombre se producir( un error.

..3 'lias e"tern


7na directiva de alias extern Oe2tern-alias-directiveR introduce un identi0icador ?ue se utili1a como un alias para un espacio de nombres. 8a especi0icaci-n del espacio de nombres con alias es externa al c-digo 0uente del programa y se aplica tambi)n a los espacios de nombre anidados del espacio de nombres con alias. e2tern-alias-directives1 e2tern-alias-directive e2tern-alias-directives e2tern-alias-directive e2tern-alias-directive1
e#tern alias identifier ;

El (mbito de una directiva de alias extern Oe2tern-alias-directiveR se extiende a trav)s de directivas using O sin&directivesR, atributos globales O&lo-al-attri- tesR y declaraciones de miembros de espacios de nombres Ona%espace-%e%-er-declarationsR de la unidad de compilaci-n o del cuerpo de espacio de nombres inmediato. 2entro de una unidad de compilaci-n o del cuerpo de espacio de nombres ?ue contiene una directiva de alias extern Oe2tern-alias-directiveR, el identi0icador introducido por la directiva de alias extern Oe2tern-aliasdirectiveR se puede utili1ar para =acer re0erencia a la $erar?u5a de espacios de nombre con alias. .e genera un error en tiempo de compilaci-n si el identi0icador OidentifierR es la palabra global. 7na directiva de alias extern Oe2tern-alias-directiveR o0rece un alias dentro de una determinada unidad de compilaci-n o cuerpo de espacio de nombres, pero no contribuye con ningHn miembro nuevo al espacio de la declaraci-n subyacente. En otras palabras, una directiva de alias extern Oe2tern-alias-directiveR no es transitiva, sino ?ue s-lo a0ecta a la unidad de compilaci-n o al cuerpo de espacio de nombres en el ?ue se da. El siguiente programa declara y utili1a dos alias externos, I e `, cada uno de los cuales representa la ruta de una $erar?u5a de espacios de nombres di0erente.
e#tern alias I; e#tern alias `; class 1est { I//N.' a; I//N.: b2; `//N.: b8; `//N.C c; !

El programa declara la existencia de los alias externos I e `, pero las de0iniciones reales de los alias son externas al programa. &=ora se puede =acer re0erencia a las clases N.: denominadas de la misma manera como I.N.: e `.N.:, o bien utili1ando el certi0icador de alias de espacios de nombres, I//N.: y `//N.:. .e genera un error si un programa declara un alias extern para el ?ue no se proporciona ninguna de0inici-n externa.

..! /irecti as 5sing


8as directivas !sing 0acilitan el uso de espacios de nombres y tipos de0inidos en otros espacios de nombres. 8as directivas using tienen un impacto en el proceso de resoluci-n de nombres de espacios de nombres o nombres de

2(2

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

tipo Ona%espace-or-t#pe-na%esR O[3.8R y de nombres simples Osi%ple-na%esR O[*. .2R, pero, exceptuando las declaraciones, las directivas using no contribuyen con nuevos miembros a los espacios de declaraci-n subyacentes de las unidades de compilaci-n o a los espacios de nombres dentro de los ?ue se utili1an. sin&-directives1 sin&-directive sin&-directives

sin&-directive

sin&-directive1 sin&-alias-directive sin&-na%espace-directive 7na directiva de alias using O sin&-alias-directiveR O[+.4.1R de0ine un alias para un espacio de nombres o un tipo. 7na directiva de espacio de nombres using O sin&-na%espace-directiveR O[+.4.2R importa los miembros de tipo de un espacio de nombres. El (mbito de una directiva using O sin&-directiveR se extiende a lo largo de las declaraciones de miembros de espacios de nombres Ona%espace-%e%-er-declarationsR de la unidad de compilaci-n o del cuerpo de espacio de nombres ?ue la contiene inmediatamente. El (mbito de una directiva using O sin&-directiveR no incluye espec50icamente las directivas using O sin&-directivesR de su mismo nivel. 'or lo tanto, las directivas using O sin&-directivesR de un mismo nivel no se a0ectan unas a otras y no in0luye el orden en el ?ue est(n escritas. ..!.1 /irecti as 5sing alias 7na directiva de alias using O sin&-alias-directiveR de0ine un identi0icador ?ue 0unciona como un alias para un espacio de nombres o un tipo dentro de la unidad de compilaci-n o cuerpo de espacio de nombres inmediatamente envolvente. sin&-alias-directive1 using identifier + na%espace-or-t#pe-na%e ; 2entro de las declaraciones de miembros de una unidad de compilaci-n o del cuerpo de un espacio de nombres ?ue contiene una directiva de alias using O sin&-alias-directiveR, se puede utili1ar el identi0icador de0inido por la directiva de alias using O sin&-alias-directiveR para =acer re0erencia al espacio de nombres o al tipo. 'or e$emploG
names&ace N2.N8 { class ' {! ! names&ace N9 { using ' + N2.N8.'; class :/ ' {! !

2entro de las declaraciones de miembros en el espacio de nombres N9, ' es un alias para N2.N8.' y, por tanto, la clase N9.: se deriva de la clase N2.N8.'. .e puede obtener el mismo e0ecto mediante la creaci-n de un alias O para N2.N8 y, a continuaci-n, =aciendo re0erencia a O.'G
names&ace N9 { using O + N2.N8; class :/ O.' {! !

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

2(3

Especificacin del lenguaje C#

El identi0icador OidentifierR de una directiva de alias using O sin&-alias-directiveR debe ser Hnico dentro del espacio de declaraciones de la unidad de compilaci-n o espacio de nombres ?ue contiene inmediatamente a dic=a directiva de alias using. 'or e$emploG
names&ace N9 { class ' {! ! names&ace N9 { using ' + N2.N8.'; !

.. )rror

' already e#ists

En el e$emplo anterior, N9 ya contiene un miembro ', as5 ?ue es un error ?ue una directiva de alias using O sin&alias-directiveR utilice ese identi0icador. Tambi)n es un error ?ue dos o m(s directivas de alias using de una misma unidad de compilaci-n o cuerpo de espacio de nombres declaren un alias con el mismo nombre. 7na directiva de alias using o0rece un alias dentro de una determinada unidad de compilaci-n o cuerpo de espacio de nombres, pero no contribuye con ningHn miembro nuevo al espacio de declaraci-n subyacente. En otras palabras, una directiva de alias using no es transitiva sino ?ue s-lo a0ecta a la unidad de compilaci-n o cuerpo de espacio de nombres en donde ocurre. En el e$emplo
names&ace N9 { using O + N2.N8; ! names&ace N9 { class :/ O.' {! !

.. )rror

O un(no,n

el (mbito de la directiva de alias using O sin&-alias-directiveR ?ue de0ine O s-lo se extiende a las declaraciones de los miembros en el cuerpo de espacio de nombres ?ue lo contiene y, por lo tanto, O es desconocido en la declaraci-n del segundo espacio de nombres. .in embargo, si se sitHa la directiva de alias using O sin&-aliasdirectiveR en la unidad de compilaci-n ?ue la contiene, el alias estar( disponible para ambas declaraciones de espacios de nombresG
using O + N2.N8; names&ace N9 { class :/ O.' {! ! names&ace N9 { class C/ O.' {! !

&l igual ?ue con los miembros normales, los nombres de0inidos por las directivas de alias using O sin&-aliasdirectivesR est(n ocultos por miembros nombrados de 0orma similar en (mbitos anidados. En el e$emplo
using O + N2.N8; names&ace N9 { class O {! class :/ O.' {! ! .. )rror O "as no member '

la re0erencia a O.' en la declaraci-n de : produce un error en tiempo de compilaci-n por?ue O =ace re0erencia a N9.O, no a N2.N8.

2(#

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

El orden en el ?ue se escriben las directivas de alias using no tiene importancia y la resoluci-n del espacio de nombres o nombre de tipo Ona%espace-or-t#pe-na%eR a los ?ue =ace re0erencia una directiva de alias using O sin&-alias-directiveR tampoco se ve a0ectado por la misma directiva de alias using ni por otras directivas using de la unidad de compilaci-n o cuerpo de espacio de nombres ?ue la contiene inmediatamente. Es decir, el espacio de nombres o nombre de tipo de una directiva de alias using se resuelve como si la unidad de compilaci-n o cuerpo de espacio de nombres ?ue la contiene inmediatamente no tuviera directivas using. 7na directiva de alias using O sin&-alias-directiveR puede verse a0ectada no obstante por directivas de alias extern Oe2tern-alias-directivesR en el cuerpo de espacio de nombres o la unidad de compilaci-n ?ue la contienen inmediatamente. En el e$emplo
names&ace N2.N8 {! names&ace N9 { e#tern alias ); using O2 + ).N; using O8 + N2; using O9 + N2.N8; using OJ + O8.N8; ! .. %a .. %a .. %a .. )rror O8 un(no,n

la Hltima directiva de alias using O sin&-alias-directiveR da como resultado un error en tiempo de compilaci-n, ya ?ue no se ve a0ectada por la primera directiva de alias using. 8a primera directiva de alias using O sin&-aliasdirectiveR no da como resultado un error puesto ?ue el (mbito del alias externo ) incluye la directiva de alias using O sin&-alias-directiveR. 7na directiva de alias using O sin&-alias-directiveR puede crear un alias para cual?uier espacio de nombres o tipo, incluyendo el espacio de nombres dentro del ?ue aparece y cual?uier espacio de nombres o tipo anidado dentro de ese espacio de nombres. El acceso a un espacio de nombres o a un tipo mediante un alias da exactamente el mismo resultado ?ue el acceso a ese espacio de nombres o tipo mediante su nombre declarado. 'or e$emplo
names&ace N2.N8 { class ' {! ! names&ace N9 { using O2 + N2; using O8 + N2.N8; class : { N2.N8.' a; O2.N8.' b; O8.' c; ! !

.. re-ers to N2.N8.' .. re-ers to N2.N8.' .. re-ers to N2.N8.'

los nombres N2.N8.', O2.N8.' y O8.' son e?uivalentes y todos se re0ieren a la clase cuyo nombre completo es N2.N8.'. 8os alias using pueden nombrar un tipo construido cerrado, pero no pueden nombrar una declaraci-n de tipo gen)rico sin enla1ar si no proporcionan argumentos de tipo. 'or e$emploG

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

2(!

Especificacin del lenguaje C# names&ace N2 { class 'D1E { class : {! ! ! names&ace N8 { using W + N2.'; using I + N2.'.:; using ` + N2.'DintE; using PD1E + N2.'D1E; !

.. )rror .. )rror .. %( .. )rror

cannot name unbound generic ty&e cannot name unbound generic ty&e using alias cannot "ave ty&e &arameters

can name closed constructed ty&e

..!.2 /irecti as 5sing espacio de nombres 7na directiva de espacio de nombres using O sin&-na%espace-directiveR importa los tipos ?ue contiene un espacio de nombres en la unidad de compilaci-n o cuerpo de espacio de nombres inmediatamente envolvente, permitiendo el uso del identi0icador sin cali0icar de cada tipo. sin&-na%espace-directive1 using na%espace-na%e ; 2entro de las declaraciones de miembros de una unidad de compilaci-n o del cuerpo de un espacio de nombres ?ue contiene una directiva de espacio de nombres using, se puede =acer re0erencia directamente a los tipos ?ue contienen ese espacio de nombres. 'or e$emploG
names&ace N2.N8 { class ' {! ! names&ace N9 { using N2.N8; class :/ ' {! !

En el anterior e$emplo, dentro de las declaraciones de miembros en el espacio de nombres N9, los miembros de tipo N2.N8 est(n directamente disponibles y, por tanto, la clase N9.: se deriva de la clase N2.N8.'. 7na directiva de espacio de nombres using importa los tipos ?ue contiene un determinado espacio de nombres, pero no importa espec50icamente los espacios de nombres anidados. En el e$emplo
names&ace N2.N8 { class ' {! ! names&ace N9 { using N2; class :/ N8.' {! ! .. )rror N8 un(no,n

la directiva de espacio de nombres using O sin&-na%espace-directiveR importa los tipos ?ue contiene N2, pero no los espacios de nombres anidados en N2. 'or ello, la re0erencia a N8.' en la declaraci-n de : produce un error en tiempo de compilaci-n por?ue no existen miembros con el nombre N8 en el (mbito.

2(6

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

& di0erencia de una directiva de alias using O sin&-alias-directiveR, una directiva de espacio de nombres using puede importar tipos cuyos identi0icadores ya est(n de0inidos dentro de la unidad de compilaci-n o cuerpo de espacio de nombres envolvente. En realidad, los nombres importados por una directiva de espacio de nombres using est(n ocultos por miembros nombrados de 0orma similar en la unidad de compilaci-n o cuerpo de espacio de nombres ?ue la contiene. 'or e$emploG
names&ace N2.N8 { class ' {! class : {! ! names&ace N9 { using N2.N8; class ' {! !

&?u5, dentro de las declaraciones de miembros en el espacio de nombres N9, ' =ace re0erencia a N9.' en lugar de a N2.N8.'. Cuando m(s de un espacio de nombres importados mediante directivas de espacio de nombres using O sin&na%espace-directivesR de la misma unidad de compilaci-n o cuerpo de espacio de nombres contiene tipos para el mismo nombre, las re0erencias a dic=o nombre se consideran ambiguas. En el e$emplo
names&ace N2 { class ' {! ! names&ace N8 { class ' {! ! names&ace N9 { using N2; using N8; class :/ ' {! ! .. )rror ' is ambiguous

tanto N2 como N8 contienen un miembro '. Como N9 importa ambas, se produce un error en tiempo de compilaci-n al =acer re0erencia a ' en N9. En este caso, el con0licto se puede resolver mediante la cali0icaci-n de re0erencias a ' o mediante la introducci-n de una directiva de alias using O sin&-alias-directiveR ?ue elige un ' determinado. 'or e$emploG
names&ace N9 { using N2; using N8; using ' + N2.'; class :/ ' {! ! .. ' means N2.'

&l igual ?ue una directiva de alias using O sin&-alias-directiveR, una directiva de espacio de nombres using O sin&-na%espace-directiveR no contribuye con ningHn miembro nuevo al espacio de declaraci-n subyacente de la unidad de compilaci-n o espacio de nombres, sino ?ue a0ecta s-lo a la unidad de compilaci-n o cuerpo de espacio de nombres donde aparece.

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

2((

Especificacin del lenguaje C#

El nombre de espacio de nombres Ona%espace-na%eR al ?ue =ace re0erencia una directiva de espacio de nombres using O sin&-na%espace-directiveR se resuelve de la misma 0orma ?ue el espacio de nombres o nombre de tipo al ?ue =ace re0erencia una directiva de alias using. 'or lo tanto, las directivas de espacio de nombres using O sin&na%espace-directivesR de una misma unidad de compilaci-n o cuerpo de espacio de nombres no se a0ectan unas a otras y pueden escribirse en cual?uier orden.

..# &iembros de espacio de nombres


7na declaraci-n de miembro de espacio de nombres Ona%espace-%e%-er-declarationR puede ser una declaraci-n de espacio de nombres Ona%espace-declarationR O[+.2R o una declaraci-n de tipo Ot#pe-declarationR O[+.#R. na%espace-%e%-er-declarations1 na%espace-%e%-er-declaration na%espace-%e%-er-declarations na%espace-%e%-er-declaration na%espace-%e%-er-declaration1 na%espace-declaration t#pe-declaration 7na unidad de compilaci-n o un cuerpo de espacio de nombres puede contener declaraciones de miembros de espacios de nombres Ona%espace-%e%-er-declarationR, y dic=as declaraciones contribuyen con nuevos miembros al espacio de declaraci-n subyacente de la unidad de compilaci-n o cuerpo de espacio de nombres ?ue las contienen.

..$ /eclaraciones de tipo


7na declaraci-n de tipo Ot#pe-declarationR es una declaraci-n de clase Oclass-declarationR O[1".1R, una declaraci-n de estructura Ostr ct-declarationR O[11.1R, una declaraci-n de inter0a1 Ointerface-declarationR O[13.1R, una declaraci-n de enumeraci-n Oen %-declarationR O[14.1R o una declaraci-n de delegado Odele&atedeclarationR O[1 .1R. t#pe-declaration1 class-declaration str ct-declaration interface-declaration en %-declaration dele&ate-declaration 7na declaraci-n de tipo Ot#pe-declarationR puede ocurrir como declaraci-n de alto nivel en una unidad de compilaci-n o como declaraci-n de miembro dentro de un espacio de nombres, de una clase o de una estructura. Cuando ocurre una declaraci-n de tipo para un tipo 1 como declaraci-n de alto nivel en una unidad de compilaci-n, el nombre completo del nuevo tipo declarado es simplemente 1. Cuando una declaraci-n de tipo para un tipo 1 se e$ecuta dentro de un espacio de nombres, de una clase o de una estructura, el nombre completo del nuevo tipo declarado es N.1, donde N es el nombre completo del espacio de nombres, de la clase o de la estructura ?ue lo contiene. 7n tipo declarado dentro de una clase o de una estructura se denomina tipo anidado O[1".3.8R. 8os modi0icadores de acceso permitidos y el acceso predeterminado para una declaraci-n de tipo dependen del contexto en el ?ue tenga lugar la declaraci-n O[3. .1RG 8os tipos declarados en las unidades de compilaci-n o espacios de nombres pueden tener acceso &ublic o internal. El acceso predeterminado es internal.

2($

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

8os tipos declarados en clases pueden tener acceso &ublic, &rotected internal, &rotected, internal o &rivate. El acceso predeterminado es &rivate. 8os tipos declarados en estructuras pueden tener acceso &ublic, internal o &rivate. El acceso predeterminado es &rivate.

..+ %alificadores de alias de espacios de nombres


El certificador de alias de espacios de no /res 88 garanti1a ?ue las bHs?uedas de nombres de tipos no se vean a0ectadas por la introducci-n de nuevos tipos y miembros. El certi0icador de alias de espacios de nombres siempre aparece entre dos identi0icadores a los ?ue se =ace re0erencia como los identi0icadores i1?uierdo y derec=o. &l contrario de lo ?ue ocurre con el certi0icador =abitual . , el identi0icador i1?uierdo del certi0icador // s-lo se busca como un alias using o extern. 7n miembro de alias completo O6 alified-alias-%e%-erR se de0ine de la siguiente maneraG 6 alified-alias-%e%-er1 identifier // identifier t#pe-ar& %ent-listopt .e puede utili1ar un miembro de alias completo O6 alified-alias-%e%-erR como un nombre de espacio de nombres o de tipo Ona%espace-or-t#pe-na%eR O[R o como el operando i1?uierdo en un acceso a miembro O%e%-er-accessR O[R. 7n miembro de alias completo O6 alified-alias-%e%-erR ad?uiere una de las estructuras siguientesG
N//$D'2 ... 'aE, donde N e $ representan a identi0icadores y D'2 ... 'aE es una lista de argumentos de tipo. Oa siempre es al menos uno.R N//$ donde N e $ representan a identi0icadores. OEn este caso, se considera ?ue a es cero.R

Con esto, el signi0icado de un miembro de alias completo O6 alified-alias-%e%-erR se determina de la siguiente maneraG .i N es el identi0icador global, el espacio de nombres global se busca por $G o o o .i el espacio de nombres global contiene un espacio de nombres denominado $ y a es cero, el miembro de alias completo O6 alified-alias-%e%-erR =ace re0erencia a dic=o espacio de nombres. 2e lo contrario, si el espacio de nombres global contiene un tipo gen)rico denominado $ y a es cero, el miembro de alias completo O6 alified-alias-%e%-erR =ace re0erencia a dic=o tipo. 2e lo contrario, si el espacio de nombres global contiene un tipo denominado $ con par(metros de tipo a, el miembro de alias completo O6 alified-alias-%e%-erR =ace re0erencia a dic=o tipo construido con los argumentos de tipo dados. 2e lo contrario, el miembro de alias completo O6 alified-alias-%e%-erR no est( de0inido y se genera un error en tiempo de compilaci-n.

2e lo contrario, comen1ando por la siguiente declaraci-n de espacio de nombres O[+.2R ?ue contiene el miembro de alias completo O6 alified-alias-%e%-erR Osi lo =ayR, continuando por cada una de las declaraciones de espacio de nombres envolventes Osi las =ayR y terminando por la unidad de compilaci-n ?ue contiene el miembro de alias completo O6 alified-alias-%e%-erR, se evalHan los siguientes pasos =asta ?ue se detecta una entidadG o .i la declaraci-n de espacio de nombres o la unidad de compilaci-n contiene una directiva de alias using O sin&-alias-directiveR ?ue asocia N con un tipo, el miembro de alias completo O6 alified-alias-%e%-erR no se de0ine y se genera un error en tiempo de compilaci-n.

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

2("

Especificacin del lenguaje C#

2e lo contrario, si la declaraci-n de espacio de nombres o la unidad de compilaci-n contiene una directiva de alias extern Oe2tern-alias-directiveR o una directiva de alias using O sin&-alias-directiveR ?ue asocia N con un espacio de nombresG .i el espacio de nombres asociado con N contiene un espacio de nombres denominado $ y a es cero, el miembro de alias completo O6 alified-alias-%e%-erR =ace re0erencia a dic=o espacio de nombres. 2e lo contrario, si el espacio de nombres asociado con N contiene un tipo no gen)rico denominado $ y a es cero, el miembro de alias completo O6 alified-alias-%e%-erR =ace re0erencia a dic=o tipo. 2e lo contrario, si el espacio de nombres asociado con N contiene un tipo denominado $ con par(metros de tipo a, el miembro de alias completo O6 alified-alias-%e%-erR =ace re0erencia a dic=o tipo construido con los argumentos de tipo dados. 2e lo contrario, el miembro de alias completo O6 alified-alias-%e%-erR no est( de0inido y se genera un error en tiempo de compilaci-n.

2e lo contrario, el miembro de alias completo O6 alified-alias-%e%-erR no est( de0inido y se genera un error en tiempo de compilaci-n.

Tenga en cuenta ?ue si utili1a el certi0icador de alias de espacios de nombres con un alias ?ue =aga re0erencia a un tipo se generar( un error en tiempo de compilaci-n. Tenga en cuenta tambi)n ?ue si el identi0icador N es global, se reali1ar( una bHs?ueda en el espacio de nombres global, incluso si =ay un alias using ?ue asocia global con un tipo o un espacio de nombres. ..+.1 5nicidad de los alias Cada unidad de compilaci-n y cada cuerpo de espacio de nombres tiene un espacio de declaraci-n independiente para alias extern y using. 'or lo tanto, mientras ?ue el nombre de un alias extern o un alias using debe ser Hnico dentro del con$unto de alias extern y using declarados en la unidad de compilaci-n o cuerpo de espacio de nombres ?ue lo contiene inmediatamente, un alias puede tener el mismo nombre ?ue un tipo o un espacio de nombres siempre ?ue se utilice con el certi0icador //. En el e$emplo
names&ace N { &ublic class ' {! &ublic class : {! ! names&ace N { using ' + System.$%; class I { '.Stream s2; '//Stream s8; ! !

.. )rror .. %(

' is ambiguous

el nombre ' tiene dos posibles signi0icados en el segundo cuerpo de espacio de nombres, puesto ?ue tanto la clase ' como el alias using ' est(n dentro del (mbito. 'or este motivo, el uso de ' en el nombre completo '.Stream es ambiguo y causa un error en tiempo de compilaci-n. .in embargo, el uso de ' con el certi0icador // no es un error por?ue ' s-lo se busca como un alias de espacio de nombres.

2$'

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

10. %lases
7na clase es una estructura de datos ?ue puede contener miembros de datos Oconstantes y camposR, miembros de 0unci-n Om)todos, propiedades, indi1adores, eventos, operadores, constructores de instancia, constructores est(ticos y destructoresR y tipos anidados. 8os tipos de clase admiten la =erencia, un mecanismo mediante el cual una clase derivada puede extender y especiali1ar una clase base.

10.1 /eclaraciones de clases


7na declaraci-n de clase Oclass-declarationR es una declaraci-n de tipo Ot#pe-declarationR O[+.#R ?ue declara una clase nueva. class-declaration1 attri- tesopt class-%odifiersopt &artialopt class identifier t#pe-para%eter-listopt class--aseopt t#pe-para%eter-constraints-cla sesopt class--od# ;opt 7na declaraci-n de clase Oclass-declarationR consiste en un con$unto de atributos Oattri- tesR O[1*R opcionales, seguido de un con$unto de modi0icadores de clase Oclass-%odifiersR O[1".1.1R, seguido de un modi0icador &artial opcional, seguido de la palabra clave class y un identi0icador OidentifierR ?ue da nombre a la clase, seguido de una especi0icaci-n opcional de lista de par(metros de tipo Ot#pe-para%eter-listR O[1".1.3R, seguido de una especi0icaci-n opcional de clase base Oclass--aseR O[1".1.4R, seguida de una especi0icaci-n opcional de cl(usulas de restricciones de par(metros de tipo Ot#pe-para%eter-constraints-cla sesR O[1".1. R, seguida de un cuerpo de clase Ointerface--od#R O[1".1.#R, y seguido de un punto y coma opcional. 7na declaraci-n de clase no puede proporcionar cl(usulas de restricciones de par(metros de tipo Ot#pepara%eter-constraints-cla sesR a menos ?ue tambi)n proporcione listas de par(metros de tipo Ot#pe-para%eterlistR. 7na declaraci-n de clase ?ue proporciona una lista de par(metros de tipo Ot#pe-para%eter-listR es una declaraci,n de clase gen6rica. 2e manera adicional, cual?uier clase anidada dentro de una declaraci-n de clase gen)rica o una declaraci-n de estructura gen)rica es en s5 misma una declaraci-n de clase gen)rica puesto ?ue se deben proporcionar los par(metros de tipo para el tipo contenedor y as5 crear un tipo construido. 10.1.1 &odificadores de clase 7na declaraci-n de clase Oclass-declarationR puede incluir opcionalmente una secuencia de modi0icadores de claseG class-%odifiers1 class-%odifier class-%odifiers class-%odifier class-%odifier1
ne, &ublic &rotected internal &rivate abstract sealed static
Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

2$1

Especificacin del lenguaje C#

Cuando el mismo modi0icador aparece varias veces en una declaraci-n de clase, se produce un error en tiempo de compilaci-n. El modi0icador ne, est( permitido en clases anidadas. Especi0ica ?ue la clase oculta un miembro =eredado con el mismo nombre, como se describe en [1".3.4. .e produce un error en tiempo de compilaci-n si el modi0icador ne, aparece en una declaraci-n de clase no anidada. 8os modi0icadores &ublic, &rotected, internal y &rivate controlan la accesibilidad de la clase. 2ependiendo del contexto en el ?ue ocurra la declaraci-n de clase, algunos de estos modi0icadores pueden no estar permitidos O[3. .1R. 8os modi0icadores abstract, sealed y static se explican en las siguientes secciones. 17.1.1.1 Clases abstractas El modi0icador abstract se utili1a para indicar ?ue una clase est( incompleta y ?ue s-lo se va a utili1ar como clase base. 7na clase abstracta se di0erencia de una clase no abstracta en lo siguienteG 4o se puede crear una instancia de una clase abstracta directamente, y es un error en tiempo de compilaci-n utili1ar el operador ne, en una clase abstracta. &un?ue es posible tener variables y valores cuyos tipos en tiempo de compilaci-n sean abstractos, tales variables y valores ser(n null o contendr(n re0erencias a instancias de clases no abstractas derivadas de los tipos abstractos. .e permite ?ue una clase abstracta contenga miembros abstractos, aun?ue no es necesario. 4o se puede sellar una clase abstracta.

Cuando una clase no abstracta se deriva de una clase abstracta, la clase no abstracta debe incluir implementaciones reales de todos los miembros abstractos =eredadosV por lo tanto, invalida estos miembros abstractos. En el e$emplo
abstract class ' { &ublic abstract void V(); ! abstract class :/ ' { &ublic void S() {! ! class C/ : { &ublic override void V() { .. actual im&lementation o- V ! !

la clase abstracta ' de0ine un m)todo abstracto V. 8a clase : de0ine un m)todo adicional S, pero no proporciona una implementaci-n de V, por lo ?ue : tambi)n debe ser declarada como abstracta. 8a clase C invalida V y proporciona una implementaci-n real. 2ado ?ue no =ay miembros abstractos en C, est( permitido ?ue C sea no abstracta, aun?ue no es necesario. 17.1.1.2 Clases !ealed El modi0icador sealed se utili1a para impedir la derivaci-n de una clase. .i se especi0ica ?ue una clase sealed es la clase base de otra clase, se produce un error en tiempo de compilaci-n. 7na clase sealed no puede ser tampoco una clase abstracta.

2$2

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

El modi0icador sealed se utili1a principalmente para impedir la derivaci-n no intencionada, pero tambi)n permite algunas optimi1aciones en tiempo de e$ecuci-n. En particular, como una clase sealed no puede tener clases derivadas, es posible trans0ormar las llamadas virtuales a miembros de 0unci-n en instancias de clase sealed en llamadas no virtuales. 17.1.1.3 Clases estticas El modi0icador static se usa para marcar la clase ?ue se va a declarar como clase est5tica. 4o se puede crear una instancia de una clase est(tica, y una clase est(tica no se puede utili1ar como tipo ni contener s-lo miembros est(ticos. .-lo una clase est(tica puede contener declaraciones de m)todos de extensi-n O[1".#.+R. 7na declaraci-n de clase est(tica est( su$eta a las siguientes restriccionesG Es posible ?ue una clase est(tica no incluya un modi0icador sealed o abstract. .in embargo, tenga en cuenta ?ue puesto ?ue no se pueden crear instancias de una clase est(tica ni )sta se puede derivar, dic=a clase se comporta como si 0uera sealed y abstract. Es posible ?ue una clase est(tica no incluya una especi0icaci-n de clase base Oclass--aseR O[1".1.4R y no puede especi0icar de manera expl5cita una clase base ni una lista de inter0aces implementadas. 7na clase est(tica =ereda de manera impl5cita del tipo object. 7na clase est(tica s-lo puede contener miembros est(ticos O[1".3.*R. Tenga en cuenta ?ue las constantes y los tipos anidados se clasi0ican como miembros est(ticos. 7na clase est(tica no puede tener miembros con accesibilidad declarada &rotected o &rotected internal.

El incumplimiento de cual?uiera de estas restricciones genera un error en tiempo de compilaci-n. 7na clase est(tica no tiene constructores de instancia. 4o es posible declarar un constructor de instancia en una clase est(tica, y no se proporciona ningHn constructor de instancia predeterminado O[1".11.4R para una clase est(tica. 8os miembros de una clase est(tica no son autom(ticamente est(ticos y las declaraciones de miembros deben incluir de manera expl5cita un modi0icador static Oexcepto para las constantes y tipos anidadosR. Cuando una clase se anida dentro de una clase exterior est(tica, la clase anidada no es est(tica a menos ?ue incluya expl5citamente un modi0icador static. 17.1.1.3.1 /e3erencia a tipos de clases estticas 7n nombre de espacio de nombres o de tipo Ona%espace-or-t#pe-na%eR O[3.8R puede =acer re0erencia a una clase est(tica si El nombre de espacio de nombres o de tipo Ona%espace-or-t#pe-na%eR es 1 en un nombre de espacio de nombres o de tipo Ona%espace-or-t#pe-na%eR con la estructura 1.$, o bien El nombre de espacio de nombres o de tipo Ona%espace-or-t#pe-na%eR es 1 en una expresi-n typeo0 Ot#peof-e2pressionR O[*. .11R con la estructura ty&eo-(1). 8a expresi-n primaria Opri%ar#-e2pressionR es ) en un acceso a miembros O%e%-er-accessR O[*. .4R con la estructura ).$.

7na expresi-n primaria Opri%ar#-e2pressionR O[*. R puede =acer re0erencia a una clase est(tica si

En otros contextos, se genera un error en tiempo de compilaci-n si se =ace re0erencia a una clase est(tica. 'or e$emplo, se genera un error si se utili1a una clase est(tica como una clase base, un tipo constituyente O[1".3.8R de un miembro, un argumento de tipo gen)rico o una restricci-n de par(metro de tipo. 2e manera similar, una clase est(tica no se puede utili1ar en un tipo de matri1, un tipo de puntero, una expresi-n ne,, una expresi-n de

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

2$3

Especificacin del lenguaje C#

conversi-n de tipos, una expresi-n is, una expresi-n as, una expresi-n si?eo- o una expresi-n de valor predeterminado. 10.1.2 &odificador parcial El modi0icador &artial se usa para indicar ?ue esta declaraci-n de clase Oclass-declarationR es una declaraci-n de tipo parcial. >arias declaraciones de tipo parciales con el mismo nombre dentro de un espacio de nombres envolvente o una declaraci-n de tipo se combinan para 0ormar una declaraci-n de tipo, siguiendo las reglas especi0icadas en la secci-n [. Hacer ?ue la declaraci-n de una clase se distribuya en segmentos separados del texto de un programa puede ser Htil si estos segmentos se producen o mantienen en contextos di0erentes. 'or e$emplo, una parte de una declaraci-n de clase puede ser generada autom(ticamente, mientras ?ue la otra se =a creado de manera manual. 8a separaci-n textual de las dos impide ?ue las actuali1aciones de una entren en con0licto con las actuali1aciones de la otra. 10.1.3 (ar)metros de tipo 7n par(metro de tipo es un identi0icador sencillo ?ue denota un marcador de posici-n para un argumento de tipo proporcionado para crear un tipo construido. 7n par(metro de tipo es un marcador de posici-n 0ormal para un tipo ?ue se proporcionar( posteriormente. 'or el contrario, un argumento de tipo O[4.4.1R es el tipo real ?ue se sustituye por el par(metro de tipo al crear un tipo construido. t#pe-para%eter-list1 D t#pe-para%eters E t#pe-para%eters1 attri- tesopt t#pe-para%eter t#pe-para%eters attri- tesopt t#pe-para%eter t#pe-para%eter1 identificador Cada par(metro de tipo de una declaraci-n de clase de0ine un nombre en el espacio de declaraci-n O[3.3R de dic=a clase. 'or lo tanto, no puede tener el mismo nombre ?ue otro par(metro de tipo o ?ue un miembro declarado en dic=a clase. 7n par(metro de tipo no puede tener el mismo nombre ?ue el tipo. 10.1.! Especificacin de clase base 7na declaraci-n de clase puede incluir una especi0icaci-n de clase base Oclass--aseR, ?ue de0ine la clase base directa de la clase y las inter0aces O[13R directamente implementadas por la clase. class--ase1 / class-t#pe / interface-t#pe-list / class-t#pe interface-t#pe-list interface-t#pe-list1 interface-t#pe interface-t#pe-list

interface-t#pe

8a clase base especi0icada en una declaraci-n de clase se puede ser un tipo de clase construido O[4.4R. 7na clase base no puede ser un par(metro de tipo en s5 mismo, aun?ue puede implicar a par(metros de tipo ?ue se encuentran dentro del (mbito.
class )#tendDUE/ U {! .. )rror ty&e &arameter used as base class

2$#

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

17.1.4.1 Clases base Cuando se incluye un tipo de clase Oclass-t#peR en la clase base Oclass--aseR, )ste especi0ica la clase base directa de la clase ?ue se declara. .i la declaraci-n de una clase no tiene clase base Oclass--aseR o )sta s-lo proporciona una lista de tipos de inter0a1, se supone ?ue la clase base directa es object. 7na clase =ereda los miembros de su clase base directa, como se describe en [1".3.3. En el e$emplo
class ' {! class :/ ' {!

se dice ?ue la clase ' es la clase base directa de :, y ?ue : deriva de '. 2ado ?ue ' no especi0ica expl5citamente una clase base directa, su clase base directa es impl5citamente object. 'ara un tipo de clase construida, si una clase base se especi0ica en la declaraci-n de clase gen)rica, la clase base del tipo construido se obtiene sustituyendo, para cada par(metro de tipo Ot#pe-para%eterR de la declaraci-n de clase base, el correspondiente argumento de tipo Ot#pe-ar& %entR del tipo construido. 2ada las declaraciones de clase gen)rica
class :D; UE {...! class SD1E/ :Dstring 145E {...!

la clase base del tipo construido SDintE ser5a :Dstring int45E. 8a clase base directa de un tipo de clase debe ser al menos tan accesible como el propio tipo de clase O[3. .2R. 'or e$emplo, se produce un error en tiempo de compilaci-n cuando una clase &ublic se deriva de una clase &rivate o internal. 8a clase base directa de un tipo de clase no debe ser de ninguno de los siguientes tiposG System.'rray, System.6elegate, System.Multicast6elegate, System.)num o System.Ualue1y&e. Es m(s, una declaraci-n de clase gen)rica no puede utili1ar System.'ttribute como una clase base indirecta. %ientras se determina el signi0icado de la especi0icaci-n de clase base directa ' de una clase :, se supone temporalmente ?ue la clase base directa de : es object. 2e esta 0orma, se asegura intuitivamente ?ue el signi0icado de una especi0icaci-n de clase base no puede depender recursivamente de s5 misma. El e$emploG
class 'D1E { &ublic class :{! ! class C / 'DC.:E {!

Es err-neo por?ue en la especi0icaci-n de la clase base 'DC.:E la clase base directa de C se considera object y, por tanto, OsegHn las reglas de [3.8R C no se considera ?ue tenga un miembro :. 8as clases base de un tipo de clase son la clase base directa y sus clases base. En otras palabras, el con$unto de las clases base es el cierre transitivo de la relaci-n de clase base directa. En el e$emplo anterior, las clases base de : son ' y object. En el e$emplo
class ' {...! class :D1E/ ' {...! class CD1E/ :D$Com&arableD1EE {...! class 6D1E/ CD145E {...!

las clases base de 6DintE son CDint45E, :D$Com&arableDint45EE, ' y object. Exceptuando la clase object, todos los tipos de clases tienen una clase base directa. 8a clase object no tiene clase base directa y es la Hltima clase base del resto de clases.

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

2$!

Especificacin del lenguaje C#

Cuando una clase : deriva de una clase ', se produce un error si ' depende de :. 7n clase depende directa ente de su clase base directa Osi existeR y depende directa ente de la clase dentro de la cual est( inmediatamente anidada Osi es el casoR. 2ada esta de0inici-n, el con$unto completo de clases de las cuales depende una clase es el cierre re0lexivo y transitivo de la relaci-n de dependencia directa. En el e$emplo
class '/ ' {!

Es err-neo por?ue la clase depende de s5 misma. !gualmente, el e$emplo


class '/ : {! class :/ C {! class C/ ' {!

es err-neo, por?ue las clases tienen una dependencia circular entre ellas. 'or Hltimo, el e$emplo
class '/ :.C {! class :/ ' { &ublic class C {! !

produce un error en tiempo de compilaci-n por?ue ' depende de :.C Osu clase base directaR, ?ue a su ve1 depende de : Osu clase envolvente inmediataR, ?ue depende circularmente de '. /bserve ?ue una clase no depende de las clases anidadas internas. En el e$emplo
class ' { class :/ ' {! ! : depende de ' Opor?ue ' es tanto su clase base directa como su clase envolvente inmediataR, pero ' no depende de : Opor?ue : no es ni una clase base ni una clase envolvente de 'R. 'or tanto, el e$emplo es correcto.

4o es posible derivar de una clase sealed. En el e$emplo


sealed class ' {! class :/ ' {! .. )rror cannot derive -rom a sealed class

la clase : es err-nea por?ue intenta derivarse de la clase sealed '. 17.1.4.2 $mplementaciones de inter3aces 7na especi0icaci-n de clase base Oclass--aseR puede incluir una lista de tipos de inter0a1, en cuyo caso se dice ?ue la clase implementa directamente esos tipos de inter0a1. 8as implementaciones de inter0aces se explican m(s detalladamente en [13.4. 10.1.# 9estricciones de par)metros de tipo 8as declaraciones de tipo y de m)todo gen)ricos pueden especi0icar opcionalmente restricciones de par(metros de tipo incluidas las cl(usulas de restricciones de par(metros de tipo Ot#pe-para%eter-constraints-cla sesR. t#pe-para%eter-constraints-cla ses1 t#pe-para%eter-constraints-cla se t#pe-para%eter-constraints-cla ses t#pe-para%eter-constraints-cla se t#pe-para%eter-constraints-cla se1 ,"ere t#pe-para%eter / t#pe-para%eter-constraints

2$6

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

t#pe-para%eter-constraints1 pri%ar#-constraint secondar#-constraints constr ctor-constraint pri%ar#-constraint secondar#-constraints pri%ar#-constraint constr ctor-constraint secondar#-constraints constr ctor-constraint pri%ar#-constraint secondar#-constraints constr ctor-constraint pri%ar#-constraint1 class-t#pe
class struct

secondar#-constraints1 interface-t#pe t#pe-para%eter secondar#-constraints secondar#-constraints constr ctor-constraint1


ne, ( )

interface-t#pe t#pe-para%eter

Cada cl(usula de restricciones de par(metros de tipo Ot#pe-para%eter-constraints-cla seR consta de un to6en ,"ere, seguido del nombre de un par(metro de tipo, de dos puntos y de la lista de restricciones para dic=o par(metro de tipo. 'uede =aber como m(ximo una cl(usula ,"ere para cada par(metro de tipo y las cl(usulas ,"ere se pueden enumerar en cual?uier orden. &l igual ?ue los s5mbolos Oto6enR get y set en un descriptor de acceso a propiedad, el s5mbolo Oto6enR ,"ere no es una palabra clave. 8a lista de restricciones proporcionada en una cl(usula ,"ere puede incluir cual?uiera de los siguientes componentes, en este ordenG una restricci-n principal Hnica, una o m(s restricciones secudarias y la restricci-n de constructor ne,() 7na restricci-n principal puede ser un tipo de clase o la restricci,n de tipo de referencia class o la restricci,n de tipo de valor struct. 7na restricci-n secundaria puede ser un par(metro de tipo Ot#pe-para%eterR o un tipo de inter0a1 Ointerface-t#peR. 8a restricci-n de tipo de re0erencia especi0ica ?ue un argumento de tipo utili1ado para el par(metro de tipo debe ser un tipo de re0erencia. Todos los tipos de clase, inter0a1, delegado y matri1, y los par(metros de tipo conocidos como un tipo de re0erencia Otal y como se de0ine a continuaci-nR cumplen con esta restricci-n. 8a restricci-n de tipo de valor especi0ica ?ue un argumento de tipo utili1ado para el par(metro de tipo debe ser un tipo de valor ?ue acepta valores 4788. Todos los tipos de estructura ?ue aceptan valores 4788, los tipos de enumeraci-n y los par(metros de tipo ?ue tienen la restricci-n de tipo de valor satis0acen esta restricci-n. Tenga en cuenta ?ue aun?ue se clasi0i?ue como un tipo de valor, un tipo ?ue acepte valores 4788 O[4.1.1"R no cumple con la restricci-n de tipo de valor. 7n par(metro de tipo ?ue tenga la restricci-n de tipo de valor no puede tener tambi)n la restricci-n de constructor Oconstr ctor-constraintR. 8os tipos de puntero nunca pueden ser argumentos de tipo y no se considera ?ue cumplen las restricciones de tipo de re0erencia o de tipo de valor. .i una restricci-n es un tipo de clase o de inter0erencia, o un par(metro de tipo, dic=o tipo especi0ica un Ptipo baseQ m5nimo ?ue cada argumento de tipo utili1ado para dic=o par(metro de tipo debe admitir. .iempre ?ue se utili1a un tipo construido o un m)todo gen)rico, el argumento de tipo se comprueba con las restricciones en el par(metro de tipo en tiempo de compilaci-n. El argumento de tipo suministrado debe cumplir las condiciones descritas en la secci-n 4.4.4.

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

2$(

Especificacin del lenguaje C#

7na restricci-n de tipo de clase Oclass-t#peR debe cumplir las siguientes reglasG El tipo debe ser un tipo de clase. El tipo no debe ser sealed. El tipo no debe serG System.'rray, System.6elegate, System.)num o System.Ualue1y&e. El tipo no debe ser object. 'uesto ?ue todos los tipos derivan de object, dic=a restricci-n no tendr5a e0ecto si se permitiera. .-lo una restricci-n puede ser un tipo de clase para un par(metro de tipo dado. El tipo debe ser un tipo de inter0a1. 7n tipo no se debe especi0icar m(s de una ve1 en una cl(usula ,"ere dada.

7n tipo especi0icado como una restricci-n de tipo de inter0a1 Ointerface-t#peR debe cumplir las siguientes reglasG

En cual?uier caso, la restricci-n puede implicar cual?uiera de los par(metros de tipo de la declaraci-n de tipo o m)todo asociada como parte de un tipo construido y puede implicar al tipo ?ue se est( declarando. Cual?uier tipo de clase o inter0a1 especi0icado como una restricci-n de par(metro de tipo debe ser al menos tan accesible O[3. .4R como el tipo o m)todo gen)rico ?ue se est( declarando. 7n tipo especi0icado como una restricci-n de par(metro de tipo Ot#pe-para%eterR debe cumplir las siguientes reglasG El tipo debe ser un par(metro de tipo. 7n tipo no se debe especi0icar m(s de una ve1 en una cl(usula ,"ere dada.

&dem(s, no debe =aber ciclos en el gr(0ico de dependencia de par(metros de tipo, donde dependencia es una relaci-n transitiva de0inida porG .i un par(metro de tipo 1 se utili1a como una restricci-n para el par(metro de tipo S, entonces S depende de 1. .i un par(metro de tipo S depende de un par(metro de tipo 1 y 1 depende de un par(metro de tipo ;, entonces S depende de ;.

2ada esta relaci-n, es un error de tiempo de compilaci-n si un par(metro de tipo depende de s5 mismo Odirecta o indirectamenteR. Cual?uier restricci-n debe ser co=erente entre par(metros de tipo dependientes. .i un par(metro de tipo S depende del par(metro de tipo 1G
1 no debe tener la restricci-n de tipo de valor. 2e lo contrario, 1 se sella de manera e0ica1 para 0or1ar a S a ser del mismo tipo ?ue 1 y eliminar as5 la necesidad de dos par(metros de tipo.

.i S tiene la restricci-n de tipo de valor, 1 no debe tener una restricci-n de tipo de clase Oclass-t#peR. .i S tiene una restricci-n de tipo de clase Oclass-t#peR ' y 1 tiene una restricci-n de tipo de clase Oclass-t#peR :, debe =aber una conversi-n de identidad o una conversi-n de re0erencia impl5cita de ' a : o una conversi-n de re0erencia impl5cita de : a '. .i S tambi)n depende del par(metro de tipo ; y ; tiene una restricci-n de tipo de clase Oclass-t#peR ' y 1 tiene una restricci-n de tipo de clase Oclass-t#peR :, debe =aber una conversi-n de identidad o una conversi-n de re0erencia impl5cita de ' a : o una conversi-n de re0erencia impl5cita de : a '.

S puede tener la restricci-n de tipo de valor y 1 la restricci-n de tipo de re0erencia. Esto limita a 1 a los tipos System.%bject, System.Ualue1y&e, System.)num y cual?uier tipo de inter0a1.

2$$

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

.i la cl(usula ,"ere para un par(metro de tipo incluye una restricci-n de constructor Ocon la estructura ne,()R, es posible utili1ar el operador ne, para crear instancias del tipo O[*. .1".1R. Cual?uier argumento de tipo utili1ado para un par(metro de tipo con una restricci-n de constructor debe tener un constructor pHblico sin par(metros Oeste constructor existe de manera impl5cita para cual?uier tipo de valorR o ser un par(metro de tipo ?ue tenga la restricci-n de tipo de valor o la restricci-n de constructor. & continuaci-n se muestran e$emplos de restriccionesG
inter-ace $*rintable { void *rint(); ! inter-ace $Com&arableD1E { int Com&are1o(1 value); ! inter-ace $aey*roviderD1E { 1 Setaey(); ! class *rinterD1E ,"ere 1/ $*rintable {...! class SortedListD1E ,"ere 1/ $Com&arableD1E {...! class 6ictionaryDa UE ,"ere a/ $Com&arableDaE ,"ere U/ $*rintable $aey*roviderDaE { ... !

ne,()

El siguiente e$emplo genera un error por?ue provoca una circularidad en el gr(0ico de dependencia de los par(metros de tipoG
class CircularDS 1E ,"ere S/ 1 ,"ere 1/ S { ... ! class SealedDS 1E ,"ere S/ 1 ,"ere 1/ struct { ... ! class ' {...! class : {...! class $ncom&atDS 1E ,"ere S/ ' 1 ,"ere 1/ : { ... ! .. )rror circularity in de&endency gra&"

En los siguientes e$emplos se muestran otras situaciones no v(lidasG


.. )rror 1 is sealed

.. )rror

incom&atible class=ty&e constraints

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

2$"

Especificacin del lenguaje C# class StructWit"ClassDS 1 ;E ,"ere S/ struct 1 ,"ere 1/ ; ,"ere ;/ ' .. )rror { ... !

' incom&atible ,it" struct

8a clase /ase efectiva de un par(metro de tipo 1 se de0ine de la siguiente maneraG .i 1 no tiene restricciones principales ni restricciones de par(metro de tipo, su clase base e0ectiva es object. .i 1 tiene la restricci-n de tipo de valor, su clase base e0ectiva es System.Ualue1y&e. .i 1 tiene una restricci-n de tipo de clase Oclass-t#peR C, pero no tiene restricciones de par(metro de tipo Ot#pe-para%eterR, su clase base e0ectiva es C. .i 1 no tiene una restricci-n de tipo de clase Oclass-t#peR, pero tiene una o m(s restricciones de par(metro de tipo Ot#pe-para%eterR, su clase base e0ectiva es el tipo m(s abarcado O[#.4.2R en el con$unto de clases base e0ectivas de sus restricciones de par(metro de tipo Ot#pe-para%eterR. 8as reglas de co=erencia garanti1an ?ue exista dic=o tipo m(s abarcado. .i 1 tiene una restricci-n de tipo de clase Oclass-t#peR y una o m(s restricciones de par(metro de tipo Ot#pepara%eterR, su clase base e0ectiva es el tipo m(s abarcado O[#.4.2R del con$unto 0ormado por la restricci-n de tipo de clase Oclass-t#peR de 1 y las clases base e0ectivas de sus restricciones de par(metro de tipo Ot#pepara%eterR. 8as reglas de co=erencia garanti1an ?ue exista dic=o tipo m(s abarcado. .i 1 tiene una restricci-n de tipo de re0erencia, pero no tiene restricciones de tipo de clase Oclass-t#peR, su clase base e0ectiva es object. .i 1 no tiene restricciones secundarias Osecondar#-constraintsR, su con$unto de inter0aces e0ectivas est( vac5o. .i 1 tiene restricciones de tipo de inter0a1 Ointerface-t#peR, pero no tiene restricciones de par(metro de tipo Ot#pe-para%eterR, su con$unto de inter0aces e0ectivas es su con$unto de restricciones de tipo de inter0a1 Ointerface-t#peR. .i 1 no tiene restricciones de tipo de inter0a1 Ointerface-t#peR, pero tiene restricciones de par(metro de tipo Ot#pe-para%eterR, su con$unto de inter0aces e0ectivas es la uni-n del con$unto de inter0aces e0ectivas de sus restricciones de par(metro de tipo Ot#pe-para%eterR. .i 1 tiene restricciones de tipo de inter0a1 Ointerface-t#peR y restricciones de par(metro de tipo Ot#pepara%eterR, su con$unto de inter0aces e0ectivas es la uni-n de su con$unto de restricciones de tipo de inter0a1 Ointerface-t#peR y del con$unto de inter0aces e0ectivas de sus restricciones de par(metro de tipo Ot#pepara%eterR.

El con1!nto de interfaces efectivas de un par(metro de tipo 1 se de0ine de la siguiente maneraG

7n par(metro de tipo es !n tipo de referencia si tiene la restricci-n de tipo de re0erencia o su clase base e0ectiva no es object ni System.Ualue1y&e. .e pueden utili1ar valores de un tipo de par(metro de tipo restringido para obtener acceso a miembros de instancia implicados en las restricciones. En el e$emplo
inter-ace $*rintable { void *rint(); !

2"'

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases class *rinterD1E ,"ere 1/ $*rintable { void *rint%ne(1 #) { #.*rint(); ! !

los m)todos de $*rintable se pueden invocar directamente en # por?ue es imprescindible ?ue 1 implemente siempre $*rintable. 10.1.$ %uerpo de clase El cuerpo de clase Oclass--od#R de una clase de0ine los miembros de esa clase. class--od#1 { class-%e%-er-declarationsopt !

10.2 Tipos parciales


7na declaraci-n de tipo se puede dividir en varias declaraciones de tipo parciales. 7na declaraci-n de tipo se construye a partir de sus elementos siguiendo las reglas de esta secci-n, con lo cual se trata como una Hnica declaraci-n durante el tiempo restante de compilaci-n y procesamiento en tiempo de e$ecuci-n del programa. 7na declaraci-n de clase Oclass-declarationR, declaraci-n de estructura Ostr ct-declarationR o declaraci-n de inter0a1 Ointerface-declarationR representa una declaraci-n de tipo parcial si incluye un modi0icador &artial. Esta palabra, &artial, no es una palabra clave, y s-lo actHa como modi0icador si aparece inmediatamente antes de una de las palabras clave class, struct o inter-ace en una declaraci-n de tipo, o antes del tipo void en una declaraci-n de m)todo. En otros contextos, se puede utili1ar como un identi0icador normal. Cada parte de una declaraci-n de tipo parcial debe incluir un modi0icador &artial. 2ebe tener el mismo nombre y estar declarada en el mismo espacio de nombres o declaraci-n de tipo ?ue las dem(s partes. El modi0icador &artial indica ?ue es posible ?ue existan partes adicionales de la declaraci-n de tipo en cual?uier otra parte, pero la existencia de dic=as partes adicionales no es un re?uisitoV la inclusi-n del modi0icador &artial es v(lida en un tipo con una Hnica declaraci-n. Todas las partes de un tipo parcial se deben compilar $untas para combinarlas en tiempo de compilaci-n en una Hnica declaraci-n de tipo. Concretamente, los tipos parciales no permiten ampliar los tipos ya compilados. 8os tipos anidados se pueden declarar en varias partes mediante el modi0icador &artial. 3eneralmente, el tipo contenedor se declara tambi)n con &artial y cada parte del tipo anidado se declara en una parte di0erente del tipo contenedor. El modi0icador &artial no se admite en declaraciones de delegado o de enumeraci-n. 10.2.1 'tributos 8os atributos de un tipo parcial se determinan combinando, en orden no especi0icado, los atributos de cada una de las partes. .i un atributo se coloca en varias partes, esto e?uivale a especi0icar el atributo varias veces en el tipo. 'or e$emplo, las dos partesG
4'ttr2 'ttr8(""ello")5 &artial class ' {! 4'ttr9 'ttr8("goodbye")5 &artial class ' {!

e?uivalen a una declaraci-n similar a la siguienteG


4'ttr2 'ttr8(""ello") class ' {! 'ttr9 'ttr8("goodbye")5

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

2"1

Especificacin del lenguaje C#

8os atributos en par(metros de tipo se combinan de manera similar. 10.2.2 &odificadores Cuando una declaraci-n de tipo parcial incluye una especi0icaci-n de accesibilidad Olos modi0icadores &ublic, &rotected, internal y &rivateR, debe concordar con las otras partes ?ue incluyen una especi0icaci-n de accesibilidad. .i ninguna de las partes de un tipo parcial incluye una especi0icaci-n de accesibilidad, al tipo se le concede la accesibilidad predeterminada apropiada O[3. .1R. .i una o m(s declaraciones parciales de un tipo anidado incluyen un modi0icador ne,, no se noti0ica ninguna advertencia si el tipo anidado oculta un miembro =eredado O[3.*.1.2R. .i una o m(s declaraciones parciales de una clase incluyen un modi0icador abstract, la clase se considera abstracta O[1".1.1.1R. 2e lo contrario, la clase se considera no abstracta. .i una o m(s declaraciones parciales de una clase incluyen un modi0icador sealed, la clase se considera sealed O[1".1.1.2R. 2e lo contrario, la clase se considera unsealed. Tenga en cuenta ?ue una clase no puede ser abstracta y sealed al mismo tiempo. Cuando se utili1a el modi0icador unsa-e en una declaraci-n de tipo parcial, s-lo dic=a parte concreta se considera en un contexto no seguro O[18.1R. 10.2.3 (ar)metros de tipo y restricciones .i un tipo gen)rico se declara en varias partes, cada una de ellas debe especi0icar los par(metros de tipo. Cada parte debe tener el mismo nHmero de par(metros de tipo y el mismo nombre para cada par(metro de tipo en orden. Cuando una declaraci-n de tipo gen)rico incluye restricciones Ocl(usulas ,"ereR, )stas deben coincidir con el resto de partes ?ue incluyen restricciones. 2e manera espec50ica, cada parte ?ue incluye restricciones debe tener restricciones para el mismo con$unto de par(metros de tipo y para cada par(metro de tipo los con$untos de restricciones principales, secundarias y de constructor deben ser e?uivalentes. 2os con$untos de restricciones son e?uivalentes si contienen los mismos miembros. .i ninguna parte de un tipo gen)rico parcial especi0ica las restricciones de par(metros de tipo, se considera ?ue estos no tienen restricciones. El e$emplo
&artial class 6ictionaryDa UE ,"ere a/ $Com&arableDaE ,"ere U/ $aey*roviderDaE $*ersistable { ... ! &artial class 6ictionaryDa UE ,"ere U/ $*ersistable $aey*roviderDaE ,"ere a/ $Com&arableDaE { ... ! &artial class 6ictionaryDa UE { ... !

es correcto por?ue a?uellas partes ?ue incluyen restricciones Olas dos primerasR especi0ican e0ectivamente el mismo con$unto de restricciones principales, secundarias y de constructor para el mismo con$unto de par(metros de tipo respectivamente.

2"2

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

10.2.! %lase base Cuando una declaraci-n de clase parcial incluye una especi0icaci-n de clase base, debe coincidir con el resto de partes ?ue incluyen una especi0icaci-n de clase base. .i ninguna parte de una clase parcial incluye una especi0icaci-n de clase base, la clase base se convierte en System.%bject O[1".1.4.1R. 10.2.# Interfaces base El con$unto de inter0aces base para un tipo declarado en varias partes es la uni-n de las inter0aces base especi0icadas en cada parte. 7na inter0a1 base concreta s-lo se puede nombrar una ve1 en cada parte, pero varias partes s5 pueden nombrar la misma inter0a1 base Oo las mismas inter0aces baseR. .-lo debe =aber una implementaci-n de los miembros de cual?uier inter0a1 base dada. En el e$emplo
&artial class C/ $' &artial class C/ $' $: {...! $: {...! &artial class C/ $C {...!

el con$unto de inter0aces base para la clase C es $', $: e $C. 3eneralmente, cada parte proporciona una implementaci-n de las inter0aces declaradas en dic=a parteV sin embargo, esto no es un re?uisito. 7na parte puede proporcionar la implementaci-n para una inter0a1 declarada en otra parte di0erenteG
&artial class I { int $Com&arable.Com&are1o(object o) {...! ! &artial class I/ $Com&arable { ... !

10.2.$ &iembros Con la excepci-n de los m)todos parciales O[1".2.*R, el con$unto de miembros de un tipo declarado en varias partes es simplemente la uni-n del con$unto de miembros declarados en cada una de las partes. 8os cuerpos de todas las partes de la declaraci-n de tipo comparten el mismo espacio de declaraci-n O[3.3R y el (mbito de cada miembro O[3.*R se extiende a los cuerpos de todas las partes. El dominio de accesibilidad de todo miembro siempre incluye todas las partes del tipo contenedorV se puede obtener acceso libremente a un miembro &rivate declarado en otra parte. .e genera un error en tiempo de compilaci-n si se declara el mismo miembro en m(s de una parte del tipo a menos ?ue dic=o miembro sea un tipo con el modi0icador &artial.
&artial class ' { int #; &artial class $nner { int y; ! ! &artial class ' { int #; .. )rror .. %( cannot declare # more t"an once

$nner is a &artial ty&e

.. )rror

cannot declare # more t"an once

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

2"3

Especificacin del lenguaje C# &artial class $nner { int ?; ! ! .. %( $nner is a &artial ty&e

&un?ue dentro de un tipo el orden de los miembros no in0luye en el c-digo C#, puede ser importante a la =ora de interactuar con otros lengua$es y entornos. En estos casos, el orden de los miembros dentro de un tipo declarado en varias partes es inde0inido. 10.2.+ &*todos parciales 8os m)todos parciales se pueden de0inir en una parte de una declaraci-n de tipo e implementarse en otra. Esta implementaci-n es opcionalV si ninguna parte implementa el m)todo parcial, la declaraci-n de m)todo parcial y todas sus llamadas se ?uitan de la declaraci-n de tipo resultante de la combinaci-n de las partes. 8os m)todos parciales no pueden de0inir el acceso a los modi0icadores, pero son impl5citamente &rivate. .u tipo de valor devuelto debe ser void, y sus par(metros no pueden tener el modi0icador out. El identi0icador &artial se reconoce como una palabra clave especial en una declaraci-n de m)todo s-lo si aparece $usto antes del tipo voidV de lo contrario se puede usar como un identi0icador normal. 7n m)todo parcial no puede implementar de manera expl5cita m)todos de inter0a1. Hay dos clases de declaraciones de m)todo parciales. .i el cuerpo de la declaraci-n de m)todo es un punto y coma, se dice ?ue la declaraci-n es una declaraci,n de 6todo parcial de definici,n. .i el cuerpo se da como un -lo6 e, se dice ?ue la declaraci-n es una declaraci,n de 6todo parcial de i ple entaci,n. En las partes de una declaraci-n de tipo s-lo puede =aber una declaraci-n de m)todo parcial de de0inici-n con una 0orma dada, y s-lo puede =aber una declaraci-n de m)todo parcial de implementaci-n con una 0irma dada. .i se proporciona una declaraci-n de m)todo parcial de implementaci-n, debe existir una declaraci-n de m)todo parcial de de0inici-n, y las declaraciones deben coincidir de la manera ?ue se especi0ica a continuaci-nG 8as declaraciones deben tener los mismos modi0icadores Oaun?ue no necesariamente en el mismo ordenR, el mismo nombre de m)todo, nHmero de par(metros de tipo y nHmero de par(metros. 8os par(metros correspondientes en las declaraciones deben tener los mismos modi0icadores Oaun?ue no necesariamente en el mismo ordenR, y los mismos tipos Odi0erencias de m-dulo en los nombres de par(metros de tipoR. 8os par(metros de tipo correspondientes en las declaraciones deben tener las mismas restricciones Odi0erencias de m-dulo en los nombres de par(metros de tipoR.

7na declaraci-n de m)todo parcial de implementaci-n puede aparecer en la misma parte ?ue la declaraci-n de m)todo parcial de de0inici-n correspondiente. .-lo participa un m)todo parcial de de0inici-n en la resoluci-n de sobrecargas. 'or lo tanto, tanto si se da como si no se da una declaraci-n de implementaci-n, las expresiones de invocaci-n pueden resolverse en invocaciones de m)todo parcial. 2ado ?ue un m)todo parcial siempre devuelve void, dic=as expresiones de invocaci-n siempre ser(n instrucciones de expresi-n. Es m(s, debido a ?ue un m)todo parcial es impl5citamente &rivate, dic=as declaraciones siempre ocurrir(n dentro de una de las partes de la declaraci-n de tipo en de la cual se declara el m)todo parcial. .i ninguna declaraci-n de tipo parcial contiene una declaraci-n de implementaci-n para un m)todo parcial dado, se ?uitar(n de la declaraci-n de tipos combinada todas las instrucciones de expresi-n ?ue la invo?uen. 'or lo tanto, la expresi-n de invocaci-n, incluidas sus expresiones constituyentes, no tiene ningHn e0ecto en tiempo de e$ecuci-n. El m)todo parcial en s5 tambi)n se ?uitar( y no ser( miembro de la declaraci-n de tipos combinada.

2"#

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

.i existe una declaraci-n de implementaci-n para un m)todo parcial dado, se conservan las invocaciones de los m)todos parciales. El m)todo parcial da lugar a una declaraci-n de m)todo similar a la declaraci-n de m)todo parcial de implementaci-n para lo siguienteG 4o se incluye el modi0icador &artial 8os atributos de la declaraci-n de m)todo resultante son los atributos combinados de la declaraci-n de m)todo parcial de implementaci-n y de de0inici-n en un orden no especi0icado. 4o se ?uitan duplicados. 8os atributos de los par(metros en la declaraci-n de m)todo resultante son los atributos combinados de los par(metros correspondientes en la declaraci-n de m)todo parcial de implementaci-n y de de0inici-n en un orden no especi0icado. 4o se ?uitan duplicados.

.i se proporciona una declaraci-n de de0inici-n, pero no una declaraci-n de implementaci-n, para un m)todo parcial %, se aplican las siguientes restriccionesG Es un error en tiempo de compilaci-n crear un delegado para el m)todo O[*. .1". R. Es un error en tiempo de compilaci-n =acer re0erencia a M dentro de una 0unci-n an-nima ?ue se convierte a un tipo de (rbol de expresiones O[#. .2R. 8as expresiones ?ue ocurren como parte de una invocaci-n de M no a0ectan al estado de asignaci-n de0initivo O[ .3R, ?ue puede conducir potencialmente a errores en tiempo de compilaci-n.
M no puede ser el punto de entrada de una aplicaci-n O[3.1R.

8os m)todos parciales son Htiles para permitir ?ue una parte de una declaraci-n de tipo personalice el comportamiento de otra parte, por e$emplo, una ?ue se genera mediante una =erramienta. Considere la siguiente declaraci-n de clase parcialG
&artial class Customer { string name; &ublic string Name { get { return name; ! set { %nNameC"anging(value); name + value; %nNameC"anged(); ! ! &artial void %nNameC"anging(string ne,Name); &artial void %nNameC"anged(); !

.i esta clase se compila sin ninguna otra parte, se ?uitar(n las declaraciones de m)todo parcial de de0inici-n y sus invocaciones, y la declaraci-n de clase combinada resultante ser( e?uivalente a la siguienteG
class Customer { string name; &ublic string Name { get { return name; ! set { name + value; ! ! !

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

2"!

Especificacin del lenguaje C#

4o obstante, si se asume ?ue se proporciona otra parte, ?ue proporciona declaraciones de implementaci-n de m)todos parcialesG
&artial class Customer { &artial void %nNameC"anging(string ne,Name) { Console.WriteLine(RC"anging R < name < R to R < ne,Name); ! &artial void %nNameC"anged() { Console.WriteLine(RC"anged to R < name); ! !

8a declaraci-n de clase combinada resultante ser( e?uivalente a la siguienteG


class Customer { string name; &ublic string Name { get { return name; ! set { %nNameC"anging(value); name + value; %nNameC"anged(); ! ! void %nNameC"anging(string ne,Name) { Console.WriteLine(RC"anging R < name < R to R < ne,Name); ! void %nNameC"anged() { Console.WriteLine(RC"anged to R < name); ! !

10.2.- Enlace de nombres &un?ue cada parte de un tipo extensible se debe declarar dentro del mismo espacio de nombres, las partes generalmente se escriben dentro de di0erentes declaraciones de espacios de nombres. 'or lo tanto, puede =aber di0erentes directivas using O[+.4R para cada parte. &l interpretar nombres simples O[*. .2R dentro de una parte, s-lo se consideran las directivas using de las declaraciones de espacios de nombres contenedor. El resultado ?ue se obtenga puede ser el mismo identi0icador con di0erentes signi0icados en di0erentes partesG
names&ace N { using List + System.Collections.'rrayList; &artial class ' { List #; ! ! names&ace N { using List + Widgets.Lin(edList;

.. # "as ty&e System.Collections.'rrayList

2"6

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases &artial class ' { List y; ! !

.. y "as ty&e Widgets.Lin(edList

10.3 &iembros de clase


8os miembros de una clase se componen de los miembros ?ue introducen las declaraciones de miembros de clase Oclass-%e%-er-declarationsR y los miembros ?ue )sta =ereda de su clase base directa. class-%e%-er-declarations1 class-%e%-er-declaration class-%e%-er-declarations class-%e%-er-declaration class-%e%-er-declaration1 constant-declaration field-declaration %ethod-declaration propert#-declaration event-declaration inde2er-declaration operator-declaration constr ctor-declaration destr ctor-declaration static-constr ctor-declaration t#pe-declaration 8os miembros de un tipo de clase se dividen en las siguientes categor5asG Constantes, ?ue representan valores constantes asociados a la clase O[1".4R. Campos, ?ue son las variables de la clase O[1". R. %)todos, ?ue implementan los c(lculos y acciones ?ue puede reali1ar la clase O[1".#R. 'ropiedades, ?ue de0inen caracter5sticas con nombre y las acciones asociadas con la lectura y la escritura de esas caracter5sticas O[1".*R. Eventos, ?ue de0inen las noti0icaciones ?ue puede generar la clase O[1".8R. !ndi1adores, ?ue permiten indi1ar las instancias de la clase de la misma manera Osint(cticamenteR ?ue las matrices O[1".+R. /peradores, ?ue de0inen los operadores de expresi-n ?ue se pueden aplicar a las instancias de la clase O[1".1"R. Constructores de instancia, ?ue implementan las acciones necesarias para iniciali1ar las instancias de la clase O[1".11R. 2estructores, ?ue implementan las acciones ?ue se deben reali1ar antes de ?ue las instancias de la clase sean descartadas de 0orma permanente O[1".13R. Constructores est(ticos, ?ue implementan las acciones necesarias para iniciali1ar la propia clase O[1".12R. Tipos, ?ue representan los tipos locales de la clase O[1".3.8R.

& los miembros ?ue pueden contener c-digo e$ecutable se los conoce colectivamente como miembros de 0unci-n Of nction %e%-ersR del tipo de clase. 8os miembros de 0unci-n de un tipo de clase son los m)todos,

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

2"(

Especificacin del lenguaje C#

propiedades, eventos, indi1adores, operadores, constructores de instancia, destructores y constructores est(ticos de dic=o tipo de clase. 7na declaraci-n de clase Oclass-declarationR crea un nuevo espacio de declaraci-n O[3.3R, y las declaraciones de miembros de clase Oclass-%e%-er-declarationsR inmediatamente contenidas en la declaraci-n de clase OclassdeclarationR introducen nuevos miembros en este espacio de declaraci-n. .e aplican las siguientes reglas a las declaraciones de miembros de clase Oclass-%e%-er-declarationsRG 8os constructores de instancia, los constructores est(ticos y los destructores deben tener el mismo nombre ?ue su clase envolvente inmediata. El resto de miembros deben tener nombres di0erentes al de la clase envolvente inmediata. El nombre de una constante, campo, propiedad, evento o tipo debe ser di0erente de los nombres del resto de miembros declarados en la misma clase. El nombre de un m)todo debe ser di0erente de los nombres del resto de miembros ?ue no sean m)todos declarados en la misma clase. &dem(s, la 0irma O[3.#R de un m)todo debe ser distinta de las 0irmas de todos los dem(s m)todos declarados en la misma clase, y dos m)todos declarados en la misma clase no pueden tener 0irmas ?ue s-lo se di0erencien por re- y out. 8a 0irma de un constructor de instancia debe di0erir de las 0irmas de todos los dem(s constructores de instancia declaradas en la misma clase, y dos constructores declarados en la misma clase no pueden tener 0irmas ?ue s-lo se di0erencien en re- y out. 8a 0irma de un indi1ador debe ser di0erente de las 0irmas de los dem(s indi1adores declarados en la misma clase. 8a 0irma de un operador debe ser di0erente de las 0irmas de los dem(s operadores declarados en la misma clase.

8os miembros =eredados de un tipo de clase O[1".3.3R no 0orman parte del espacio de declaraci-n de la clase. 'or ello, una clase derivada puede declarar un miembro con el mismo nombre o 0irma ?ue el de un miembro =eredado O?ue en realidad oculta el miembro =eredadoR. 10.3.1 El tipo de instancia Cada declaraci-n de clase tiene un tipo enla1ado O[4.4.3R, el tipo de instancia. 'ara una declaraci-n de clase gen)rica, el tipo de instancia se 0orma creando un tipo construido O[4.4R a partir de la declaraci-n de tipo, siendo cada uno de los argumentos de tipo suministrados el par(metro de tipo e?uivalente. 'uesto ?ue el tipo de instancia utili1a los par(metros de tipo, s-lo se puede utili1ar donde los par(metros de tipo est(n dentro del (mbito, es decir, dentro de la declaraci-n de clase. El tipo de instancia es el tipo de t"is para el c-digo escrito dentro de la declaraci-n de clase. 'ara las clases no gen)ricas, el tipo de instancia es simplemente la clase declarada. En el siguiente e$emplo se muestran varias declaraciones de clase $unto con sus tipos de instanciaG
class 'D1E { class : {! class CD;E {! ! class 6 {! .. instance ty&e/ 6 .. instance ty&e/ 'D1E .. instance ty&e/ 'D1E.: .. instance ty&e/ 'D1E.CD;E

10.3.2 &iembros de tipos construidos 8os miembros no =eredados de un tipo construido se obtienen sustituyendo, para cada par(metro de tipo Ot#pepara%eterR de la declaraci-n de miembro, el argumento de tipo Ot#pe-ar& %entR correspondiente del tipo construido. El proceso de sustituci-n se basa en el signi0icado sem(ntico de las declaraciones de tipo y no se trata simplemente de una sustituci-n textual.
2"$
Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

'or e$emplo, dadas la declaraci-n de clase gen)ricaG


class SenD1 ;E { &ublic 14 5 a; &ublic void S(int i 1 t SenD; 1E gt) {...! &ublic ; *ro& { get {...! set {...! ! &ublic int H(double d) {...! !

el tipo construido SenDint45 $Com&arableDstringEE consta de los siguientes miembrosG


&ublic int4 545 a; &ublic void S(int i int45 t SenD$Com&arableDstringE int45E gt) {...! &ublic $Com&arableDstringE *ro& { get {...! set {...! ! &ublic int H(double d) {...!

El tipo del miembro a de una declaraci-n de clase gen)rica Sen es una Pmatri1 bidimensional de 1Q, por lo ?ue el tipo del miembro a del tipo construido mencionado anteriormente es una Pmatri1 bidimensional de una matri1 unidimensional de intQ o int4 545. 2entro de los miembros de 0unci-n de instancia, el tipo de t"is es el tipo de instancia O[1".3.1R de la declaraci-n contenedora. Todos los miembros de una clase gen)rica pueden utili1ar par(metros de tipo de cual?uier clase envolvente, ya sea directamente o como parte de un tipo construido. Cuando un tipo construido cerrado concreto O[4.4.2R se utili1a en tiempo de e$ecuci-n, cada uso de un par(metro de tipo se reempla1a con el argumento de tipo real suministrado al tipo construido. 'or e$emploG
class CDUE { &ublic U -2; &ublic CDUE -8 + null; &ublic C(U #) { t"is.-2 + #; t"is.-8 + t"is; ! ! class '&&lication { static void Main() { CDintE #2 + ne, CDintE(2); Console.WriteLine(#2.-2);

.. *rints 2

CDdoubleE #8 + ne, CDdoubleE(9.2J2K); Console.WriteLine(#8.-2); .. *rints 9.2J2K ! !

10.3.3 Herencia 7na clase hereda los miembros de su tipo de clase base directa. 8a =erencia signi0ica ?ue una clase contiene impl5citamente todos los miembros de su tipo de clase base directa, excepto los constructores de instancia, los constructores est(ticos y los destructores de la clase base. Estos son algunos aspectos importantes de la =erenciaG 8a =erencia es transitiva. .i C se deriva de : y : se deriva de ', entonces C =ereda los miembros declarados en : y los miembros declarados en '.

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

2""

Especificacin del lenguaje C#

7na clase derivada e2tiende su clase base directa. 7na clase derivada puede agregar nuevos miembros a los =eredados, pero no puede ?uitar la de0inici-n de un miembro =eredado. 8os constructores de instancia, los constructores est(ticos y los destructores no se =eredan, pero el resto de miembros s5, independientemente de la accesibilidad ?ue tengan declarada O[3. R. .in embargo, dependiendo de la accesibilidad ?ue tengan declarada, es posible ?ue los miembros =eredados no sean accesibles en una clase derivada. 7na clase derivada puede oc!ltar O[3.*.1.2R miembros =eredados declarando nuevos miembros con el mismo nombre o 0irma. 4o obstante, tenga en cuenta ?ue ocultar un miembro =eredado no signi0ica ?uitarlo, simplemente =ace ?ue el miembro no sea directamente accesible a trav)s de la clase derivada.

3''

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

7na instancia de una clase contiene un con$unto de todos los campos de instancia declarados en la clase y en sus clases base y se produce una conversi-n impl5cita O[#.1.#R de los tipos de la clase derivada a cual?uiera de los tipos de su clase base. 7na re0erencia a una instancia de una clase derivada puede ser tratada como re0erencia a una instancia de cual?uiera de sus clases base. 7na clase puede declarar m)todos, propiedades e indi1adores virtuales, y las clases derivadas invalidan la implementaci-n de dic=os miembros de 0unci-n. Esto permite ?ue las clases muestren un comportamiento polim-r0ico, ya ?ue las acciones ?ue reali1a una llamada a un miembro de 0unci-n var5an segHn el tipo de instancia a trav)s de la ?ue se invoca al miembro de 0unci-n en tiempo de e$ecuci-n. El miembro =eredado de un tipo de clase construido son los miembros del tipo de clase base inmediato O[1".1.4.1R, ?ue se =alla al sustituir los argumentos de tipo del tipo construido en cada ocurrencia de los par(metros de tipo correspondientes en la especi0icaci-n de clase base O-ase-class-specificationR. & su ve1, estos miembros se trans0orman mediante la sustituci-n en cada par(metro de tipo Ot#pe-para%eterR dentro de la declaraci-n de miembro, del argumento de tipo Ot#pe-ar& %entR correspondiente de la especi0icaci-n de clase base O-ase-class-specificationR.
class :D;E { &ublic ; V(long inde#) {...! ! class 6D1E/ :D145E { &ublic 1 S(string s) {...! !

En el e$emplo anterior, el tipo construido 6DintE tiene un miembro no =eredado &ublic int S(string s) ?ue se obtiene sustituyendo el argumento de tipo int para el par(metro de tipo 1. 6DintE tambi)n tiene un miembro =eredado de la declaraci-n de clase :. Este miembro =eredado se determina de0iniendo primero el tipo de clase base :Dint45E de 6DintE mediante la sustituci-n de int para 1 en la especi0icaci-n de clase base :D145E. & continuaci-n, como argumento de tipo para :, int45 se sustituye para ; en &ublic ; V(long inde#), produciendo el miembro =eredado &ublic int45 V(long inde#). 10.3.! &odificador 1e@ 7na declaraci-n de miembro de clase Oclass-%e%-er-declarationR puede declarar un miembro con el mismo nombre o 0irma ?ue el de un miembro =eredado. Cuando esto ocurre, se dice ?ue el miembro de la clase derivada oc!lta el miembro de la clase base. /cultar un miembro =eredado no se considera un error, pero =ace ?ue el compilador emita una advertencia. 'ara suprimir la advertencia, la declaraci-n del miembro de la clase derivada puede incluir un modi0icador ne, para indicar ?ue el miembro derivado pretende ocultar el miembro base. Este tema se explica con m(s detalle en la secci-n [3.*.1.2. .i se incluye un modi0icador ne, en una declaraci-n ?ue no oculta un miembro =eredado, se emite una advertencia a tal e0ecto. Esta advertencia se evita ?uitando el modi0icador ne,. 10.3.# &odificadores de acceso 7na declaraci-n de miembro de clase Oclass-%e%-er-declarationR puede tener uno de los cinco posibles tipos de accesibilidad declarada O[3. .1RG &ublic, &rotected internal, &rotected, internal o &rivate. Excepto en la combinaci-n &rotected internal, especi0icar m(s de un modi0icador de acceso produce un error en tiempo de compilaci-n. Cuando una declaraci-n de miembro de clase Oclass-%e%-er-declarationR no incluye ningHn modi0icador de acceso, se supone ?ue es &rivate.

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

3'1

Especificacin del lenguaje C#

10.3.$ Tipos constituyentes 8os tipos ?ue se utili1an en la declaraci-n de un miembro se denominan tipos constituyentes del miembro. 8os posibles tipos constituyentes son los tipos de una constante, de un campo, de una propiedad, de un evento o de un indi1ador, el tipo de valor devuelto de un m)todo u operador y los tipos de los par(metros de un m)todo, indi1ador, operador o constructor de instancia. 8os tipos constituyentes de un miembro deben ser al menos tan accesibles como el propio miembro O[3. .4R. 10.3.+ &iembros est)ticos y de instancia 8os miembros de una clase son ie /ros est5ticos o ie /ros de instancia. En t)rminos generales, se podr5a decir ?ue los miembros est(ticos pertenecen a los tipos de clases y los miembros de instancia pertenecen a los ob$etos Oinstancias de tipos de clasesR. Cuando la declaraci-n de un campo, m)todo, propiedad, evento, operador o constructor incluye un modi0icador static, est( declarando un miembro est(tico. 7na declaraci-n de constante o tipo declara impl5citamente un miembro est(tico. 8os miembros est(ticos tienen las siguientes caracter5sticasG Cuando un acceso a miembro O%e%-er-accessR =ace re0erencia a un miembro est(tico M O[*. .4R con la estructura ).M, ) debe denotar un tipo ?ue contenga M. .i ) denota una instancia, se produce un error en tiempo de compilaci-n. 7n campo est(tico identi0ica de manera exacta una ubicaci-n de almacenamiento para ?ue sea compartida por todas las instancias de un tipo de clase cerrado dado. !ndependientemente del nHmero de instancias ?ue se creen de un tipo de clase cerrad determinado, s-lo =abr( una copia de un campo est(tico. 7n miembro de 0unci-n est(tico Om)todo, propiedad, evento, operador o constructorR no opera en una instancia espec50ica, y se produce un error en tiempo de compilaci-n si se =ace re0erencia a t"is en dic=o miembro de 0unci-n.

Cuando la declaraci-n de un campo, m)todo, propiedad, evento, indi1ador, constructor o destructor no incluye un modi0icador static, est( declarando un miembro de instancia Olos miembros de instancia se conocen tambi)n como miembros no est(ticosR. 8os miembros de instancia tienen las siguientes caracter5sticasG Cuando un acceso a miembro O%e%-er-accessR =ace re0erencia a un miembro de instancia M O[*. .4R con la estructura ).M, ) debe denotar una instancia de un tipo ?ue contenga M. .i ) denota un tipo, se produce un error en tiempo de compilaci-n. Cada instancia de una clase contiene un con$unto independiente de todos los campos de instancia de la clase. 7n miembro de 0unci-n de instancia Om)todo, propiedad, indi1ador, constructor de instancia o destructorR opera en una determinada instancia de la clase y es posible tener acceso a dic=a instancia con t"is O[*. .*R.
class 1est { int #; static int y; void V() { # + 2; y + 2; ! .. %( .. %( same as t"is.# + 2 same as 1est.y + 2

En el e$emplo siguiente se ilustran las reglas para el acceso a miembros est(ticos y de instanciaG

static void S() { # + 2; .. )rror cannot access t"is.# y + 2; .. %( same as 1est.y + 2 !

3'2

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases static void 1est t + t.# + 2; t.y + 2; 1est.# + 1est.y + ! ! Main() { ne, 1est(); .. %( .. )rror 2; .. )rror 2; .. %(

cannot access static member t"roug" instance cannot access instance member t"roug" ty&e

El m)todo V muestra ?ue se puede utili1ar un nombre simple Osi%ple-na%eR O[*. .2R en un miembro de 0unci-n de instancia para tener acceso tanto a miembros de instancia como a miembros est(ticos. El m)todo S muestra ?ue en un miembro de 0unci-n est(tico, se produce un error en tiempo de compilaci-n si se obtiene acceso a un miembro de instancia a trav)s de un nombre simple Osi%ple-na%eR. El m)todo Main muestra ?ue en un acceso de miembro O%e%-er-accessR O[*. .4R, se deben utili1ar instancias para tener acceso a los miembros de instancia y tipos para tener acceso a los miembros est(ticos. 10.3.- Tipos anidados 7n tipo declarado dentro de una declaraci-n de estructura o clase se denomina tipo anidado. 7n tipo declarado dentro de una unidad de compilaci-n o de un espacio de nombres se denomina tipo no anidado. En el e$emplo
using System; class ' { class : { static void V() { Console.WriteLine("'.:.V"); ! ! !

la clase : es un tipo anidado por?ue se declara dentro de la clase ' y la clase ' es un tipo no anidado por?ue se declara dentro de una unidad de compilaci-n. 17.3.+.1 Eombre completo El nombre completo O[3.8.1R de un tipo anidado es S.N, donde S es el nombre completo del tipo en el ?ue se declara el tipo N. 17.3.+.2 Fccesibilidad declarada 8os tipos no anidados pueden tener accesibilidad declarada &ublic o internal, aun?ue la accesibilidad declarada predeterminada es internal. 8os tipos anidados tambi)n pueden tener esas mismas 0ormas de accesibilidad declarada y otras adicionales, en 0unci-n de si el tipo ?ue los contiene es una clase o una estructuraG 7n tipo anidado declarado en una clase puede tener cual?uiera de las cinco 0ormas de accesibilidad declarada O&ublic, &rotected internal, &rotected, internal o &rivateR y, como en otros miembros de clase, la 0orma predeterminada es &rivate. 7n tipo anidado declarado en una estructura puede tener cual?uiera de las 0ormas de accesibilidad declarada &ublic, internal o &rivate y, como en otros miembros de estructura, la 0orma predeterminada es &rivate.

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

3'3

Especificacin del lenguaje C#

El e$emplo
&ublic class List { .. *rivate data structure &rivate class Node { &ublic object 6ata; &ublic Node Ne#t; &ublic Node(object data t"is.6ata + data; t"is.Ne#t + ne#t; ! ! &rivate Node -irst + null; &rivate Node last + null; .. *ublic inter-ace &ublic void 'dd1oVront(object o) {...! &ublic void 'dd1o:ac((object o) {...! &ublic object OemoveVromVront() {...! &ublic object OemoveVrom:ac(() {...! &ublic int Count { get {...! ! ! Node ne#t) {

declara una clase anidada privada denominada Node. 17.3.+.3 'cultar 7n tipo anidado puede ocultar O[3.*.1R un miembro de base. Est( permitido utili1ar el modi0icador ne, en las declaraciones de tipos anidados, por lo ?ue dic=a ocultaci-n se puede expresar expl5citamente. En el e$emplo
using System; class :ase { &ublic static void M() { Console.WriteLine(":ase.M"); ! ! class 6erived/ :ase { ne, &ublic class M { &ublic static void V() { Console.WriteLine("6erived.M.V"); ! ! ! class 1est { static void Main() { 6erived.M.V(); ! !

se muestra una clase anidada M ?ue oculta el m)todo M de0inido en :ase.

3'#

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

17.3.+.4 Fcceso t-is 7n tipo anidado y el tipo ?ue lo contiene no tienen una relaci-n especial con respecto al acceso t=is Othis-accessR O[*. .*R. En concreto, no se puede utili1ar t"is dentro de un tipo anidado para =acer re0erencia a miembros de instancia del tipo ?ue lo contiene. En los casos en los ?ue un tipo anidado necesite tener acceso a los miembros de instancia del tipo contenedor, se puede utili1ar t"is para la instancia del tipo contenedor como argumento de constructor del tipo anidado. El siguiente e$emplo
using System; class C { int i + 289; &ublic void V() { Nested n + ne, Nested(t"is); n.S(); ! &ublic class Nested { C t"is\c; &ublic Nested(C c) { t"is\c + c; ! &ublic void S() { Console.WriteLine(t"is\c.i); ! ! ! class 1est { static void Main() { C c + ne, C(); c.V(); ! !

muestra esta t)cnica. 7na instancia de C crea una instancia de Nested y pasa su propio t"is al constructor de Nested para proporcionar acceso posterior a los miembros de instancia de C. 17.3.+. Fcceso a miembros privados y prote"idos del tipo contenedor 7n tipo anidado tiene acceso a todos los miembros accesibles a su tipo contenedor, incluyendo miembros ?ue tienen accesibilidad declarada &rivate o &rotected. En el e$emplo
using System; class C { &rivate static void V() { Console.WriteLine("C.V"); ! &ublic class Nested { &ublic static void S() { V(); ! ! !

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

3'!

Especificacin del lenguaje C# class 1est { static void Main() { C.Nested.S(); ! !

se muestra una clase C ?ue contiene una clase anidada Nested. 2entro de Nested, el m)todo S llama al m)todo est(tico V de0inido en C, y V tiene accesibilidad declarada privada. 7n tipo anidado tambi)n puede tener acceso a miembros protegidos de0inidos en un tipo de base de su tipo contenedor. En el e$emplo
using System; class :ase { &rotected void V() { Console.WriteLine(":ase.V"); ! ! class 6erived/ :ase { &ublic class Nested { &ublic void S() { 6erived d + ne, 6erived(); d.V(); .. o( ! ! ! class 1est { static void Main() { 6erived.Nested n + ne, 6erived.Nested(); n.S(); ! !

la clase anidada 6erived.Nested obtiene acceso al m)todo protegido V de0inido en la clase base de 6erived, :ase, llamando a trav)s de una instancia de 6erived. 17.3.+.6 :ipos anidados en clases "enricas 7na declaraci-n de clase gen)rica puede contener declaraciones de tipo anidado. 8os par(metros de tipo de la clase envolvente se pueden utili1ar dentro de los tipos anidados. 7na declaraci-n de tipo anidado puede contener par(metros de tipo adicionales ?ue s-lo se apli?uen al tipo anidado. Cada declaraci-n de tipo contenida dentro de una declaraci-n de clase gen)rica es impl5citamente una declaraci-n de tipo gen)rico. Cuando se escribe una re0erencia en un tipo anidado dentro de un tipo gen)rico, debe enumerarse el tipo construido contenedor y sus argumentos de tipo. .in embargo, desde dentro de la clase exterior, el tipo anidado se puede utili1ar sin cuali0icaci-nV el tipo de instancia de la clase exterior se puede utili1ar impl5citamente al construir el tipo anidado. En el siguiente e$emplo se muestran tres maneras di0erentes de =acer re0erencia a un tipo construido creado desde $nnerV los dos primeros son e?uivalentesG
class %uterD1E { class $nnerD;E { &ublic static void V(1 t !

; u) {...!

3'6

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases static void V(1 t) { %uterD1E.$nnerDstringE.V(t $nnerDstringE.V(t "abc"); %uterDintE.$nnerDstringE.V(9 %uter.$nnerDstringE.V(t ! !

"abc"); "abc");

.. 1"ese t,o statements "ave .. t"e same e--ect .. 1"is ty&e is di--erent .. )rror %uter needs ty&e arg

"abc");

&un?ue el estilo de programaci-n no es correcto, un par(metro de tipo en un tipo anidado puede ocultar un par(metro de miembro o de tipo en el tipo externoG
class %uterD1E { class $nnerD1E { &ublic 1 t; ! ! .. Ualid "ides %uter_s 1

.. Oe-ers to $nner_s 1

10.3.. 1ombres de miembro reser ados 'ara 0acilitar la implementaci-n subyacente de C# en tiempo de e$ecuci-n, la implementaci-n, para cada declaraci-n de miembro del c-digo 0uente ?ue sea una propiedad, un evento o un indi1ador, debe reservar dos 0irmas de m)todos basadas en el tipo de la declaraci-n de miembro, su nombre y su tipo. .e produce un error en tiempo de compilaci-n cuando un programa declara un miembro cuya 0irma coincida con una de estas 0irmas reservadas, incluso aun?ue la implementaci-n subyacente en tiempo de e$ecuci-n no =aga uso de dic=as reservas. 8os nombres reservados no presentan declaraciones, por lo ?ue no intervienen en la bHs?ueda de miembros. .in embargo, las 0irmas de m)todos reservados asociados a una declaraci-n s5 intervienen en la =erencia O[1".3.3R y pueden ser ocultados por el nuevo modi0icador O[1".3.4R. 8a reserva de estos nombres tiene tres prop-sitosG 'ermitir ?ue la implementaci-n subyacente utilice un identi0icador normal como nombre de m)todo para obtener o establecer el acceso a la caracter5stica del lengua$e C#. 'ermitir la interoperabilidad con otros lengua$es utili1ando un identi0icador normal como nombre de m)todo para obtener o establecer el acceso a la caracter5stica del lengua$e C#. &segurar ?ue el c-digo 0uente aceptado por un compilador compatible tambi)n es aceptado por otros compiladores, =aciendo ?ue las especi0icaciones de nombres de miembros reservados sean consistentes a trav)s de todas las implementaciones de C#.

8a declaraci-n de un destructor O[1".13R tambi)n causa la reserva de una 0irma O[1".3.+.4R. 17.3.5.1 Eombres de miembros reservados para propiedades 'ara una propiedad * O[1".*R de tipo 1, se reservan las siguientes 0irmasG
1 get\*(); void set\*(1 value);

.e reservan ambas 0irmas, tanto si la propiedad es de s-lo lectura como de s-lo escritura. En el e$emplo
using System;

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

3'(

Especificacin del lenguaje C# class ' { &ublic int * { get { return 289; ! ! ! class :/ ' { ne, &ublic int get\*() { return JKX; ! ne, &ublic void set\*(int value) { ! ! class 1est { static void Main() { : b + ne, :(); ' a + b; Console.WriteLine(a.*); Console.WriteLine(b.*); Console.WriteLine(b.get\*()); ! !

una clase ' de0ine una propiedad de s-lo lectura *, reservando as5 las 0irmas para los m)todos get\* y set\*. 7na clase : se deriva de ' y oculta ambas 0irmas reservadas. El e$emplo produce el resultadoG
289 289 JKX

17.3.5.2 Eombres de miembros reservados para eventos 'ara un evento ) O[1".8R de tipo delegado 1, se reservan las siguientes 0irmasG
void add\)(1 "andler); void remove\)(1 "andler);

17.3.5.3 Eombres de miembros reservados para indi%adores 'ara un indi1ador O[1".+R de tipo 1 con la lista de par(metros L, se reservan las siguientes 0irmasG
1 get\$tem(L); void set\$tem(L 1 value);

.e reservan ambas 0irmas, tanto si el indi1ador es de s-lo lectura como de s-lo escritura. &dem(s, se reserva el nombre de miembro $tem. 17.3.5.4 Eombres de miembros reservados para destructores 'ara una clase ?ue contiene un destructor O[1".13R, se reserva la siguiente 0irmaG
void Vinali?e();

10.! %onstantes
7na constante es un miembro de clase ?ue representa un valor constanteG un valor ?ue puede calcularse en tiempo de compilaci-n. 7na declaraci-n de constante Oconstant-declarationR especi0ica una o varias constantes de un determinado tipo.

3'$

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

constant-declaration1 attri- tesopt constant-%odifiersopt const t#pe constant-declarators ; constant-%odifiers1 constant-%odifier constant-%odifiers constant-%odifier constant-%odifier1
ne, &ublic &rotected internal &rivate

constant-declarators1 constant-declarator constant-declarators

constant-declarator

constant-declarator1 identifier @ constant-e2pression 7na declaraci-n de constante Oconstant-declarationR puede incluir un con$unto de atributos Oattri- tesR O[1*R, un modi0icador ne, O[1".3.4R y una combinaci-n v(lida de los cuatro modi0icadores de acceso O[1".3. R. 8os atributos y modi0icadores se aplican a todos los miembros declarados en la declaraci-n de constante OconstantdeclarationR. &un?ue las constantes se consideran miembros est(ticos, una declaraci-n de constante OconstantdeclarationR no necesita ni permite un modi0icador static. Cuando el mismo modi0icador aparece varias veces en una declaraci-n de constante, se produce un error. El tipo Ot#peR de una declaraci-n de constante Oconstant-declarationR especi0ica el tipo de los miembros ?ue se incluyen en la declaraci-n. El tipo va seguido de una lista de declaradoresBdeBconstante Oconstant-declaratorsR, cada uno de los cuales incluye un nuevo miembro. 7n declarador de constante Oconstant-declaratorR consta de un identi0icador OidentifierR ?ue da nombre al miembro, seguido del s5mbolo Oto6enR P+Q y de una expresi-n constante Oconstant-e2pressionR O[*.18R ?ue establece el valor del miembro. El tipo Ot#peR especi0icado en una declaraci-n de constante debe ser sbyte, byte, s"ort, us"ort, int, uint, long, ulong, c"ar, -loat, double, decimal, bool, string, un tipo de enumeraci-n Oen %-t#peR, o un tipo de re0erencia Oreference-t#peR. Cada expresi-n constante Oconstant-e2pressionR debe dar un valor del tipo destino o de un tipo ?ue se pueda convertir al tipo destino mediante una conversi-n impl5cita O[#.1R. El tipo Ot#peR de una constante debe ser al menos tan accesible como la propia constante O[3. .4R. 'ara obtener el valor de una constante en una expresi-n se utili1a un nombre simple Osi%ple-na%eR O[R o un acceso a miembro O%e%-er-accessR O[R. 7na constante puede participar en una expresi-n constante Oconstant-e2pressionR. 'or lo tanto, se puede utili1ar una constante en cual?uier constructor ?ue necesite una expresi-n constante. E$emplos de este tipo de constructores incluyen las eti?uetas case, instrucciones goto case, declaraciones de miembros enum, atributos y otras declaraciones de constantes. Como se describe en la [*.18, una expresi-n constante Oconstant-e2pressionR es una expresi-n ?ue se puede evaluar completamente en tiempo de compilaci-n. 'uesto ?ue la Hnica 0orma de crear un valor no nulo de un tipo de re0erencia Oreference-t#peR distinto de string es aplicar el operador ne,, y como el operador ne, no est( permitido en una expresi-n constante Oconstant-e2pressionR, el Hnico valor posible para las constantes de tipos de re0erencia Oreference-t#pesR distintos de string es null.

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

3'"

Especificacin del lenguaje C#

Cuando se desea un nombre simb-lico para un valor constante, pero el tipo del valor no se permite en una declaraci-n de constante, o cuando el valor no se puede calcular en tiempo de compilaci-n con una expresi-n constante Oconstant-e2pressionR, en su lugar puede utili1arse un campo readonly O[1". .2R. 7na declaraci-n de constante ?ue declara varias constantes e?uivale a varias declaraciones de una sola constante con los mismos atributos, los mismos modi0icadores y el mismo tipo. 'or e$emploG
class ' { &ublic const double I + 2.3 ! ` + 8.3 P + 9.3;

e?uivale a
class ' { &ublic const double I + 2.3; &ublic const double ` + 8.3; &ublic const double P + 9.3; !

Est( permitido ?ue las constantes dependan de otras constantes dentro del mismo programa, siempre y cuando las dependencias no sean circulares. El compilador evalHa autom(ticamente las declaraciones de constantes en el orden apropiado. En el e$emplo
class ' { &ublic const int I + :.P < 2; &ublic const int ` + 23; ! class : { &ublic const int P + '.` < 2; !

el compilador evalHa primero '.`, despu)s :.P y 0inalmente '.I, produciendo los valores 23, 22 y 28. 8as declaraciones de constantes pueden depender de constantes de otros programas, pero dic=as dependencias s-lo son posibles en una direcci-n. Haciendo re0erencia al e$emplo anterior, si ' y : 0ueran declaradas en programas independientes, ser5a posible ?ue '.I dependiera de :.P, pero entonces :.P no podr5a depender simult(neamente de '.`.

10.# %ampos
7n ca po es un miembro ?ue representa una variable asociada a un ob$eto o una clase. 7na declaraci-n de campo Ofield-declarationR especi0ica uno o varios campos de un determinado tipo. field-declaration1 attri- tesopt field-%odifiersopt t#pe varia-le-declarators ; field-%odifiers1 field-%odifier field-%odifiers field-%odifier

31'

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

field-%odifier1
ne, &ublic &rotected internal &rivate static readonly volatile

varia-le-declarators1 varia-le-declarator varia-le-declarators

varia-le-declarator

varia-le-declarator1 identificador identifier @ varia-le-initiali0er varia-le-initiali0er1 e2pression arra#-initiali0er 7na declaraci-n de campo Ofield-declarationR puede incluir un con$unto de atributos Oattri- tesR O[1*R, un modi0icador ne, O[1".3.4R, una combinaci-n v(lida de los cuatro modi0icadores de acceso O[1".3. R y un modi0icador static O[1". .1R. &dem(s, una declaraci-n de campo Ofield-declarationR puede incluir un modi0icador readonly O[1". .2R o un modi0icador volatile O[1". .3R pero no ambos. 8os atributos y modi0icadores se aplican a todos los miembros declarados en la declaraci-n de campo Ofield-declarationR. Es un error ?ue el mismo modi0icador apare1ca varias veces en una declaraci-n de campo. El tipo Ot#peR de una declaraci-n de campo Ofield-declarationR especi0ica el tipo de los miembros ?ue se incluyen en la declaraci-n. El tipo es seguido de una lista de declaradores de variable Ovaria-le-declaratorsR, cada uno de los cuales incluye un nuevo miembro. 7n declarador de variable Ovaria-le-declaratorR est( 0ormado por un identi0icador OidentifierR ?ue da nombre al miembro, ?ue opcionalmente puede ir seguido del s5mbolo Oto6enR P+Q y de un iniciali1ador de variable Ovaria-le-initiali0erR O[1". . R ?ue establece el valor inicial del miembro. El tipo Ot#peR de un campo debe ser al menos tan accesible como el propio campo O[3. .4R. 'ara obtener el valor de un campo en una expresi-n se utili1a un nombre simple Osi%ple-na%eR O[*. .2R o un acceso a miembro O%e%-er-accessR O[*. .4R. El valor de un campo ?ue no sea de s-lo lectura se modi0ica mediante una asignaci-n Oassi&n%entR O[*.1#R. El valor de un campo ?ue no sea de s-lo lectura se puede obtener y modi0icar utili1ando operadores de incremento y decremento post0i$os O[*. .+R, y operadores de incremento y decremento pre0i$os O[*.#. R. 7na declaraci-n de campo ?ue declara varios campos e?uivale a varias declaraciones de un Hnico campo con los mismos atributos, los mismos modi0icadores y el mismo tipo. 'or e$emploG
class ' { &ublic static int I + 2 ! ` P + 233;

e?uivale a
class ' { &ublic static int I + 2; &ublic static int `; &ublic static int P + 233; !

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

311

Especificacin del lenguaje C#

10.#.1 %ampos est)ticos y de instancia Cuando una declaraci-n de campo incluye un modi0icador static, los campos presentados en la declaraci-n son ca pos est5ticos. Cuando no existe un modi0icador static, los campos presentados en la declaraci-n son campos de instancia Oinstance fieldsR. 8os campos est(ticos y los campos de instancia son dos de los distintos tipos de variables O[ R compatibles con C# y en ocasiones se les llama varia/les est5ticas y varia/les de instancia, respectivamente. 7n campo est(tico no 0orma parte de una instancia espec50ica, sino ?ue es compartido entre todas las instancias de un tipo cerrado O[R. 4o importa cu(ntas instancias de un tipo de clase cerrado se creen, nunca =ay m(s de una copia de un campo est(tico para el dominio de aplicaci-n asociado. 'or e$emploG
class CDUE { static int count + 3; &ublic C() { count<<; ! &ublic static int Count { get { return count; ! ! ! class '&&lication { static void Main() { CDintE #2 + ne, CDintE(); Console.WriteLine(CDintE.Count); CDdoubleE #8 + ne, CDdoubleE(); Console.WriteLine(CDintE.Count); CDintE #9 + ne, CDintE(); Console.WriteLine(CDintE.Count); ! !

.. *rints 2 .. *rints 2 .. *rints 8

7n campo de instancia pertenece siempre a una instancia. 2e manera espec50ica, cada instancia de una clase contiene un con$unto independiente de todos los campos de instancia de la clase. Cuando se =ace re0erencia a un campo en un acceso a miembro O%e%-er-accessR O[*. .4R con la estructura ).M, si M es un campo est(tico, ) debe denotar un tipo ?ue contenga M, y si M es un campo de instancia, E debe denotar una instancia de un tipo ?ue contenga M. 8as di0erencias entre miembros est(ticos y de instancia se tratan con m(s detalle en [1".3.*. 10.#.2 %ampos de slo lectura Cuando una declaraci-n de campo Ofield-declaratioR incluye un modi0icador readonly, los campos presentados en la declaraci-n son campos de s,lo lect!ra. 8as asignaciones directas a campos de s-lo lectura Hnicamente pueden 0ormar parte de la declaraci-n, de un constructor de instancia o bien de un constructor est(tico de la misma clase. OEs posible asignar varias veces un campo de s-lo lectura en estos contextosR. En concreto, s-lo se permiten asignaciones directas a un campo readonly en las siguientes situacionesG En el declarador de variable Ovaria-le-declaratorR ?ue introduce la variableV mediante la inclusi-n de un iniciali1ador de variable Ovaria-le-initiali0erR en la declaraci-nR.

312

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

'ara un campo de instancia, en los constructores de instancia de la clase ?ue contiene la declaraci-n de campoV para un campo est(tico, en el constructor est(tico de la clase ?ue contiene la declaraci-n de campo. Zstos son tambi)n los Hnicos contextos en los ?ue es v(lido pasar un campo readonly como par(metro out o re-.

.e produce un error en tiempo de compilaci-n al intentar =acer una asignaci-n a un campo readonly o pasarlo como par(metro out o re- en cual?uier otro contexto. 17. .2.1 <tili%ar campos de slo lectura estticos para constantes 7n campo static readonly es Htil cuando se desea un nombre simb-lico para un valor constante, pero el tipo del valor no se permite en una declaraci-n const, o cuando el valor no se puede calcular en tiempo de compilaci-n. En el e$emplo
&ublic class Color { &ublic static readonly &ublic static readonly &ublic static readonly &ublic static readonly &ublic static readonly &rivate byte red green &ublic Color(byte r red + r; green + g; blue + b; ! ! Color Color Color Color Color :lac( + ne, Color(3 3 3); W"ite + ne, Color(8KK 8KK 8KK); Oed + ne, Color(8KK 3 3); Sreen + ne, Color(3 8KK 3); :lue + ne, Color(3 3 8KK); byte b) {

blue;

byte g

los miembros :lac(, W"ite, Oed, Sreen y :lue no pueden ser declarados como miembros const por?ue sus valores no se pueden calcular en tiempo de compilaci-n. .in embargo, produce el mismo e0ecto declararlos como static readonly. 17. .2.2 .ersiones de constantes y campos de slo lectura estticos 8as constantes y los campos de s-lo lectura tienen di0erentes sem(nticas para el control de versiones binarias. Cuando una expresi-n =ace re0erencia a una constante, el valor de la constante se obtiene en tiempo de compilaci-n, pero cuando una expresi-n =ace re0erencia a un campo de s-lo lectura, el valor del campo se obtiene en tiempo de e$ecuci-n. Considere una aplicaci-n ?ue conste de dos programas independientesG
using System; names&ace *rogram2 { &ublic class ;tils { &ublic static readonly int I + 2; ! ! names&ace *rogram8 { class 1est { static void Main() { Console.WriteLine(*rogram2.;tils.I); ! ! !

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

313

Especificacin del lenguaje C#

8os espacios de nombres *rogram2 y *rogram8 indican dos programas ?ue se compilan de 0orma independiente. 2ebido a ?ue el campo *rogram2.;tils.I se declara como de s-lo lectura est(tico, el resultado de la instrucci-n Console.WriteLine no se conoce en tiempo de compilaci-n, sino ?ue se obtiene en tiempo de e$ecuci-n. 'or lo tanto, si se cambia el valor de I y se vuelve a compilar *rogram2, la instrucci-n Console.WriteLine genera el nuevo valor aun?ue no se vuelva a compilar *rogram8. 4o obstante, si I =ubiera sido una constante, el valor de I se =abr5a obtenido al compilar *rogram8 y no se ver5a a0ectado por los cambios reali1ados en *rogram2 =asta ?ue se volviera a compilar *rogram8. 10.#.3 %ampos olatile Cuando una declaraci-n de campo Ofield-declarationR incluye un modi0icador volatile, los campos presentados en la declaraci-n son ca pos vol5tiles. 'ara los campos no vol(tiles, las t)cnicas de optimi1aci-n ?ue reordenan las instrucciones pueden dar resultados inesperados e impredecibles en programas multiproceso ?ue tengan acceso no sincroni1ado a campos, como los ?ue proporciona la instrucci-n loc6 Oloc3-state%entR O[8.12R. Estas optimi1aciones pueden ser reali1adas por el compilador, el sistema en tiempo de e$ecuci-n o el =ard9are. 'ara campos vol(tiles, tales optimi1aciones de reordenaci-n est(n restringidasG 8a lectura de los campos vol(tiles se denomina lect!ra vol5til. 7na lectura vol(til tiene Psem(ntica de ad?uisici-nQG est( garanti1ado ?ue se produce antes de cual?uier re0erencia a la memoria ?ue tenga lugar con posterioridad a ella en la secuencia de la instrucci-n. 8a escritura de campos vol(tiles se denomina escrit!ra vol5til. 7na escritura vol(til tiene Psem(ntica de liberaci-nQG est( garanti1ado ?ue se produce despu)s de cual?uier re0erencia a la memoria ?ue tenga lugar con anterioridad a la instrucci-n de escritura en la secuencia de la instrucci-n.

Estas restricciones aseguran ?ue todos los subprocesos reconocer(n las escrituras vol(tiles reali1adas por cual?uier otro subproceso en el orden en ?ue se reali1aron. 4o se re?uiere de una implementaci-n correcta ?ue proporcione una sola reordenaci-n total de las escrituras vol(tiles desde la perspectiva de todos los subprocesos de e$ecuci-n. El tipo de un campo vol(til debe ser uno de los siguientesG 7n tipo de re0erencia Oreference-t#peR. El tipo byte, sbyte, s"ort, us"ort, int, uint, c"ar, -loat, bool, System.$nt*tr o System.;$nt*tr. 7n tipo enum Oen %-t#peR con un tipo base enum de byte, sbyte, s"ort, us"ort, int o uint.
using System; using System.1"reading; class 1est { &ublic static int result; &ublic static volatile bool -inis"ed; static void 1"read8() { result + 2J9; -inis"ed + true; ! static void Main() { -inis"ed + -alse; .. Oun 1"read8() in a ne, t"read ne, 1"read(ne, 1"readStart(1"read8)).Start();

En el e$emplo

31#

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases .. Wait -or 1"read8 to signal t"at it "as a result by setting .. -inis"ed to true. -or (;;) { i- (-inis"ed) { Console.WriteLine("result + {3!" result); return; ! ! ! !

se genera el siguiente resultadoG


result + 2J9

En este e$emplo, el m)todo Main inicia un nuevo subproceso ?ue e$ecuta el m)todo 1"read8. Este m)todo almacena un valor en un campo no vol(til denominado result y a continuaci-n almacena true en el campo vol(til -inis"ed. El subproceso principal espera a ?ue se estable1ca el campo -inis"ed en true y, a continuaci-n, lee el campo result. 2ado ?ue se declar- -inis"ed como volatile, el subproceso principal debe leer el valor 2J9 del campo result. .i el campo -inis"ed no se =ubiera declarado como volatile, estar5a permitido ?ue la operaci-n de almacenamiento en result 0uese visible para el subproceso principal desp ?s del almacenamiento en -inis"ed, y por tanto tambi)n lo ser5a ?ue el subproceso principal leyese el valor 3 en el campo result. 2eclarar -inis"ed como un campo volatile impide tales inco=erencias. 10.#.! Iniciali8acin de campos El valor inicial de un campo, tanto si se trata de un campo est(tico como de un campo de instancia, es el valor predeterminado O[ .2R del tipo del campo. 4o es posible observar el valor de un campo antes de ?ue ocurra su iniciali1aci-n predeterminada y, por lo tanto, un campo nunca es Pdesiniciali1adoQ. El e$emplo
using System; class 1est { static bool b; int i; static void Main() { 1est t + ne, 1est(); Console.WriteLine("b + {3! ! !

i + {2!"

t.i);

produce el resultado
b + Valse i + 3

por?ue b e i se iniciali1an autom(ticamente a valores predeterminados. 10.#.# Iniciali8adores de ariables 8as declaraciones de campos pueden incluir iniciali1adores de variable Ovaria-le-initiali0ersR. En campos est(ticos, los iniciali1adores de variables corresponden a instrucciones de asignaci-n ?ue se e$ecutan durante la iniciali1aci-n de la clase. En campos de instancia, los iniciali1adores de variables corresponden a instrucciones de asignaci-n ?ue se e$ecutan cuando se crea una instancia de la clase. El e$emplo
using System;

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

31!

Especificacin del lenguaje C# class 1est { static double # + Mat".SQrt(8.3); int i + 233; string s + "Hello"; static void Main() { 1est a + ne, 1est(); Console.WriteLine("# + {3! ! !

i + {2!

s + {8!"

a.i

a.s);

produce el resultado
# + 2.J2J829KX89M92 i + 233 s + Hello

por?ue la asignaci-n de # se produce cuando se e$ecutan los iniciali1adores de campos est(ticos y las asignaciones a i y a s se producen cuando se e$ecutan los iniciali1adores de campos de instancia. 8a iniciali1aci-n al valor predeterminado descrita en [1". .4 ocurre para todos los campos, incluyendo campos ?ue tienen iniciali1adores de variables. 'or lo tanto, cuando se iniciali1a una clase, primero se iniciali1an todos sus campos est(ticos a sus valores predeterminados y, a continuaci-n, se e$ecutan los iniciali1adores de campos est(ticos en orden textual. !gualmente, cuando se crea una instancia de una clase, primero se iniciali1an todos sus campos de instancia a sus valores predeterminados y, a continuaci-n, se e$ecutan los iniciali1adores de campos de instancia en orden textual. Es posible observar campos est(ticos con iniciali1adores de variables en su estado de valor predeterminado. .in embargo, est( totalmente desaconse$ado por ra1ones de estilo. El e$emplo
using System; class 1est { static int a + b < 2; static int b + a < 2; static void Main() { Console.WriteLine("a + {3! ! ! b + {2!" a b);

expone este comportamiento. & pesar de las de0iniciones circulares de a y b, el programa es correcto. 2a como resultado
a + 2 b + 8

por?ue los campos est(ticos a y b se iniciali1an a 3 Oel valor predeterminado para intR antes de ?ue se e$ecuten sus iniciali1adores. Cuando se e$ecuta el iniciali1ador para a, el valor de b es cero y a se iniciali1a a 2. Cuando se e$ecuta el inciali1ador para b, el valor de a ya es 2 y b se iniciali1a a 8. 17. . .1 $niciali%acin de campos estticos 8os iniciali1adores de variable de un campo est(tico de una clase corresponden a una secuencia de asignaciones ?ue se e$ecutan en el orden textual en ?ue aparecen en la declaraci-n de la clase. .i en la clase existe un constructor est(tico O[1".12R, la e$ecuci-n de los iniciali1adores de campo est(tico se produce inmediatamente antes de la e$ecuci-n de tal constructor est(tico. En caso contrario, los iniciali1adores de campo est(tico se e$ecutan en un momento ?ue depende de la iniciali1aci-n y ?ue es anterior a la primera utili1aci-n de un campo est(tico de esta clase. El e$emplo
using System;

316

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases class 1est { static void Main() { Console.WriteLine("{3! {2!" ! &ublic static int V(string s) { Console.WriteLine(s); return 2; ! ! class ' { &ublic static int I + 1est.V("$nit '"); ! class : { &ublic static int ` + 1est.V("$nit :"); !

:.`

'.I);

podr5a producir el resultadoG


$nit ' $nit : 2 2

o el siguienteG
$nit : $nit ' 2 2

por?ue la e$ecuci-n de los iniciali1adores de I e ` puede producirse en cual?uier ordenV s-lo es imprescindible ?ue se produ1ca antes de las re0erencias a esos campos. 4o obstante, en el e$emplo
using System; class 1est { static void Main() { Console.WriteLine("{3! {2!" ! &ublic static int V(string s) { Console.WriteLine(s); return 2; ! ! class ' { static '() {! &ublic static int I + 1est.V("$nit '"); ! class : { static :() {! &ublic static int ` + 1est.V("$nit :"); !

:.`

'.I);

el resultado debe serG


$nit : $nit ' 2 2

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

31(

Especificacin del lenguaje C#

por?ue las reglas de e$ecuci-n de los constructores est(ticos Ocomo se de0ine en [1".12R dictan ?ue el constructor est(tico de : Oy por lo tanto, los iniciali1adores de campo est(tico de :R debe e$ecutarse antes ?ue el constructor est(tico de ' y sus iniciali1adores de campo. 17. . .2 $niciali%acin de campos de instancia 8os iniciali1adores de variable de un campo de instancia de una clase corresponden a una secuencia de asignaciones ?ue se e$ecutan inmediatamente al entrar en cual?uiera de los constructores de instancia O[1".11.1R de la clase. 8os iniciali1adores de variable se e$ecutan en el orden textual en ?ue aparecen en la declaraci-n de clase. El proceso de creaci-n e iniciali1aci-n de una instancia de clase se describe con m(s detalle en [1".11. 7n iniciali1ador de variable para un campo de instancia no puede =acer re0erencia a la instancia ?ue est( creando. 'or lo tanto, supone un error en tiempo de compilaci-n ?ue en un iniciali1ador de variable se =aga re0erencia a t"is o a un miembro de instancia mediante un nombre simple Osi%ple-na%eR. En el e$emplo
class ' { int # + 2; int y + # < 2; !

.. )rror

re-erence to instance member o- t"is

el iniciali1ador de variable para y produce un error en tiempo de compilaci-n por?ue =ace re0erencia a un miembro de la instancia ?ue se est( creando.

10.$ &*todos
7n 6todo es un miembro ?ue implementa un c(lculo o una acci-n ?ue puede reali1ar un ob$eto o una clase. 8os m)todos se declaran mediante declaraciones de m)todos O%ethod-declarationsRG %ethod-declaration1 %ethod-header %ethod--od# %ethod-header1 attri- tesopt %ethod-%odifiersopt &artialopt ret rn-t#pe %e%-er-na%e t#pe-para%eter-listopt ( for%al-para%eter-listopt ) t#pe-para%eter-constraints-cla sesopt %ethod-%odifiers1 %ethod-%odifier %ethod-%odifiers %ethod-%odifier %ethod-%odifier1
ne, &ublic &rotected internal &rivate static virtual sealed override abstract e#tern

ret rn-t#pe1 t#pe


void

31$

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

%e%-er-na%e1 identificador interface-t#pe . identificador %ethod--od#1 -loc3


;

7na declaraci-n de m)todo O%ethod-declarationR puede incluir un con$unto de atributos Oattri- tesR O[1*R y una combinaci-n v(lida de los cuatro modi0icadores de acceso O[1".3. R,ne, O[1".3.4R, static O[1".#.2R, virtual O[1".#.3R, override O[1".#.4R, sealed O[1".#. R, abstract O[1".#.#R y e#tern O[1".#.*R. 7na declaraci-n tiene una combinaci-n v(lida de modi0icadores si se cumplen las siguientes condicionesG 8a declaraci-n incluye una combinaci-n v(lida de modi0icadores de acceso O[1".3. R. 8a declaraci-n no incluye el mismo modi0icador varias veces. 8a declaraci-n incluye al menos uno de los modi0icadores siguientesG static, virtual y override. 8a declaraci-n incluye como m(ximo uno de los modi0icadores siguientesG ne, y override. .i la declaraci-n incluye el modi0icador abstract, no podr( incluir ninguno de los siguientes modi0icadoresG static, virtual, sealed o e#tern. .i la declaraci-n incluye el modi0icador &rivate, no podr( incluir ninguno de los siguientes modi0icadoresG virtual, override o abstract. .i la declaraci-n incluye el modi0icador sealed, tambi)n incluir( el modi0icador override. .i la declaraci-n incluye el modi0icador &artial, no podr( incluir ninguno de los siguientes modi0icadoresG ne,, &ublic, &rotected, internal, &rivate, virtual, sealed, override, abstract o e#tern.

El tipo de valor devuelto Oret rn-t#peR de una declaraci-n de m)todo especi0ica el tipo del valor calculado y devuelto por el m)todo. .i el m)todo no devuelve un valor, el tipo del valor devuelto Oret rn-t#peR es void. .i la declaraci-n incluye el modi0icador &artial, el tipo de valor devuelto tambi)n debe ser void. El nombre de miembro O%e%-er-na%eR especi0ica el nombre del m)todo. .alvo ?ue el m)todo sea una implementaci-n de miembro de inter0a1 expl5cita O[13.4.1R, el nombre de miembro O%e%-er-na%eR es simplemente un identi0icador OidentifierR. 'ara una implementaci-n de miembro de inter0a1 expl5cita, el nombre de miembro O%e%-er-na%eR consiste en un tipo de inter0a1 Ointerface-t#peR seguido de P.Q y un identi0icador OidentifierR. 8a lista de par(metros 0ormales Ot#pe-para%eter-listR opcional especi0ica los par(metros de tipo del m)todo O[1".1.3R. .i se especi0ica una lista de par(metros de tipo Ot#pe-para%eter-listR, el m)todo es un 6todo gen6rico. .i el m)todo tiene un modi0icador e#tern, no se puede especi0icar una lista de par(metros de tipo Ot#pe-para%eter-listR. 8a lista de par(metros 0ormales Ofor%al-para%eter-listR opcional especi0ica los par(metros del m)todo O[1".#.1R. 8as cl(usulas de restricciones de par(metros de tipo Ot#pe-para%eter-constraints-cla sesR opcionales especi0ican las restricciones en par(metros de tipo individuales O[1".1. R y s-lo se pueden especi0icar si se proporciona tambi)n una lista de par(metros de tipo Ot#pe-para%eter-listR, y el m)todo no tiene un modi0icador override.

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

31"

Especificacin del lenguaje C#

El tipo de valor devuelto Oret rn-t#peR y cada uno de los tipos a los ?ue se =ace re0erencia en la lista de par(metros 0ormales Ofor%al-para%eter-listR de un m)todo deben tener como m5nimo el mismo nivel de accesibilidad ?ue el m)todo O[3. .4R. 'ara los m)todos abstract y e#tern, el cuerpo del m)todo O%ethod--od#R consiste simplemente en un punto y coma. 'ara m)todos &artial el cuerpo del m)todo O%ethod--od#R puede consistir en un punto y coma o en un blo?ue O-loc3R. 'ara el resto de m)todos, el cuerpo del m)todo O%ethod--od#R consiste en un blo?ue O-loc3R ?ue especi0ica las instrucciones a e$ecutar cuando se invoca el m)todo. El nombre, la lista de par(metros de tipo y la lista de par(metros 0ormales de un m)todo de0inen la 0irma O[3.#R del m)todo. En concreto, la 0irma de un m)todo se compone del nombre del m)todo, el nHmero de par(metros de tipo y de modi0icadores, y los tipos de sus par(metros 0ormales. Con este 0in, todo par(metro de tipo del m)todo ?ue se produce en el tipo de un par(metro 0ormal se identi0ica no por su nombre, sino por su posici-n ordinal en la lista de argumentos de tipo del m)todo. El tipo de valor devuelto no es parte de la 0irma de un m)todo, ni los nombres de los par(metros de tipo o de los par(metros 0ormales. El nombre de un m)todo debe ser di0erente de los nombres del resto de miembros ?ue no sean m)todos declarados en la misma clase. &dem(s, la 0irma de un m)todo debe ser distinta de las 0irmas de todos los dem(s m)todos declarados en la misma clase, y dos m)todos declarados en la misma clase no pueden tener 0irmas ?ue s-lo se di0erencien por re- y out. 8os par(metros de tipo Ot#pe-para%etersR del m)todo se encuentran dentro del (mbito de la declaraci-n del m)todo O%ethod-declarationR y se pueden utili1ar para 0ormar tipos, en todo ese (mbito, en tipos de valores devueltos Oret rn-t#peR, cuerpos del m)todo O%ethod--od#R y cl(usulas de restricciones de par(metros de tipo Ot#pe-para%eter-constraints-cla sesR, pero no en atributos Oattri- tesR. Todos los par(metros 0ormales y par(metros de tipo deben tener nombres di0erentes. 10.$.1 (ar)metros de m*todos 8os par(metros de un m)todo, si existen, se declaran mediante la lista de par(metros 0ormales Ofor%alpara%eter-listR del m)todo. for%al-para%eter-list1 fi2ed-para%eters fi2ed-para%eters para%eter-arra# fi2ed-para%eters1 fi2ed-para%eter fi2ed-para%eters

para%eter-arra#

fi2ed-para%eter

fi2ed-para%eter1 attri- tesopt para%eter-%odifieropt t#pe identifier para%eter-%odifier1


reout t"is

para%eter-arra#1 attri- tesopt &arams arra#-t#pe identifier 8a lista de par(metros 0ormales consiste en uno o varios par(metros separados por comas de los cuales s-lo el Hltimo puede ser una matri1 de par(metros Opara%eter-arra#R. 7n par(metro de tipo 0i$ado Ofi2ed-para%eterR consiste en un con$unto opcional de atributos Oattri- tesR O[1*R, un modi0icador re-, out o t"is opcional, un tipo Ot#peR y un identi0icador OidentifierR. Cada par(metro de tipo

32'

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

0i$ado Ofi2ed-para%eterR declara un par(metro con el tipo y nombre especi0icados. El modi0icador t"is designa el m)todo como un m)todo de extensi-n y s-lo se permite en el primer par(metro de un m)todo est(tico. 8os m)todos de extensi-n se describen con m(s detalle en la secci-n [1".#.+. 7na matri1 de par(metros Opara%eter-arra#R consiste en un con$unto opcional de atributos Oattri- tesR O[1*R, un modi0icador &arams, un tipo de matri1 Oarra#-t#peR y un identi0icador OidentifierR. 7na matri1 de par(metros declara un Hnico par(metro con el tipo de matri1 y nombre especi0icados. El tipo de matri1 Oarra#-t#peR de una matri1 de par(metros debe ser unidimensional O[12.1R. Cuando se llama a un m)todo, la matri1 de par(metros permite especi0icar un Hnico argumento del tipo de matri1 dado, o cero o varios argumentos del tipo de elemento de matri1. 8as matrices de par(metros se describen m(s detalladamente en [1".#.1.4. 7na declaraci-n de m)todo crea un espacio de declaraci-n independiente para los par(metros, los par(metros de tipo y las variables locales. 8a lista de par(metros de tipo y la lista de par(metros 0ormales del m)todo, as5 como las declaraciones de variables locales en el blo?ue O-loc3R del m)todo introducen los nombres en ese espacio de declaraci-n. bue dos miembros de un espacio de declaraci-n del m)todo tengan el mismo nombre supone un error. bue el espacio de declaraci-n del m)todo y el espacio de declaraci-n de la variable local de un espacio de declaraci-n anidado contengan elementos con el mismo nombre supone un error. 8a invocaci-n de un m)todo O[*. . .1R crea una copia, espec50ica de esa invocaci-n, de los par(metros 0ormales y de las variables locales del m)todo, y la lista de argumentos de la invocaci-n asigna valores o re0erencias a variables a los par(metros 0ormales reci)n creados. 2entro del blo?ue O-loc3R de un m)todo, se puede =acer re0erencia a los par(metros 0ormales mediante sus identi0icadores en expresiones de nombre simple Osi%plena%eR O[*. .2R. Existen cuatro tipos de par(metros 0ormalesG 'ar(metros de valor, ?ue se declaran sin modi0icadores. 'ar(metros de re0erencia, ?ue se declaran con el modi0icador re-. 'ar(metros de salida, ?ue se declaran con el modi0icador out. %atrices de par(metros, ?ue se declaran con el modi0icador &arams.

Como se describe en [3.#, los modi0icadores re- y out 0orman parte de la 0irma de un m)todo, pero no el modi0icador &arams. 17.6.1.1 Parmetros de valor 7n par(metro declarado sin modi0icadores es un par(metro de valor. 7n par(metro de valor corresponde a una variable local ?ue obtiene su valor inicial del correspondiente argumento proporcionado en la invocaci-n del m)todo. Cuando un par(metro 0ormal es un par(metro de valor, el argumento correspondiente de la invocaci-n del m)todo debe ser una expresi-n de un tipo ?ue sea convertible impl5citamente O[#.1R al tipo del par(metro 0ormal. 7n m)todo puede asignar nuevos valores a un par(metro de valor. Tales asignaciones s-lo a0ectan a la ubicaci-n de almacenamiento local representada por el par(metro de valor, no tienen ningHn e0ecto sobre el argumento real de0inido en la invocaci-n del m)todo. 17.6.1.2 Parmetros de re3erencia 7n par(metro de re0erencia es un par(metro ?ue se declara con un modi0icador re-. & di0erencia de un par(metro de valor, un par(metro de re0erencia no crea una nueva ubicaci-n de almacenamiento. En lugar de ello, un par(metro de re0erencia representa la misma ubicaci-n de almacenamiento ?ue la variable especi0icada como argumento en la invocaci-n del m)todo.

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

321

Especificacin del lenguaje C#

Cuando un par(metro 0ormal es un par(metro de re0erencia, el argumento correspondiente de la invocaci-n del m)todo se debe componer de la palabra clave re- seguida de una re0erencia de variable Ovaria-le-referenceR O[ .3.3R del mismo tipo del par(metro 0ormal. 7na variable debe estar asignada de manera de0initiva antes de ?ue se pueda pasar como par(metro de re0erencia. 2entro de un m)todo, un par(metro de re0erencia siempre se considera asignado de manera de0initiva. 7n m)todo declarado como iterador O[1".14R no puede tener par(metros de re0erencia. El e$emplo
using System; class 1est { static void S,a&(re- int # int tem& + #; # + y; y + tem&; !

re- int y) {

static void Main() { int i + 2 j + 8; S,a&(re- i re- j); Console.WriteLine("i + {3! ! !

j + {2!"

j);

produce el resultado
i + 8 j + 2

'ara la invocaci-n de S,a& en Main, # representa a i e y representa a j. 'or lo tanto, la invocaci-n tiene el e0ecto de intercambiar los valores de i y de j. En un m)todo ?ue toma par(metros de re0erencia, varios nombres pueden representar la misma ubicaci-n de almacenamiento. En el e$emplo
class ' { string s; void s a b ! V(re- string a + "%ne"; + "1,o"; + "1"ree"; re- string b) {

void S() { V(re- s ! !

re- s);

la invocaci-n de V en S pasa una re0erencia a s para a y b. 2e esta 0orma, en esa invocaci-n, los nombres s, a y b =acen re0erencia todos ellos a la misma ubicaci-n de almacenamiento, y las tres asignaciones modi0ican el campo de instancia s. 17.6.1.3 Parmetros de salida 7n par(metro de salida es un par(metro ?ue se declara con un modi0icador out. &l igual ?ue un par(metro de re0erencia, un par(metro de salida no crea una nueva ubicaci-n de almacenamiento. En lugar de ello, un par(metro de salida representa la misma ubicaci-n de almacenamiento ?ue la variable especi0icada como argumento en la invocaci-n del m)todo.

322

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

Cuando un par(metro 0ormal es un par(metro de salida, el argumento correspondiente de la invocaci-n del m)todo se debe componer de la palabra clave out seguida de una re0erencia de variable Ovaria-le-referenceR O[ .3.3R del mismo tipo del par(metro 0ormal. 7na variable no necesita estar asignada de manera de0initiva antes de ser pasada como par(metro de salida, pero si se =ace un seguimiento de una invocaci-n donde se pas- una variable como par(metro de salida, la variable se considera asignada de manera de0initiva. 2entro de un m)todo, de manera similar a una variable local, un par(metro de salida se considera inicialmente no asignado y debe ser asignado de manera de0initiva antes de utili1ar su valor. Cada par(metro de salida de un m)todo debe estar asignado de manera de0initiva antes de ?ue el m)todo devuelva la llamada. 7n m)todo declarado como m)todo parcial O[R o un iterador O[R no puede tener par(metros de salida. 8os par(metros de salida se utili1an normalmente en m)todos ?ue devuelven varios valores. 'or e$emploG
using System; class 1est { static void S&lit*at"(string &at" out string dir out string name) { int i + &at".Lengt"; ,"ile (i E 3) { c"ar c" + &at"4i C 25; i- (c" ++ WZZW HH c" ++ W.W HH c" ++ W/W) brea(; i==; ! dir + &at".Substring(3 i); name + &at".Substring(i); ! static void Main() { string dir name; S&lit*at"("c/ZZWindo,sZZSystemZZ"ello.t#t" Console.WriteLine(dir); Console.WriteLine(name); ! !

out dir

out name);

El e$emplo produce el resultadoG


c/ZWindo,sZSystemZ "ello.t#t

/bserve ?ue las variables dir y name pueden estar sin asignar antes de pasar a S&lit*at", y ?ue se consideran asignadas de manera de0initiva siguiendo la llamada. 17.6.1.4 Matrices de parmetros 7n par(metro declarado con un modi0icador &arams es una matri1 de par(metros. .i una lista de par(metros 0ormales incluye una matri1 de par(metros, )sta debe ser el Hltimo par(metro de la lista y debe ser de tipo unidimensional. 'or e$emplo, los tipos string45 y string4545 se pueden utili1ar como tipo de una matri1 de par(metros, pero el tipo string4 5 no. 4o se puede combinar el modi0icador &arams con los modi0icadores re- y out. 7na matri1 de par(metros permite especi0icar argumentos en cual?uiera de las dos 0ormas de una invocaci-n de m)todoG El argumento especi0icado para una matri1 de par(metros puede ser una Hnica expresi-n de un tipo ?ue sea convertible impl5citamente O[#.1R al tipo de la matri1 de par(metros. En este caso, la matri1 de par(metros actHa exactamente como un par(metro de valor.

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

323

Especificacin del lenguaje C#

&lternativamente, la invocaci-n puede especi0icar cero o m(s argumentos para la matri1 de par(metros, donde cada argumento es una expresi-n de un tipo impl5citamente convertible O[#.1R al tipo de elemento de la matri1 de par(metros. En este caso, la invocaci-n crea una instancia del tipo de la matri1 de par(metros con una longitud correspondiente al nHmero de argumentos, iniciali1a los elementos de la instancia de matri1 con los valores de los argumentos especi0icados y utili1a la instancia de matri1 reci)n creada como argumento real.

Excepto en lo ?ue se re0iere a permitir un nHmero variable de argumentos en una invocaci-n, una matri1 de par(metros e?uivale exactamente a un par(metro de valor O[1".#.1.1R del mismo tipo. El e$emplo
using System; class 1est { static void V(&arams int45 args) { Console.Write("'rray contains {3! elements/" -oreac" (int i in args) Console.Write(" {3!" i); Console.WriteLine(); ! static void Main() { int45 arr + {2 8 9!; V(arr); V(23 83 93 J3); V(); ! !

args.Lengt");

produce el resultado
'rray contains 9 elements/ 2 8 9 'rray contains J elements/ 23 83 93 J3 'rray contains 3 elements/

8a primera invocaci-n de V simplemente pasa la matri1 a como un par(metro de valor. 8a segunda invocaci-n de V crea autom(ticamente una matri1 int45 de cuatro elementos con los valores de elemento especi0icados y pasa esa instancia de matri1 como par(metro de valor. 2el mismo modo, la tercera invocaci-n de V crea una matri1 int45 de cero elementos y pasa esa instancia como par(metro de valor. 8as invocaciones segunda y tercera e?uivalen exactamente a escribirG
V(ne, int45 {23 83 V(ne, int45 {!); 93 J3!);

Cuando se reali1a la resoluci-n de sobrecarga, un m)todo con una matri1 de par(metros puede ser aplicable en su 0orma normal o en su 0orma expandida O[*.4.3.1R. 8a 0orma expandida de un m)todo est( disponible s-lo si no es aplicable la 0orma normal del m)todo y Hnicamente cuando no est) declarado ya en el mismo tipo un m)todo con la misma 0irma ?ue la 0orma expandida. El e$emplo
using System; class 1est { static void V(&arams object45 a) { Console.WriteLine("V(object45)"); ! static void V() { Console.WriteLine("V()"); !

32#

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases static void V(object a3 object a2) { Console.WriteLine("V(object object)"); ! static void Main() { V(); V(2); V(2 8); V(2 8 9); V(2 8 9 J); ! !

produce el resultado
V(); V(object45); V(object object); V(object45); V(object45);

En el e$emplo, dos de las posibles 0ormas expandidas del m)todo con una matri1 de par(metros ya est(n incluidas en la clase como m)todos regulares. 'or lo tanto, estas 0ormas expandidas no son consideradas cuando se reali1a la resoluci-n de sobrecarga, y las invocaciones del primer y tercer m)todo seleccionan los m)todos regulares. Cuando una clase declara un m)todo con una matri1 de par(metros, se suelen incluir tambi)n algunas de las 0ormas expandidas como m)todos regulares. &s5 es posible evitar la asignaci-n de una instancia de matri1 ?ue se produce cuando se invoca una 0orma expandida de un m)todo con una matri1 de par(metros. Cuando el tipo de una matri1 de par(metros es object45, puede producirse una ambigIedad entre la 0orma normal del m)todo y la 0orma expandida para un Hnico par(metro object. 8a ra1-n de la ambigIedad es ?ue un tipo object45 es impl5citamente convertible al tipo object. 8a ambigIedad no representa un problema, ya ?ue se puede resolver insertando una conversi-n si es necesario. El e$emplo
using System; class 1est { static void V(&arams object45 args) { -oreac" (object o in args) { Console.Write(o.Set1y&e().VullName); Console.Write(" "); ! Console.WriteLine(); ! static void Main() { object45 a + {2 "Hello" object o + a; V(a); V((object)a); V(o); V((object45)o); ! ! 289.JKX!;

produce el resultado
System.$nt98 System.String System.6ouble System.%bject45 System.%bject45 System.$nt98 System.String System.6ouble

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

32!

Especificacin del lenguaje C#

En la primera y Hltima invocaci-n de V, la 0orma normal de V es aplicable por?ue existe una conversi-n impl5cita del tipo del argumento al tipo del par(metro Oambos son de tipo object45R. 'or lo tanto, la resoluci-n de sobrecarga selecciona la 0orma normal de V y el argumento se pasa como un par(metro de valor regular. En las invocaciones segunda y tercera, la 0orma normal de V no es aplicable por?ue no existe una conversi-n impl5cita del tipo del argumento al tipo del par(metro Oel tipo object no se puede convertir impl5citamente al tipo object45R. .in embargo, la 0orma expandida de V es aplicable, y por ello la selecciona la resoluci-n de sobrecarga. Como resultado, la invocaci-n crea una matri1 object45 de un elemento, y dic=o elemento de la matri1 se iniciali1a con el valor del argumento especi0icado O?ue a su ve1 es una re0erencia a un object45R. 10.$.2 &*todos est)ticos y de instancia Cuando una declaraci-n de m)todo incluye un modi0icador static, se dice ?ue el m)todo es est(tico. .i no existe un modi0icador static, se dice ?ue es un m)todo de instancia. 7n m)todo est(tico no opera en una instancia espec50ica, y se produce un error en tiempo de compilaci-n al =acer re0erencia a t"is en un m)todo est(tico. 7n m)todo de instancia opera en una determinada instancia de una clase y es posible tener acceso a dic=a instancia con t"is O[*. .*R. Cuando se =ace re0erencia a un m)todo en un acceso a miembro O%e%-er-accessR O[*. .4R con la estructura ).M, si M es un m)todo est(tico, ) debe denotar un tipo ?ue contenga M, y si M es un m)todo de instancia, ) debe denotar una instancia de un tipo ?ue contenga M. 8as di0erencias entre miembros est(ticos y de instancia se tratan con m(s detalle en [1".3.*. 10.$.3 &*todos irtuales Cuando una declaraci-n de m)todo de instancia incluye un modi0icador virtual, se dice ?ue el m)todo es un m)todo virtual. .i no existe un modi0icador virtual, se dice ?ue el m)todo es un m)todo no virtual. 8a implementaci-n de un m)todo no virtual es invariable. 8a implementaci-n es la misma tanto si se invoca un m)todo en una instancia de la clase en la ?ue se declar- o en una instancia de una clase derivada. En cambio, la implementaci-n de un m)todo virtual se puede sustituir por clases derivadas. El proceso de sustituci-n de la implementaci-n de un m)todo virtual =eredado es conocido como invalidaci,n del m)todo O[1".#.4R. En la invocaci-n de un m)todo virtual, el tipo en tie po de e1ec!ci,n de la instancia para la ?ue tiene lugar la invocaci-n determina la implementaci-n del m)todo real a invocar. Cuando se invoca a un m)todo no virtual, el 0actor determinante es el tipo en tie po de co pilaci,n de la instancia. Concretamente, cuando se invoca un m)todo denominado N con una lista de argumentos ' en una instancia con un tipo C en tiempo de compilaci-n y un tipo O en tiempo de e$ecuci-n Odonde O es C o una clase derivada de CR, la invocaci-n se procesa de la 0orma siguienteG En primer lugar, la resoluci-n de sobrecarga se aplica a C, N y ' para seleccionar un m)todo espec50ico M del con$unto de m)todos declarados en y =eredados por C. Esto se describe en la secci-n [*. . .1. & continuaci-n, si M es un m)todo no virtual, se invoca M. .i no, M es un m)todo virtual, y se invoca la implementaci-n m(s derivada de M con respecto a O.

'ara cada m)todo virtual ?ue se =a declarado en una clase o =eredado por ella, existe una i ple entaci,n 5s derivada del m)todo con respecto a esa clase. 8a implementaci-n m(s derivada de un m)todo virtual M con respecto a una clase O est( determinada de la siguiente maneraG .i O contiene la declaraci-n virtual de M, )sta es la implementaci-n m(s derivada de M. En caso contrario, si O contiene un override de M, )sta es la implementaci-n m(s derivada de M.

326

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

En caso contrario, la implementaci-n m(s derivada de M con respecto a O es la misma ?ue la implementaci-n m(s derivada de M con respecto a la clase base directa de O.
using System; class ' { &ublic void V() { Console.WriteLine("'.V"); ! &ublic virtual void S() { Console.WriteLine("'.S"); ! ! class :/ ' { ne, &ublic void V() { Console.WriteLine(":.V"); ! &ublic override void S() { Console.WriteLine(":.S"); ! ! class 1est { static void Main() { : b + ne, :(); ' a + b; a.V(); b.V(); a.S(); b.S(); ! !

En el siguiente e$emplo se ilustran las di0erencias entre los m)todos virtuales y los m)todos no virtualesG

En el e$emplo, ' un m)todo no virtual V y un m)todo virtual S. 8a clase : introduce un n evo m)todo no virtual V, con lo cual oc lta el m)todo V =eredado y adem(s invalida el m)todo S =eredado. El e$emplo produce el siguiente resultadoG
'.V :.V :.S :.S

/bserve ?ue la instrucci-n a.S() invoca a :.S, no a '.S. Esto se debe a ?ue el tipo en tiempo de e$ecuci-n de la instancia O?ue es :R, y no el tipo en tiempo de compilaci-n O?ue es 'R, determina la implementaci-n del m)todo real ?ue se invoca. 2ebido a ?ue se permite ?ue los m)todos oculten m)todos =eredados, es posible ?ue una clase contenga varios m)todos virtuales con la misma 0irma. Esto no presenta un problema de ambigIedad puesto ?ue todos los m)todos, salvo el m(s derivado, est(n ocultos. En el e$emplo
using System; class ' { &ublic virtual void V() { Console.WriteLine("'.V"); ! ! class :/ ' { &ublic override void V() { Console.WriteLine(":.V"); ! ! class C/ : { ne, &ublic virtual void V() { Console.WriteLine("C.V"); ! !

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

32(

Especificacin del lenguaje C# class 6/ C { &ublic override void V() { Console.WriteLine("6.V"); ! ! class 1est { static void Main() { 6 d + ne, 6(); ' a + d; : b + d; C c + d; a.V(); b.V(); c.V(); d.V(); ! !

las clases C y 6 contienen dos m)todos virtuales con la misma 0irmaG el ?ue introduce ' y el ?ue introduce C. El m)todo introducido por C oculta el m)todo ?ue se =ereda de '. 2e este modo, la declaraci-n override en 6 invalida el m)todo introducido por C, y no es posible ?ue 6 invalide el m)todo introducido por '. El e$emplo produce el resultadoG
:.V :.V 6.V 6.V

/bserve ?ue es posible invocar el m)todo virtual oculto mediante el acceso a una instancia de 6 a trav)s de un tipo menos derivado en el ?ue el m)todo no est( oculto. 10.$.! &*todos de in alidacin Cuando una declaraci-n de m)todo de instancia incluye un modi0icador override, se dice ?ue el m)todo es un 6todo de invalidaci,n. 7n m)todo de invalidaci-n invalida un m)todo virtual =eredado con la misma 0irma. %ientras ?ue una declaraci-n de m)todo virtual introd ce un m)todo nuevo, una declaraci-n de m)todo de invalidaci-n especiali0a un m)todo virtual =eredado existente proporcionando una nueva implementaci-n de ese m)todo. El m)todo invalidado por una declaraci-n override se conoce como 6todo /ase invalidado. 'ara un m)todo de invalidaci-n M declarado en una clase C, el m)todo base invalidado se determina examinando cada clase base de C, comen1ando con la clase base directa de C y continuando con cada una de las sucesivas clases base directas =asta ?ue, en un tipo de clase base dado se encuentre al menos un m)todo accesible ?ue tenga la misma 0irma ?ue M despu)s de la sustituci-n de los argumentos de tipo. 'ara encontrar el m)todo base invalidado, un m)todo se considera accesible si es &ublic, &rotected, &rotected internal o internal y est( declarado en el mismo programa ?ue C. .e produce un error en tiempo de compilaci-n a menos ?ue se cumplan todas las condiciones siguientes en una declaraci-n de invalidaci-nG .e puede encontrar un m)todo base invalidado como se =a descrito anteriormente. Existe exactamente ese m)todo base invalidado. Esta restricci-n tiene e0ecto s-lo si el tipo de la clase base es un tipo construido donde la sustituci-n de argumentos de tipo =ace ?ue las 0irmas de los dos m)todos sean id)nticas. El m)todo base invalidado es un m)todo virtual, abstracto o de invalidaci-n. En otras palabras, el m)todo base invalidado no puede ser est(tico ni no virtual. El m)todo base invalidado no es un m)todo sellado.


32$

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

8a declaraci-n de invalidaci-n y el m)todo base invalidado tienen el mismo tipo de valor devuelto. 8a declaraci-n de invalidaci-n y el m)todo base invalidado tienen la misma accesibilidad declarada. Es decir, una declaraci-n de invalidaci-n no puede cambiar la accesibilidad del m)todo virtual. .in embargo, si el m)todo base invalidado es protected OprotegidoR o internal OinternoR y est( declarado en un ensamblado di0erente del ensamblado ?ue contiene el m)todo de invalidaci-n, se debe proteger la accesibilidad declarada del m)todo de invalidaci-n. 8a declaraci-n de invalidaci-n no especi0ica cl(usulas de restricciones de par(metros de tipo. En lugar de eso, se =eredan las restricciones del m)todo base de invalidaci-n.
abstract class CD1E { &ublic virtual 1 V() {...! &ublic virtual CD1E S() {...! &ublic virtual void H(CD1E #) {...! ! class 6/ CDstringE { &ublic override string V() {...! &ublic override CDstringE S() {...! &ublic override void H(CD1E #) {...! ! class )D1 ;E/ CD;E { &ublic override ; V() {...! &ublic override CD;E S() {...! &ublic override void H(CD1E #) {...! !

En el siguiente e$emplo se muestra el 0uncionamiento de las reglas de invalidaci-n para clases gen)ricasG

.. %( .. %( .. )rror s"ould be CDstringE

.. %( .. %( .. )rror s"ould be CD;E

7na declaraci-n de invalidaci-n puede obtener acceso al m)todo base invalidado mediante un acceso base O-ase-accessR O[*. .8R. En el e$emplo
class ' { int #; &ublic virtual void *rintVields() { Console.WriteLine("# + {3!" #); ! ! class :/ ' { int y; &ublic override void *rintVields() { base.*rintVields(); Console.WriteLine("y + {3!" y); ! !

la invocaci-n de base.*rintVields() en : invoca al m)todo *rintVields declarado en '. 7n acceso base O-ase-accessR des=abilita el mecanismo de llamada virtual y simplemente trata el m)todo base como un m)todo no virtual. .i la llamada en : se =ubiera escrito ((')t"is).*rintVields(), invocar5a de 0orma recursiva el m)todo *rintVields declarado en :, no el declarado en ' ya ?ue *rintVields es virtual y el tipo en tiempo de e$ecuci-n de ((')t"is) es :.

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

32"

Especificacin del lenguaje C#

.-lo cuando un m)todo incluye un modi0icador override puede invalidar otro m)todo. En los dem(s casos, un m)todo con la misma 0irma ?ue un m)todo =eredado simplemente oculta el m)todo =eredado. En el e$emplo
class ' { &ublic virtual void V() {! ! class :/ ' { &ublic virtual void V() {! !

.. Warning

"iding in"erited V()

el m)todo V de : no incluye un modi0icador override y, por tanto, no invalida el m)todo V en '. En realidad, el m)todo V de : oculta el m)todo en ' y se emite una advertencia por?ue la declaraci-n no incluye un modi0icador ne,. En el e$emplo
class ' { &ublic virtual void V() {! ! class :/ ' { ne, &rivate void V() {! ! class C/ : { &ublic override void V() {! !

.. Hides '.V ,it"in body o- :

.. %(

overrides '.V

el m)todo V en : oculta el m)todo V virtual =eredado de '. Como el nuevo m)todo V de : tiene acceso privado, su (mbito s-lo incluye el cuerpo de la clase de : y no se extiende =acia C. 'or tanto, se permite la declaraci-n de V en C para invalidar el m)todo V ?ue =a =eredado de '. 10.$.# &*todos sellados Cuando una declaraci-n de m)todo de instancia incluye un modi0icador sealed, se dice ?ue el m)todo es un 6todo sellado OsealedR. .i una declaraci-n de m)todo de instancia incluye el modi0icador sealed, tambi)n debe incluir el modi0icador override. El uso del modi0icador sealed impide ?ue una clase derivada siga invalidando el m)todo. En el e$emplo
using System; class ' { &ublic virtual void V() { Console.WriteLine("'.V"); ! &ublic virtual void S() { Console.WriteLine("'.S"); ! ! class :/ ' { sealed override &ublic void V() { Console.WriteLine(":.V"); !

33'

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases override &ublic void S() { Console.WriteLine(":.S"); ! ! class C/ : { override &ublic void S() { Console.WriteLine("C.S"); ! !

la clase : proporciona dos m)todos de invalidaci-nG un m)todo V ?ue tiene el modi0icador sealed y un m)todo S ?ue no lo tiene. El uso en : del modi0icador Omodi-ierR sealed impide ?ue C siga invalidando V. 10.$.$ &*todos abstractos Cuando una declaraci-n de m)todo de instancia incluye un modi0icador abstract, se dice ?ue el m)todo es un 6todo a/stracto. &un?ue un m)todo abstracto es tambi)n impl5citamente un m)todo virtual, no puede tener el modi0icador virtual. 7na declaraci-n de m)todo abstracto introduce un nuevo m)todo virtual pero no proporciona una implementaci-n del m)todo. En cambio, es necesario ?ue las clases derivadas no abstractas proporcionen su propia implementaci-n mediante la invalidaci-n del m)todo. 2ebido a ?ue un m)todo abstracto no proporciona una implementaci-n real, el cuerpo del m)todo O%ethod--od#R de un m)todo abstracto consiste simplemente en un punto y coma. 8as declaraciones de m)todos abstractos s-lo se permiten en clases abstractas O[1".1.1.1R. En el e$emplo
&ublic abstract class S"a&e { &ublic abstract void *aint(Sra&"ics g ! &ublic class )lli&se/ S"a&e { &ublic override void *aint(Sra&"ics g g.6ra,)lli&se(r); ! ! &ublic class :o#/ S"a&e { &ublic override void *aint(Sra&"ics g g.6ra,Oect(r); ! ! Oectangle r);

Oectangle r) {

Oectangle r) {

la clase S"a&e de0ine la noci-n abstracta de un ob$eto de 0orma geom)trica ?ue puede dibu$arse a s5 mismo. El m)todo *aint es abstracto por?ue no existe una implementaci-n predeterminada signi0icativa. 8as clases )lli&se y :o# son implementaciones S"a&e concretas. Ka ?ue estas clases no son abstractas, son necesarias para invalidar el m)todo *aint y proporcionar una implementaci-n real. .upone un error en tiempo de compilaci-n ?ue un acceso base O-ase-accessR O[*. .8R =aga re0erencia a un m)todo abstracto. En el e$emplo
abstract class ' { &ublic abstract void V(); !

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

331

Especificacin del lenguaje C# class :/ ' { &ublic override void V() { base.V(); ! !

.. )rror

base.V is abstract

se produce un error en tiempo de compilaci-n en la llamada base.V() debido a ?ue =ace re0erencia a un m)todo abstracto. 7na declaraci-n de m)todo abstracto puede invalidar un m)todo virtual. Esto permite ?ue una clase abstracta 0uerce una nueva implementaci-n del m)todo en las clases derivadas, e impide la disponibilidad de la implementaci-n original del m)todo. En el e$emplo
using System; class ' { &ublic virtual void V() { Console.WriteLine("'.V"); ! ! abstract class :/ ' { &ublic abstract override void V(); ! class C/ : { &ublic override void V() { Console.WriteLine("C.V"); ! !

la clase ' declara un m)todo virtual, la clase : invalida este m)todo con un m)todo abstracto y la clase C invalida el m)todo abstracto para proporcionar su propia implementaci-n. 10.$.+ &*todos e"ternos Cuando una declaraci-n de m)todo incluye un modi0icador e#tern, se dice ?ue el m)todo es un 6todo e.terno. 8os m)todos externos se implementan externamente, utili1ando generalmente un lengua$e distinto de C#. 2ebido a ?ue la declaraci-n de un m)todo externo no proporciona una implementaci-n real, el cuerpo del m)todo O%ethod--od#R de un m)todo externo consiste simplemente en un punto y coma. 7n m)todo externo puede no ser gen)rico. El modi0icador e#tern se suele utili1ar $unto con el atributo 6ll$m&ort O[1*. .1R, permitiendo implementar los m)todos externos mediante Aibliotecas de v5nculos din(micos O.dllR. El entorno de e$ecuci-n puede ser compatible con otros mecanismos ?ue permitan las implementaciones de m)todos externos. Cuando un m)todo externo incluye un atributo 6ll$m&ort, la declaraci-n del m)todo tambi)n debe incluir el modi0icador static. En este e$emplo se demuestra el uso del modi0icador e#tern y del atributo 6ll$m&ortG
using System.1e#t; using System.Security.*ermissions; using System.Ountime.$ntero&Services; class *at" { 46ll$m&ort("(ernel98" SetLast)rror+true)5 static e#tern bool Create6irectory(string name 46ll$m&ort("(ernel98" SetLast)rror+true)5 static e#tern bool Oemove6irectory(string name);

Security'ttribute sa);

332

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases 46ll$m&ort("(ernel98" SetLast)rror+true)5 static e#tern int SetCurrent6irectory(int bu-Si?e

String:uilder bu-);

46ll$m&ort("(ernel98" SetLast)rror+true)5 static e#tern bool SetCurrent6irectory(string name); !

10.$.- &*todos parciales Cuando una declaraci-n de m)todo incluye un modi0icador &artial, se dice ?ue el m)todo es un 6todo parcial. 8os m)todos parciales s-lo se pueden declarar como tipos parciales O[1".2R, y est(n su$etos a un nHmero de restricciones. 8os m)todos parciales se describen con m(s detalles en la secci-n [1".2.*. 10.$.. &*todos de e"tensin Cuando el primer par(metro de un m)todo de instancia incluye un modi0icador t"is, se dice ?ue el m)todo es un 6todo a/stracto. 8os m)todos de extensi-n s-lo se pueden declarar en clases est(ticas no anidadas y no gen)ricas. El primer par(metro de un m)todo de extensi-n no puede tener ningHn modi0icador ?ue no sea t"is, y el tipo de par(metro no puede ser un tipo de puntero. En el siguiente e$emplo se muestra una clase est(tica ?ue declara dos m)todos de extensi-nG
&ublic static class )#tensions { &ublic static int 1o$nt98(t"is string s) { return $nt98.*arse(s); ! &ublic static 145 SliceD1E(t"is 145 source int inde# int count) { i- (inde# D 3 HH count D 3 HH source.Lengt" C inde# D count) t"ro, ne, 'rgument)#ce&tion(); 145 result + ne, 14count5; 'rray.Co&y(source inde# result 3 count); return result; ! !

7n m)todo de extensi-n es un m)todo est(tico regular. &dem(s, dentro del (mbito de su clase est(tica envolvente, es posible invocar un m)todo de extensi-n mediante una sintaxis de invocaci-n de m)todos de instancia O[*. . .2R, utili1ando la expresi-n del receptor como primer argumento. El siguiente programa utili1a los m)todos de extensi-n declarados antesG
static class *rogram { static void Main() { string45 strings + { "2" "88" "999" "JJJJ" !; -oreac" (string s in strings.Slice(2 8)) { Console.WriteLine(s.1o$nt98()); ! ! !

El m)todo .lice est( disponible en stringgh, y el m)todo To!nt32 est( disponible en string OcadenaR, por?ue se =an declarado como m)todos de extensi-n. El signi0icado del programa es igual ?ue el ?ue sigue, utili1ando llamadas a m)todos est(ticos ordinariosG

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

333

Especificacin del lenguaje C# static class *rogram { static void Main() { string45 strings + { "2" "88" "999" "JJJJ" !; -oreac" (string s in )#tensions.Slice(strings 2 Console.WriteLine()#tensions.1o$nt98(s)); ! ! !

8)) {

10.$.10 %uerpo del m*todo El cuerpo de m)todo O%ethod--od#R de una declaraci-n de m)todo consiste en un blo?ue O-loc3R o en un punto y coma. 8as declaraciones de m)todos abstractos y externos no proporcionan una implementaci-n del m)todo, por lo ?ue los cuerpos de estos m)todos son simplemente un punto y coma. 'ara el resto de m)todos, el cuerpo del m)todo es un blo?ue O[8.2R ?ue contiene las instrucciones a e$ecutar cuando se invoca el m)todo. Cuando el tipo de valor devuelto por un m)todo es void, no est( permitido ?ue las instrucciones return O[8.+.4R del cuerpo del m)todo especi0i?uen una expresi-n. .i la e$ecuci-n del cuerpo del m)todo de un m)todo void se completa normalmente Oes decir, el control llega al 0inal del cuerpo del m)todoR, el m)todo regresa al llamador. Cuando el tipo de valor devuelto por un m)todo no es void, cada instrucci-n return del cuerpo del m)todo debe especi0icar una expresi-n de un tipo convertible impl5citamente al tipo de valor devuelto. El 0inal del cuerpo de un m)todo ?ue devuelve un valor no debe ser alcan1able. En otras palabras, en los m)todos ?ue devuelven valores no est( permitido ?ue el control llegue al 0inal del cuerpo del m)todo. En el e$emplo
class ' { &ublic int V() {! &ublic int S() { return 2; ! &ublic int H(bool b) { i- (b) { return 2; ! else { return 3; ! ! ! .. )rror return value reQuired

el m)todo V ?ue devuelve un valor produce un error en tiempo de compilaci-n, por?ue el control puede alcan1ar el 0inal del cuerpo del m)todo. 8os m)todos S y H son correctos por?ue todos los caminos de e$ecuci-n posibles terminan en una instrucci-n return ?ue especi0ica un valor a devolver. 10.$.11 4obrecarga de m*todos 8as reglas de resoluci-n de sobrecarga de m)todos se describen en [*.4.2.

10.+ (ropiedades
7na propiedad es un miembro ?ue proporciona acceso a una caracter5stica de un ob$eto o una clase. 8os e$emplos de propiedades incluyen la longitud de una cadena, el tamaUo de una 0uente, el t5tulo de una ventana, el nombre de un cliente, etc. 8as propiedades son una extensi-n natural de los camposV ambos son miembros
33#
Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

denominados con tipos asociados, y la sintaxis ?ue se utili1a para el acceso a campos y propiedades es la misma. 4o obstante, a di0erencia de los campos, las propiedades no denotan ubicaciones de almacenamiento. 8as propiedades tienen descriptores de acceso ?ue especi0ican las instrucciones ?ue deben e$ecutarse para leer o escribir sus valores. 8as propiedades proporcionan un mecanismo para asociar acciones a la lectura y escritura de los atributos de un ob$eto. &dem(s, permiten el c(lculo de dic=os atributos. 8as propiedades se declaran mediante declaraciones de propiedad Opropert#-declarationsRG propert#-declaration1 attri- tesopt propert#-%odifiersopt t#pe %e%-er-na%e { accessor-declarations ! propert#-%odifiers1 propert#-%odifier propert#-%odifiers propert#-%odifier propert#-%odifier1
ne, &ublic &rotected internal &rivate static virtual sealed override abstract e#tern

%e%-er-na%e1 identificador interface-t#pe . identificador 7na declaraci-n de propiedad Opropert#-declarationR puede incluir un con$unto de atributos Oattri- tesR O[1*R y una combinaci-n v(lida de los cuatro modi0icadores de acceso O[1".3. R, los modi0icadores ne, O[1".3.4R, static O[1".#.2R, virtual O[1".#.3R, override O[1".#.4R, sealed O[1".#. R, abstract O[1".#.#R y e#tern O[1".#.*R. 8as declaraciones de propiedad est(n su$etas a las mismas reglas ?ue las declaraciones de m)todo O[1".#R en lo ?ue respecta a las combinaciones v(lidas de modi0icadores. El tipo Ot#peR de una declaraci-n de propiedad especi0ica el tipo de la propiedad introducida en la declaraci-n, y el nombre de miembro O%e%-er-na%eR especi0ica el nombre de la propiedad. .alvo ?ue la propiedad sea una implementaci-n de miembro de inter0a1 expl5cita, el nombre de miembro O%e%-er-na%eR es simplemente un identi0icador OidentifierR. 'ara una implementaci-n de miembro de inter0a1 expl5cita O[13.4.1R, el nombre de miembro O%e%-er-na%eR se compone de un tipo de inter0a1 Ointerface-t#peR seguido de P.Q y un identi0icador OidentifierR. El tipo Ot#peR de una propiedad debe ser al menos tan accesible como la misma propiedad O[3. .4R. 8as declaraciones de descriptores de acceso Oaccessor-declarationsR, ?ue deben estar encerradas entre los s5mbolos Oto6enR P{Q y P!Q, declaran los descriptores de acceso O[1".*.2R de la propiedad. 8os descriptores de acceso especi0ican las instrucciones e$ecutables asociadas a la lectura y escritura de la propiedad. &un?ue la sintaxis para tener acceso a una propiedad es id)ntica a la de un campo, una propiedad no est( clasi0icada como variable. 'or tanto, no se puede trans0erir una propiedad como un argumento re- u out.

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

33!

Especificacin del lenguaje C#

Cuando una declaraci-n de propiedad incluye un modi0icador e#tern, se dice ?ue la propiedad es una propiedad e.terna. 2ebido a ?ue la declaraci-n de una propiedad externa no proporciona una implementaci-n real, cada una de sus declaraciones de descriptores de acceso Oaccessor-declarationsR consiste en un punto y coma. 10.+.1 (ropiedades est)ticas y de instancia Cuando una declaraci-n de propiedad incluye un modi0icador static, se dice ?ue la propiedad es una propiedad est5tica. .i no existe un modi0icador static, se dice ?ue la propiedad es una propiedad de instancia. 7na propiedad est(tica no est( asociada a una instancia espec50ica y supone un error en tiempo de compilaci-n =acer re0erencia a t"is en los descriptores de acceso de una propiedad est(tica. 7na propiedad de instancia est( asociada a una determinada instancia de una clase y es posible tener acceso a dic=a instancia con t"is O[*. .*R en los descriptores de acceso de la propiedad. Cuando se =ace re0erencia a una propiedad en un acceso a miembro O%e%-er-accessR O[*. .4R con la estructura ).M, si M es una propiedad est(tica, ) debe denotar un tipo ?ue contenga M, y si M es una propiedad de instancia, ) debe denotar una instancia de un tipo ?ue contenga M. 8as di0erencias entre miembros est(ticos y de instancia se tratan con m(s detalle en [1".3.*. 10.+.2 /escriptores de acceso 8as declaraciones de descriptores de acceso Oaccessor-declarationsR de una propiedad especi0ican las instrucciones e$ecutables asociadas a la lectura y escritura de la propiedad. accessor-declarations1 &et-accessor-declaration set-accessor-declarationopt set-accessor-declaration &et-accessor-declarationopt &et-accessor-declaration1 attri- tesopt accessor-%odifieropt get accessor--od# set-accessor-declaration1 attri- tesopt accessor-%odifieropt set accessor--od# accessor-%odifier1
&rotected internal &rivate &rotected internal internal &rotected

accessor--od#1 -loc3
;

8as declaraciones de descriptores de acceso se componen de una declaraci-n de descriptor de acceso get O&etaccessor-declarationR, en una declaraci-n de descriptor de acceso set Oset-accessor-declarationR o en ambas. Cada declaraci-n de descriptor de acceso consta del to6en get o set seguido de un modi0icador de descriptor de acceso Oaccessor-%odifierR opcional. El uso de los modi0icadores de descriptores de acceso Oaccessor-%odifiersR est( controlador por las siguientes restriccionesG

336

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

Es posible ?ue un modi0icador de descriptor de acceso Oaccessor-%odifierR no se utilice en una inter0a1 ni en una implementaci-n de miembros de inter0a1 expl5citos. 'ara una propiedad o para un indi1ador ?ue no tiene un modi0icador override, s-lo se permite un modi0icador de descriptor de acceso Oaccessor-%odifierR si la propiedad o el indi1ador tiene un descriptor de acceso get y set, y s-lo se permite en uno de esos descriptores de acceso. 'ara una propiedad o un indi1ador ?ue incluye un modi0icador override un descriptor de acceso debe coincidir con el modi0icador de descriptor de acceso Oaccessor-%odifierR, si lo =ay, del descriptor de acceso ?ue se est( invalidando. El modi0icador de descriptor de acceso Oaccessor-%odifierR debe declarar una accesibilidad ?ue sea estrictamente m(s restrictiva ?ue la accesibilidad declarada de la misma propiedad o indi1ador. 'ara ser precisoG o o o o .i la propiedad o el indi1ador tiene una accesibilidad declarada de &ublic, el modi0icador de descriptor de acceso Oaccessor-%odifierR puede ser internal, &rotected o &rivate. .i la propiedad o el indi1ador tiene una accesibilidad declarada de &rotected internal el modi0icador de descriptor de acceso Oaccessor-%odifierR puede ser internal, &rotected o &rivate. .i la propiedad o el indi1ador tiene una accesibilidad declarada de internal o &rotected, el modi0icador de descriptor de acceso Oaccessor-%odifierR debe ser &rivate. .i la propiedad o el indi1ador tiene una accesibilidad declarada de &rivate, no se puede utili1ar el modi0icador de descriptor de acceso Oaccessor-%odifierR.

'ara las propiedades abstract y e#tern, el cuerpo de descriptor de acceso Oaccessor--od#R de cada descriptor de acceso especi0icado consiste simplemente en un punto y coma. 7na propiedad no abstracta y no externa puede ser una propiedad a!to 5tica ente i ple entada, en cuyo caso se deben dar ambos descriptores de acceso, get y set, y ambos con punto y coma O[1".*.3R. 'ara los descriptores de acceso de cual?uier otra propiedad no abstracta y no externa, el cuerpo de descriptor de acceso Oaccessor--od#R es un blo?ue O-loc3R ?ue especi0ica las instrucciones ?ue deben e$ecutarse cuando se invo?ue al correspondiente descriptor de acceso. 7n descriptor de acceso get corresponde a un m)todo sin par(metros ?ue devuelve un valor del tipo de la propiedad. Exceptuando cuando se trata del destino de una asignaci-n, al =acer re0erencia a una propiedad en una expresi-n, se invoca al descriptor de acceso get de la propiedad para calcular su valor O[*.1.1R. El cuerpo de un descriptor de acceso get debe cumplir las reglas de los m)todos ?ue devuelven valores, descritas en la secci-n [1".#.1". En concreto, todas las instrucciones return del cuerpo de un descriptor de acceso get deben especi0icar una expresi-n ?ue sea convertible impl5citamente al tipo de la propiedad. &dem(s, el 0inal de un descriptor de acceso get no debe ser alcan1able. 7n descriptor de acceso set corresponde a un m)todo con un solo par(metro de valor del tipo de la propiedad y un tipo de valor devuelto void. El par(metro impl5cito de un descriptor de acceso set siempre se denomina value. Cuando se =ace re0erencia a una propiedad como el destino de una asignaci-n O[*.1#R o como el operando de los operadores << o == O[*. .+, [*.#. R, se invoca el descriptor de acceso set con un argumento Ocuyo valor es el del lado derec=o de la asignaci-n o del operando del operador << o ==R, ?ue proporciona el nuevo valor O[*.1#.1R. El cuerpo de un descriptor de acceso set debe cumplir las reglas de los m)todos void, descritas en la secci-n [1".#.1". En concreto, no est( permitido ?ue las instrucciones return del cuerpo de un descriptor de acceso set especi0i?uen una expresi-n. 2ebido a ?ue un descriptor de acceso set tiene impl5citamente un par(metro denominado value, supone un error en tiempo de compilaci-n ?ue una declaraci-n de variable local o una declaraci-n de constante en un descriptor de acceso set tengan ese nombre. Aas(ndose en la existencia o no de los descriptores de acceso get y set, las propiedades se clasi0ican enG

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

33(

Especificacin del lenguaje C#

7na propiedad ?ue incluye los descriptores de acceso get y set se dice ?ue es una propiedad de lect!raescrit!ra. 7na propiedad ?ue s-lo tiene un descriptor de acceso get se dice ?ue es una propiedad de s,lo lect!ra. .upone un error en tiempo de compilaci-n ?ue una propiedad de s-lo lectura sea el destino de una asignaci-n. 7na propiedad ?ue s-lo tiene un descriptor de acceso set se dice ?ue es una propiedad de s,lo escrit!ra. .alvo cuando la propiedad sea el destino de una asignaci-n, supone un error en tiempo de compilaci-n =acer re0erencia en una expresi-n a una propiedad de s-lo escritura.
&ublic class :utton/ Control { &rivate string ca&tion; &ublic string Ca&tion { get { return ca&tion; ! set { i- (ca&tion @+ value) { ca&tion + value; Oe&aint(); ! ! ! &ublic override void *aint(Sra&"ics g .. *ainting code goes "ere ! ! Oectangle r) {

En el e$emplo

el control :utton declara una propiedad pHblica Ca&tion. El descriptor de acceso get de la propiedad Ca&tion devuelve la cadena almacenada en el campo privado ca&tion. El descriptor de acceso set comprueba si el nuevo valor es di0erente del valor actual y, en ese caso, almacena el nuevo valor y vuelve a dibu$ar el control. 8as propiedades siguen a menudo el diseUo descrito anteriormenteG el descriptor de acceso get simplemente devuelve un valor almacenado en un campo privado, y el descriptor de acceso set modi0ica el campo privado y despu)s reali1a otras acciones adicionales necesarias para actuali1ar completamente el estado del ob$eto. 2ada la clase :utton de0inida anteriormente, en el siguiente e$emplo se muestra el uso de la propiedad Ca&tionG
:utton o(:utton + ne, :utton(); o(:utton.Ca&tion + "%a"; string s + o(:utton.Ca&tion; .. $nvo(es set accessor .. $nvo(es get accessor

&?u5, el descriptor de acceso set se invoca mediante la asignaci-n de un valor a la propiedad, y el descriptor de acceso get se invoca =aciendo re0erencia a )sta en una expresi-n. 8os descriptores de acceso get y set de una propiedad no son miembros distintos, y no es posible declarar los descriptores de acceso de una propiedad de 0orma independiente. 'or ello, no es posible ?ue los dos descriptores de acceso de una propiedad de lecturaBescritura tengan distinta accesibilidad. En el e$emplo
class ' { &rivate string name; &ublic string Name { get { return name; ! ! .. )rror du&licate member name

33$

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases &ublic string Name { set { name + value; ! ! ! .. )rror du&licate member name

no se declara una Hnica propiedad de s-lo lectura. .e declaran dos propiedades con el mismo nombre, una de s-lo lectura y otra de s-lo escritura. 2ado ?ue dos miembros ?ue se declaran en la misma clase no pueden tener el mismo nombre, el c-digo del e$emplo generar( un error de compilaci-n. Cuando una clase derivada declara una propiedad con el mismo nombre ?ue una propiedad =eredada, la propiedad derivada oculta la propiedad =eredada tanto para lectura como para escritura. En el e$emplo
class ' { &ublic int * { set {... ! ! class :/ ' { ne, &ublic int * { get {... ! !

la propiedad * en : oculta la propiedad * en ' para lectura y para escritura. 'or lo tanto, en las instrucciones
: b + ne, :(); b.* + 2; .. )rror :.* is read=only ((')b).* + 2; .. %( re-erence to '.*

la asignaci-n a b.* causa un error en tiempo de compilaci-n del ?ue debe in0ormarse, ya ?ue la propiedad * de s-lo lectura en : oculta la propiedad * de s-lo escritura en '. /bserve, sin embargo, ?ue se puede utili1ar una conversi-n para tener acceso a la propiedad * oculta. & di0erencia de los campos pHblicos, las propiedades proporcionan una separaci-n entre el estado interno de un ob$eto y su inter0a1 pHblica. Considere este e$emploG
class Label { &rivate int # y; &rivate string ca&tion; &ublic Label(int # int y string ca&tion) { t"is.# + #; t"is.y + y; t"is.ca&tion + ca&tion; ! &ublic int I { get { return #; ! ! &ublic int ` { get { return y; ! ! &ublic *oint Location { get { return ne, *oint(# ! &ublic string Ca&tion { get { return ca&tion; ! ! ! y); !

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

33"

Especificacin del lenguaje C#

&?u5, la clase Label utili1a dos campos int, # e y, para almacenar su ubicaci-n. 8a ubicaci-n se expone pHblicamente con las propiedades I e `, y con la propiedad Location de tipo *oint. .i en una 0utura versi-n de Label 0uera m(s conveniente almacenar internamente la ubicaci-n como un *oint, se podr5a reali1ar el cambio sin ?ue a0ectara a la inter0a1 pHblica de la claseG
class Label { &rivate *oint location; &rivate string ca&tion; &ublic Label(int # int y string ca&tion) { t"is.location + ne, *oint(# y); t"is.ca&tion + ca&tion; ! &ublic int I { get { return location.#; ! ! &ublic int ` { get { return location.y; ! ! &ublic *oint Location { get { return location; ! ! &ublic string Ca&tion { get { return ca&tion; ! ! !

.i # e y 0ueran campos &ublic readonly, no ser5a posible reali1ar ese cambio en la clase Label. 8a exposici-n del estado mediante propiedades no es menos e0iciente ?ue exponer los campos directamente. En concreto, cuando una propiedad no es virtual y contiene s-lo una pe?ueUa cantidad de c-digo, el entorno de e$ecuci-n puede reempla1ar las llamadas a los descriptores de acceso con el c-digo real de los descriptores de acceso. Este proceso es conocido con el nombre de en lnea, y permite ?ue el acceso a las propiedades sea tan e0iciente como el acceso a los campos, preservando la mayor 0lexibilidad de las propiedades. 'uesto ?ue invocar un descriptor de acceso get e?uivale conceptualmente a leer el valor de un campo, se considera una t)cnica de programaci-n poco recomendable el ?ue los descriptores de acceso get muestren e0ectos secundarios. En el e$emplo
class Counter { &rivate int ne#t; &ublic int Ne#t { get { return ne#t<<; ! ! !

el valor de la propiedad Ne#t depende del nHmero de veces ?ue se =aya tenido acceso anteriormente a la propiedad. 'or consiguiente, puesto ?ue el acceso a la propiedad produce un e0ecto secundario observable, es pre0erible implementar la propiedad como m)todo. 8a convenci-n Psin e0ectos secundariosQ ?ue se aplica a los descriptores de acceso get no signi0ica ?ue )stos deban escribirse siempre Hnicamente para ?ue devuelvan los valores almacenados en campos. 2e =ec=o, los descriptores de acceso get a menudo calculan el valor de una propiedad mediante el acceso a varios campos o invocando m)todos. 4o obstante, un descriptor de acceso get diseUado correctamente no lleva a cabo acciones ?ue generen cambios observables en el estado del ob$eto.

3#'

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

'ueden utili1arse propiedades para retrasar la iniciali1aci-n de un recurso =asta el momento en ?ue se =aga re0erencia al mismo. 'or e$emploG
using System.$%; &ublic class Console { &rivate static 1e#tOeader reader; &rivate static 1e#tWriter ,riter; &rivate static 1e#tWriter error; &ublic static 1e#tOeader $n { get { i- (reader ++ null) { reader + ne, StreamOeader(Console.%&enStandard$n&ut()); ! return reader; ! ! &ublic static 1e#tWriter %ut { get { i- (,riter ++ null) { ,riter + ne, StreamWriter(Console.%&enStandard%ut&ut()); ! return ,riter; ! ! &ublic static 1e#tWriter )rror { get { i- (error ++ null) { error + ne, StreamWriter(Console.%&enStandard)rror()); ! return error; ! ! !

8a clase Console contiene tres propiedades, $n, %ut y )rror, ?ue representan los dispositivos est(ndar de entrada, salida y error, respectivamente. %ediante la exposici-n de estos miembros como propiedades, la clase ConsoleStreams puede retrasar su iniciali1aci-n =asta ?ue se utilicen realmente. 'or e$emplo, en la primera re0erencia a la propiedad %ut del c-digo siguiente
Console.%ut.WriteLine(""ello ,orld");

se crea el 1e#tWriter subyacente para el dispositivo de salida. 'ero si la aplicaci-n no =ace re0erencia a las propiedades $n y )rror, entonces no se crean ob$etos para esos dispositivos. 10.+.3 (ropiedades autom)ticamente implementadas Cuando una propiedad se especi0ica como propiedad autom(ticamente implementada, pasa a estar disponible para la propiedad un campo de respaldo oculto autom(ticamente, y los descriptores de acceso se implementan para leer y escribir en dic=o campo de respaldo. El siguiente e$emploG
&ublic class *oint { &ublic int I { get; set; ! .. automatically im&lemented &ublic int ` { get; set; ! .. automatically im&lemented !

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

3#1

Especificacin del lenguaje C#

e?uivale a la siguiente declaraci-nG


&ublic class *oint { &rivate int #; &rivate int y; &ublic int I { get { return #; ! set { # + value; ! ! &ublic int ` { get { return y; ! set { y + value; ! ! !

&l estar inaccesible el campo de respaldo, s-lo se puede leer y escribir mediante los descriptores de acceso de la propiedad, incluso dentro del tipo contenedor. Esto signi0ica ?ue las propiedades autom(ticamente implementadas de s-lo escritura o de s-lo lectura no tienen sentido, y no se permiten. 4o obstante, es posible establecer el nivel de acceso de cada descriptor de acceso de manera distinta. 'or tanto, el e0ecto de una propiedad de s-lo lectura con un campo de respaldo privado se puede imitar del siguiente modoG
&ublic class Oead%nly*oint { &ublic int I { get; &rivate set; ! &ublic int ` { get; &rivate set; ! &ublic Oead%nly*oint(int # int y) { I + #; ` + y; ! !

Esta restricci-n tambi)n signi0ica ?ue s-lo se puede lograr una asignaci-n de0initiva de tipos struct con propiedades autoimplementadas mediante un constructor est(ndar de la estructura, ya ?ue la asignaci-n a la propiedad en s5 re?uiere ?ue la estructura est) asignada de manera de0initiva. Esto signi0ica ?ue los constructores de0inidos por el usuario deben llamar al constructor predeterminado. 10.+.! 'ccesibilidad .i un descriptor de acceso tiene un modi0icador de descriptor de acceso Oaccessor-%odifierR, el dominio de accesibilidad O[3. .2R del descriptor de acceso viene determinado por la accesibilidad declarada del modi0icador de descriptor de acceso Oaccessor-%odifierR. .i un descriptor de acceso no tiene un modi0icador de descriptor de acceso Oaccessor-%odifierR, el dominio de accesibilidad del descriptor de acceso viene determinado por la accesibilidad declarada de la propiedad o del indi1ador. 8a presencia de un modi0icador de descriptor de acceso Oaccessor-%odifierR nunca a0ecta a la bHs?ueda de miembros O[*.3R ni a la resoluci-n de sobrecargas O[*.4.3R. 8os modi0icadores de la propiedad o del indi1ador siempre determinan ?u) propiedad o indi1ador est( enla1ada independientemente del contexto del acceso. 7na ve1 seleccionada una propiedad o indi1ador concreto, los dominios de accesibilidad de los descriptores de acceso espec50icos implicados se utili1an para determinar si el uso es v(lidoG .i el uso es un valor O[*.1.1R, el descriptor de acceso get debe existir y ser accesible. .i el uso es como destino de una asignaci-n simple O[*.1#.1R, el descriptor de acceso set debe existir y ser accesible. .i el uso es como el destino de la asignaci-n compuesta O[*.1#.2R o como el destino de los operadores << o == O[*. .+, [*.#. R, deben existir los descriptores de acceso get y set, y estar accesibles.

En el siguiente e$emplo, la propiedad '.1e#t est( oculta por la propiedad :.1e#t, incluso en contextos donde s-lo se llama al descriptor de acceso set. 'or el contrario, la propiedad :.Count no es accesible para la clase M por lo ?ue se utili1a la propiedad accesible '.Count en su lugar.
class ' { &ublic string 1e#t { get { return ""ello"; ! set { ! !

3#2

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases &ublic int Count { get { return K; ! set { ! ! ! class :/ ' { &rivate string te#t + "goodbye"; &rivate int count + 3; ne, &ublic string 1e#t { get { return te#t; ! &rotected set { te#t + value; ! ! ne, &rotected int Count { get { return count; ! set { count + value; ! ! ! class M { static void Main() { : b + ne, :(); b.Count + 28; int i + b.Count; b.1e#t + ""o,dy"; string s + b.1e#t; ! !

.. .. .. ..

Calls '.Count set accessor Calls '.Count get accessor )rror :.1e#t set accessor not accessible Calls :.1e#t get accessor

Es posible ?ue un descriptor de acceso ?ue se utili1a para implementar una inter0a1 no tenga un modi0icador de descriptor de acceso Oaccessor-%odifierR. .i s-lo se utili1a un descriptor de acceso para implementar una inter0a1, el otro descriptor de acceso se puede declarar con un modi0icador de descriptor de acceso Oaccessor%odifierRG
&ublic inter-ace $ { string *ro& { get; ! ! &ublic class C/ $ { &ublic *ro& { get { return "'&ril"; ! internal set {...! ! !

.. Must not "ave a modi-ier "ere .. %( because $.*ro& "as no set accessor

10.+.# /escriptores de acceso irtualD selladoD de in alidacin y abstracto 7na declaraci-n de propiedad virtual especi0ica ?ue los descriptores de acceso de la propiedad son virtuales. El modi0icador virtual se aplica a los dos descriptores de acceso de una propiedad de lecturaBescritura. 4o es posible ?ue s-lo uno de los descriptores de acceso de lecturaBescritura sea virtual. 7na declaraci-n de propiedad abstract especi0ica ?ue los descriptores de acceso de la propiedad son virtuales, pero no proporcionan una implementaci-n real de los descriptores de acceso. En cambio, es necesario ?ue las clases derivadas no abstractas proporcionen su propia implementaci-n para los descriptores de acceso mediante la invalidaci-n de la propiedad. Como un descriptor de acceso para una declaraci-n de propiedad abstracta no proporciona una implementaci-n real, su cuerpo de descriptor de acceso Oaccessor--od#R consiste simplemente en un punto y coma.

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

3#3

Especificacin del lenguaje C#

7na declaraci-n de propiedad ?ue incluye los dos modi0icadores abstract y override especi0ica ?ue la propiedad es abstracta y ?ue invalida una propiedad base. 8os descriptores de acceso de este tipo de propiedad son tambi)n abstractos. 8as declaraciones de propiedades abstractas s-lo se permiten en clases abstractas O[1".1.1.1R. 8os descriptores de acceso de una propiedad virtual =eredada se pueden invalidar en una clase derivada incluyendo una declaraci-n de propiedad ?ue especi0i?ue una directiva override. Esto se conoce como declaraci,n de propiedad invalidada. 7na declaraci-n de propiedad invalidada no declara una nueva propiedad. En su lugar, simplemente especiali1a las implementaciones de los descriptores de acceso de una propiedad virtual existente. 7na declaraci-n de propiedad invalidada debe especi0icar exactamente los mismos modi0icadores de accesibilidad, tipo y nombre ?ue la propiedad =eredada. .i la propiedad =eredada s-lo tiene un descriptor de acceso Opor e$emplo, si la propiedad =eredada es de s-lo lectura o de s-lo escrituraR, la propiedad invalidada debe incluir s-lo ese descriptor de acceso. .i la propiedad =eredada incluye ambos descriptores de acceso Opor e$emplo, si la propiedad =eredada es de lecturaBescrituraR, la propiedad invalidada puede incluir un descriptor de acceso o ambos. 7na declaraci-n de propiedad invalidada puede incluir el modi0icador sealed. El uso de este modi0icador impide ?ue una clase derivada siga invalidando la propiedad. 8os descriptores de acceso de una propiedad sellada tambi)n son sellados. .alvo en las di0erencias re0erentes a la sintaxis de declaraci-n e invocaci-n, los descriptores de acceso virtuales, sellados, de invalidaci-n y abstractos se comportan exactamente igual ?ue los m)todos virtuales, sellados, de invalidaci-n y abstractos. Espec50icamente, las reglas descritas en las secciones [1".#.3, [1".#.4, [1".#. y [1".#.# se aplican como si los descriptores de acceso 0ueran m)todos con una 0orma correspondienteG 7n descriptor de acceso get corresponde a un m)todo sin par(metros ?ue devuelve un valor del tipo de la propiedad y los mismos modi0icadores ?ue la propiedad contenedora. 7n descriptor de acceso set corresponde a un m)todo con un Hnico par(metro de valor del tipo de la propiedad, un tipo de valor devuelto void y los mismos modi0icadores ?ue la propiedad contenedora.
abstract class ' { int y; &ublic virtual int I { get { return 3; ! ! &ublic virtual int ` { get { return y; ! set { y + value; ! ! &ublic abstract int P { get; set; ! ! I es una propiedad virtual de s-lo lectura, ` es una propiedad virtual de s-lo escritura, y P es una propiedad abstracta de lecturaBescritura. 'uesto ?ue P es abstracta, la clase contenedora ' debe declararse como abstracta.

En el e$emplo

& continuaci-n se muestra una clase ?ue se deriva de la clase 'G


class :/ ' { int ?; &ublic override int I { get { return base.I < 2; ! !

3##

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases &ublic override int ` { set { base.` + value D 37 3/ value; ! ! &ublic override int P { get { return ?; ! set { ? + value; ! ! !

&?u5, las declaraciones de I, ` y P son declaraciones de propiedades invalidadas. Cada declaraci-n de propiedad coincide exactamente con los modi0icadores de accesibilidad, tipo y nombre de la propiedad =eredada correspondiente. El descriptor de acceso get de I y el descriptor de acceso set de ` utili1an la palabra clave base para tener acceso a los descriptores de acceso =eredados. 8a declaraci-n de P invalida ambos descriptores de acceso abstractosV de este modo, no =ay miembros de 0unci-n abstracta pendientes en :, y )sta puede ser una clase no abstracta. Cuando una propiedad se declara override, los descriptores de acceso deben estar accesibles al c-digo de invalidaci-n. &dem(s, la accesibilidad declarada tanto de la propiedad como del indi1ador y los descriptores de acceso deben coincidir con los de los miembros y descriptores de acceso invalidados. 'or e$emploG
&ublic class : { &ublic virtual int * { &rotected set {...! get {...! ! ! &ublic class 6/ : { &ublic override int * { &rotected set {...! get {...! ! !

.. Must s&eci-y &rotected "ere .. Must not "ave a modi-ier "ere

10.- E entos
7n evento es un miembro ?ue permite a un ob$eto o una clase proporcionar noti0icaciones. 8os clientes pueden ad$untar c-digo e$ecutable a los eventos mediante controladores de eventos. 8os eventos se declaran mediante declaraciones de eventos Oevent-declarationsRG event-declaration1 attri- tesopt event-%odifiersopt event t#pe varia-le-declarators ; attri- tesopt event-%odifiersopt event t#pe %e%-er-na%e { event-accessor-declarations ! event-%odifiers1 event-%odifier event-%odifiers event-%odifier

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

3#!

Especificacin del lenguaje C#

event-%odifier1
ne, &ublic &rotected internal &rivate static virtual sealed override abstract e#tern

event-accessor-declarations1 add-accessor-declaration re%ove-accessor-declaration re%ove-accessor-declaration add-accessor-declaration add-accessor-declaration1 attri- tesopt add -loc3 re%ove-accessor-declaration1 attri- tesopt remove -loc3 7na declaraci-n de evento Oevent-declarationR puede incluir un con$unto de atributos Oattri- tesR O[1*R y una combinaci-n v(lida de los cuatro modi0icadores de acceso O[1".3. R, ne, O[1".3.4R, static O[1".#.2R, virtual O[1".#.3R, override O[1".#.4R, sealed O[1".#. R, abstract O[1".#.#R y e#tern O[1".#.*R. 8as declaraciones de evento est(n su$etas a las mismas reglas ?ue las declaraciones de m)todo O[1".#R en lo ?ue respecta a las combinaciones v(lidas de modi0icadores. El tipo Ot#peR de una declaraci-n de evento debe ser un tipo delegado Odele&ate-t#peR O[4.2R y dic=o tipo delegado debe ser al menos tan accesible como el propio evento O[3. .4R. 7na declaraci-n de evento puede incluir declaraciones de descriptores de acceso a eventos Oevent-accessordeclarationsR. .in embargo, si no 0uera as5, el compilador las proporcionar( autom(ticamente para los eventos no externos y no abstractos O[1".8.1RV para los eventos externos, los descriptores de acceso se proporcionan externamente. 7na declaraci-n de evento ?ue omite declaraciones de acceso a eventos Oevent-accessor-declarationsR de0ine uno o varios eventos, uno para cada declarador de variable Ovaria-le-declaratorsR. 8os atributos y modi0icadores se aplican a todos los miembros declarados en esa declaraci-n de evento Oevent-declarationR. Es un error en tiempo de compilaci-n ?ue una declaraci-n de evento Oevent-declarationR incluya el modi0icador abstract y declaraciones de acceso a eventos Oevent-accessor-declarationsR entre llaves. Cuando la declaraci-n de un evento incluye un modi0icador e#tern, se dice ?ue el evento es un evento e.terno. 2ebido a ?ue una declaraci-n de evento externo no proporciona ninguna implementaci-n real, supone un error incluir a la ve1 el modi0icador e#tern y las declaraciones de descriptor de acceso a eventos Oevent-accessordeclarationsR. 7n evento se puede utili1ar como el operando i1?uierdo de los operadores <+ y =+ O[*.1#.3R. Estos operadores se utili1an para ad$untar o ?uitar respectivamente controladores de eventos de un evento, y los modi0icadores de acceso del evento controlan los contextos en los ?ue se permiten estas operaciones. Como <+ y =+ son las Hnicas operaciones permitidas en un evento 0uera del tipo ?ue declara el evento, mediante c-digo externo se pueden agregar o ?uitar controladores de un evento, pero no se puede obtener ni modi0icar la lista subyacente de controladores de eventos de ninguna otra 0orma.

3#6

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

En una operaci-n con la estructura # <+ y o # =+ y, cuando # es un evento y la re0erencia tiene lugar 0uera del tipo ?ue contiene la declaraci-n de #, el resultado de la operaci-n es de tipo void Oen oposici-n al tipo #, con el valor de # despu)s de la asignaci-nR. Esta regla pro=5be ?ue el c-digo externo examine indirectamente el delegado subyacente de un evento. En el siguiente e$emplo se muestra c-mo ad$untar controladores de eventos a instancias de la clase :uttonG
&ublic delegate void )ventHandler(object sender &ublic class :utton/ Control { &ublic event )ventHandler Clic(; ! &ublic class Login6ialog/ Vorm { :utton %(:utton; :utton Cancel:utton; &ublic Login6ialog() { %(:utton + ne, :utton(...); %(:utton.Clic( <+ ne, )ventHandler(%(:uttonClic(); Cancel:utton + ne, :utton(...); Cancel:utton.Clic( <+ ne, )ventHandler(Cancel:uttonClic(); ! void %(:uttonClic((object sender )vent'rgs e) { .. Handle %(:utton.Clic( event ! void Cancel:uttonClic((object sender )vent'rgs e) { .. Handle Cancel:utton.Clic( event ! ! )vent'rgs e);

&?u5, el constructor de instancia para Login6ialog crea dos instancias de :utton y ad$unta controladores de evento a los eventos de Clic(. 10.-.1 E entos como campos 2entro del texto del programa de la clase o estructura ?ue contiene la declaraci-n de un evento, algunos eventos se pueden utili1ar como campos. 'ara utili1arlo de esta 0orma, un evento no debe ser abstract ni e#tern, ni debe incluir expl5citamente declaraciones de descriptores de acceso a eventos Oevent-accessor-declarationsR. Este tipo de eventos se puede utili1ar en cual?uier contexto ?ue admita campos. El campo contiene un delegado O[1 R ?ue =ace re0erencia a la lista de controladores de eventos ?ue se =an agregado al evento. .i no se =a agregado ningHn controlador de evento, el campo contiene null. En el e$emplo
&ublic delegate void )ventHandler(object sender &ublic class :utton/ Control { &ublic event )ventHandler Clic(; &rotected void %nClic(()vent'rgs e) { i- (Clic( @+ null) Clic((t"is e); ! &ublic void Oeset() { Clic( + null; ! ! Clic( se utili1a como un campo dentro de la clase :utton. Como se demuestra en el e$emplo, el campo se puede examinar, modi0icar y utili1ar en expresiones de invocaci-n a delegados. El m)todo %nClic( en la clase )vent'rgs e);

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

3#(

Especificacin del lenguaje C# :utton PproduceQ el evento Clic(. 8a noci-n de iniciar un evento e?uivale exactamente a invocar el delegado

representado por el eventoV por lo tanto, no =ay construcciones especiales del lengua$e para producir eventos. /bserve ?ue la invocaci-n del delegado est( precedida por una comprobaci-n ?ue con0irma ?ue el delegado no es nulo. :uera de la declaraci-n de la clase :utton, el miembro Clic( s-lo se puede utili1ar como operando i1?uierdo de los operadores <+ y =+, como en
b.Clic( <+ ne, )ventHandler(b);

?ue anexa un delegado a la lista de invocaci-n del evento Clic(, y


b.Clic( C+ ne, )ventHandler(b);

?ue ?uita un delegado de la lista de invocaci-n del evento Clic(. &l compilar un campo como un evento, el compilador crea autom(ticamente espacio de almacenamiento para alo$ar el delegado, y crea descriptores de acceso para el evento ?ue agregan o ?uitan controladores de evento del campo del delegado. 'ara no causar ningHn tipo de inseguridad en el subproceso, las operaciones de agregado o eliminaci-n se e0ectHan blo?ueando O[8.12R el ob$eto contenedor para un evento de instanciaV o bien el ob$eto de tipo O[*. .1".#R para un evento est(tico. 'or lo tanto, una declaraci-n de evento de instancia de la 0ormaG
class I { &ublic event 6 )v; !

puede compilarse de manera e?uivalente aG


class I { &rivate 6 \\)v; .. -ield to "old t"e delegate

&ublic event 6 )v { add { loc((t"is) { \\)v + \\)v < value; ! ! remove { loc((t"is) { \\)v + \\)v = value; ! ! ! !

En la clase I, sin embargo, las re0erencias a )v se compilan para =acer re0erencia al campo oculto \\)v. El nombre P\\)vQ es arbitrarioV el campo oculto puede tener cual?uier nombre o incluso no tener ninguno. 2e igual modo, una declaraci-n de evento est(tico de la 0ormaG
class I { &ublic static event 6 )v; !

puede compilarse de manera e?uivalente aG


class I { &rivate static 6 \\)v; .. -ield to "old t"e delegate

&ublic static event 6 )v { add { loc((ty&eo-(I)) { \\)v + \\)v < value; ! !

3#$

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases remove { loc((ty&eo-(I)) { \\)v + \\)v = value; ! ! ! !

10.-.2 /escriptores de acceso de e ento 8as declaraciones de eventos normalmente omiten las declaraciones de descriptores de acceso a eventos Oeventaccessor-declarationsR, como en el e$emplo anterior de :utton. 7na situaci-n en la ?ue puede darse es en el caso de ?ue el costo de almacenamiento de un campo por evento no sea aceptable. En estos casos, una clase puede incluir declaraciones de descriptores de acceso a eventos Oevent-accessor-declarationsR y utili1ar un mecanismo privado para almacenar la lista de controladores de eventos. 8as declaraciones de descriptores de acceso a eventos Oevent-accessor-declarationsR de un evento especi0ican las instrucciones e$ecutables asociadas a la acci-n de agregar o ?uitar controladores de eventos. 8as declaraciones del descriptor de acceso consisten en una declaraci-n de descriptor de acceso add Oaddaccessor-declarationR y en una declaraci-n de descriptor de acceso remove Ore%ove-accessor-declarationR. Cada declaraci-n de descriptor de acceso consiste en el to6en add o remove seguido de un blo?ue O-loc3R. El blo?ue O-loc3R asociado a una declaraci-n de descriptor de acceso add Oadd-accessor-declarationR especi0ica las instrucciones ?ue se van a e$ecutar cuando se agrega un controlador de evento, y el blo?ue O-loc3R asociado a una declaraci-n de descriptor de acceso remove Ore%ove-accessor-declarationR especi0ica las instrucciones a e$ecutar cuando se ?uita un controlador de evento. Cada declaraci-n de descriptor de acceso add Oadd-accessor-declarationR y declaraci-n de descriptor de acceso remove Ore%ove-accessor-declarationR corresponde a un m)todo con un solo par(metro de valor del tipo del evento y un tipo de valor devuelto void. El par(metro impl5cito de un descriptor de acceso a evento se denomina value. Cuando se utili1a un evento en una asignaci-n de evento, se utili1a el descriptor de acceso de evento apropiado. .i el operador de asignaci-n es espec50icamente <+, se utili1a el descriptor de acceso add y, si es =+, el descriptor de acceso remove. En ambos casos, el operando derec=o del operador de asignaci-n se utili1a como argumento para el descriptor de acceso del evento. El blo?ue de una declaraci-n de descriptor de acceso add Oadd-accessor-declarationR o de una declaraci-n de descriptor de acceso remove Ore%ove-accessordeclarationR debe cumplir las reglas para los m)todos void descritas en [1".#.1". En concreto, no est( permitido ?ue las instrucciones return del blo?ue especi0i?uen una expresi-n. 2ebido a ?ue un descriptor de acceso a evento tiene impl5citamente un par(metro denominado value, se producir( un error en tiempo de compilaci-n si una variable local o una constante declaradas en un descriptor de acceso a evento tienen ese nombre. En el e$emplo
class Control/ Com&onent { .. ;niQue (eys -or events static readonly object mouse6o,n)ventaey + ne, object(); static readonly object mouse;&)ventaey + ne, object(); .. Oeturn event "andler associated ,it" (ey &rotected 6elegate Set)ventHandler(object (ey) {...! .. 'dd event "andler associated ,it" (ey &rotected void 'dd)ventHandler(object (ey 6elegate "andler) {...! 6elegate "andler) {...!

.. Oemove event "andler associated ,it" (ey &rotected void Oemove)ventHandler(object (ey

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

3#"

Especificacin del lenguaje C# .. Mouse6o,n event &ublic event Mouse)ventHandler Mouse6o,n { add { 'dd)ventHandler(mouse6o,n)ventaey value); ! remove { Oemove)ventHandler(mouse6o,n)ventaey value); ! ! .. Mouse;& event &ublic event Mouse)ventHandler Mouse;& { add { 'dd)ventHandler(mouse;&)ventaey value); ! remove { Oemove)ventHandler(mouse;&)ventaey value); ! ! .. $nvo(e t"e Mouse;& event &rotected void %nMouse;&(Mouse)vent'rgs args) { Mouse)ventHandler "andler; "andler + (Mouse)ventHandler)Set)ventHandler(mouse;&)ventaey); i- ("andler @+ null) "andler(t"is args); ! !

la clase Control implementa un mecanismo de almacenamiento interno para los eventos. El m)todo 'dd)ventHandler asocia un valor de delegado a una clave, el m)todo Set)ventHandler devuelve el delegado asociado actualmente a una clave, y el m)todo Oemove)ventHandler ?uita un delegado como controlador de evento del evento especi0icado. 'resumiblemente, el mecanismo de almacenamiento subyacente est( diseUado para ?ue no suponga un costo el =ec=o de asociar un valor de delegado null a una clave y, por lo tanto, los eventos no controlados no consumen almacenamiento. 10.-.3 E entos est)ticos y de instancia Cuando la declaraci-n de un evento incluye un modi0icador static, se dice ?ue el evento es un evento est5tico. Cuando no existe un modi0icador static, se dice ?ue el evento es un evento de instancia. 7n evento est(tico no est( asociado a una instancia espec50ica y supone un error en tiempo de compilaci-n =acer re0erencia a t"is en los descriptores de acceso de un evento est(tico. 7n evento de instancia est( asociado a una determinada instancia de una clase y es posible tener acceso a la instancia con t"is O[*. .*R en los descriptores de acceso del evento. Cuando se =ace re0erencia a un evento en un acceso a miembro O%e%-er-accessR O[*. .4R con la estructura ).M, si M es un evento est(tico, ) debe denotar un tipo ?ue contenga M, y si M es un evento de instancia, ) debe denotar una instancia de un tipo ?ue contenga M. 8as di0erencias entre miembros est(ticos y de instancia se tratan con m(s detalle en [1".3.*. 10.-.! /escriptores de acceso irtualD selladoD de in alidacin y abstracto 7na declaraci-n de evento virtual especi0ica ?ue los descriptores de acceso del evento son virtuales. El modi0icador virtual se aplica a todos los descriptores de acceso de un evento. 7na declaraci-n de evento abstract especi0ica ?ue los descriptores de acceso del evento son virtuales, pero no proporciona una implementaci-n real de los descriptores de acceso. En su lugar, es necesario ?ue las clases derivadas no abstractas proporcionen su propia implementaci-n para los descriptores de acceso mediante la invalidaci-n del evento. 2ebido a ?ue un descriptor de acceso para una declaraci-n de evento abstracto no proporciona una implementaci-n real, no puede proporcionar declaraciones de descriptores de acceso a eventos Oevent-accessor-declarationsR entre llaves. 7na declaraci-n de evento ?ue incluye los modi0icadores abstract y override especi0ica ?ue el evento es abstracto y ?ue invalida un evento base. 8os descriptores de acceso de este tipo de eventos son tambi)n abstractos.

3!'

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

8as declaraciones de eventos abstractos s-lo se permiten en clases abstractas O[1".1.1.1R. 8os descriptores de acceso de un evento virtual =eredado pueden ser invalidados en una clase derivada incluyendo una declaraci-n de evento ?ue especi0i?ue un modi0icador override. Esto se conoce con el nombre de declaraci,n de evento invalidado. 7na declaraci-n de evento invalidado no declara un evento nuevo. En lugar de eso, simplemente especiali1a las implementaciones de los descriptores de acceso de un evento virtual existente. 7na declaraci-n de evento invalidado debe especi0icar exactamente los mismos modi0icadores de accesibilidad, tipo y nombre ?ue el evento invalidado. 7na declaraci-n de evento invalidado puede incluir el modi0icador sealed. El uso de este modi0icador impide ?ue una clase derivada siga invalidando el evento. 8os descriptores de acceso de un evento sellado tambi)n son sellados. .upone un error en tiempo de compilaci-n ?ue una declaraci-n de evento invalidado incluya el modi0icador ne,. .alvo en las di0erencias re0erentes a la sintaxis de declaraci-n e invocaci-n, los descriptores de acceso virtuales, sellados, de invalidaci-n y abstractos se comportan exactamente igual ?ue los m)todos virtuales, sellados, de invalidaci-n y abstractos. Espec50icamente, las reglas descritas en las secciones [1".#.3, [1".#.4, [1".#. y [1".#.# se aplican como si los descriptores de acceso 0ueran m)todos con una 0orma correspondiente. Cada descriptor de acceso corresponde a un m)todo con un solo par(metro de valor del tipo del evento, un tipo de valor devuelto void y los mismos modi0icadores ?ue el evento contenedor.

10.. Indi8adores
7n indi-ador es un miembro ?ue permite indi1ar un ob$eto de la misma manera ?ue una matri1. 8os indi1adores se declaran mediante declaraciones de indi1adores Oinde2er-declarationsRG inde2er-declaration1 attri- tesopt inde2er-%odifiersopt inde2er-declarator { accessor-declarations ! inde2er-%odifiers1 inde2er-%odifier inde2er-%odifiers inde2er-%odifier inde2er-%odifier1
ne, &ublic &rotected internal &rivate virtual sealed override abstract e#tern

inde2er-declarator1 t#pe t"is 4 for%al-para%eter-list 5 t#pe interface-t#pe . t"is 4 for%al-para%eter-list 5 7na declaraci-n de indi1ador Oinde2er-declarationR puede incluir un con$unto de atributos Oattri- tesR O[1*R y una combinaci-n v(lida de los cuatro modi0icadores de acceso O[1".3. R, ne, O[1".3.4R, virtual O[1".#.3R, override O[1".#.4R, sealed O[1".#. R, abstract O[1".#.#R y e#tern O[1".#.*R.

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

3!1

Especificacin del lenguaje C#

8as declaraciones de indi1adores est(n su$etas a las mismas reglas ?ue las declaraciones de m)todos O[1".#R en lo ?ue respecta a las combinaciones v(lidas de modi0icadores, con la Hnica excepci-n de ?ue el modi0icador static no est( permitido en una declaraci-n de indi1ador. 8os modi0icadores virtual, override y abstract se excluyen mutuamente excepto en un caso. 8os modi0icadores abstract y override pueden utili1arse con$untamente de manera ?ue un indi1ador abstracto pueda invalidar a uno virtual. El tipo Ot#peR de una declaraci-n de indi1ador especi0ica el tipo de elemento del indi1ador ?ue se incluye en la declaraci-n. & menos ?ue el indi1ador no sea una implementaci-n expl5cita de miembro de inter0a1, el tipo Ot#peR va seguido de la palabra clave t"is. 'ara una implementaci-n expl5cita de miembro de inter0a1, el tipo Ot#peR viene seguido de un tipo de inter0a1 Ointerface-t#peR, de un P.Q y de la palabra clave t"is. & di0erencia de otros miembros, los indi1adores no tienen nombres de0inidos por el usuario. 8a lista de par(metros 0ormales Ofor%al-para%eter-listR especi0ica los par(metros del indi1ador. 8a lista de par(metros 0ormales de un indi1ador se corresponde con la de un m)todo O[1".#.1R, exceptuando ?ue al menos se debe especi0icar un par(metro y ?ue no se permiten los modi0icadores de par(metro re- ni out. El tipo Ot#peR de un indi1ador y cada uno de los tipos a los ?ue se =ace re0erencia en la lista de par(metros 0ormales Ofor%al-para%eter-listR deben tener como m5nimo el mismo nivel de accesibilidad ?ue el propio indi1ador O[3. .4R. 8as declaraciones de descriptores de acceso Oaccessor-declarationsR O[1".*.2R, ?ue deben estar encerradas entre los s5mbolos Oto6enR P{Q y P!Q, declaran los descriptores de acceso del indi1ador. 8os descriptores de acceso especi0ican las instrucciones e$ecutables asociadas a los elementos de lectura y escritura del indi1ador. &un?ue la sintaxis para tener acceso a un elemento de indi1ador es la misma ?ue para un elemento de matri1, un elemento de indi1ador no est( clasi0icado como variable. 'or tanto, no se puede pasar un elemento de indi1ador como argumento re- u out. 8a lista de par(metros 0ormales de un indi1ador de0ine la 0irma O[3.#R del indi1ador. En concreto, la 0irma de un indi1ador est( 0ormada por el nHmero de par(metros 0ormales y sus tipos. El tipo y el nombre de los elementos de los par(metros 0ormales no 0orman parte de la 0irma del indi1ador. 8a 0irma de un indi1ador debe ser di0erente de las 0irmas de los dem(s indi1adores declarados en la misma clase. 8os indi1adores y las propiedades son similares conceptualmente, pero tienen las siguientes di0erenciasG 7na propiedad se identi0ica por su nombre, mientras ?ue un indi1ador se identi0ica por su 0irma. 'ara tener acceso a una propiedad se utili1a un nombre simple Osi%ple-na%eR O[*. .2R o un acceso de miembro O%e%-er-accessR O[*. .4R, pero a un elemento del indi1ador se tiene acceso a trav)s de un acceso de elemento Oele%ent-accessR O[*. .#.2R. 7na propiedad puede ser un miembro static y un indi1ador siempre es un miembro de instancia. 7n descriptor de acceso get de una propiedad corresponde a un m)todo sin par(metros, pero un descriptor de acceso get de un indi1ador corresponde a un m)todo con la misma lista de par(metros 0ormales ?ue el indi1ador. 7n descriptor de acceso set de una propiedad corresponde a un m)todo con un solo par(metro denominado value, pero un descriptor de acceso set de un indi1ador corresponde a un m)todo con la misma lista de par(metros 0ormales ?ue el indi1ador y un par(metro adicional denominado value. .upone un error en tiempo de compilaci-n ?ue un descriptor de acceso de un indi1ador declare una variable local con el mismo nombre ?ue un par(metro del indi1ador.

3!2

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

En una declaraci-n de propiedad invalidada, se tiene acceso a la propiedad =eredada utili1ando la sintaxis
base.*, donde * es el nombre de la propiedad. En una declaraci-n de indi1ador invalidado, se tiene acceso al indi1ador =eredado utili1ando la sintaxis base4)5, donde ) es una lista de expresiones separadas por

comas. &l margen de estas di0erencias, todas las reglas de0inidas en [1".*.2 y [1".*.3 se aplican tanto a los descriptores de acceso de indi1adores como a los descriptores de acceso de propiedades. Cuando la declaraci-n de un indi1ador incluye un modi0icador e#tern, se dice ?ue es un indi-ador e.terno. 2ebido a ?ue la declaraci-n de un indi1ador externo no proporciona una implementaci-n real, cada una de sus declaraciones de descriptores de acceso Oaccessor-declarationsR consiste en un punto y coma. En el e$emplo siguiente se declara una clase :it'rray ?ue implementa un indi1ador para obtener acceso a los bits individuales de una matri1 de bits.
using System; class :it'rray { int45 bits; int lengt"; &ublic :it'rray(int lengt") { i- (lengt" D 3) t"ro, ne, 'rgument)#ce&tion(); bits + ne, int4((lengt" = 2) EE K) < 25; t"is.lengt" + lengt"; ! &ublic int Lengt" { get { return lengt"; ! ! &ublic bool t"is4int inde#5 { get { i- (inde# D 3 HH inde# E+ lengt") { t"ro, ne, $nde#%ut%-Oange)#ce&tion(); ! return (bits4inde# EE K5 F 2 DD inde#) @+ 3; ! set { i- (inde# D 3 HH inde# E+ lengt") { t"ro, ne, $nde#%ut%-Oange)#ce&tion(); ! i- (value) { bits4inde# EE K5 H+ 2 DD inde#; ! else { bits4inde# EE K5 F+ A(2 DD inde#); ! ! ! !

7na instancia de la clase :it'rray consume muc=a menos memoria ?ue el correspondiente bool45 Oya ?ue cada valor de la instancia del primero ocupa s-lo un bit en lugar del byte ?ue consume el HltimoR, pero permite las mismas operaciones ?ue bool45.

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

3!3

Especificacin del lenguaje C#

8a siguiente clase Count*rimes utili1a una :it'rray y el cl(sico algoritmo de PcribaQ para calcular el nHmero de primos entre 1 y un nHmero m(ximo dadoG
class Count*rimes { static int Count(int ma#) { :it'rray -lags + ne, :it'rray(ma# < 2); int count + 2; -or (int i + 8; i D+ ma#; i<<) { i- (@-lags4i5) { -or (int j + i > 8; j D+ ma#; j <+ i) -lags4j5 + true; count<<; ! ! return count; ! static void Main(string45 args) { int ma# + int.*arse(args435); int count + Count(ma#); Console.WriteLine("Vound {3! &rimes bet,een 2 and {2!" ! !

count

ma#);

/bserve ?ue la sintaxis para tener acceso a los elementos de :it'rray es precisamente la misma ?ue para bool45. En el siguiente e$emplo se muestra una clase de una cuadr5cula de 2# por 1" ?ue tiene un indi1ador con dos par(metros. El primer par(metro debe ser una letra mayHscula o minHscula dentro del intervalo &W\, y el segundo debe ser un nHmero entero dentro del intervalo "W+.
using System; class Srid { const int NumOo,s + 8X; const int NumCols + 23; int4 5 cells + ne, int4NumOo,s NumCols5; &ublic int t"is4c"ar c int col5 { get { c + C"ar.1o;&&er(c); i- (c D W'W HH c E WPW) { t"ro, ne, 'rgument)#ce&tion(); ! i- (col D 3 HH col E+ NumCols) { t"ro, ne, $nde#%ut%-Oange)#ce&tion(); ! return cells4c = W'W col5; ! set { c + C"ar.1o;&&er(c); i- (c D W'W HH c E WPW) { t"ro, ne, 'rgument)#ce&tion(); ! i- (col D 3 HH col E+ NumCols) { t"ro, ne, $nde#%ut%-Oange)#ce&tion(); ! cells4c = W'W col5 + value; ! ! !

3!#

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

10...1 4obrecarga de indi8adores 8as reglas de resoluci-n de sobrecarga de indi1adores se describen en [*.4.2.

10.10 ,peradores
7n operador es un miembro ?ue de0ine el signi0icado de un operador de expresi-n ?ue puede aplicarse a instancias de la clase. 8os operadores se declaran mediante declaraciones de operadores Ooperator-declarationsRG operator-declaration1 attri- tesopt operator-%odifiers operator-declarator operator--od# operator-%odifiers1 operator-%odifier operator-%odifiers operator-%odifier operator-%odifier1
&ublic static e#tern

operator-declarator1 nar#-operator-declarator -inar#-operator-declarator conversion-operator-declarator nar#-operator-declarator1 t#pe o&erator overloada-le- nar#-operator ( t#pe identifier ) overloada-le- nar#-operator1
< = @ A <<

no de
== true -alse

-inar#-operator-declarator1 t#pe o&erator overloada-le--inar#-operator ( t#pe identifier overloada-le--inar#-operator1


< = > . B F H G DD

t#pe identifier )

ri&ht-shift
++ @+ E D E+ D+

conversion-operator-declarator1 im&licit o&erator t#pe ( t#pe identifier ) e#&licit o&erator t#pe ( t#pe identifier )

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

3!!

Especificacin del lenguaje C#

operator--od#1 -loc3
;

Hay tres categor5as de operadores sobrecargablesG operadores unarios O[1".1".1R, operadores binarios O[1".1".2R y operadores de conversi-n O[1".1".3R. Cuando la declaraci-n de un operador incluye un modi0icador e#tern, se dice ?ue el operador es un operador e.terno. 2ebido a ?ue un operador externo no proporciona una implementaci-n real, su cuerpo de operador Ooperator--od#R consiste en un punto y coma. 'ara el resto de operadores, el cuerpo de operador Ooperator-od#R consiste en un blo?ue O-loc3R ?ue especi0ica las instrucciones ?ue deben e$ecutarse cuando se invoca al operador. El blo?ue O-loc3R de un operador debe cumplir las reglas de los m)todos ?ue devuelven valores, descritas en [1".#.1". 8as siguientes reglas se aplican a todas las declaraciones de operadoresG 7na declaraci-n de operador debe incluir los modi0icadores &ublic y static. 8os par(metros de un operador deben ser par(metros de valor. .upone un error en tiempo de compilaci-n ?ue una declaraci-n de operador especi0i?ue los par(metros re- u out. 8a 0irma de un operador O[1".1".1, [1".1".2, [1".1".3R debe ser di0erente de las 0irmas de todos los dem(s operadores declarados en la misma clase. Todos los tipos a los ?ue se =ace re0erencia en una declaraci-n de operador deben ser por lo menos tan accesibles como el propio operador O[3. .4R. Cuando el mismo modi0icador aparece varias veces en una declaraci-n de operador, se produce un error.

Cada categor5a de operador impone restricciones adicionales, ?ue se describen en las secciones siguientes. &l igual ?ue otros miembros, los operadores declarados en una clase base se =eredan por sus clases derivadas. 2ebido a ?ue las declaraciones de operadores siempre necesitan ?ue la clase o la estructura donde se declara el operador participe en la 0irma del operador, no es posible ?ue un operador declarado en una clase derivada oculte un operador declarado en una clase base. 'or lo tanto, nunca es necesario el modi0icador ne,, y por ello no se permite en una declaraci-n de operador. 'uede encontrar in0ormaci-n adicional sobre operadores unarios y binarios en la [*.2. 'uede encontrar in0ormaci-n adicional sobre operadores de conversi-n en [#.4. 10.10.1 ,peradores unarios 8as siguientes reglas se aplican a las declaraciones de operadores unarios, donde 1 denota el tipo de instancia de la clase o estructura ?ue contiene la declaraci-n del operadorG 7n operador unario <, =, @ o A debe adoptar un Hnico par(metro del tipo 1 o 17 y puede devolver cual?uier tipo. 7n operador unario << o == debe obtener un solo par(metro de tipo 1 o 17 y debe devolver el mismo tipo o un tipo derivado de )l. 7n operador unario true o -alse debe adoptar un Hnico par(metro de tipo 1 o 17 y debe devolver el tipo bool.

8a 0irma de un operador unario consiste en el to6en de operador O<, =, @, H, <<, ==, true o -alseR y el tipo del par(metro 0ormal. El tipo de valor devuelto no 0orma parte de la 0irma de un operador unario, ni es el nombre del par(metro 0ormal.

3!6

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

8os operadores unarios true y -alse re?uieren declaraciones par a par. .e produce un error en tiempo de compilaci-n si una clase declara uno de estos operadores sin declarar el otro. 8os operadores true y -alse se describen m(s detalladamente en las secciones [*.11.2 y [*.1+. En el siguiente e$emplo se muestra una implementaci-n y la utili1aci-n subsiguiente del operador << para una clase de vector de tipo enteroG
&ublic class $ntUector { &ublic $ntUector(int lengt") {...! &ublic int Lengt" {...! &ublic int t"is4int inde#5 {...! .. read=only &ro&erty .. read=,rite inde#er

&ublic static $ntUector o&erator <<($ntUector iv) { $ntUector tem& + ne, $ntUector(iv.Lengt"); -or (int i + 3; i D iv.Lengt"; i<<) tem&4i5 + iv4i5 < 2; return tem&; ! ! class 1est { static void Main() { $ntUector iv2 + ne, $ntUector(J); $ntUector iv8; iv8 + iv2<<; iv8 + <<iv2; ! !

.. vector o- J # 3 iv2 contains J # 2 iv2 contains J # 8

.. iv8 contains J # 3 .. iv8 contains J # 8

/bserve c-mo el m)todo del operador devuelve el valor producido al sumar 1 al operando, al igual ?ue los operadores de incremento y decremento post0i$o O[*. .+R, y los operadores de incremento y decremento pre0i$o O[*.#. R. & di0erencia de CSS, este m)todo no necesita modi0icar el valor de su operando directamente. 2e =ec=o, la modi0icaci-n del valor del operando in0ringir5a la sem(ntica est(ndar del operador post0i$o de incremento. 10.10.2 ,peradores binarios 8as siguientes reglas se aplican a las declaraciones de operadores binarios, donde 1 denota el tipo de instancia de la clase o estructura ?ue contiene la declaraci-n del operadorG 7n operador binario ?ue no sea de despla1amiento debe adoptar dos par(metros Oal menos uno debe tener el tipo 1 o 17R y puede devolver cual?uier tipo. 7n operador binario DD o EE debe adoptar dos par(metros Oel primero debe tener el tipo 1 o 17 y el segundo debe tener el tipo int o int7R y puede devolver cual?uier tipo.

8a 0irma de un operador binario consiste en el s5mbolo Oto6enR O<, =, >, ., B, F, H, G, DD, EE, ++, @+, E, D, E+ o D+R y los tipos de los dos par(metros 0ormales. El tipo de valor devuelto y los nombres de los par(metros 0ormales no 0orman parte de la 0irma de un operador binario. &lgunos operadores binarios re?uieren declaraci-n de par a par. 'ara la declaraci-n de cada operador del par, debe existir una declaraci-n coincidente del otro operador del par. 8as declaraciones de dos operadores coinciden cuando tienen el mismo tipo de valor devuelto y el mismo tipo para cada par(metro. 8os siguientes operadores re?uieren declaraci-n par a parG
o&erator ++ y o&erator @+ o&erator E y o&erator D o&erator E+ y o&erator D+

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

3!(

Especificacin del lenguaje C#

10.10.3 ,peradores de con ersin 7na declaraci-n de operador de conversi-n introduce una conversi,n definida por el !s!ario O[#.4R ?ue aumenta las conversiones impl5citas y expl5citas prede0inidas. 7na declaraci-n de operador de conversi-n ?ue incluye la palabra clave im&licit de0ine una conversi-n impl5cita de0inida por el usuario. 8as conversiones impl5citas pueden ocurrir en distintas situaciones, incluyendo las invocaciones de miembros de 0unci-n, las expresiones de conversi-n y las asignaciones. Esta categor5a se explica con m(s detalle en la secci-n [#.1. 7na declaraci-n de operador de conversi-n ?ue incluye la palabra clave e#&licit de0ine una conversi-n expl5cita de0inida por el usuario. 8as conversiones expl5citas pueden ocurrir en las expresiones de conversi-n, y se describen detalladamente en [#.2. 7n operador de conversi-n convierte de un tipo origen, indicado por el tipo del par(metro del operador de conversi-n, a un tipo destino, indicado por el tipo de valor devuelto del operador de conversi-n. 'ara un tipo de origen S y de destino 1 dados, si S o 1 son tipos ?ue aceptan valores 4788, S3 y 13 =acen re0erencia a sus tipos subyacentes, en caso contrario S3 y 13 son iguales ?ue S y 1 respectivamente. 7na clase o estructura tiene permitido declarar una conversi-n de un tipo de origen S a un tipo de destino 1 solamente si son verdaderos todos los puntos siguientesG
S3 y 13 son tipos di0erentes. S3 o 13 es el tipo de clase o estructura en el ?ue tiene lugar la declaraci-n del operador.

4i S3 ni 13 es un tipo de inter0a1 Ointerface-t#peR. Excluyendo las conversiones de0inidas por el usuario, una conversi-n no existe de S a 1 ni de 1 a S.

En lo ?ue respecta a estas reglas, cual?uier par(metro de tipo asociado con S o 1 se considera un tipo Hnico sin relaci-n de =erencia con otros tiposV asimismo, se omite cual?uier restricci-n en dic=os par(metros de tipo. En el e$emplo
class CD1E {...! class 6D1E/ CD1E { &ublic static im&licit o&erator CDintE(6D1E value) {...! &ublic static im&licit o&erator CD1E(6D1E value) {...! !

.. %( .. )rror

&ublic static im&licit o&erator CDstringE(6D1E value) {...! .. %(

las dos primeras declaraciones de operador se permiten por?ue, para los ob$etivos especi0icados en la secci-n [1".+.3, 1, int y string se consideran respectivamente tipos Hnicos sin relaci-n. .in embargo, el tercer operador es un error por?ue CD1E es la clase base de 6D1E. 2e la segunda regla se deriva ?ue un operador de conversi-n debe convertir a o del tipo de la clase o estructura en la ?ue se declara el operador. 'or e$emplo, es posible ?ue un tipo de clase o de estructura C de0ina una conversi-n de C a int y de int a C, pero no de int a bool. 4o es posible rede0inir directamente una conversi-n prede0inida. 'or lo tanto, no est( permitido utili1ar operadores de conversi-n para convertir de o a object por?ue ya existen conversiones impl5citas y expl5citas entre object y el resto de tipos. &dem(s, ni el tipo de origen ni el de destino de una conversi-n puede ser un tipo base del otro, por?ue entonces ya existir5a una conversi-n.

3!$

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

.in embargo, s* posible declarar operadores en tipos gen)ricos ?ue, para determinados argumentos de tipo, especi0i?uen conversiones ?ue ya existan como conversiones prede0inidas. En el e$emplo
struct ConvertibleD1E { &ublic static im&licit o&erator ConvertibleD1E(1 value) {...! &ublic static e#&licit o&erator 1(ConvertibleD1E value) {...! !

cuando el tipo object se especi0ica como un argumento de tipo para 1, el segundo operador declara una conversi-n ?ue ya existe Oexiste una conversi-n impl5cita y, por lo tanto, tambi)n expl5cita desde cual?uier tipo al tipo objectR. En los casos donde se da una conversi-n prede0inida entre dos tipos, se omite toda conversi-n de0inida por el usuario entre dic=os tipos. ConcretamenteG .i ya existe una conversi-n impl5cita prede0inida O[#.1R del tipo S al tipo 1, se omitir(n todas las conversiones de0inidas por el usuario Oimpl5citas o expl5citasR de S a 1. .i ya existe una conversi-n expl5cita prede0inida O[#,2R del tipo S al tipo 1, se omitir(n todas las conversiones expl5citas de0inidas por el usuario de S a 1. .in embargo, se seguir(n considerando las conversiones impl5citas de0inidas por el usuario de S a 1.

'ara todos los tipos, excepto para object, los operadores declarados por el tipo ConvertibleD1E anteriormente mencionado no entran en con0licto con las conversiones prede0inidas. 'or e$emploG
void i i n n ! V(int i ConvertibleDintE n) { + n; .. + (int)n; .. + i; .. + (ConvertibleDintE)i; .. )rror ;ser=de-ined e#&licit conversion ;ser=de-ined im&licit conversion ;ser=de-ined im&licit conversion

.in embargo, para el tipo object, las conversiones prede0inidas ocultan conversiones de0inidas por el usuario en todos los casos excepto en unoG
void o o n n ! V(object o ConvertibleDobjectE n) { + n; .. *re=de-ined bo#ing conversion + (object)n; .. *re=de-ined bo#ing conversion + o; .. ;ser=de-ined im&licit conversion + (ConvertibleDobjectE)o; .. *re=de-ined unbo#ing conversion

8as conversiones de0inidas por el usuario no pueden convertir de o a tipos de inter0a1 Ointerface-t#pesR. Esta restricci-n impide, en particular, ?ue se produ1can trans0ormaciones de0inidas por el usuario cuando se convierte a un tipo de inter0a1 Ointerface-t#peR, y asegura ?ue una conversi-n a un tipo de inter0a1 se e$ecute correctamente s-lo si el ob$eto ?ue se est( convirtiendo implementa realmente el tipo de inter0a1. 8a 0irma de un operador de conversi-n est( 0ormado por el tipo de origen y el tipo de destino O)sta es la Hnica 0orma de miembro en la ?ue el tipo de valor devuelto participa en la 0irmaR. 8a clasi0icaci-n im&licit o e#&licit de un operador de conversi-n no 0orma parte de la 0irma del operador. 'or lo tanto, una clase o una estructura no puede declarar a la ve1 operadores de conversi-n im&licit y e#&licit con los mismos tipos de origen y destino. En general, las conversiones impl5citas de0inidas por el usuario deben diseUarse para ?ue nunca produ1can excepciones ni pierdan in0ormaci-n. .i una conversi-n de0inida por el usuario puede dar lugar a excepciones Opor e$emplo, debido a ?ue el argumento de origen est( 0uera del intervaloR o a p)rdida de in0ormaci-n Ocomo descartar los bits de mayor ordenR, dic=a conversi-n deber5a de0inirse como expl5cita.

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

3!"

Especificacin del lenguaje C#

En el e$emplo
using System; &ublic struct 6igit { byte value; &ublic 6igit(byte value) { i- (value D 3 HH value E L) t"ro, ne, 'rgument)#ce&tion(); t"is.value + value; ! &ublic static im&licit o&erator byte(6igit d) { return d.value; ! &ublic static e#&licit o&erator 6igit(byte b) { return ne, 6igit(b); ! !

la conversi-n de 6igit a byte es impl5cita por?ue nunca produce excepciones ni pierde in0ormaci-n, pero la conversi-n de byte a 6igit es expl5cita ya ?ue 6igit s-lo puede representar un subcon$unto de los posibles valores de un byte.

10.11 %onstructores de instancia


7n constr!ctor de instancia es un miembro ?ue implementa las acciones ?ue se re?uieren para iniciali1ar una instancia de una clase. 8os constructores de instancia se declaran mediante declaraciones de constructor Oconstr ctor-declarationsRG constr ctor-declaration1 attri- tesopt constr ctor-%odifiersopt constr ctor-declarator constr ctor--od# constr ctor-%odifiers1 constr ctor-%odifier constr ctor-%odifiers constr ctor-%odifier constr ctor-%odifier1
&ublic &rotected internal &rivate e#tern

constr ctor-declarator1 identifier ( for%al-para%eter-listopt ) constr ctor-initiali0eropt constr ctor-initiali0er1 / base ( ar& %ent-listopt ) / t"is ( ar& %ent-listopt ) constr ctor--od#1 -loc3
;

7na declaraci-n de constructor Oconstr ctor-declarationR puede incluir un con$unto de atributos Oattri- tesR O[R, una combinaci-n v(lida de los cuatro modi0icadores de acceso O[R y un modi0icador e#tern O[R. 4o se permite ?ue una declaraci-n de constructor incluya un mismo modi0icador varias veces.

36'

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

El identi0icador OidentifierR de un declarador de constructor Oconstr ctor-declaratorR debe nombrar la clase en la ?ue se declara el constructor de instancia. .i se especi0ica cual?uier otro nombre, se produce un error en tiempo de compilaci-n. 8a lista de par(metros 0ormales Ofor%al-para%eter-listR opcional de un constructor de instancia est( su$eta a las mismas reglas ?ue la lista de par(metros 0ormales Ofor%al-para%eter-listR de un m)todo O[1".#R. 8a lista de par(metros 0ormales de0ine la 0irma O[3.#R de un constructor de instancia y dirige el proceso por el ?ue la resoluci-n de sobrecarga O[*.4.2R selecciona un constructor de instancia en particular en una invocaci-n. Cada uno de los tipos a los ?ue se =ace re0erencia en la lista de par(metros 0ormales Ofor%al-para%eter-listR de un constructor de instancia deben tener como m5nimo el mismo nivel de accesibilidad ?ue el propio constructor O[3. .4R. El iniciali1ador de constructor Oconstr ctor-initiali0erR opcional especi0ica otro constructor de instancia al ?ue =ay ?ue invocar antes de e$ecutar las instrucciones ?ue aparecen en el cuerpo del constructor Oconstr ctor--od#R del primer constructor de instancia. Esta categor5a se explica con m(s detalle en la secci-n [1".11.1. Cuando la declaraci-n de un constructor incluye un modi0icador e#tern, se dice ?ue el constructor es un constr!ctor e.terno. 2ebido a ?ue la declaraci-n de constructor externo no proporciona una implementaci-n real, su cuerpo del constructor Oconstr ctor--od#R consiste en un punto y coma. 'ara el resto de constructores, el cuerpo del constructor Oconstr ctor--od#R consiste en un blo?ue O-loc3R ?ue especi0ica las instrucciones para iniciali1ar una nueva instancia de la clase. Esto corresponde exactamente al blo?ue O-loc3R de un m)todo de instancia con un tipo de valor devuelto void O[1".#.1"R. 8os constructores de instancia no se =eredan. 'or lo tanto, una clase s-lo tiene los constructores de instancia ?ue se declaran realmente en la clase. .i una clase no contiene ninguna declaraci-n de constructor de instancia, se proporciona autom(ticamente un constructor de instancia predeterminado O[1".11.4R. 8os constructores de instancia se invocan mediante expresiones de creaci-n de ob$etos Oo->ect-creatione2pressionsR O[*. .1".1R y a trav)s de iniciali1adores de constructor Oconstr ctor-initiali0ersR. 10.11.1 Iniciali8adores de constructor Todos los constructores de instancia Oexcepto a?uellos para la clase objectR incluyen impl5citamente una invocaci-n de otro constructor de instancia inmediatamente antes del cuerpo del constructor Oconstr ctor--od#R. El constructor ?ue se invoca impl5citamente est( determinado por el iniciali1ador de constructor Oconstr ctorinitiali0erRG 7n iniciali1ador de constructor de instancia con la estructura base(ar& %ent-listopt), es decir 4base Olista de argumentos opcionalRh, causa la invocaci-n de un constructor de instancia desde la clase base directa. Este constructor se selecciona utili1ando la lista de argumentos Oar& %ent-listR y las reglas de resoluci-n de sobrecargas de [*.4.3. El con$unto de constructores de instancia candidatos est( compuesto de todos los constructores de instancia accesibles contenidos en la clase base directa, o del constructor predeterminado O[1".11.4R, si en la clase base directa no se declara ningHn constructores de instancia. .i el con$unto est( vac5o o no es posible identi0icar el me$or constructor de instancia, se produce un error en tiempo de compilaci-n. 7n iniciali1ador de constructor de instancia con la estructura t"is(argument=listo&t) causa la invocaci-n de un constructor de instancia desde la propia clase. El constructor se selecciona utili1ando la lista de argumentos Oar& %ent-listR y las reglas de resoluci-n de sobrecargas de [*.4.3. El con$unto de constructores de instancia candidatos est( 0ormado por todos los constructores de instancia accesibles declarados en la clase. .i el con$unto est( vac5o o no es posible identi0icar el me$or constructor de instancia, se produce un error en tiempo de compilaci-n. .i la declaraci-n de un constructor de instancia incluye un iniciali1ador de constructor ?ue invoca al propio constructor, se produce un error en tiempo de compilaci-n.

.i un constructor de instancia no tiene iniciali1ador de constructor, se proporciona impl5citamente uno con la estructura base(). 'or lo tanto, una declaraci-n de constructor de instancia de la 0orma
C(...) {...!

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

361

Especificacin del lenguaje C#

e?uivale exactamente a
C(...)/ base() {...!

El (mbito de los par(metros dados en la lista de par(metros 0ormales Ofor%al-para%eter-listR de una declaraci-n de constructor de instancia incluye el iniciali1ador de constructor de dic=a declaraci-n. 'or lo tanto, un iniciali1ador de constructor puede tener acceso a los par(metros del constructor. 'or e$emploG
class ' { &ublic '(int # ! class :/ ' { &ublic :(int # ! int y) {!

int y)/ base(# < y

# = y) {!

7n iniciali1ador de constructor de instancia no puede tener acceso a la instancia ?ue est( siendo creada. 'or ello, se produce un error en tiempo de compilaci-n si se =ace re0erencia a t"is en una expresi-n de argumento del iniciali1ador del constructor, al igual ?ue se produce un error en tiempo de compilaci-n si una expresi-n de argumento =ace re0erencia a cual?uier miembro de instancia a trav)s del nombre simple Osi%ple-na%eR. 10.11.2 Iniciali8adores de ariables de instancia Cuando un constructor de instancia no tiene iniciali1ador de constructor, o cuando tiene uno de la 0orma base(...), el constructor reali1a impl5citamente las iniciali1aciones especi0icadas por los iniciali1adores de variables Ovaria-le-initiali0ersR de los campos de instancia declarados en su clase. Esto corresponde a una secuencia de asignaciones ?ue se e$ecutan inmediatamente al entrar en el constructor y antes de invocar impl5citamente al constructor de la clase base directa. 8os iniciali1adores de variable se e$ecutan en el orden textual en ?ue aparecen en la declaraci-n de clase. 10.11.3 Ejecucin de constructores 8os iniciali1adores de variables se trans0orman en instrucciones de asignaci-n, ?ue se e$ecutan antes de la invocaci-n del constructor de instancia de la clase base. Tal ordenamiento garanti1a ?ue todos los campos de instancia son iniciali1ados por sus iniciali1adores de variable antes de ?ue se e$ecute cual?uier instrucci-n ?ue tenga acceso a la instancia. 2ado el e$emploG
using System; class ' { &ublic '() { *rintVields(); ! &ublic virtual void *rintVields() {! ! class :/ ' { int # + 2; int y; &ublic :() { y + =2; !

362

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases &ublic override void *rintVields() { Console.WriteLine("# + {3! y + {2!" ! !

y);

cuando se utili1a ne, :() para crear una instancia de :, el resultado ?ue se produce esG
# + 2 y + 3

El valor de # es 1 por?ue el iniciali1ador de variable se e$ecuta antes de ?ue se invo?ue el constructor de instancia de la clase base. .in embargo, el valor de y es " Oel valor predeterminado para un tipo intR por?ue la asignaci-n a y no se e$ecuta =asta ?ue el constructor de la clase base devuelve el control. Es Htil considerar los iniciali1adores de variables de instancia y los iniciali1adores de constructor como instrucciones ?ue se insertan autom(ticamente antes del cuerpo del constructor Oconstr ctor--od#R. El e$emplo
using System; using System.Collections; class ' { int # + 2

y + =2

count;

&ublic '() { count + 3; ! &ublic '(int n) { count + n; ! ! class :/ ' { double sQrt8 + Mat".SQrt(8.3); 'rrayList items + ne, 'rrayList(233); int ma#; &ublic :()/ t"is(233) { items.'dd("de-ault"); ! &ublic :(int n)/ base(n C 2) { ma# + n; ! !

contiene varios iniciali1adores de variable e iniciali1adores de constructor de ambas 0ormas Obase y t"isR. El c-digo del e$emplo se corresponde con el c-digo siguiente, donde cada comentario indica una instrucci-n ?ue se inserta autom(ticamente Ola sintaxis utili1ada para invocar el constructor insertado autom(ticamente no es correcta, pero sirve para ilustrar el mecanismoR.
using System.Collections; class ' { int #

count; .. Uariable initiali?er .. Uariable initiali?er .. $nvo(e object() constructor

&ublic '() { # + 2; y + =2; object(); count + 3; !

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

363

Especificacin del lenguaje C# &ublic '(int n) { # + 2; y + =2; object(); count + n; ! ! class :/ ' { double sQrt8; 'rrayList items; int ma#; &ublic :()/ t"is(233) { :(233); items.'dd("de-ault"); ! &ublic :(int n)/ base(n C 2) { sQrt8 + Mat".SQrt(8.3); items + ne, 'rrayList(233); '(n C 2); ma# + n; ! ! .. $nvo(e :(int) constructor

.. Uariable initiali?er .. Uariable initiali?er .. $nvo(e object() constructor

.. Uariable initiali?er .. Uariable initiali?er .. $nvo(e '(int) constructor

10.11.! %onstructores predeterminados .i una clase no contiene ninguna declaraci-n de constructores de instancia, se proporciona autom(ticamente un constructor de instancia predeterminado. El constructor predeterminado simplemente invoca el constructor sin par(metros de la clase base directa. .i la clase base directa no tiene un constructor de instancia sin par(metros accesible, se producir( un error en tiempo de compilaci-n. .i la clase es abstracta, la accesibilidad declarada para el constructor predeterminado es protected. .i no, la accesibilidad declarada para el constructor predeterminado es public. 'or lo tanto, el constructor predeterminado es siempre de la 0orma
&rotected C()/ base() {!

o
&ublic C()/ base() {!

donde C es el nombre de la clase. En el e$emplo


class Message { object sender; string te#t; !

se proporciona un constructor predeterminado debido a ?ue la clase no contiene ninguna declaraci-n de constructor de instancia. &s5, el e$emplo es exactamente e?uivalente a
class Message { object sender; string te#t; &ublic Message()/ base() {! !

36#

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

10.11.# %onstructores (ri ate Cuando una clase 1 s-lo declara constructores de instancia privados, las clases externas al texto del programa de 1 no pueden ni derivarse ni crear directamente instancias de 1. 'or lo tanto, si una clase contiene s-lo miembros est(ticos y no se desea crear una instancia con )l, puede evitarse tal instancia agregando un constructor de instancia privado ?ue est) vac5o. 'or e$emploG
&ublic class 1rig { &rivate 1rig() {! .. *revent instantiation

&ublic const double *$ + 9.2J2KL8XK9KYLML989YJX; &ublic static double Sin(double #) {...! &ublic static double Cos(double #) {...! &ublic static double 1an(double #) {...! !

8a clase 1rig agrupa m)todos y constantes relacionados, pero su intenci-n no es crear una instancia de la misma. 'or ello declara un Hnico constructor de instancia privado vac5o. .e debe declarar al menos un constructor de instancia para suprimir la generaci-n autom(tica de un constructor predeterminado. 10.11.$ (ar)metros de constructor de instancia opcionales 8a 0orma t"is(...) de un iniciali1ador de constructor se suele utili1ar con$untamente con sobrecarga para implementar par(metros de constructor de instancia opcionales. En el e$emplo
class 1e#t { &ublic 1e#t()/ t"is(3 &ublic 1e#t(int # 3 null) {! y null) {!

int y)/ t"is(#

&ublic 1e#t(int # int y string s) { .. 'ctual constructor im&lementation ! !

los dos primeros constructores de instancia s-lo proporcionan los valores predeterminados para los argumentos ?ue 0altan. &mbos usan un iniciali1ador de constructor t"is(...) para invocar el tercer constructor de instancia, ?ue es el ?ue realmente iniciali1a la nueva instancia. El e0ecto son par(metros de constructor opcionalesG
1e#t t2 + ne, 1e#t(); .. Same as 1e#t(3 1e#t t8 + ne, 1e#t(K 23); .. Same as 1e#t(K 1e#t t9 + ne, 1e#t(K 83 "Hello"); 3 null) 23 null)

10.12 %onstructores static


7n constr!ctor est5tico es un miembro ?ue implementa las acciones ?ue se re?uieren para iniciali1ar un tipo de clase cerrado. 8os constructores est(ticos se declaran mediante declaraciones de constructores est(ticos Ostaticconstr ctor-declarationsRG static-constr ctor-declaration1 attri- tesopt static-constr ctor-%odifiers identifier ( ) static-constr ctor--od# static-constr ctor-%odifiers1
e#ternopt static static e#ternopt

static-constr ctor--od#1 -loc3


;

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

36!

Especificacin del lenguaje C#

7na declaraci-n de constructor est(tico Ostatic-constr ctor-declarationR puede incluir un con$unto de atributos Oattri- tesR O[1*R y un modi0icador e#tern O[1".#.*R. El identi0icador OidentifierR de una declaraci-n de constructor est(tico Ostatic-constr ctor-declarationR debe nombrar la clase en la ?ue se declara el constructor est(tico. .i se especi0ica cual?uier otro nombre, se produce un error en tiempo de compilaci-n. Cuando la declaraci-n de un constructor est(tico incluye un modi0icador e#tern, se dice ?ue el constructor es un constr!ctor est5tico e.terno. 2ebido a ?ue la declaraci-n de constructor est(tico externo no proporciona una implementaci-n real, su cuerpo de constructor est(tico Ostatic-constr ctor--od#R consiste en un punto y coma. 'ara todas las dem(s declaraciones de constructor est(tico, el cuerpo del constructor est(tico Ostatic-constr ctor-od#R se compone de un blo?ue O-loc3R ?ue especi0ica las instrucciones ?ue deben e$ecutarse para poder iniciali1ar la clase. Esto corresponde exactamente al cuerpo del m)todo O%ethod--od#R est(tico con un tipo de valor devuelto void O[1".#.1"R. 8os constructores est(ticos no se =eredan y no pueden ser llamados directamente. El constructor est(tico de un tipo de clase cerrado se e$ecuta como muc=o una ve1 en un dominio de aplicaci-n dado. 8a e$ecuci-n de un constructor est(tico la desencadena el primero de los siguientes eventos ?ue se produ1can en un dominio de aplicaci-n. .e crea una instancia del tipo de clase. .e =ace re0erencia a cual?uiera de los miembros est(ticos del tipo de clase.

.i una clase contiene el m)todo Main O[3.1R en el ?ue comien1a la e$ecuci-n, el constructor est(tico de esta clase se e$ecuta antes de ?ue se llame al m)todo Main. 'ara iniciali1ar un nuevo tipo de clase cerrado, primero se crea un nuevo con$unto de campos est(ticos O[1". .1R para dic=o tipo cerrado. Cada uno de los campos est(ticos recupera su valor predeterminado O[ .2R. & continuaci-n, los iniciali1adores de campos est(ticos O[1". . .1R se e$ecutan para dic=os campos est(ticos. 'or Hltimo, se e$ecuta el constructor est(tico. En el e$emplo
using System; class 1est { static void Main() { '.V(); :.V(); ! ! class ' { static '() { Console.WriteLine("$nit '"); ! &ublic static void V() { Console.WriteLine("'.V"); ! !

366

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases class : { static :() { Console.WriteLine("$nit :"); ! &ublic static void V() { Console.WriteLine(":.V"); ! !

el resultado debe serG


$nit ' '.V $nit : :.V

por?ue la e$ecuci-n del constructor est(tico de ' se desencadena al llamar a '.V, y la e$ecuci-n del constructor est(tico de : se desencadena cuando se llama a :.V. Es posible construir dependencias circulares ?ue permitan a los campos est(ticos con iniciali1adores de variables ser observados en su estado de valor predeterminado. El e$emplo
using System; class ' { &ublic static int I; static '() { I + :.` < 2; ! ! class : { &ublic static int ` + '.I < 2; static :() {! static void Main() { Console.WriteLine("I + {3! ! ! ` + {2!" '.I :.`);

produce el resultado
I + 2 ` + 8

'ara e$ecutar el m)todo Main, el sistema e$ecuta en primer lugar el iniciali1ador de :.`, antes ?ue el constructor est(tico de la clase :. El iniciali1ador de ` =ace ?ue se e$ecute el constructor est(tico de ', por?ue se =ace re0erencia al valor de '.I. 'or su parte, el constructor est(tico de ' continHa para calcular el valor de I y, para =acerlo, obtiene el valor predeterminado de `, ?ue es cero. &s5, '.I se iniciali1a a 1. & continuaci-n se completa el proceso de e$ecutar los iniciali1adores de campos est(ticos de ' y el constructor est(tico, volviendo al c(lculo del valor inicial de `, cuyo resultado es 2. 'uesto ?ue el constructor est(tico se e$ecuta exactamente una ve1 para cada tipo de clase construida cerrada, resulta un lugar conveniente para exigir las comprobaciones en tiempo de e$ecuci-n en el par(metro de tipo ?ue no se pueden comprobar durante la compilaci-n mediante restricciones O[1".1. R. 'or e$emplo, el siguiente tipo utili1a un constructor est(tico para exigir ?ue el argumento de tipo es un enumG

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

36(

Especificacin del lenguaje C# class SenD1E ,"ere 1/ struct { static Sen() { i- (@ty&eo-(1).$s)num) { t"ro, ne, 'rgument)#ce&tion("1 must be an enum"); ! ! !

10.13 /estructores
7n destr!ctor es un miembro ?ue implementa las acciones necesarias para destruir una instancia de una clase. 7n destructor se declara mediante una declaraci-n de destructor Odestr ctor-declarationRG destr ctor-declaration1 attri- tesopt e#ternopt A identifier ( ) destr ctor--od# destr ctor--od#1 -loc3
;

7na declaraci-n de destructor Odestr ctor-declarationR puede incluir un con$unto de atributos Oattri- tesR O[1*R. El identi0icador OidentifierR de una declaraci-n de destructor Odestr ctor-declaratorR debe nombrar la clase en la ?ue se declara el destructor. .i se especi0ica cual?uier otro nombre, se produce un error en tiempo de compilaci-n. Cuando una declaraci-n de destructor incluye un modi0icador e#tern, se dice ?ue es un destr!ctor e.terno. 2ebido a ?ue la declaraci-n de destructor externo no proporciona una implementaci-n real, su cuerpo de destructor Odestr ctor--od#R consiste en un punto y coma. 'ara el resto de destructores, el cuerpo del destructor Odestr ctor--od#R consiste en un blo?ue O-loc3R ?ue especi0ica las instrucciones necesarias para destruir una instancia de la clase. 7n cuerpo de destructor Odestr ctor--od#R corresponde exactamente al cuerpo del m)todo O%ethod--od#R de un m)todo de instancia con un tipo de valor devuelto void O[R. 8os destructores no se =eredan. 'or lo tanto, una clase s-lo tiene el destructor ?ue se puede declarar en la propia clase. Como un destructor no puede tener par(metros, no puede ser sobrecargadoV por lo tanto, una clase s-lo puede tener como m(ximo un destructor. 8os destructores se invocan autom(ticamente y no se pueden invocar expl5citamente. 7na instancia se convierte en candidata para destrucci-n cuando ya ninguna parte de c-digo puede utili1arla. 8a e$ecuci-n del destructor de la instancia puede ocurrir en cual?uier momento una ve1 ?ue la instancia se convierta en candidata para destrucci-n. Cuando se destruye una instancia, se llama a los destructores de su cadena de =erencia en orden, de la m(s derivada a la menos derivada. 7n destructor puede e$ecutarse en cual?uier subproceso. 'ara leer una explicaci-n m(s detallada de las reglas ?ue controlan c-mo y cu(ndo se e$ecuta un destructor, vea la secci-n [3.+. El resultado del e$emplo
using System; class ' { A'() { Console.WriteLine("'Ws destructor"); ! !

36$

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases class :/ ' { A:() { Console.WriteLine(":Ws destructor"); ! ! class 1est { static void Main() { : b + ne, :(); b + null; SC.Collect(); SC.WaitVor*endingVinali?ers(); ! !

es
:_s destructor '_s destructor

ya ?ue en una cadena de =erencia los destructores se llaman en orden, de la m(s derivada a la menos derivada. 8os destructores se implementan invalidando el m)todo virtual Vinali?e en System.%bject. 8os programas de C# no permiten invalidar este m)todo o llamarlo directamente Oo a invalidarlos del mismoR. 'or e$emplo, el programa
class ' { override &rotected void Vinali?e() {! &ublic void V() { t"is.Vinali?e(); ! ! .. error .. error

contiene dos errores. El compilador se comporta como si este m)todo, y sus invalidaciones, no existieran. 'or lo tanto, este programaG
class ' { void Vinali?e() {! ! .. &ermitted

es v(lido, y el m)todo mostrado oculta el m)todo Vinali?e de System.%bject. 'ara leer una explicaci-n del comportamiento producido cuando se inicia una excepci-n desde un destructor, vea la secci-n [1#.3.

10.1! Iteradores
7n miembro de 0unci-n O[*.4R implementado mediante un blo?ue de iteradores O[8.2R se denomina iterador. 7n blo?ue de iteradores se puede utili1ar como cuerpo del miembro de 0unci-n siempre ?ue el tipo de valor devuelto del miembro de 0unci-n correspondiente sea una de las inter0aces del enumerador O[1".14.1R o una de las inter0aces enumerables O[1".14.2R. 'uede tener lugar como cuerpo de m)todo O%ethod--od#R, cuerpo de operador Ooperator--od#R o cuerpo de descriptor de acceso Oaccessor--od#R, mientras ?ue los eventos, constructores de instancia, constructores est(ticos y destructores no se pueden implementar como iteradores. Cuando un miembro de 0unci-n se implementa utili1ando un blo?ue de iteradores, se genera un error en tiempo de compilaci-n si la lista de par(metros 0ormales del miembro de 0unci-n especi0ica un par(metro re- u out.

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

36"

Especificacin del lenguaje C#

10.1!.1 Interfaces del enumerador 8as interfaces del en! erador son la inter0a1 no gen)rica System.Collections.$)numerator y todas las creaciones de instancias de la inter0a1 gen)rica System.Collections.Seneric.$)numeratorD1E. 'ara ser breves, en este cap5tulo estas inter0aces se denominar(n $)numerator e $)numeratorD1E respectivamente. 10.1!.2 Interfaces enumerables 8as interfaces en! era/les son la inter0a1 no gen)rica System.Collections.$)numerable y todas las creaciones de instancias de la inter0a1 gen)rica System.Collections.Seneric.$)numerableD1E. 'ara ser breves, en este cap5tulo estas inter0aces se denominar(n $)numerable e $)numerableD1E respectivamente. 10.1!.3 Tipo Eield 7n iterador genera una secuencia de valores, todos del mismo tipo. Este tipo se denomina tipo yield del iterador. El tipo yield de un iterador ?ue devuelve $)numerator o $)numerable es object. El tipo yield de un iterador ?ue devuelve $)numeratorD1E o $)numerable es object.

10.1!.! ,bjetos del enumerador Cuando un miembro de 0unci-n ?ue devuelve un tipo de inter0a1 del enumerador se implementa utili1ando un blo?ue de iteradores, al invocar el miembro de 0unci-n no se e$ecuta inmediatamente el c-digo del blo?ue de iteradores. En su lugar, se crea y se devuelve un o/1eto del en! erador. Este ob$eto encapsula el c-digo especi0icado en el blo?ue de iteradores y la e$ecuci-n del c-digo dentro del blo?ue de iteradores cuando se invoca el m)todo MoveNe#t del ob$eto del enumerador. 7n ob$eto del enumerador tiene las siguientes caracter5sticasG !mplementa $)numerator e $)numeratorD1E, donde 1 es el tipo yield del blo?ue de iteradores. !mplementa System.$6is&osable. .e iniciali1a con una copia de los valores de los argumentos Osi los =ayR y el valor de la instancia ?ue se pas- al miembro de 0unci-n. Tiene cuatro estados potencialesG antes, en e1ec!ci,n, s!spendido y desp!6s e inicialmente se encuentra en el estado antes.

7n ob$eto del enumerador es generalmente una instancia de una clase de enumerador generado por compilador ?ue encapsula el c-digo en el blo?ue de iteradores e implementa las inter0aces del enumerador, pero tambi)n son posibles otros m)todos de implementaci-n. .i el compilador genera una clase de enumerador, )sta se anidar( directa o indirectamente en la clase ?ue contiene el miembro de 0unci-n, tendr( accesibilidad privada y un nHmero reservado para el uso del compilador O[2.4.2R. 7n ob$eto del enumerador puede implementar m(s inter0aces ?ue las especi0icadas anteriormente. En las siguientes secciones se describe el comportamiento exacto de los miembros MoveNe#t, Current y 6is&ose de las implementaciones de las inter0aces $)numerable y $)numerableD1E proporcionadas por un ob$eto del enumerador. Tenga en cuenta ?ue los ob$etos del enumerador no admiten el m)todo $)numerator.Oeset. .i se invoca este m)todo, se genera una excepci-n System.NotSu&&orted)#ce&tion. 17.14.4.1 &l mtodo MoveEe2t El m)todo MoveNe#t de un ob$eto del enumerador encapsula el c-digo de un blo?ue de iteradores. .i se invoca el m)todo MoveNe#t, se e$ecuta c-digo en el blo?ue de iteradores y se establece la propiedad Current del

3('

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

ob$eto del enumerador de la manera apropiada. 8a acci-n concreta reali1ada por MoveNe#t depende del estado del ob$eto del enumerador cuando se invoca MoveNe#tG .i el estado del ob$eto del enumerador es antes y se invoca MoveNe#tG o o o Cambia el estado a en e1ec!ci,n. .e iniciali1an los par(metros Oincluido t"isR del blo?ue de iteradores para los valores de argumentos y de instancias guardados cuando se iniciali1- el ob$eto del enumerador. .e e$ecuta el blo?ue de iteradores desde el principio =asta ?ue se interrumpe la e$ecuci-n Ode la manera descrita a continuaci-nR.

.i el estado del ob$eto del enumerador es en e1ec!ci,n, el resultado de la invocaci-n de MoveNe#t no se especi0ica. .i el estado del ob$eto del enumerador es s!spendido y se invoca MoveNe#tG o o Cambia el estado a en e1ec!ci,n. .e restauran los valores de todas las variables y par(metros locales Oincluido t=isR a los valores guardados durante la Hltima ve1 ?ue se suspendi- el blo?ue de iteradores. Tenga en cuenta ?ue el contenido de todos los ob$etos a los ?ue estas variables =acen re0erencia puede =aber cambiado desde la Hltima llamada a %ove4ext. .e reanuda la e$ecuci-n del blo?ue de iteradores inmediatamente despu)s de la instrucci-n yield return ?ue provoc- la suspensi-n de la e$ecuci-n y continHa =asta ?ue )sta se interrumpe Ode la manera descrita a continuaci-nR.

.i el estado del ob$eto del enumerador es desp!6s y se invoca MoveNe#t se obtiene -alse.

Cuando MoveNe#t e$ecuta el blo?ue de iteradores, se puede interrumpir la e$ecuci-n de cuatro manerasG mediante las instrucciones yield return y yield brea(, detectando el 0inal del blo?ue de iteradores, generando una excepci-n y propag(ndola 0uera del blo?ue de iteradores. Cuando se detecta una instrucci-n yield return O[8.14RG o o 8a expresi-n de la instrucci-n se evalHa, se convierte en el tipo yield y se asigna a la propiedad Current del ob$eto del enumerador. .e suspende la e$ecuci-n del cuerpo del iterador. 8os valores de todas las variables y par(metros locales Oincluido t"isR se guardan, al igual ?ue la ubicaci-n de esta instrucci-n yield return. .i la instrucci-n yield return se encuentra dentro de uno o m(s blo?ues try, los blo?ues -inally asociados no se e$ecutan en este momento. El estado del ob$eto del enumerador cambia a s!spendido. El m)todo MoveNe#t devuelve true a su llamador indicando ?ue la iteraci-n avan1- correctamente al siguiente valor. .i la instrucci-n yield brea( se encuentra dentro de uno o m(s blo?ues try, se e$ecutan los blo?ues -inally. El estado del ob$eto del enumerador cambia a desp!6s. El m)todo MoveNe#t devuelve -alse a su llamador indicando ?ue la iteraci-n est( completa.

o o

Cuando se detecta una instrucci-n yield brea( O[8.14RG o o o

Cuando se detecta el 0inal del cuerpo del iteradorG

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

3(1

Especificacin del lenguaje C#

o o o o o

El estado del ob$eto del enumerador cambia a desp!6s. El m)todo MoveNe#t devuelve -alse a su llamador indicando ?ue la iteraci-n est( completa. &l propagarse, la excepci-n =abr( e$ecutado los blo?ues -inally apropiados en el cuerpo del iterador. El estado del ob$eto del enumerador cambia a desp!6s. 8a propagaci-n de la excepci-n continHa al llamador del m)todo MoveNe#t.

Cuando se genera una excepci-n y se propaga 0uera del blo?ue de iteradoresG

17.14.4.2 *a propiedad Current 8as instrucciones yield return a0ectan a las propiedades Current del ob$eto del enumerador en el blo?ue de iteradores. Cuando un ob$eto del enumerador se encuentra en el estado s!spendido, el valor de Current es el valor establecido por la llamada anterior a MoveNe#t. Cuando un ob$eto del enumerador se encuentra en los estados antes, en e1ec!ci,n o desp!6s, el resultado del acceso a Current no se especi0ica. 'ara un blo?ue de iteradores con un tipo yield di0erente de object, el acceso a Current mediante la implementaci-n de $)numerable del ob$eto del enumerador e?uivale al acceso a Current mediante la implementaci-n de $)numeratorD1E del ob$eto del enumerador y el resultado se convierte en object. 17.14.4.3 &l mtodo (ispose El m)todo 6is&ose se utili1a para limpiar la iteraci-n ya ?ue el estado del ob$eto del enumerador pasa a ser desp!6s. .i el estado del ob$eto del enumerador es antes y se invoca 6is&ose, el estado pasa a ser desp!6s. .i el estado del ob$eto del enumerador es en e1ec!ci,n, el resultado de la invocaci-n de 6is&ose no se especi0ica. .i el estado del ob$eto del enumerador es s!spendido y se invoca 6is&oseG o o Cambia el estado a en e1ec!ci,n. Todos los blo?ues 0inally se e$ecutan como si la Hltima instrucci-n yield return e$ecutada 0uera una instrucci-n yield brea(. .i esto causa ?ue se genere una excepci-n y se propague 0uera del cuerpo del iterador, el estado del ob$eto del enumerador se establecer( en desp!6s y la excepci-n se propagar( al llamador del m)todo 6is&ose. Cambia el estado a desp!6s.

.i el estado del ob$eto del enumerador es desp!6s y se invoca 6is&ose, no =ay cambios.

10.1!.# ,bjetos enumerables Cuando se utili1a un blo?ue de iteradores para implementar un miembro de 0unci-n ?ue devuelve un tipo de inter0a1 enumerable y se invoca el miembro de 0unci-n, el c-digo de dic=o blo?ue no se e$ecuta inmediatamente. En su lugar se crea y se devuelve un o/1eto en! era/le. El m)todo Set)numerator del ob$eto enumerable devuelve un ob$eto del enumerador ?ue encapsula el c-digo especi0icado en el blo?ue de iteradores y la e$ecuci-n del c-digo del blo?ue de iteradores tiene lugar cuando se invoca el m)todo MoveNe#t del ob$eto del enumerador. 7n ob$eto enumerable tiene las siguientes caracter5sticasG !mplementa $)numerable e $)numerableD1E, donde 1 es el tipo yield del blo?ue de iteradores.

3(2

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

.e iniciali1a con una copia de los valores de los argumentos Osi los =ayR y el valor de la instancia ?ue se pas- al miembro de 0unci-n.

3eneralmente, un ob$eto enumerable es una instancia de una clase enumerable generada por compilador ?ue encapsula el c-digo en el blo?ue de iteradores e implementa las inter0aces enumerables, pero tambi)n son posibles otros m)todos de implementaci-n. .i el compilador genera una clase enumerable, )sta se anidar( directa o indirectamente en la clase ?ue contiene el miembro de 0unci-n, tendr( accesibilidad privada y un nombre reservado para el uso del compilador O[2.4.2R. 7n ob$eto enumerable puede implementar m(s inter0aces ?ue las especi0icadas anteriormente. En concreto, un ob$eto enumerable tambi)n puede implementar $)numerator e $)numeratorD1E de manera ?ue puede servir tanto de enumerable como de enumerador. En dic=o tipo de implementaci-n, la primer ve1 ?ue se invoca un m)todo Set)numerator del ob$eto enumerable, se devuelve el mismo ob$eto enumerable. En las siguientes invocaciones de Set)numerator del ob$eto enumerable, si las =ay, se devuelve una copia del ob$eto enumerable. 'or lo tanto, cada enumerador devuelto tiene su propio estado y los cambios de un enumerador no a0ectar(n a otro. 17.14. .1 &l mtodo 9et&numerator 7n ob$eto enumerable implementa los m)todos Set)numerator de las inter0aces $)numerable e $)numerableD1E. 8os dos m)todos Set)numerator comparten una implementaci-n comHn ?ue ad?uiere y devuelve un ob$eto de enumerador disponible. El ob$eto del enumerador se iniciali1a con los valores de los argumentos y el valor de la instancia guardados al iniciali1ar el ob$etoV de lo contrario, el ob$eto del enumerador 0unciona de la manera descrita en la secci-n [1".14.4. 10.1!.$ Ejemplo de implementacin En esta secci-n se describe una posible implementaci-n de iteradores en t)rminos de construcciones est(ndar del lengua$e C#. 8a implementaci-n a?u5 descrita se basa en los mismos principios utili1ados por el compilador de %icroso0t C#, pero no es una implementaci-n obligatoria ni tampoco la Hnica posible. 8a siguiente clase Stac(D1E implementa su m)todo Set)numerator con un iterador. El iterador enumera los elementos de la pila en orden descendente.
using System; using System.Collections; using System.Collections.Seneric; class Stac(D1E/ $)numerableD1E { 145 items; int count; &ublic void *us"(1 item) { i- (items ++ null) { items + ne, 14J5; ! else i- (items.Lengt" ++ count) { 145 ne,$tems + ne, 14count > 85; 'rray.Co&y(items 3 ne,$tems 3 items + ne,$tems; ! items4count<<5 + item; ! &ublic 1 *o&() { 1 result + items4==count5; items4count5 + de-ault(1); return result; !

count);

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

3(3

Especificacin del lenguaje C# &ublic $)numeratorD1E Set)numerator() { -or (int i + count = 2; i E+ 3; ==i) yield return items4i5; ! !

El m)todo Set)numerator se puede traducir en una creaci-n de instancias de una clase de enumerador generada por compilador ?ue encapsula el c-digo en el blo?ue de iteradores como en muestra a continuaci-n.
class Stac(D1E/ $)numerableD1E { ... &ublic $)numeratorD1E Set)numerator() { return ne, \\)numerator2(t"is); ! class \\)numerator2/ $)numeratorD1E { int \\state; 1 \\current; Stac(D1E \\t"is; int i; $)numerator

&ublic \\)numerator2(Stac(D1E \\t"is) { t"is.\\t"is + \\t"is; ! &ublic 1 Current { get { return \\current; ! ! object $)numerator.Current { get { return \\current; ! ! &ublic bool MoveNe#t() { s,itc" (\\state) { case 2/ goto \\state2; case 8/ goto \\state8; ! i + \\t"is.count = 2; \\loo&/ i- (i D 3) goto \\state8; \\current + \\t"is.items4i5; \\state + 2; return true; \\state2/ ==i; goto \\loo&; \\state8/ \\state + 8; return -alse; ! &ublic void 6is&ose() { \\state + 8; ! void $)numerator.Oeset() { t"ro, ne, NotSu&&orted)#ce&tion(); ! ! !

En la traducci-n anterior, el c-digo del blo?ue de iteradores se convierte en un e?uipo de estado y se coloca en el m)todo MoveNe#t de la clase del enumerador. 8a variable local i se convierte en un campo en el ob$eto del enumerador para ?ue pueda continuar existiendo cuando se vuelva a invocar MoveNe#t.

3(#

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

En el siguiente e$emplo se muestra una sencilla tabla de multiplicar de enteros del 1 al 1". El m)todo Vrom1o del e$emplo devuelve un ob$eto enumerable y se implementa utili1ando un iterador.
using System; using System.Collections.Seneric; class 1est { static $)numerableDintE Vrom1o(int -rom int to) { ,"ile (-rom D+ to) yield return -rom<<; ! static void Main() { $)numerableDintE e + Vrom1o(2 23); -oreac" (int # in e) { -oreac" (int y in e) { Console.Write("{3 9! " # > y); ! Console.WriteLine(); ! ! !

El m)todo Vrom1o se puede traducir en una creaci-n de instancias de una clase enumerable generada por compilador ?ue encapsula el c-digo en el blo?ue de iteradores como se muestra a continuaci-n.
using using using using System; System.1"reading; System.Collections; System.Collections.Seneric;

class 1est { ... static $)numerableDintE Vrom1o(int -rom return ne, \\)numerable2(-rom to); ! class \\)numerable2/ $)numerableDintE $)numerable $)numeratorDintE $)numerator { int \\state; int \\current; int \\-rom; int -rom; int to; int i; &ublic \\)numerable2(int \\-rom t"is.\\-rom + \\-rom; t"is.to + to; ! int to) { int to) {

&ublic $)numeratorDintE Set)numerator() { \\)numerable2 result + t"is; i- ($nterloc(ed.Com&are)#c"ange(re- \\state result + ne, \\)numerable2(\\-rom to); result.\\state + 2; ! result.-rom + result.\\-rom; return result; ! $)numerator $)numerable.Set)numerator() { return ($)numerator)Set)numerator(); !

3) @+ 3) {

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

3(!

Especificacin del lenguaje C# &ublic int Current { get { return \\current; ! ! object $)numerator.Current { get { return \\current; ! ! &ublic bool MoveNe#t() { s,itc" (\\state) { case 2/ i- (-rom E to) goto case 8; \\current + -rom<<; \\state + 2; return true; case 8/ \\state + 8; return -alse; de-ault/ t"ro, ne, $nvalid%&eration)#ce&tion(); ! ! &ublic void 6is&ose() { \\state + 8; ! void $)numerator.Oeset() { t"ro, ne, NotSu&&orted)#ce&tion(); ! ! !

8a clase enumerable implementa las inter0aces tanto enumerables como de enumerador de manera ?ue actHa como enumerable y como enumerador. 8a primera ve1 ?ue se invoca el m)todo Set)numerator, se devuelve el mismo ob$eto enumerable. En las siguientes invocaciones de Set)numerator del ob$eto enumerable, si las =ay, se devuelve una copia del ob$eto enumerable. 'or lo tanto, cada enumerador devuelto tiene su propio estado y los cambios de un enumerador no a0ectar(n a otro. El m)todo $nterloc(ed.Com&are)#c"ange se utili1a para garanti1ar la seguridad en el subproceso. 8os par(metros -rom y to se convierten en campos en la clase enumerable. 'uesto ?ue -rom se modi0ica en el blo?ue de iteradores, se introduce un campo \\-rom para mantener el valor inicial dado a -rom en cada enumerador. El m)todo MoveNe#t genera una excepci-n $nvalid%&eration)#ce&tion si se llama cuando \\state es 3. 2e esta manera se evita el uso del ob$eto enumerable como un ob$eto del enumerador sin llamar primero a Set)numerator. En el siguiente e$emplo se muestra una clase simple de (rbol. 8a clase 1reeD1E implementa el m)todo Set)numerator con un iterador. El iterador enumera los elementos del (rbol en orden in0i$o.
using System; using System.Collections.Seneric; class 1reeD1E/ $)numerableD1E { 1 value; 1reeD1E le-t; 1reeD1E rig"t; &ublic 1ree(1 value 1reeD1E le-t t"is.value + value; t"is.le-t + le-t; t"is.rig"t + rig"t; ! 1reeD1E rig"t) {

3(6

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases &ublic $)numeratorD1E Set)numerator() { i- (le-t @+ null) -oreac" (1 # in le-t) yield #; yield value; i- (rig"t @+ null) -oreac" (1 # in rig"t) yield #; ! ! class *rogram { static 1reeD1E Ma(e1reeD1E(145 items int le-t i- (le-t E rig"t) return null; int i + (le-t < rig"t) . 8; return ne, 1reeD1E(items4i5 Ma(e1ree(items le-t i = 2) Ma(e1ree(items i < 2 rig"t)); ! static 1reeD1E Ma(e1reeD1E(&arams 145 items) { return Ma(e1ree(items 3 items.Lengt" = 2); ! .. 1"e out&ut o- t"e &rogram is/ .. 2 8 9 J K X M Y L .. Mon 1ue Wed 1"u Vri Sat Sun static void Main() { 1reeDintE ints + Ma(e1ree(2 8 9 J K X M Y L); -oreac" (int i in ints) Console.Write("{3! " i); Console.WriteLine(); 1reeDstringE strings + Ma(e1ree( "Mon" "1ue" "Wed" "1"u" "Vri" "Sat" "Sun"); -oreac" (string s in strings) Console.Write("{3! " s); Console.WriteLine(); ! !

int rig"t) {

El m)todo Set)numerator se puede traducir en una creaci-n de instancias de una clase de enumerador generada por compilador ?ue encapsula el c-digo en el blo?ue de iteradores como en muestra a continuaci-n.
class 1reeD1E/ $)numerableD1E { ... &ublic $)numeratorD1E Set)numerator() { return ne, \\)numerator2(t"is); ! class \\)numerator2 / $)numeratorD1E { NodeD1E \\t"is; $)numeratorD1E \\le-t \\rig"t; int \\state; 1 \\current; $)numerator

&ublic \\)numerator2(NodeD1E \\t"is) { t"is.\\t"is + \\t"is; ! &ublic 1 Current { get { return \\current; ! ! object $)numerator.Current { get { return \\current; ! !

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

3((

Especificacin del lenguaje C# &ublic bool MoveNe#t() { try { s,itc" (\\state) { case 3/ \\state + =2; i- (\\t"is.le-t ++ null) goto \\yield\value; \\le-t + \\t"is.le-t.Set)numerator(); goto case 2; case 2/ \\state + =8; i- (@\\le-t.MoveNe#t()) goto \\le-t\dis&ose; \\current + \\le-t.Current; \\state + 2; return true; \\le-t\dis&ose/ \\state + =2; \\le-t.6is&ose(); \\yield\value/ \\current + \\t"is.value; \\state + 8; return true; case 8/ \\state + =2; i- (\\t"is.rig"t ++ null) goto \\end; \\rig"t + \\t"is.rig"t.Set)numerator(); goto case 9; case 9/ \\state + =9; i- (@\\rig"t.MoveNe#t()) goto \\rig"t\dis&ose; \\current + \\rig"t.Current; \\state + 9; return true; \\rig"t\dis&ose/ \\state + =2; \\rig"t.6is&ose(); \\end/ \\state + J; brea(; ! ! -inally { i- (\\state D 3) 6is&ose(); ! return -alse; ! &ublic void 6is&ose() { try { s,itc" (\\state) { case 2/ case =8/ \\le-t.6is&ose(); brea(; case 9/ case =9/ \\rig"t.6is&ose(); brea(;

3($

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases ! ! -inally { \\state + J; ! ! void $)numerator.Oeset() { t"ro, ne, NotSu&&orted)#ce&tion(); ! ! !

8os temporales generados por compilador utili1ados en las instrucciones -oreac" se convierten en los campos \\le-t y \\rig"t del ob$eto del enumerador. El campo \\state del ob$eto del enumerador se actuali1a cuidadosamente con el 0in de llamar al m)todo 6is&ose() adecuado en caso de ?ue se genere una excepci-n. Tenga en cuenta ?ue no es posible escribir el c-digo traducido con sencillas instrucciones -oreac".

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

3("

Especificacin del lenguaje C#

11. Estructuras
8as estructuras son similares a las clases en ?ue pueden representar estructuras de datos ?ue pueden contener miembros de datos y miembros de 0unci-n. 4o obstante, a di0erencia de las clases, las estructuras son tipos de valores y no re?uieren asignaci-n del mont-n. 7na variable de un tipo de estructura contiene directamente los datos de la estructura, mientras ?ue una variable de un tipo de clase contiene una re0erencia a los datos, ?ue se conocer( posteriormente como ob$eto. 8as estructuras son particularmente Htiles para estructuras de datos pe?ueUas ?ue tienen sem(nticas de valor. 8os nHmeros comple$os, los puntos de un sistema de coordenadas o los pares de valores clave de un diccionario son buenos e$emplos de estructuras. 8a clave de estas estructuras de datos es ?ue tienen pocos miembros de datos, ?ue no necesitan utili1ar =erencia o identidad re0erencial y ?ue pueden ser implementadas convenientemente utili1ando sem(nticas de valor donde la asignaci-n copia el valor en lugar de la re0erencia. Como se describe en [4.1.4, los tipos simples ?ue proporciona C#, como int, double y bool, son en realidad tipos de estructuras. Como estos tipos prede0inidos son estructuras, es posible tambi)n utili1ar estructuras y sobrecarga de operadores para implementar nuevos tipos PprimitivosQ en el lengua$e C#. &l 0inal de este cap5tulo O[11.4R se proporcionan dos e$emplos de estos tipos.

11.1 /eclaraciones de estructuras


7na declaraci-n de estructura Ostr ct-declarationR es una declaraci-n de tipo Ot#pe-declarationR O[+.#R ?ue declara una nueva estructura. str ct-declaration1 attri- tesopt str ct-%odifiersopt &artialopt struct identifier t#pe-para%eter-listopt str ct-interfacesopt t#pe-para%eter-constraints-cla sesopt str ct--od# ;opt 7na declaraci-n de estructura Ostr ct-declarationR consiste en un con$unto de atributos Oattri- tesR O[1*R, seguido de un con$unto opcional de modi0icadores de estructura Ostr ct-%odifiersR O[11.1.1R, seguido de un modi0icador &artial opcional, seguido de la palabra clave struct y un identi0icador OidentifierR ?ue da nombre a la estructura, seguido de una especi0icaci-n opcional de lista de par(metros de tipo Ot#pe-para%eterlistR O[1".1.3R, seguida de una especi0icaci-n opcional de inter0aces de estructura Ostr ct-interfacesR O[11.1.2R, seguida de una especi0icaci-n opcional de cl(usulas de restricciones de par(metros de tipo Ot#pe-para%eterconstraints-cla sesR O[1".1. R, seguida de un cuerpo de estructura Ostr ct--od#R O[11.1.4R, y seguido de un punto y coma opcional. 11.1.1 &odificadores de estructuras 7na declaraci-n de estructura Ostr ct-declarationR puede incluir opcionalmente una secuencia de modi0icadores de estructuraG str ct-%odifiers1 str ct-%odifier str ct-%odifiers str ct-%odifier

3$'

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

str ct-%odifier1
ne, &ublic &rotected internal &rivate

Cuando el mismo modi0icador aparece varias veces en una declaraci-n de estructura, se produce un error en tiempo de compilaci-n. 8os modi0icadores de una declaraci-n de estructura tienen el mismo signi0icado ?ue los de las declaraciones de clases O[1".1R. 11.1.2 &odificador parcial El modi0icador &artial indica ?ue esta declaraci-n de estructura Ostr ct-interfacesR es una declaraci-n de tipo parcial. >arias declaraciones parciales de estructura con el mismo nombre dentro de un espacio de nombres envolvente o una declaraci-n de tipo se combinan para 0ormar una declaraci-n de estructura, siguiendo las reglas especi0icadas en la secci-n [1".2. 11.1.3 Interfaces 4truct 7na declaraci-n de estructura puede incluir una especi0icaci-n de inter0aces de estructura Ostr ct-interfacesR, en cuyo caso se dice ?ue la estructura implementa directamente los tipos de inter0a1 dados. str ct-interfaces1 / interface-t#pe-list 8as implementaciones de inter0aces se explican m(s detalladamente en [13.4. 11.1.! %uerpo de estructura El cuerpo de estructura Ostr ct--od#R de una estructura de0ine los miembros de la estructura. str ct--od#1 { str ct-%e%-er-declarationsopt !

11.2 &iembros de estructura


8os miembros de una estructura OstructR se componen de los miembros introducidos por sus declaraciones de miembros de estructura Ostr ct-%e%-er-declarationsR y los miembros =eredados del tipo System.Ualue1y&e. str ct-%e%-er-declarations1 str ct-%e%-er-declaration str ct-%e%-er-declarations str ct-%e%-er-declaration str ct-%e%-er-declaration1 constant-declaration field-declaration %ethod-declaration propert#-declaration event-declaration inde2er-declaration operator-declaration constr ctor-declaration static-constr ctor-declaration t#pe-declaration

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

3$1

Especificacin del lenguaje C#

Excepto por las di0erencias indicadas en [11.3, las descripciones de miembros de clase proporcionadas en las secciones [1".3 a [1".14 tambi)n se aplican a los miembros de estructuras.

11.3 /iferencias entre clase y estructura


8as estructuras se di0erencian de las clases de di0erentes manerasG 8as estructuras son tipos de valor O[11.3.1R. Todos los tipos de estructura OstructR se =eredan impl5citamente de la clase System.Ualue1y&e O[11.3.2R. 8a asignaci-n a una variable de un tipo struct crea una copia del valor ?ue se asigne O[11.3.3R. El valor predeterminado de una estructura es el valor producido al establecer todos los campos de tipos de valores en su valor predeterminado, y todos los campos de tipos de re0erencia en null O[11.3.4R. 8as operaciones boxing y unboxing se utili1an para reali1ar la conversi-n entre un tipo struct y un tipo object O[11.3. R. El signi0icado de t"is es di0erente para las estructuras O[*. .*R. 8as declaraciones de campos de instancia para una estructura no pueden incluir iniciali1adores de variables O[11.3.*R. 7na estructura no puede declarar un constructor de instancia sin par(metros O[11.3.8R. 4o est( permitido ?ue una estructura declare un destructor O[11.3.+R.

11.3.1 4em)nticas de alor 8as estructuras son tipos de valor O[4.1R y se dice ?ue tienen sem(nticas de valor. 8as clases, por el contrario, son tipos de re0erencia O[4.2R y se dice ?ue tienen sem(nticas de re0erencia. 7na variable de un tipo de estructura contiene directamente los datos de la estructura, mientras ?ue una variable de un tipo de clase contiene una re0erencia a los datos, ?ue se conocer( posteriormente como ob$eto. Cuando una estructura : contiene un campo de instancia ' y ' es un tipo struct, supone un error en tiempo de compilaci-n ?ue ' dependa de :. 7na estructura I tiene una dependencia directa con una estructura ` si I contiene un campo de instancia del tipo `. 2ada esta de0inici-n, el con$unto completo de estructuras de las cuales depende una estructura es el cierre transitivo de la relaci-n de dependencia directa. 'or e$emploG
struct Node { int data; Node ne#t; .. error ! Node directly de&ends on itsel-

es un error por?ue Node contiene un campo de instancia de su propio tipo. /tro e$emplo
struct ' { : b; ! struct : { C c; ! struct C { ' a; !

es un error por?ue cada uno de los tipos ', : y C dependen entre s5. En el caso de las clases, es posible ?ue dos variables =agan re0erencia al mismo ob$eto y, por tanto, ?ue las operaciones en una variable a0ecten al ob$eto al ?ue =ace re0erencia la otra variable. En el caso de las estructuras, cada variable tiene su propia copia de los datos Oexceptuando las variables de los par(metros re- y outR, de manera ?ue no posible ?ue las operaciones de una a0ecten a la otra. 2ado ?ue las estructuras no son tipos de re0erencia, no es posible ?ue los valores de un tipo struct sean null.

3$2

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

2ada la declaraci-n
struct *oint { &ublic int # y; int y) {

&ublic *oint(int # t"is.# + #; t"is.y + y; ! !

el 0ragmento de c-digo
*oint a + ne, *oint(23 23); *oint b + a; a.# + 233; System.Console.WriteLine(b.#);

devuelve como resultado el valor 1". 8a asignaci-n de a a b crea una copia del valor y por tanto b no se ve a0ectada por la asignaci-n a a.#. En cambio, si se =ubiera declarado *oint como clase, el resultado ser5a 233 puesto ?ue a y b =ar5an re0erencia al mismo ob$eto. 11.3.2 Herencia Todos los tipos struct =eredan impl5citamente de la clase System.Ualue1y&e, la cual, a su ve1, =ereda de la clase object. 7na declaraci-n de estructura puede especi0icar una lista de inter0aces implementadas, pero no es posible ?ue especi0i?ue una clase base. 8os tipos de estructura nunca son abstractos y son siempre sellados impl5citamente. 'or lo tanto, los modi0icadores abstract y sealed no est(n permitidos en una declaraci-n de estructura. 2ebido a ?ue las estructuras no permiten la =erencia, la accesibilidad declarada de un miembro de estructura no puede ser &rotected ni &rotected internal. 8os miembros de 0unci-n de una estructura no pueden ser abstract ni virtual, y s-lo se permite el modi0icador override para invalidar m)todos =eredados de System.Ualue1y&e. 11.3.3 'signacin 8a asignaci-n a una variable de un tipo struct crea una copia del valor ?ue se asigne. Esto di0iere de la asignaci-n a una variable de un tipo de clase, ?ue copia la re0erencia pero no el ob$eto identi0icado por la re0erencia. 2e 0orma similar a una asignaci-n, cuando se pasa una estructura como par(metro de valor o se devuelve como resultado de un miembro de 0unci-n, se crea una copia de la estructura. 7na estructura se puede pasar por re0erencia a un miembro de 0unci-n utili1ando un par(metro re- u out. Cuando una propiedad o un indi1ador de una estructura es el destino de una asignaci-n, la expresi-n de instancia asociada con el acceso a la propiedad o indi1ador debe estar clasi0icada como una variable. .i la expresi-n de instancia est( clasi0icada como un valor, se produce un error de compilaci-n. Esta categor5a se explica con m(s detalle en la secci-n [*.1#.1. 11.3.! Valores predeterminados Como se describe en la secci-n [ .2, cuando se crean algunos tipos de variables se iniciali1an autom(ticamente a sus valores predeterminados. 'ara variables de tipos de clase y otros tipos de re0erencia, el valor predeterminado es null. .in embargo, como las estructuras son tipos de valor ?ue no pueden ser null, el valor predeterminado de una estructura es el valor producido al establecer todos los campos de tipos de valores a sus valores predeterminados y todos los campos de tipo de re0erencia a null.

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

3$3

Especificacin del lenguaje C#

Haciendo re0erencia a la estructura *oint declarada anteriormente, en el e$emplo


*oint45 a + ne, *oint42335;

se iniciali1a cada *oint de la matri1 al valor producido cuando se establecen los campos # e y a cero. El valor predeterminado de una estructura corresponde al valor devuelto por el constructor predeterminado de la estructura O[4.1.2R. & di0erencia de una clase, una estructura no permite declarar un constructor de instancia sin par(metros. En su lugar, cada estructura tiene impl5citamente un constructor de instancia sin par(metros ?ue siempre devuelve el valor ?ue resulta de establecer todos los campos de tipos de valores a sus valores predeterminados y todos los campos de tipo de re0erencia a null. 8as estructuras deben diseUarse considerando ?ue el estado de iniciali1aci-n predeterminado sea un estado v(lido. En el e$emplo
using System; struct aeyUalue*air { string (ey; string value; &ublic aeyUalue*air(string (ey string value) { i- ((ey ++ null HH value ++ null) t"ro, ne, 'rgument)#ce&tion(); t"is.(ey + (ey; t"is.value + value; ! !

el constructor de instancia de0inido por el usuario evita los valores nulos s-lo donde es llamado expl5citamente. En los casos en los ?ue una variable aeyUalue*air est) su$eta a una iniciali1aci-n de valor predeterminado, los campos (ey y value ser(n nulos y la estructura debe estar preparada para controlar este estado. 11.3.# %on ersiones bo"ing y unbo"ing 7n valor de un tipo de clase se puede convertir a un tipo object o a un tipo de inter0a1 ?ue es implementada por la clase simplemente tratando la re0erencia como otro tipo en tiempo de compilaci-n. !gualmente, un valor del tipo object o un valor de un tipo de inter0a1 se puede convertir de nuevo a un tipo de clase sin cambiar la re0erencia Opero en este caso es necesaria una comprobaci-n de tipo en tiempo de e$ecuci-nR. 2ado ?ue las estructuras no son tipos de re0erencia, estas operaciones se implementan de 0orma di0erente para los tipos de estructura. Cuando se convierte un valor de un tipo struct a un tipo object o a un tipo de inter0a1 ?ue es implementada por la estructura, tiene lugar una operaci-n boxing. 2e la misma 0orma, cuando un valor de tipo object o un valor de tipo de inter0a1 se vuelve a convertir a un tipo struct, tiene lugar una operaci-n unboxing. 7na di0erencia 0undamental con las mismas operaciones en los tipos de clase es ?ue las conversiones boxing y unboxing copian el valor de estructura OstructR en la instancia o 0uera de la instancia a la ?ue se =a aplicado la conversi-n boxing. 'or lo tanto, despu)s de una operaci-n boxing o unboxing, los cambios reali1ados en la estructura a la ?ue se =a aplicado la conversi-n unboxing no se re0le$an en la estructura donde se =a aplicado la conversi-n boxing. Cuando un tipo struct invalida un m)todo virtual =eredado de System.%bject Ocomo )Quals, SetHas"Code o 1oStringR, la invocaci-n del m)todo virtual mediante una instancia del tipo struct no provoca la conversi-n boxing. Esto es cierto incluso cuando se utili1a la estructura como un par(metro de tipo y la invocaci-n tiene lugar mediante una instancia del tipo de par(metro de tipo. 'or e$emploG
using System; struct Counter { int value;

3$#

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases &ublic override string 1oString() { value<<; return value.1oString(); ! ! class *rogram { static void 1estD1E() ,"ere 1/ ne,() { 1 # + ne, 1(); Console.WriteLine(#.1oString()); Console.WriteLine(#.1oString()); Console.WriteLine(#.1oString()); ! static void Main() { 1estDCounterE(); ! !

El resultado del programa esG


2 8 9

&un?ue el =ec=o de ?ue 1oString tenga e0ectos secundarios denota un estilo incorrecto, en el e$emplo se demuestra ?ue no se reali1- ninguna conversi-n boxing para las tres invocaciones de #.1oString(). 2e manera similar, la conversi-n boxing nunca tiene lugar de manera impl5cita cuando se obtiene acceso a un miembro en un par(metro de tipo restringido. 'or e$emplo, supongamos ?ue una inter0a1 $Counter contiene un m)todo $ncrement ?ue se puede utili1ar para modi0icar un valor. .i $Counter se utili1a como una restricci-n, la implementaci-n del m)todo $ncrement se llama con una re0erencia a la variable en la ?ue se llam- a $ncrement y nunca una copia con una conversi-n boxing aplicada.
using System; inter-ace $Counter { void $ncrement(); ! struct Counter/ $Counter { int value; &ublic override string 1oString() { return value.1oString(); ! void $Counter.$ncrement() { value<<; ! ! class *rogram { static void 1estD1E() ,"ere 1/ $Counter ne,() { 1 # + ne, 1(); Console.WriteLine(#); #.$ncrement(); .. Modi-y # Console.WriteLine(#); (($Counter)#).$ncrement(); .. Modi-y bo#ed co&y o- # Console.WriteLine(#); !

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

3$!

Especificacin del lenguaje C# static void Main() { 1estDCounterE(); ! !

8a primera llamada a $ncrement modi0ica el valor en la variable #. Esto no es e?uivalente a la segunda llamada a $ncrement, ?ue modi0ica el valor en una copia de # a la ?ue se aplic- una conversi-n boxing. 'or lo tanto, el resultado del programa esG
3 2 2

'ara obtener in0ormaci-n detallada sobre boxing y unboxing, vea [4.3. 11.3.$ 4ignificado de T?is 2entro de un constructor de instancia o de un miembro de 0unci-n de una clase, t"is est( clasi0icado como un valor. 'or lo tanto, mientras ?ue t"is se puede utili1ar para =acer re0erencia a la instancia para la ?ue 0ue invocado el miembro de 0unci-n, no es posible reali1ar una asignaci-n a t"is en un miembro de 0unci-n de una clase. 2entro de un constructor de instancia de una estructura, t"is corresponde a un par(metro out del tipo de estructura, y dentro de un miembro de 0unci-n de instancia de una estructura, t"is corresponde a un par(metro re- del tipo struct. En ambos casos, t"is est( clasi0icado como una variable, y es posible modi0icar toda la estructura para la ?ue 0ue invocado el miembro de 0unci-n reali1ando una asignaci-n a t"is o pasando t"is como un par(metro re- u out. 11.3.+ Iniciali8adores de campo Como se describe en la secci-n [11.3.4, el valor predeterminado de una estructura se compone del valor ?ue resulta de establecer todos los campos de tipos de valores a sus valores predeterminados y de todos los campos de tipo de re0erencia a null. 'or esta ra1-n, una estructura no permite declaraciones de campos de instancia para incluir iniciali1adores de variables. Esta restricci-n s-lo se aplica a los campos de instancia. 8os campos est(ticos de una estructura pueden incluir iniciali1adores de variable. En el e$emplo
struct *oint { &ublic int # + 2; &ublic int y + 2; ! .. )rror .. )rror initiali?er not &ermitted initiali?er not &ermitted

=ay un error por?ue la declaraci-n del campo de instancia incluye iniciali1adores de variables. 11.3.- %onstructores & di0erencia de una clase, una estructura no permite declarar un constructor de instancia sin par(metros. En su lugar, cada estructura tiene impl5citamente un constructor de instancia sin par(metros ?ue siempre devuelve el valor ?ue resulta de establecer todos los campos de tipos de valores a sus valores predeterminados y todos los campos de tipo de re0erencia a null O[4.1.2R. 7na estructura puede declarar constructores de instancia con par(metros. 'or e$emploG
struct *oint { int # y;

3$6

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases &ublic *oint(int # t"is.# + #; t"is.y + y; ! ! int y) {

2ada la declaraci-n anterior, las instrucciones


*oint &2 + ne, *oint(); *oint &8 + ne, *oint(3 3);

crean un *oint con # e y iniciali1ados a cero. 7n constructor de instancia de estructura no puede incluir un iniciali1ador de constructor con la 0orma base(...). .i el constructor de instancia de la estructura no especi0ica un iniciali1ador de constructor, la variable t"is corresponde a un par(metro out del tipo struct, y de 0orma similar a un par(metro out, t"is debe ser asignado de manera de0initiva O[ .3R a cada ubicaci-n a la ?ue vuelva el constructor. .i el constructor de instancia de la estructura especi0ica un iniciali1ador de constructor, la variable t"is corresponde a un par(metro re- del tipo struct, y de 0orma similar a un par(metro re-, t"is se considera de0initivamente asignado en la entrada al cuerpo del constructor. /bserve la implementaci-n del constructor de instancia siguienteG
struct *oint { int # y; &ublic int I { set { # + value; ! ! &ublic int ` { set { y + value; ! ! &ublic *oint(int # int y) { I + #; .. error t"is is not yet de-initely assigned ` + y; .. error t"is is not yet de-initely assigned ! !

4o puede llamarse a ninguna 0unci-n de miembro de instancia Oincluyendo los descriptores de acceso set para las propiedades I e `R =asta ?ue todos los campos de la estructura ?ue est( construy)ndose se =ayan asignado de0initivamente. /bserve, no obstante, ?ue si *oint 0uera una clase en lugar de una estructura, estar5a permitida la implementaci-n del constructor de instancia. 11.3.. /estructores 4o est( permitido ?ue una estructura declare un destructor. 11.3.10 %onstructores static 8os constructores est(ticos OstaticR para estructuras siguen la mayor5a de las mismas reglas ?ue las clases. 8a e$ecuci-n de un constructor est(tico para un tipo struct la desencadena el primero de los siguientes eventos ?ue se produ1can en un dominio de aplicaci-nG .e =ace re0erencia a un miembro de instancia del tipo struct. .e =ace re0erencia a un miembro est(tico del tipo struct. .e llama a un constructor expl5citamente declarado del tipo struct.

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

3$(

Especificacin del lenguaje C#

8a creaci-n de valores predeterminados O[11.3.4R de tipos de estructura no desencadena el constructor est(tico. O7n e$emplo de esto es el valor inicial de los elementos de una matri1.R

11.! Ejemplos de estructuras


& continuaci-n, se muestran dos e$emplos signi0icativos de la utili1aci-n de tipos struct para crear tipos ?ue puedan utili1arse de manera similar a los tipos integrados del lengua$e, pero con sem(nticas modi0icadas. 11.!.1 Tipo entero de base de datos 8a estructura 6:$nt siguiente implementa un tipo entero ?ue puede representar el con$unto completo de valores del tipo int, adem(s de un estado adicional ?ue indica un valor desconocido. 7n tipo de estas caracter5sticas se utili1a normalmente en bases de datos.
using System; &ublic struct 6:$nt { .. 1"e Null member re&resents an un(no,n 6:$nt value. &ublic static readonly 6:$nt Null + ne, 6:$nt(); .. W"en t"e de-ined -ield is true t"is 6:$nt re&resents a (no,n value .. ,"ic" is stored in t"e value -ield. W"en t"e de-ined -ield is -alse .. t"is 6:$nt re&resents an un(no,n value and t"e value -ield is 3. int value; bool de-ined; .. *rivate instance constructor. Creates a 6:$nt ,it" a (no,n value. 6:$nt(int value) { t"is.value + value; t"is.de-ined + true; ! .. 1"e $sNull &ro&erty is true i- t"is 6:$nt re&resents an un(no,n value. &ublic bool $sNull { get { return @de-ined; ! ! .. 1"e Ualue &ro&erty is t"e (no,n value o- t"is 6:$nt .. 6:$nt re&resents an un(no,n value. &ublic int Ualue { get { return value; ! ! .. $m&licit conversion -rom int to 6:$nt. &ublic static im&licit o&erator 6:$nt(int #) { return ne, 6:$nt(#); ! .. )#&licit conversion -rom 6:$nt to int. 1"ro,s an e#ce&tion i- t"e .. given 6:$nt re&resents an un(no,n value. &ublic static e#&licit o&erator int(6:$nt #) { i- (@#.de-ined) t"ro, ne, $nvalid%&eration)#ce&tion(); return #.value; ! &ublic static 6:$nt o&erator <(6:$nt #) { return #; ! &ublic static 6:$nt o&erator =(6:$nt #) { return #.de-ined 7 =#.value / Null; ! or 3 i- t"is

3$$

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases &ublic static 6:$nt o&erator <(6:$nt # 6:$nt y) { return #.de-ined FF y.de-ined7 #.value < y.value/ Null; ! &ublic static 6:$nt o&erator =(6:$nt # 6:$nt y) { return #.de-ined FF y.de-ined7 #.value = y.value/ Null; ! &ublic static 6:$nt o&erator >(6:$nt # 6:$nt y) { return #.de-ined FF y.de-ined7 #.value > y.value/ Null; ! &ublic static 6:$nt o&erator .(6:$nt # 6:$nt y) { return #.de-ined FF y.de-ined7 #.value . y.value/ Null; ! &ublic static 6:$nt o&erator B(6:$nt # 6:$nt y) { return #.de-ined FF y.de-ined7 #.value B y.value/ Null; ! &ublic static 6::ool o&erator ++(6:$nt # 6:$nt y) { return #.de-ined FF y.de-ined7 #.value ++ y.value/ 6::ool.Null; ! &ublic static 6::ool o&erator @+(6:$nt # 6:$nt y) { return #.de-ined FF y.de-ined7 #.value @+ y.value/ 6::ool.Null; ! &ublic static 6::ool o&erator E(6:$nt # 6:$nt y) { return #.de-ined FF y.de-ined7 #.value E y.value/ 6::ool.Null; ! &ublic static 6::ool o&erator D(6:$nt # 6:$nt y) { return #.de-ined FF y.de-ined7 #.value D y.value/ 6::ool.Null; ! &ublic static 6::ool o&erator E+(6:$nt # 6:$nt y) { return #.de-ined FF y.de-ined7 #.value E+ y.value/ 6::ool.Null; ! &ublic static 6::ool o&erator D+(6:$nt # 6:$nt y) { return #.de-ined FF y.de-ined7 #.value D+ y.value/ 6::ool.Null; ! &ublic override bool )Quals(object obj) { i- (@(obj is 6:$nt)) return -alse; 6:$nt # + (6:$nt)obj; return value ++ #.value FF de-ined ++ #.de-ined; ! &ublic override int SetHas"Code() { return value; ! &ublic override string 1oString() { return de-ined7 value.1oString()/ R6:$nt.NullT; ! !

11.!.2 Tipo booleano de base de datos 8a estructura 6::ool siguiente implementa un tipo l-gico de tres valores. 8os valores posibles de este tipo son 6::ool.1rue, 6::ool.Valse y 6::ool.Null, donde el miembro Null indica un valor desconocido. Estos tipos l-gicos de tres valores se utili1an con 0recuencia en bases de datos.

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

3$"

Especificacin del lenguaje C# using System; &ublic struct 6::ool { .. 1"e t"ree &ossible 6::ool values. &ublic static readonly 6::ool Null + ne, 6::ool(3); &ublic static readonly 6::ool Valse + ne, 6::ool(=2); &ublic static readonly 6::ool 1rue + ne, 6::ool(2); .. *rivate -ield t"at stores C2 sbyte value; .. *rivate instance constructor. 1"e value &arameter must be C2 6::ool(int value) { t"is.value + (sbyte)value; ! .. *ro&erties to e#amine t"e value o- a 6::ool. Oeturn true i- t"is .. 6::ool "as t"e given value -alse ot"er,ise. &ublic bool $sNull { get { return value ++ 3; ! ! &ublic bool $sValse { get { return value D 3; ! ! &ublic bool $s1rue { get { return value E 3; ! ! .. $m&licit conversion -rom bool to 6::ool. Ma&s true to 6::ool.1rue and .. -alse to 6::ool.Valse. &ublic static im&licit o&erator 6::ool(bool #) { return #7 1rue/ Valse; ! .. )#&licit conversion -rom 6::ool to bool. 1"ro,s an e#ce&tion i- t"e .. given 6::ool is Null ot"er,ise returns true or -alse. &ublic static e#&licit o&erator bool(6::ool #) { i- (#.value ++ 3) t"ro, ne, $nvalid%&eration)#ce&tion(); return #.value E 3; ! .. )Quality o&erator. Oeturns Null i- eit"er o&erand is Null .. returns 1rue or Valse. &ublic static 6::ool o&erator ++(6::ool # 6::ool y) { i- (#.value ++ 3 HH y.value ++ 3) return Null; return #.value ++ y.value7 1rue/ Valse; ! .. $neQuality o&erator. Oeturns Null i- eit"er o&erand is Null .. returns 1rue or Valse. &ublic static 6::ool o&erator @+(6::ool # 6::ool y) { i- (#.value ++ 3 HH y.value ++ 3) return Null; return #.value @+ y.value7 1rue/ Valse; ! .. Logical negation o&erator. Oeturns 1rue i- t"e o&erand is Valse .. i- t"e o&erand is Null or Valse i- t"e o&erand is 1rue. &ublic static 6::ool o&erator @(6::ool #) { return ne, 6::ool(=#.value); ! .. Logical 'N6 o&erator. Oeturns Valse i- eit"er o&erand is Valse .. ot"er,ise Null i- eit"er o&erand is Null ot"er,ise 1rue. &ublic static 6::ool o&erator F(6::ool # 6::ool y) { return ne, 6::ool(#.value D y.value7 #.value/ y.value); ! Null ot"er,ise ot"er,ise 3 or 2. 3 2 -or Valse Null 1rue.

3"'

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases .. Logical %O o&erator. Oeturns 1rue i- eit"er o&erand is 1rue .. Null i- eit"er o&erand is Null ot"er,ise Valse. &ublic static 6::ool o&erator H(6::ool # 6::ool y) { return ne, 6::ool(#.value E y.value7 #.value/ y.value); ! .. 6e-initely true o&erator. Oeturns true i- t"e o&erand is 1rue .. ot"er,ise. &ublic static bool o&erator true(6::ool #) { return #.value E 3; ! .. 6e-initely -alse o&erator. Oeturns true i- t"e o&erand is Valse .. ot"er,ise. &ublic static bool o&erator -alse(6::ool #) { return #.value D 3; ! &ublic override bool )Quals(object obj) { i- (@(obj is 6::ool)) return -alse; return value ++ ((6::ool)obj).value; ! &ublic override int SetHas"Code() { return value; ! &ublic override string 1oString() { i- (value E 3) return "6::ool.1rue"; i- (value D 3) return "6::ool.Valse"; return "6::ool.Null"; ! ! -alse -alse ot"er,ise

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

3"1

Especificacin del lenguaje C#

12. &atrices
7na matri1 es una estructura de datos ?ue contiene una serie de variables a las ?ue se obtiene acceso a trav)s de 5ndices calculados. 8as variables contenidas en una matri1, tambi)n conocidas como elementos de la matri1, son todas del mismo tipo, denominado tipo de elemento de la matri1. 7na matri1 tiene un rango ?ue determina el nHmero de 5ndices asociados a cada elemento de la matri1. El rango de una matri1 tambi)n se conoce como nHmero de dimensiones de la matri1. 7na matri1 con un rango de uno se denomina atri- !nidi ensional. 7na matri1 con un rango mayor ?ue uno se denomina atri!ltidi ensional. 8as matrices multidimensionales de un determinado tamaUo se suelen denominar matrices bidimensionales, tridimensionales, etc. Cada dimensi-n de una matri1 tiene una longitud asociada, ?ue es un nHmero entero mayor o igual a cero. 8as longitudes de dimensi-n no 0orman parte del tipo de matri1, sino ?ue se establecen cuando se crea una instancia del tipo de matri1 en tiempo de e$ecuci-n. 8a longitud de una dimensi-n determina el intervalo v(lido de 5ndices para esa dimensi-nG para una dimensi-n de longitud N, los 5ndices pueden tomar valores de cero a N C 2 inclusive. El nHmero total de elementos en una matri1 es el producto de las longitudes de cada dimensi-n de la matri1. .i alguna de las dimensiones de una matri1 tiene una longitud cero, se dice ?ue la matri1 est( vac5a. 8os elementos de una matri1 pueden ser de cual?uier tipo, incluido un tipo de matri1.

12.1 Tipos de matri8


7n tipo de matri1 se escribe como un tipo ?ue no es de matri1 Onon-arra#-t#peR seguido de uno o m(s especi0icadores de rango Oran3-specifiersRG arra#-t#pe1 non-arra#-t#pe ran3-specifiers non-arra#-t#pe1 t#pe ran3-specifiers1 ran3-specifier ran3-specifiers ran3-specifier ran3-specifier1 4 di%-separatorsopt 5 di%-separators1 di%-separators 7n tipo ?ue no es de matri1 Onon-arra#-t#peR es cual?uier tipo ?ue no es en s5 mismo un tipo de matri1 Oarra#-t#peR. El rango de un tipo de matri1 viene dado por el especi0icador de rango Oran3-specifierR situado en el extremo i1?uierdo del tipo de matri1 Oarra#-t#peRG as5, un especi0icador de rango indica ?ue la matri1 posee un rango de uno m(s el nHmero de to6ens ^ ^ del especi0icador de rango. El tipo de elemento de un tipo de matri1 es el tipo resultante de eliminar el especi0icador de rango Oran3specifierR del extremo i1?uierdoG

3"2

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

7n tipo de matri1 con la estructura 14O5 es una matri1 de rango O y un tipo de elemento 1 ?ue no sea de matri1. 7n tipo de matri1 con la estructura 14O54O25...4ON5 es una matri1 de rango O y un tipo de elemento 14O25...4ON5.

8o ?ue sucede es ?ue los especi0icadores de rango Oran3-specifiersR se leen de i1?uierda a derec=a, antes del tipo de elemento 0inal ?ue no es de matri1. El tipo int454 54 5 es una matri1 unidimensional ?ue contiene matrices tridimensionales de matrices bidimensionales de tipo int. En tiempo de e$ecuci-n, el valor de un tipo de matri1 puede ser null o una re0erencia a una instancia de dic=o tipo. 12.1.1 Tipo 4ystem.'rray El tipo System.'rray es el tipo base abstracto de todos los tipos de matrices. .e produce una conversi-n de re0erencia impl5cita O[#.1.#R entre cual?uier tipo de matri1 y un tipo System.'rray, as5 como una conversi-n de re0erencia expl5cita O[#.2.4R de System.'rray a cual?uier tipo de matri1. /bserve ?ue System.'rray no es en s5 mismo un tipo de matri1 Oarra#-t#peR. &l contrario, es un tipo de clase Oclass-t#peR del ?ue se derivan todos los tipos de matri1 Oarra#-t#pesR. En tiempo de e$ecuci-n, un valor de tipo System.'rray puede ser null o una re0erencia a una instancia de cual?uier tipo de matri1. 12.1.2 &atrices y la interfa8 I6ist gen*rica 7na matri1 unidimensional 145 implementa la inter0a1 System.Collections.Seneric.$ListD1E O$ListD1E en su 0orma abreviadaR y sus inter0aces base. 'or lo tanto, =ay una conversi-n impl5cita de 145 a $ListD1E y sus inter0aces base. &dem(s, si =ay una conversi-n impl5cita de re0erencia de S a 1 entonces S45 implementa $ListD1E y =ay una conversi-n impl5cita de re0erencia de S45 a $ListD1E y sus inter0aces base O[#.1.#R. .i =ay una conversi-n expl5cita de re0erencia de S a 1 entonces =ay una conversi-n expl5cita de re0erencia de S45 a $ListD1E y sus inter0aces base O[#.2.4R. 'or e$emploG
using System.Collections.Seneric; class 1est { static void string45 object45 object45

Main() { sa + ne, string4K5; oa2 + ne, object4K5; oa8 + sa; lst2 lst8 lst9 lstJ + + + + sa; oa2; sa; oa2; .. .. .. .. %( )rror %( %( cast needed

$ListDstringE $ListDstringE $ListDobjectE $ListDobjectE

$ListDstringE lstK + ($ListDstringE)oa2; $ListDstringE lstX + ($ListDstringE)oa8; ! !

.. )#ce&tion .. %(

8a asignaci-n lst8 + oa2 genera un error en tiempo de compilaci-n, puesto ?ue la conversi-n de object45 a $ListDstringE es una conversi-n expl5cita, no impl5cita. 8a conversi-n ($ListDstringE)oa2 iniciar( una excepci-n en tiempo de e$ecuci-n puesto ?ue oa2 =ace re0erencia a object45 y no a string45. .in embargo, la conversi-n($ListDstringE)oa8 no iniciar( una excepci-n ya ?ue oa8 =ace re0erencia a string45. .i =ay una conversi-n impl5cita o expl5cita de re0erencia de S45 a $ListD1E, tambi)n =ay una conversi-n expl5cita de re0erencia de $ListD1E y sus inter0aces base a S45 O[#.2.4R.

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

3"3

Especificacin del lenguaje C#

Cuando un tipo de matri1 S45 implementa $ListD1E, algunos de los miembros de la inter0a1 implementada pueden iniciar excepciones. El comportamiento concreto de la implementaci-n de la inter0a1 se escapa al (mbito de esta especi0icaci-n.

12.2 %reacin de matrices


8as instancias de matri1 se crean mediante expresiones de creaci-n de matrices Oarra#-creation-e2pressionsR O[*. .1".4R o mediante declaraciones de campo o variable local ?ue incluyen un iniciali1ador de matri1 Oarra#initiali0erR O[12.#R. Cuando se crea una instancia de matri1, se establecen el rango y longitud de cada dimensi-n y a continuaci-n permanecen constante por toda la duraci-n de la instancia. Es decir, no es posible cambiar el rango de una instancia de matri1 existente ni cambiar el tamaUo de sus dimensiones. 7na instancia de matri1 es siempre de tipo de matri1. El tipo System.'rray es un tipo abstracto del ?ue no se pueden crear instancias. 8os elementos de matrices creadas mediante expresiones de creaci-n de matrices Oarra#-creation-e2pressionsR se iniciali1an siempre con sus valores predeterminados O[ .2R.

12.3 'cceso a los elementos de matri8


El acceso a los elementos de una matri1 se obtiene mediante expresiones de acceso a elementos Oele%ent-accessR O[*. .#.1R con la estructura '4$2 $8 ... $N5, donde ' es una expresi-n de un tipo de matri1 y cada $I es una expresi-n de tipo int, uint, long, ulong, o de un tipo ?ue puede convertirse de manera impl5cita a uno o varios de estos tipos. El resultado de un acceso a elemento de matri1 es una variable, en concreto el elemento de matri1 seleccionado por los 5ndices. 8os elementos de una matri1 se pueden enumerar mediante una instrucci-n -oreac" O[8.8.4R.

12.! &iembros de matri8


Cada tipo de matri1 =ereda los miembros declarados por el tipo System.'rray.

12.# %o arian8a de matrices


'or cada dos tipos de re0erencia Oreference-t#pesR ' y :, si existe una conversi-n de re0erencia impl5cita O[#.1.#R o expl5cita O[#.2.4R entre ' y :, tambi)n tiene lugar la misma conversi-n de re0erencia entre el tipo de matri1 '4O5 y el tipo de matri1 :4O5, donde O es cual?uier especi0icador de rango Oran3-specifierR, si bien es el mismo para ambos tipos de matri1. Esta relaci-n se conoce como covarian-a atricial. 8a covarian1a matricial signi0ica, en concreto, ?ue un valor de un tipo de matri1 '4O5 puede ser en realidad una re0erencia a una instancia de un tipo de matri1 :4O5, siempre ?ue exista una conversi-n de re0erencia impl5cita entre : y '. 2ebido a la covarian1a de matrices, las asignaciones a elementos de matrices de tipo de re0erencia incluyen una comprobaci-n en tiempo de e$ecuci-n ?ue garanti1a ?ue el valor ?ue se asigna al elemento de matri1 es realmente de un tipo permitido O[*.1#.1R. 'or e$emploG
class 1est { static void Vill(object45 array int inde# int count object value) { -or (int i + inde#; i D inde# < count; i<<) array4i5 + value; !

3"#

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases static void Main() { string45 strings + ne, string42335; Vill(strings 3 233 ";nde-ined"); Vill(strings 3 23 null); Vill(strings L3 23 3); ! !

8a asignaci-n a array4i5 en el m)todo Vill incluye impl5citamente una comprobaci-n en tiempo de e$ecuci-n, ?ue garanti1a ?ue el ob$eto al ?ue =ace re0erencia value es null o bien una instancia de un tipo compatible con el tipo de elemento real de la matri1 array. En Main, las dos primeras llamadas a Vill se e$ecutan con correctamente, pero la tercera llamada provoca una excepci-n System.'rray1y&eMismatc")#ce&tion al e$ecutarse la primera asignaci-n a array4i5. 8a excepci-n se produce por?ue no se puede almacenar un valor int boxed en una matri1 string. 8a covarian1a matricial no abarca las matrices de tipos de valor Oval e-t#pesR. 'or e$emplo, no =ay ninguna conversi-n ?ue permita tratar un tipo int45 como object45.

12.$ Iniciali8adores de matrices


8os iniciali1adores de matrices se pueden especi0icar en declaraciones de campo O[1". R, declaraciones de variable local O[8. .1R y expresiones de creaci-n de matrices O[*. .1".4RG arra#-initiali0er1 { varia-le-initiali0er-listopt ! { varia-le-initiali0er-list ! varia-le-initiali0er-list1 varia-le-initiali0er varia-le-initiali0er-list varia-le-initiali0er1 e2pression arra#-initiali0er 7n iniciali1ador de matrices se compone de una secuencia de iniciali1adores de variable, ?ue 0iguran entre los to6ens P{Q y P!Q y separados por P Q. Cada iniciali1ador de variable es una expresi-n o, en el caso de una matri1 multidimensional, un iniciali1ador de matri1 anidado. El contexto en ?ue se utili1a un iniciali1ador de matri1 determina el tipo de la matri1 ?ue se iniciali1a. En una expresi-n de creaci-n de matrices, el tipo de matri1 precede inmediatamente al iniciali1ador, o se in0iere de las expresiones del iniciali1ador de matrices. En una declaraci-n de campo o de variable, el tipo de matri1 es el tipo del campo o variable ?ue se est( declarando. Cuando se utili1a un iniciali1ador de matri1 en una declaraci-n de campo o de variable, comoG
int45 a + {3 8 J X Y!; 8 J X Y!;

varia-le-initiali0er

e?uivale a la siguiente expresi-n de creaci-n de matri1G


int45 a + ne, int45 {3

'ara una matri1 unidimensional, el iniciali1ador de matri1 debe estar compuesto de una secuencia de expresiones ?ue sean compatibles en materia de asignaci-n con el tipo de elemento de la matri1. 8as expresiones iniciali1an los elementos de matri1 por orden creciente, comen1ando a partir del elemento en el 5ndice cero. El nHmero de expresiones del iniciali1ador de matri1 determina la longitud de la instancia de matri1 ?ue se est( creando. 'or e$emplo, el iniciali1ador de matri1 anterior crea una instancia int45 de longitud y a continuaci-n iniciali1a la instancia con los siguientes valoresG
a435 + 3; a425 + 8; a485 + J; a495 + X; a4J5 + Y;

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

3"!

Especificacin del lenguaje C#

'ara una matri1 multidimensional, el iniciali1ador de matri1 debe tener tantos niveles de anidamiento como dimensiones tenga la matri1. El nivel de anidamiento superior se corresponde con la dimensi-n situada en el extremo i1?uierdo y el nivel de anidamiento in0erior se corresponde con la dimensi-n situada en el extremo derec=o. 8a longitud de cada una de las dimensiones de la matri1 est( determinada por el nHmero de elementos del nivel de anidamiento correspondiente en el iniciali1ador de la matri1. 'or cada iniciali1ador de matri1 anidado, el nHmero de elementos debe ser igual al de los dem(s iniciali1adores de matri1 ?ue est(n situados en el mismo nivel. En el e$emploG
int4 5 b + {{3 2! {8 9! {J K! {X M! {Y L!!;

se crea una matri1 bidimensional con una longitud de cinco para la dimensi-n del extremo i1?uierdo y una longitud de dos para la dimensi-n del extremo derec=oG
int4 5 b + ne, int4K b43 b42 b48 b49 b4J 35 35 35 35 35 + + + + + 3; 8; J; X; Y; b43 b42 b48 b49 b4J 25 25 25 25 25 85; + + + + + 2; 9; K; M; L;

y a continuaci-n se iniciali1a la instancia de la matri1 con los valores siguientesG

.i a una dimensi-n di0erente a la situada m(s a la derec=a se le asigna una longitud cero, se asume ?ue las dimensiones posteriores tambi)n tienen una longitud cero. El e$emploG
int4 5 c + {!;

crea una matri1 bidimensional con una longitud de cero tanto para la dimensi-n situada m(s a la i1?uierda como para la dimensi-n situada m(s a la derec=aG
int4 5 c + ne, int43 35;

Cuando una expresi-n de creaci-n de matri1 incluye tanto longitudes de dimensi-n expl5citas como un iniciali1ador de matri1, las longitudes deben ser expresiones constantes, y el nHmero de elementos en cada nivel de anidamiento debe coincidir con la longitud de dimensi-n correspondiente. & continuaci-n se describen algunos e$emplosG
int i int45 int45 int45 + # y ? 9; + ne, int495 {3 + ne, int4i5 {3 + ne, int495 {3 2 2 2 8!; 8!; 8 9!; .. %a .. )rror .. )rror i not a constant lengt".initiali?er mismatc"

&?u5, el iniciali1ador de y es un error de compilaci-n por?ue la expresi-n de longitud de dimensi-n no es una constante, y el iniciali1ador de ? es un error de compilaci-n por?ue la longitud y el nHmero de elementos del iniciali1ador no coinciden.

3"6

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

13. Interfaces
7na inter0a1 de0ine un contrato. 7na clase o estructura ?ue implementa una inter0a1 debe ad=erirse a su contrato. 7na inter0a1 puede derivarse de varias inter0aces base, y una clase o estructura puede implementar varias inter0aces. 8as inter0aces pueden contener m)todos, propiedades, eventos e indi1adores. 8a propia inter0a1 no proporciona implementaciones para los miembros ?ue de0ine. 8a inter0a1 s-lo especi0ica los miembros ?ue las clases o estructuras deben proporcionar, y ?ue implementan la inter0a1.

13.1 /eclaraciones de interfa8


7na declaraci-n de inter0a1 Ointerface-declarationR es una declaraci-n de tipo Ot#pe-declarationR O[+.#R ?ue declara un nuevo tipo de inter0a1. interface-declaration1 attri- tesopt interface-%odifiersopt &artialopt inter-ace identifier t#pe-para%eter-listopt interface--aseopt t#pe-para%eter-constraints-cla sesopt interface--od# ;opt 7na declaraci-n de inter0a1 Ointerface-declarationR consiste en un con$unto de atributos Oattri- tesR O[R opcionales, seguido de un modi0icador &artial opcional O[R, seguido de la palabra clave inter-ace y un identi0icador OidentifierR ?ue da nombre a la inter0a1, seguido de una especi0icaci-n opcional de lista de par(metros de tipo Ot#pe-para%eter-listR O[R, seguido de una especi0icaci-n opcional de base de inter0a1 Ointerface--aseR O[R, seguida de una especi0icaci-n opcional de cl(usulas de restricciones de par(metros de tipo Ot#pe-para%eter-constraints-cla sesR O[1".1. R, seguida de un cuerpo de inter0a1 Ointerface--od#R O[13.1.4R, y seguido de un punto y coma opcional. 13.1.1 &odificadores de interfa8 7na declaraci-n de inter0a1 Ointerface-declarationR puede incluir opcionalmente una secuencia de modi0icadores de inter0a1G interface-%odifiers1 interface-%odifier interface-%odifiers interface-%odifier interface-%odifier1
ne, &ublic &rotected internal &rivate

Cuando el mismo modi0icador aparece varias veces en una declaraci-n de inter0a1, se produce un error en tiempo de compilaci-n. El modi0icador ne, s-lo se permite en inter0aces de0inidas dentro de una clase. Especi0ica ?ue la inter0a1 oculta un miembro =eredado con el mismo nombre, como se describe en [1".3.4. 8os modi0icadores &ublic, &rotected, internal y &rivate controlan la accesibilidad a la inter0a1. 2ependiendo del contexto en ?ue se produ1ca la declaraci-n de inter0a1, puede ?ue s-lo se permitan algunos de estos modi0icadores O[3. .1R.
Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

3"(

Especificacin del lenguaje C#

13.1.2 &odificador parcial El modi0icador &artial indica ?ue esta declaraci-n de inter0a1 Ointerface-declarationR es una declaraci-n de tipo parcial. >arias declaraciones de inter0a1 parcial con el mismo nombre dentro de un espacio de nombres envolvente o una declaraci-n de tipo se combinan para 0ormar una declaraci-n de inter0a1, siguiendo las reglas especi0icadas en la secci-n [1".2. 13.1.3 Interfaces base 7na inter0a1 puede =eredar de cero o m(s tipos de inter0a1, ?ue se denominan interfaces /ase e.plcitas de la inter0a1. Cuando una inter0a1 tiene una o m(s inter0aces base expl5citas, el identi0icador de inter0a1, en la declaraci-n, viene seguido de un car(cter de dos puntos y una lista de identi0icadores de tipos de inter0a1 base separados por comas. interface--ase1 / interface-t#pe-list En un tipo de inter0a1 construido, las inter0aces base expl5citas se 0orman tomando las declaraciones de inter0a1 base expl5cita de la declaraci-n de tipo gen)rico y sustituyendo, para cada par(metro de tipo Ot#pe-para%eterR de la declaraci-n de inter0a1 base, el argumento de tipo Ot#pe-ar& %entR correspondiente del tipo construido. 8as inter0aces base expl5citas de una inter0a1 deben ser por lo menos tan accesibles como la propia inter0a1 O[3. .4R. 'or e$emplo, supone un error en tiempo de compilaci-n especi0icar una inter0a1 &rivate o internal en la inter0a1 base Ointerface--aseR de una inter0a1 &ublic. !gualmente, se produce un error en tiempo de compilaci-n cuando una inter0a1 =ereda directa o indirectamente de s5 misma. 8as interfaces /ase de una inter0a1 son las inter0aces base expl5citas y sus inter0aces base. En otras palabras, el con$unto de inter0aces base se compone de la terminaci-n transitiva completa de las inter0aces base expl5citas, sus inter0aces base expl5citas, etc. 7na inter0a1 =ereda a todos los miembros de sus inter0aces base. En el e$emplo
inter-ace $Control { void *aint(); ! inter-ace $1e#t:o#/ $Control { void Set1e#t(string te#t); ! inter-ace $List:o#/ $Control { void Set$tems(string45 items); ! inter-ace $Combo:o#/ $1e#t:o# $List:o# {!

las inter0aces base de $Combo:o# son $Control, $1e#t:o# e $List:o#. Es decir, la inter0a1 $Combo:o# anterior =ereda los miembros Set1e#t y Set$tems, as5 como *aint. 7na clase o estructura ?ue implementa una inter0a1 tambi)n implementa impl5citamente todas las inter0aces base de dic=a inter0a1. 13.1.! %uerpo de interfa8 El cuerpo de una inter0a1 Ointerface--od#R de0ine sus miembros respectivos. interface--od#1 { interface-%e%-er-declarationsopt !

3"$

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

13.2 &iembros de interfa8


8os miembros de una inter0a1 son los miembros =eredados de las inter0aces base y los miembros declarados por la propia inter0a1. interface-%e%-er-declarations1 interface-%e%-er-declaration interface-%e%-er-declarations interface-%e%-er-declaration interface-%e%-er-declaration1 interface-%ethod-declaration interface-propert#-declaration interface-event-declaration interface-inde2er-declaration 7na declaraci-n de inter0a1 puede declarar cero o varios miembros. 8os miembros de una inter0a1 pueden ser m)todos, propiedades, eventos o indi1adores. 7na inter0a1 no puede contener constantes, campos, operadores, constructores de instancia, destructores ni tipos, ni tampoco puede una inter0a1 contener miembros est(ticos de ningHn tipo. Todos los miembros de inter0a1 tienen impl5citamente acceso pHblico. .upone un error en tiempo de compilaci-n ?ue las declaraciones de miembros de inter0a1 contengan modi0icadores. En particular, los miembros de inter0aces no pueden declararse con los modi0icadores abstract, &ublic, &rotected, internal, &rivate, virtual, override o static. En el e$emplo
&ublic delegate void StringList)vent($StringList sender); &ublic inter-ace $StringList { void 'dd(string s); int Count { get; ! event StringList)vent C"anged; string t"is4int inde#5 { get; set; ! !

se declara una inter0a1 ?ue contiene cada uno de los tipos posibles de miembroG un m)todo, una propiedad, un evento y un indi1ador. 7na declaraci-n de inter0a1 Ointerface-declarationR crea un nuevo espacio de declaraci-n O[3.3R, y las declaraciones de miembro de inter0a1 Ointerface-%e%-er-declarationsR contenidas inmediatamente en la declaraci-n de inter0a1 agregan nuevos miembros al espacio de declaraci-n. 8as siguientes reglas se aplican a las declaraciones de miembros de inter0a1 Ointerface-%e%-er-declarationsRG El nombre de un m)todo debe ser di0erente del de cual?uier otra propiedad o evento declarados en la misma inter0a1. &dem(s, la 0irma O[3.#R de un m)todo debe ser distinta de las 0irmas de todos los dem(s m)todos declarados en la misma inter0a1, y dos m)todos declarados en la misma inter0a1 no pueden tener 0irmas ?ue s-lo se di0erencien por re- y out. El nombre de una propiedad o evento debe ser di0erente de los nombres de todos los dem(s miembros declarados en la misma inter0a1. 8a 0irma de un indi1ador debe ser di0erente de las 0irmas de los dem(s indi1adores declarados en la misma inter0a1.

8os miembros =eredados de una inter0a1 no 0orman parte espec50icamente del espacio de declaraci-n de la inter0a1. 2e esta 0orma, una inter0a1 puede declarar un miembro con el mismo nombre o 0irma ?ue un miembro

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

3""

Especificacin del lenguaje C#

=eredado. Cuando esto ocurre, se dice ?ue el miembro de inter0a1 derivado oc lta el miembro de inter0a1 base. /cultar un miembro =eredado no se considera un error, pero =ace ?ue el compilador emita una advertencia. 'ara evitar la advertencia, la declaraci-n del miembro de inter0a1 derivado debe incluir el modi0icador ne, para indicar ?ue el miembro derivado est( destinado a ocultar el miembro base. Este tema se explica con m(s detalle en la secci-n [3.*.1.2. .i se incluye un modi0icador ne, en una declaraci-n ?ue no oculta un miembro =eredado, se emite una advertencia a tal e0ecto. Esta advertencia se evita ?uitando el modi0icador ne,. Tenga en cuenta ?ue los miembros de la clase object no son, estrictamente =ablando, miembros de ninguna inter0a1 O[13.2R. .in embargo, los miembros de la clase object est(n disponibles a trav)s de la bHs?ueda de miembros en cual?uier tipo de inter0a1 O[*.3R. 13.2.1 &*todos de interfa8 8os m)todos de inter0a1 se declaran mediante declaraciones de m)todos de inter0a1 Ointerface-%ethoddeclarationsRG interface-%ethod-declaration1 attri- tesopt ne,opt ret rn-t#pe identifier t#pe-para%eter-list ( for%al-para%eter-listopt ) t#pe-para%eter-constraints-cla sesopt ; 8os atributos Oattri- tesR, el tipo de valor devuelto Oret rn-t#peR, el identi0icador OidentifierR y la lista de par(metros 0ormales Ofor%al-para%eter-listR de una declaraci-n de m)todo de inter0a1 pueden tener el mismo signi0icado ?ue los de una declaraci-n de m)todo perteneciente a una clase O[1".#R. 4o se permite ?ue una declaraci-n de m)todo de inter0a1 especi0i?ue un cuerpo del m)todo, y la declaraci-n por tanto siempre termina con un punto y coma. 13.2.2 (ropiedades de interfa8 8as propiedades de inter0a1 se declaran mediante declaraciones de propiedad de inter0a1 Ointerface-propert#declarationsRG interface-propert#-declaration1 attri- tesopt ne,opt t#pe identifier { interface-accessors ! interface-accessors1 attri- tesopt get attri- tesopt set attri- tesopt get attri- tesopt set
; ; ; attri- tesopt set ; ; attri- tesopt get ;

8os atributos Oattri- tesR, el tipo Ot#peR y el identi0icador OidentifierR de una declaraci-n de propiedad de inter0a1 pueden tener el mismo signi0icado ?ue los de una declaraci-n de propiedad perteneciente a una clase O[1".*R. 8os descriptores de acceso correspondientes a una declaraci-n de propiedad de inter0a1 son los descriptores de acceso de una declaraci-n de propiedad de clase O[1".*.2R, salvo ?ue el cuerpo del descriptor de acceso siempre debe ser un punto y coma. &s5, el prop-sito de los descriptores de acceso es indicar si la propiedad es de lectura y escritura, de s-lo lectura o de s-lo escritura. 13.2.3 E entos de interfa8 8os eventos de inter0a1 se declaran mediante declaraciones de evento de inter0a1 Ointerface-event-declarationsRG interface-event-declaration1 attri- tesopt ne,opt event t#pe identifier ;

#''

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

8os atributos Oattri- tesR, el tipo Ot#peR y el identi0icador OidentifierR de una declaraci-n de evento de inter0a1 tienen el mismo signi0icado ?ue los de una declaraci-n de evento perteneciente a una clase O[1".8R. 13.2.! Indi8adores de interfa8 8os indi1adores de inter0a1 se declaran mediante declaraciones de indi1ador de inter0a1 Ointerface-inde2erdeclarationsRG interface-inde2er-declaration1 attri- tesopt ne,opt t#pe t"is 4 for%al-para%eter-list 5 { interface-accessors ! 8os atributos Oattri- tesR, el tipo Ot#peR y la lista de par(metros 0ormales Ofor%al-para%eter-listR de una declaraci-n de indi1ador de inter0a1 tienen el mismo signi0icado ?ue los de una declaraci-n de indi1ador perteneciente a una clase O[1".+R. 8os descriptores de acceso correspondientes a una declaraci-n de indi1ador de inter0a1 son los descriptores de acceso de una declaraci-n de indi1ador de clase O[1".+R, salvo ?ue el cuerpo del descriptor de acceso siempre debe ser un punto y coma. &s5, el prop-sito de los descriptores de acceso es indicar si el indi1ador es de lectura y escritura, de s-lo lectura o de s-lo escritura. 13.2.# 'cceso a miembros de interfa8 El acceso a los miembros de inter0a1 tiene lugar mediante las expresiones de acceso a miembros O[*. .4R y expresiones de acceso a indi1adores O[*. .#.2R de la 0orma $.M e $4'5, donde $ es un tipo de inter0a1, M es un m)todo, propiedad o evento de dic=o tipo de inter0a1 y ' es una lista de argumentos del indi1ador. 'ara inter0aces ?ue son estrictamente de =erencia simple Otodas las inter0aces de la cadena de =erencia tienen exactamente cero o una sola inter0a1 base directaR, los e0ectos de las reglas de bHs?ueda de miembros O[*.3R, llamadas a m)todos O[*. . .1R y acceso a indi1adores O[*. .#.2R son exactamente iguales ?ue las aplicables a clases y estructurasG m(s miembros derivados ocultan menos miembros derivados con el mismo nombre o 0irma. .in embargo, para inter0aces de =erencia mHltiple, pueden existir ambigIedades cuando dos o m(s inter0aces base no relacionadas entre s5 declaran miembros con el mismo nombre o 0irma. Esta secci-n muestra varios e$emplos de tales situaciones. En todos los casos, pueden utili1arse las conversiones impl5citas para resolver las ambigIedades. En el e$emplo
inter-ace $List { int Count { get; set; ! ! inter-ace $Counter { void Count(int i); ! inter-ace $ListCounter/ $List class C { void 1est($ListCounter #) { #.Count(2); #.Count + 2; (($List)#).Count + 2; (($Counter)#).Count(2); ! ! $Counter {!

.. .. .. ..

)rror )rror %( invo(es $List.Count.set %( invo(es $Counter.Count

las dos primeras instrucciones causan errores en tiempo de compilaci-n, ya ?ue la bHs?ueda de miembros O[*.3R de Count en $ListCounter es ambigua. Como muestra el e$emplo, la ambigIedad se resuelve convirtiendo #

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

#'1

Especificacin del lenguaje C#

en el tipo de inter0a1 base apropiado. Tales conversiones no tienen costo de e$ecuci-nV simplemente consisten en ver la instancia como un tipo menos derivado en tiempo de compilaci-n. En el e$emplo
inter-ace $$nteger { void 'dd(int i); ! inter-ace $6ouble { void 'dd(double d); ! inter-ace $Number/ $$nteger class C { void 1est($Number n) { n.'dd(2); n.'dd(2.3); (($$nteger)n).'dd(2); (($6ouble)n).'dd(2); ! ! $6ouble {!

.. .. .. ..

$nvo(es $$nteger.'dd %nly $6ouble.'dd is a&&licable %nly $$nteger.'dd is a candidate %nly $6ouble.'dd is a candidate

la invocaci-n n.'dd(2) selecciona $$nteger.'dd al aplicar las reglas de resoluci-n de sobrecargas de [*.4.3. 2e manera similar, la invocaci-n n.'dd(2.3) selecciona $6ouble.'dd. Cuando se insertan conversiones expl5citas, s-lo =ay un m)todo candidato y por ello no =ay ambigIedad. En el e$emplo
inter-ace $:ase { void V(int i); ! inter-ace $Le-t/ $:ase { ne, void V(int i); ! inter-ace $Oig"t/ $:ase { void S(); ! inter-ace $6erived/ $Le-t $Oig"t {! class ' { void 1est($6erived d) { d.V(2); .. $nvo(es $Le-t.V (($:ase)d).V(2); .. $nvo(es $:ase.V (($Le-t)d).V(2); .. $nvo(es $Le-t.V (($Oig"t)d).V(2); .. $nvo(es $:ase.V ! !

el miembro $:ase.V est( oculto por el miembro $Le-t.V. 8a invocaci-n d.V(2) selecciona $Le-t.V, aun?ue $:ase.V no parece ?uedar oculta en la ruta de acceso ?ue conduce a $Oig"t. 8a regla intuitiva para la ocultaci-n en inter0aces de =erencia mHltiple es sencillaG si un miembros est( oculto en cual?uier ruta de acceso, ?ueda oculto en todas las rutas de acceso. 2ebido a ?ue la ruta de acceso desde

#'2

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases $6erived =asta $Le-t e $:ase oculta $:ase.V, el miembro tambi)n ?ueda oculto en la ruta de acceso desde $6erived =asta $Oig"t e $:ase.

13.3 1ombres completos de miembros de interfa8


& menudo se conoce un miembro de inter0a1 por su no /re co pleto. El nombre completo de un miembro de inter0a1 se compone del nombre de la inter0a1 en ?ue se declara el miembro, seguido de un punto y del nombre del miembro. El nombre completo de un miembro =ace re0erencia a la inter0a1 donde se declara. 'or e$emplo, dadas las declaraciones
inter-ace $Control { void *aint(); ! inter-ace $1e#t:o#/ $Control { void Set1e#t(string te#t); !

el nombre completo de *aint es $Control.*aint y el de Set1e#t es $1e#t:o#.Set1e#t. En el e$emplo anterior, no es posible =acer re0erencia a *aint como $1e#t:o#.*aint. Cuando una inter0a1 0orma parte de un espacio de nombres, el nombre completo de un miembro de inter0a1 incluye el espacio de nombres. 'or e$emploG
names&ace System { &ublic inter-ace $Cloneable { object Clone(); ! !

&?u5, el nombre completo del m)todo Clone es System.$Cloneable.Clone.

13.! Implementaciones de interfaces


8as inter0aces pueden implementarse mediante clases y estructuras. 'ara indicar ?ue una clase o estructura implementa directamente una inter0a1, el identi0icador de la inter0a1 se incluye en la lista de clases base de la clase o estructura. 'or e$emploG
inter-ace $Cloneable { object Clone(); ! inter-ace $Com&arable { int Com&are1o(object ot"er); ! class List)ntry/ $Cloneable $Com&arable { &ublic object Clone() {...! &ublic int Com&are1o(object ot"er) {...! !

7na clase o estructura ?ue implementa directamente una inter0a1 tambi)n implementa directamente todas las inter0aces base de dic=a inter0a1. Esto es cierto aun?ue la clase o estructura no muestre expl5citamente todas las inter0aces base de la lista de clases base. 'or e$emploG

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

#'3

Especificacin del lenguaje C# inter-ace $Control { void *aint(); ! inter-ace $1e#t:o#/ $Control { void Set1e#t(string te#t); ! class 1e#t:o#/ $1e#t:o# { &ublic void *aint() {...! &ublic void Set1e#t(string te#t) {...! !

&?u5, la clase 1e#t:o# implementa $Control e $1e#t:o#. Cuando una clase C implementa directamente una inter0a1, todas las clases derivadas de C tambi)n implementan la inter0a1 impl5citamente. 8as inter0aces base especi0icadas en una declaraci-n de clase pueden ser tipos de inter0a1 construidos O[4.4R. 7na inter0a1 base no puede ser un par(metro de tipo en s5 mismo, aun?ue puede implicar a par(metros de tipo ?ue se encuentran dentro del (mbito. En el siguiente c-digo se muestra la manera en ?ue una clase puede implementar y ampliar tipos construidosG
class CD; UE {! inter-ace $2DUE {! class 6/ CDstring intE class )D1E/ CDint 1E $2DstringE {! $2D1E {!

8a inter0a1 base de una declaraci-n de clase gen)rica debe cumplir la regla de exclusividad descrita en [13.4.2. 13.!.1 Implementaciones de miembro de interfa8 e"pl2citas En cuesti-n de implementaci-n de inter0aces, una clase o estructura puede declarar i ple entaciones e.plcitas de ie /ros de interfa-. 7na implementaci-n expl5cita de miembro de inter0a1 es una declaraci-n de m)todo, propiedad, evento o indi1ador ?ue =ace re0erencia a un nombre completo de miembro de inter0a1. 'or e$emploG
inter-ace $ListD1E { 145 Set)lements(); ! inter-ace $6ictionaryDa UE { U t"is4a (ey5; void 'dd(a (ey ! class ListD1E/ $ListD1E $6ictionaryDint 1E { 145 $ListD1E.Set)lements() {...! 1 $6ictionaryDint 1E.t"is4int inde#5 {...! void $6ictionaryDint 1E.'dd(int inde# ! 1 value) {...! U value);

&?u5, $6ictionaryDint 1E.t"is e $6ictionaryDint 1E.'dd son implementaciones expl5citas de miembros de inter0a1. En algunos casos, el nombre de un miembro de inter0a1 puede no ser apropiado para la clase ?ue lo implementa, en cuyo caso puede implementarse con la implementaci-n expl5cita de miembros de inter0a1. Es probable ?ue

#'#

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

una clase ?ue implemente una abstracci-n de arc=ivo, por e$emplo, implemente una 0unci-n miembro Close ?ue tenga el e0ecto de liberar el recurso de arc=ivo e implemente el m)todo 6is&ose de la inter0a1 $6is&osable mediante la implementaci-n expl5cita de miembros de inter0a1G
inter-ace $6is&osable { void 6is&ose(); ! class MyVile/ $6is&osable { void $6is&osable.6is&ose() { Close(); ! &ublic void Close() { .. 6o ,"atWs necessary to close t"e -ile System.SC.Su&&ressVinali?e(t"is); ! !

4o es posible obtener acceso a una implementaci-n expl5cita de miembros de inter0a1 utili1ando el nombre completo en una llamada a un m)todo, instrucci-n de acceso a propiedad o acceso a indi1ador. .-lo se puede obtener acceso a una implementaci-n expl5cita de miembros de inter0a1 a trav)s de una instancia de inter0a1, en cuyo caso se =ace re0erencia a ella por el nombre del miembro. .i en una implementaci-n expl5cita de miembros de inter0a1 se incluyen modi0icadores de acceso o modi0icadores abstract, virtual, override o static, se producir(n errores en tiempo de compilaci-n. 8as implementaciones expl5citas de miembros de inter0a1 tienen di0erentes caracter5sticas de acceso respecto a otros miembros. 2ado ?ue este tipo de implementaciones nunca son accesibles por su nombre completo en una llamada a un m)todo o una instrucci-n de acceso a una propiedad, son en cierto sentido privadas. .in embargo, debido a ?ue se puede obtener acceso a ellas a trav)s de una instancia de propiedad, tambi)n son en otro sentido pHblicas. 8as implementaciones expl5citas de miembros de inter0a1 tienen dos principales ob$etivosG 'uesto ?ue no se puede obtener acceso a ellas por medio de instancias de clase o estructura, permiten excluir las implementaciones de inter0a1 de la inter0a1 pHblica de una clase o estructura. Esto resulta de especial utilidad cuando una clase o estructura implementa una inter0a1 interna ?ue no es de inter)s para ningHn consumidor de dic=a clase o estructura. 8as implementaciones expl5citas de miembros de inter0a1 permiten la eliminaci-n de la ambigIedad en los miembros de inter0a1 ?ue tienen la misma 0irma. .in ellas, una clase o estructura no podr5a contener di0erentes implementaciones de los miembros de inter0a1 de id)ntica 0irma y tipo de valor devueltoV tampoco podr5a contener ninguna implementaci-n de los miembros de inter0a1 de igual 0irma pero distinto tipo de valor devuelto.

'ara ?ue una implementaci-n expl5cita de miembros de inter0a1 sea v(lida, la clase o estructura debe dar nombre a una inter0a1 en su clase base ?ue contenga un miembro cuyo nombre completo, tipo y tipos de par(metro coincidan exactamente con los de la implementaci-n expl5cita de miembros de inter0a1. &s5, en la clase siguiente
class S"a&e/ $Cloneable { object $Cloneable.Clone() {...! int $Com&arable.Com&are1o(object ot"er) {...! ! .. invalid

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

#'!

Especificacin del lenguaje C#

la declaraci-n de $Com&arable.Com&are1o produce un error en tiempo de compilaci-n, por?ue $Com&arable no aparece en la lista de clases base de S"a&e y no es una inter0a1 base de $Cloneable. !gualmente, en las declaraciones
class S"a&e/ $Cloneable { object $Cloneable.Clone() {...! ! class )lli&se/ S"a&e { object $Cloneable.Clone() {...! !

.. invalid

la declaraci-n de $Cloneable.Clone en )lli&se supone un error en tiempo de compilaci-n, ya ?ue $Cloneable no aparece expresamente citada en la lista de clases base de )lli&se. El nombre completo de un miembro de inter0a1 debe =acer re0erencia a la inter0a1 donde se declara. &s5, en las declaraciones
inter-ace $Control { void *aint(); ! inter-ace $1e#t:o#/ $Control { void Set1e#t(string te#t); ! class 1e#t:o#/ $1e#t:o# { void $Control.*aint() {...! void $1e#t:o#.Set1e#t(string te#t) {...! !

la implementaci-n expl5cita de miembro de inter0a1 de *aint debe escribirse como $Control.*aint. 13.!.2 E"clusi idad de interfaces implementadas 8as inter0aces implementadas por una declaraci-n de tipo gen)rico deben ser Hnicas para todos los tipos construidos posibles. .in esta regla, ser5a imposible determinar el m)todo correcto para llamar a determinados tipos construidos. 'or e$emplo, supongamos ?ue se permite escribir una declaraci-n de clase gen)rica de la siguiente maneraG
inter-ace $D1E { void V(); ! class ID; UE/ $D;E $DUE { void $D;E.V() {...! void $DUE.V() {...! ! $DintE # + ne, IDint intE(); #.V(); .. )rror/ $D;E and $DUE con-lict

.i se permitiese, ser5a imposible determinar ?u) c-digo e$ecutar en el siguiente casoG

'ara determinar si la lista de inter0aces de una declaraci-n de tipo gen)rico es v(lida, se llevan a cabo los siguientes pasosG

#'6

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

.upongamos ?ue L es la lista de inter0aces directamente especi0icada en una declaraci-n de clase, estructura o inter0a1 gen)rica C. &gregue a L cual?uier inter0a1 base de las inter0aces ?ue ya se encuentran en L. buite todos los duplicados de L. .i despu)s de sustituir los argumentos de tipo en L, los tipos construidos creados desde C provocan ?ue dos inter0aces de L sean id)nticas, la declaraci-n de C no es v(lida. 8as declaraciones de restricci-n no se tienen en cuenta a la =ora de determinar todos los tipos construidos posibles.

En la declaraci-n de clase I anterior, la lista de inter0aces L est( 0ormada por $D;E e $DUE. 8a declaraci-n no es v(lida por?ue cual?uier tipo construido con ; y U del mismo tipo causar5a ?ue estas dos inter0aces sean tipos id)nticos. Es posible uni0icar las inter0aces especi0icadas en niveles de =erencia di0erentesG
inter-ace $D1E { void V(); ! class :aseD;E/ $D;E { void $D;E.V() {b! ! class 6erivedD; UE/ :aseD;E { void $DUE.V() {b! ! $DUE .. %(

Este c-digo es v(lido aun?ue 6erivedD; UE implemente tanto $D;E como $DUE. El c-digo
$DintE # + ne, 6erivedDint intE(); #.V();

invoca al m)todo en 6erived, puesto ?ue 6erivedDint intE vuelve a implementar $DintE de manera e0ectiva O[13.4.#R. 13.!.3 Implementacin de m*todos gen*ricos Cuando un m)todo gen)rico implementa de manera impl5cita un m)todo de inter0a1, las restricciones dadas para cada par(metro de tipo del m)todo deben ser e?uivalentes en ambas declaraciones Odespu)s de reempla1ar los par(metros de tipo de inter0a1 por los argumentos de tipo apropiadosR, donde los par(metros de tipo del m)todo se identi0ican por sus posiciones ordinales de i1?uierda a derec=a. Cuando un m)todo gen)rico implementa expl5citamente un m)todo de inter0a1, sin embargo, no se permite ninguna restricci-n en el m)todo implementador. En lugar de eso, se =eredan las restricciones del m)todo de inter0a1
inter-ace $D' : CE { void VD1E(1 t) ,"ere 1/ '; void SD1E(1 t) ,"ere 1/ :; void HD1E(1 t) ,"ere 1/ C; ! class C/ $Dobject C stringE { &ublic void VD1E(1 t) {...! &ublic void SD1E(1 t) ,"ere 1/ C {...! &ublic void HD1E(1 t) ,"ere 1/ string {...! !

.. %( .. %( .. )rror

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

#'(

Especificacin del lenguaje C#

El m)todo C.VD1E implementa de manera impl5cita $Dobject C stringE.VD1E. En este caso, C.VD1E no debe ni puede especi0icar la restricci-n 1/ object ya ?ue object es una restricci-n impl5cita en todos los par(metros de tipo. El m)todo C.SD1E implementa de manera impl5cita $Dobject C stringE.SD1E por?ue las restricciones coinciden con las de la inter0a1 despu)s de sustituir los par(metros de tipo de inter0a1 por los argumentos de tipo correspondientes. 8a restricci-n para el m)todo C.HD1E es un error por?ue los tipos sealed Ostring en este casoR no se pueden utili1ar como restricciones. Tambi)n ser5a un error omitir la restricci-n ya ?ue las implementaciones impl5citas del m)todo de inter0a1 deben coincidir. 'or lo tanto, es imposible implementar de manera impl5cita $Dobject C stringE.HD1E. Este m)todo de inter0a1 s-lo se puede implementar con una implementaci-n expl5cita del miembro de inter0a1G
class C/ $Dobject C stringE { ... &ublic void HD;E(; u) ,"ere ;/ class {...! void $Dobject C stringE.HD1E(1 t) { string s + t; .. %( HD1E(t); ! !

En este e$emplo, la implementaci-n expl5cita del miembro de inter0a1 invoca un m)todo pHblico ?ue tiene restricciones estrictamente m(s d)biles. Tenga en cuenta ?ue la asignaci-n de t a s es v(lida puesto ?ue 1 =ereda una restricci-n de 1/ string, aun?ue esta restricci-n no es expresable en el c-digo 0uente. 13.!.! 'signacin de interfaces 7na clase o estructura debe proporcionar implementaciones de todos los miembros de las inter0aces enumeradas en su lista de clases base. El proceso de locali1ar implementaciones de miembros de inter0a1 en una clase o estructura de implementaci-n se conoce como asignaci,n de interfaces. 8a asignaci-n de inter0a1 para una clase o estructura C locali1a una implementaci-n para cada uno de los miembros de todas las inter0aces especi0icadas en la lista de clases base de C. 8a implementaci-n de un miembro de inter0a1 $.M concreto, donde $ es la inter0a1 donde se declara el miembro M, se determina al examinar todas las clases o estructuras S, comen1ando desde C y repitiendo el paso para cada clase base sucesiva de C, =asta encontrar una coincidenciaG .i S contiene una declaraci-n de una implementaci-n expl5cita de miembros de inter0a1 ?ue coincide con $ y M, este miembro es la implementaci-n de $.M. 'or otro lado, si S contiene una declaraci-n de un miembro pHblico no est(tico ?ue coincide con M, este miembro es la implementaci-n de $.M. .i =ay m(s de un miembro ?ue coincide, no se especi0ica ?u) miembro es la implementaci-n de $.M. Esta situaci-n s-lo ocurre si S es un tipo construido donde los dos miembros, tal como se declara en el tipo gen)rico, tienen 0irmas di0erentes, pero los argumentos de tipo =acen ?ue sus 0irmas sean id)nticas.

.e produce un error en tiempo de compilaci-n si no es posible locali1ar implementaciones de todos los miembros de cada inter0a1 especi0icada en la lista de clases base de C. /bserve ?ue los miembros de una inter0a1 incluyen a?uellos miembros =eredados de sus inter0aces base. & e0ectos de la asignaci-n de inter0a1, un miembro de clase ' coincide con un miembro de inter0a1 : cuandoG
' y : son m)todos, y el nombre, tipo y listas de par(metros 0ormales de ' y : son id)nticos. ' y : son propiedades, el nombre y tipo de ' y : son id)nticos y ' posee los mismos descriptores de acceso ?ue : Ose permite ?ue ' tenga descriptores de acceso adicionales si no es una implementaci-n expl5cita de

miembros de inter0a1R.

#'$

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

' y : son eventos, y el nombre y tipo de ' y : son id)nticos. ' y : son indi1adores, el tipo y listas de par(metros 0ormales de ' y : son id)nticos y ' posee los mismos descriptores de acceso ?ue : Ose permite ?ue ' tenga descriptores de acceso adicionales si no es una

implementaci-n expl5cita de miembros de inter0a1R. &lgunas de las principales implicaciones del algoritmo de asignaci-n de inter0a1 sonG 8as implementaciones expl5citas de miembros de inter0a1 tienen prioridad sobre los dem(s miembros de una misma clase o estructura a la =ora de determinar el miembro de clase o estructura ?ue implementa a un miembro de inter0a1. 4i los miembros no pHblicos ni los no est(ticos participan en la asignaci-n de inter0a1.
inter-ace $Cloneable { object Clone(); ! class C/ $Cloneable { object $Cloneable.Clone() {...! &ublic object Clone() {...! !

En el e$emplo

el miembro $Cloneable.Clone de C se convierte en la implementaci-n de Clone en $Cloneable, por?ue las implementaciones expl5citas de miembros de inter0a1 tienen prioridad sobre los dem(s miembros. .i una clase o estructura implementa dos o m(s inter0aces ?ue contienen un miembro con el mismo nombre, tipo y tipos de par(metros, es posible asignar cada uno de los miembros de inter0a1 a un Hnico miembro de clase o estructura. 'or e$emploG
inter-ace $Control { void *aint(); ! inter-ace $Vorm { void *aint(); ! class *age/ $Control $Vorm { &ublic void *aint() {...! !

&?u5, los m)todos *aint de $Control e $Vorm se asignan al m)todo *aint en *age. 4aturalmente, tambi)n es posible traba$ar con di0erentes implementaciones expl5citas de miembros de inter0a1 para los dos m)todos. .i una clase o estructura implementa una inter0a1 ?ue contiene miembros ocultos, necesariamente deber(n implementarse algunos miembros por medio de la implementaci-n expl5cita de miembros de inter0a1. 'or e$emploG
inter-ace $:ase { int * { get; ! !

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

#'"

Especificacin del lenguaje C# inter-ace $6erived/ $:ase { ne, int *(); !

7na implementaci-n de esta inter0a1 re?uerir5a al menos una implementaci-n expl5cita de miembros de inter0a1, y tomar5a una de las siguientes 0ormasG
class C/ $6erived { int $:ase.* { get {...! ! int $6erived.*() {...! ! class C/ $6erived { &ublic int * { get {...! ! int $6erived.*() {...! ! class C/ $6erived { int $:ase.* { get {...! ! &ublic int *() {...! !

Cuando una clase implementa varias inter0aces con la misma inter0a1 base, s-lo puede =aber una implementaci-n de la inter0a1 base. En el e$emplo
inter-ace $Control { void *aint(); ! inter-ace $1e#t:o#/ $Control { void Set1e#t(string te#t); ! inter-ace $List:o#/ $Control { void Set$tems(string45 items); ! class Combo:o#/ $Control $1e#t:o# { void $Control.*aint() {...! $List:o#

void $1e#t:o#.Set1e#t(string te#t) {...! void $List:o#.Set$tems(string45 items) {...! !

no es posible ?ue =aya implementaciones independientes para el miembro de inter0a1 $Control ?ue 0igura en la lista de clases base, el miembro $Control =eredado por $1e#t:o# y el miembro $Control =eredado por $List:o#. 2e =ec=o, no existe una identidad separada para estas inter0aces. En realidad, las implementaciones de $1e#t:o# e $List:o# comparten la misma implementaci-n de $Control, y se considera ?ue Combo:o# Hnicamente implementa tres inter0acesG $Control, $1e#t:o# e $List:o#. 8os miembros de una clase base participan en la asignaci-n de inter0a1. En el e$emplo
inter-ace $nter-ace2 { void V(); !

#1'

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases class Class2 { &ublic void V() {! &ublic void S() {! ! class Class8/ Class2 $nter-ace2 { ne, &ublic void S() {! !

el m)todo V de Class2 se utili1a en la implementaci-n de $nter-ace2 en Class8. 13.!.# Herencia de implementacin de interfaces 7na clase =ereda todas las implementaciones de inter0a1 proporcionadas por sus clases base. .in rei ple entar expl5citamente una inter0a1, una clase derivada no puede alterar de ningHn modo las asignaciones de inter0a1 ?ue =ereda de sus clases base. 'or e$emplo, en las declaraciones
inter-ace $Control { void *aint(); ! class Control/ $Control { &ublic void *aint() {...! ! class 1e#t:o#/ Control { ne, &ublic void *aint() {...! !

el m)todo *aint de 1e#t:o# oculta el m)todo *aint de Control, pero no altera la asignaci-n de Control.*aint a $Control.*aint, y las llamadas a *aint a trav)s de instancias de clase y de inter0a1 tendr(n los e0ectos siguientesG
Control c + 1e#t:o# t + $Control ic $Control it c.*aint(); t.*aint(); ic.*aint(); it.*aint(); ne, Control(); ne, 1e#t:o#(); + c; + t; .. invo(es .. invo(es .. invo(es .. invo(es

Control.*aint(); 1e#t:o#.*aint(); Control.*aint(); Control.*aint();

.in embargo, cuando se asigna un m)todo de inter0a1 a un m)todo virtual de una clase, es posible ?ue las clases derivadas invaliden el m)todo virtual y alteren la implementaci-n de la inter0a1. 'or e$emplo, al rescribir las declaraciones anteriores de esta manera
inter-ace $Control { void *aint(); ! class Control/ $Control { &ublic virtual void *aint() {...! ! class 1e#t:o#/ Control { &ublic override void *aint() {...! !

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

#11

Especificacin del lenguaje C#

se observar(n los siguientes e0ectos


Control c + 1e#t:o# t + $Control ic $Control it c.*aint(); t.*aint(); ic.*aint(); it.*aint(); ne, Control(); ne, 1e#t:o#(); + c; + t; .. invo(es .. invo(es .. invo(es .. invo(es

Control.*aint(); 1e#t:o#.*aint(); Control.*aint(); 1e#t:o#.*aint();

2ado ?ue las implementaciones expl5citas de miembros de inter0a1 no pueden declararse como virtuales, no es posible invalidarlas. .in embargo, es per0ectamente v(lido ?ue una implementaci-n expl5cita de miembros de inter0a1 llame a otro m)todo, y se puede declarar dic=o m)todo como virtual para permitir ?ue las clases derivadas lo invaliden. 'or e$emploG
inter-ace $Control { void *aint(); ! class Control/ $Control { void $Control.*aint() { *aintControl(); ! &rotected virtual void *aintControl() {...! ! class 1e#t:o#/ Control { &rotected override void *aintControl() {...! !

&?u5, las clases derivadas de Control pueden especiali1ar la implementaci-n de $Control.*aint invalidando el m)todo *aintControl. 13.!.$ 9eimplementacin de interfaces 7na clase ?ue =ereda una implementaci-n de inter0a1 puede rei ple entar la inter0a1 incluy)ndola en la lista de clases base. 7na reimplementaci-n de una inter0a1 sigue exactamente las mismas reglas de asignaci-n de inter0a1 ?ue la implementaci-n inicial de una inter0a1. &s5, la asignaci-n de inter0a1 =eredada no tiene e0ecto alguno en la asignaci-n de inter0a1 especi0icada para la reimplementaci-n de la inter0a1. 'or e$emplo, en las declaraciones
inter-ace $Control { void *aint(); ! class Control/ $Control { void $Control.*aint() {...! ! class MyControl/ Control $Control { &ublic void *aint() {! !

el =ec=o de ?ue Control asigne $Control.*aint a Control.$Control.*aint no a0ecta a la reimplementaci-n en MyControl, ?ue asigna $Control.*aint a MyControl.*aint. 8as declaraciones =eredadas de miembros pHblicos y las implementaciones expl5citas =eredadas de miembros de inter0a1 participan en el proceso de asignaci-n de inter0a1 para las inter0aces implementadas. 'or e$emploG

#12

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases inter-ace $Met"ods { void V(); void S(); void H(); void $(); ! class :ase/ $Met"ods { void $Met"ods.V() {! void $Met"ods.S() {! &ublic void H() {! &ublic void $() {! ! class 6erived/ :ase $Met"ods { &ublic void V() {! void $Met"ods.H() {! !

&?u5, la implementaci-n de $Met"ods en 6erived asigna los m)todos de inter0a1 a 6erived.V, :ase.$Met"ods.S, 6erived.$Met"ods.H y :ase.$. Cuando una clase implementa una inter0a1, tambi)n implementa impl5citamente todas las inter0aces base de dic=a inter0a1. 2e igual 0orma, una reimplementaci-n de una inter0a1 tambi)n es impl5citamente una reimplementaci-n de todas sus inter0aces base. 'or e$emploG
inter-ace $:ase { void V(); ! inter-ace $6erived/ $:ase { void S(); ! class C/ $6erived { void $:ase.V() {...! void $6erived.S() {...! ! class 6/ C $6erived { &ublic void V() {...! &ublic void S() {...! !

&?u5, la reimplementaci-n de $6erived tambi)n reimplementa $:ase, asignando $:ase.V a 6.V. 13.!.+ Interfaces y clases abstractas &l igual ?ue una clase no abstracta, una clase abstracta debe proporcionar implementaciones de todos los miembros de las inter0aces ?ue 0iguran en su lista de clases base. .in embargo, una clase abstracta puede asignar m)todos de inter0a1 a m)todos abstractos. 'or e$emploG
inter-ace $Met"ods { void V(); void S(); !

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

#13

Especificacin del lenguaje C# abstract class C/ $Met"ods { &ublic abstract void V(); &ublic abstract void S(); !

&?u5, la implementaci-n de $Met"ods asigna V y S a m)todos abstractos, ?ue pueden invalidarse en clases no abstractas ?ue se deriven de C. 2ebe observarse ?ue las implementaciones expl5citas de miembros de inter0a1 no pueden ser abstractas, pero s5 pueden llamar a m)todos abstractos. 'or e$emploG
inter-ace $Met"ods { void V(); void S(); ! abstract class C/ $Met"ods { void $Met"ods.V() { VV(); ! void $Met"ods.S() { SS(); ! &rotected abstract void VV(); &rotected abstract void SS(); !

&?u5, las clases no abstractas ?ue se derivan de C deber5an invalidar VV y SS, proporcionando de esa 0orma la propia implementaci-n de $Met"ods.

#1#

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

1!. Enumeraciones
7n tipo en! En el e$emplo
enum Color { Oed Sreen :lue !

es un tipo de valor distintivo O[4.1R ?ue declara un con$unto de constantes con nombre.

se declara un tipo enum denominado Color con los miembros Oed, Sreen y :lue.

1!.1 /eclaraciones de enumeracin


7na declaraci-n de enumeraci-n declara un nuevo tipo enum. 7na declaraci-n de enumeraci-n comien1a con la palabra clave enum y de0ine su nombre, su tipo de acceso, su tipo subyacente y sus miembros. en %-declaration1 attri- tesopt en %-%odifiersopt enum identifier en %--aseopt en %--od# ;opt en %--ase1 / inte&ral-t#pe en %--od#1 { en %-%e%-er-declarationsopt ! { en %-%e%-er-declarations ! Cada tipo enum tiene un tipo integral correspondiente denominado tipo s!/yacente del tipo enum. Este tipo subyacente debe poder representar todos los valores de enumerador de0inidos en la enumeraci-n. 7na declaraci-n de enumeraci-n puede declarar expl5citamente un tipo subyacente byte, sbyte, s"ort, us"ort, int uint long o ulong. /bserve ?ue no se puede utili1ar c"ar como tipo subyacente. 7na declaraci-n de enumeraci-n ?ue no declara expl5citamente un tipo subyacente tiene int como tipo subyacente. En el e$emplo
enum Color/ long { Oed Sreen :lue !

se declara una enumeraci-n con el tipo subyacente long. 7n programador podr5a utili1ar un tipo subyacente long, como en el e$emplo, para =abilitar el uso de valores ?ue est)n en el intervalo de long, pero no en el de int, o para preservar esta opci-n para el 0uturo.

1!.2 &odificadores de enumeracin


7na declaraci-n de enumeraci-n Oen %-declarationR puede incluir opcionalmente una secuencia de modi0icadores de enumeraci-nG

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

#1!

Especificacin del lenguaje C#

en %-%odifiers1 en %-%odifier en %-%odifiers en %-%odifier en %-%odifier1


ne, &ublic &rotected internal &rivate

Cuando el mismo modi0icador aparece varias veces en una declaraci-n de enumeraci-n, se produce un error en tiempo de compilaci-n. 8os modi0icadores de una declaraci-n de enumeraci-n tienen el mismo signi0icado ?ue los de las declaraciones de clases O[1".1.1R. /bserve, sin embargo, ?ue los modi0icadores abstract y sealed no est(n permitidos en una declaraci-n de enumeraci-n. 8as enumeraciones no pueden ser abstractas y no permiten derivaci-n.

1!.3 &iembros de enumeracin


El cuerpo de una declaraci-n de tipo enum de0ine cero o varios miembros de enumeraci-n, ?ue son las constantes con nombre del tipo enum. 4o puede =aber dos miembros de enumeraci-n con el mismo nombre. en %-%e%-er-declarations1 en %-%e%-er-declaration en %-%e%-er-declarations

en %-%e%-er-declaration

en %-%e%-er-declaration1 attri- tesopt identifier attri- tesopt identifier + constant-e2pression Cada miembro de enumeraci-n tiene un valor asociado constante. El tipo de este valor es el tipo subyacente de la enumeraci-n contenedora. El valor constante de cada miembro de enumeraci-n debe estar comprendido en el intervalo del tipo subyacente de la enumeraci-n. En el e$emplo
enum Color/ uint { Oed + =2 Sreen + =8 :lue + =9 !

se produce un error en tiempo de compilaci-n, por?ue los valores constantes =2, =8 y C9 no est(n en el intervalo del tipo integral subyacente uint. >arios miembros de enumeraci-n pueden compartir el mismo valor asociado. En el e$emplo
enum Color { Oed Sreen :lue Ma# + :lue !

se muestra una enumeraci-n en la ?ue dos de sus miembros O:lue y Ma#R tienen el mismo valor asociado. El valor asociado de un miembro de enumeraci-n se asigna bien impl5cita o expl5citamente. .i la declaraci-n del miembro de enumeraci-n tiene un iniciali1ador de expresi-n constante Oconstant-e2pressionR, el valor de dic=a expresi-n, convertido de manera impl5cita al tipo subyacente de la enumeraci-n, es el valor asociado del

#16

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

miembro de enumeraci-n. .i la declaraci-n del miembro de enumeraci-n no tiene iniciali1ador, su valor asociado se establece de 0orma impl5cita, de la siguiente 0ormaG .i el miembro de enumeraci-n es el primero de los declarados en el tipo enum, su valor asociado es cero. En cual?uier otro caso, el valor asociado del miembro de enumeraci-n se obtiene al aumentar en uno el valor asociado del miembro de enumeraci-n precedente en el c-digo. Este valor aumentado debe estar incluido en el intervalo de valores ?ue puede representar el tipo subyacente, en caso contrario, se produce un error de compilaci-n.
using System; enum Color { Oed Sreen + 23 :lue ! class 1est { static void Main() { Console.WriteLine(StringVromColor(Color.Oed)); Console.WriteLine(StringVromColor(Color.Sreen)); Console.WriteLine(StringVromColor(Color.:lue)); ! static string StringVromColor(Color c) { s,itc" (c) { case Color.Oed/ return String.Vormat("Oed + {3!" case Color.Sreen/ return String.Vormat("Sreen + {3!" case Color.:lue/ return String.Vormat(":lue + {3!" de-ault/ return "$nvalid color"; ! ! !

En el e$emplo

(int) c); (int) c); (int) c);

se imprimen los nombres de los miembros de enumeraci-n y sus valores asociados. El resultado esG
Oed + 3 Sreen + 23 :lue + 22

por las siguientes ra1onesG al miembro de enumeraci-n Oed se le asigna autom(ticamente el valor cero Opuesto ?ue no tiene iniciali1ador y es el primer miembro de enumeraci-nRV al miembro de enumeraci-n Sreen se le asigna expl5citamente el valor 23V y al miembro de enumeraci-n :lue se le asigna autom(ticamente el valor del miembro ?ue le precede en el c-digo m(s uno.

El valor asociado de un miembro de enumeraci-n no puede, directa ni indirectamente, usar el valor de su propio miembro de enumeraci-n asociado. &parte de esta restricci-n de circularidad, los iniciali1adores de miembros de enumeraci-n pueden =acer re0erencia con libertad a otros iniciali1adores de miembros de enumeraci-n, sin importar su posici-n en el c-digo. 2entro de un iniciali1ador de miembro de enumeraci-n, los valores de los
Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

#1(

Especificacin del lenguaje C#

dem(s miembros de enumeraci-n siempre se tratan como si tuvieran el tipo de su tipo subyacente, de manera ?ue no son necesarias las conversiones de tipos al =acer re0erencia a otros miembros de enumeraci-n. En el e$emplo
enum Circular { ' + : : !

se produce un error durante la compilaci-n por?ue las declaraciones de ' y : son circulares. ' depende de : expl5citamente, y : depende de ' impl5citamente. 8os miembros de enumeraci-n se denominan y se establece su (mbito de manera exactamente an(loga a los campos pertenecientes a clases. El (mbito de un miembro de enumeraci-n es el cuerpo de su tipo enum contenedor. 2entro de ese (mbito, se puede =acer re0erencia a los miembros de enumeraci-n por su nombre simple. 2esde cual?uier otra ubicaci-n del c-digo, debe certi0icarse el nombre de un miembro de enumeraci-n con el nombre de su tipo enum. 8os miembros de enumeraci-n no tienen ninguna accesibilidad declaradaG un miembro de enumeraci-n es accesible si el tipo enum ?ue lo contiene es accesible.

1!.! Tipo 4ystem.Enum


El tipo System.)num es la clase base abstracta de todos los tipos enum Oes distinta y di0erente del tipo subyacente del tipo enumR, y los miembros =eredados de System.)num est(n disponibles en cual?uier tipo enum. Existe una conversi-n boxing O[4.3.1R de cada tipo enum a System.)num y tambi)n existe una conversi-n unboxing O[4.3.2R de System.)num a cual?uier tipo enum. /bserve ?ue System.)num no es en s5 mismo un tipo enum Oen %-t#peR. &l contrario, es un tipo de clase Oclass-t#peR del ?ue se derivan todos los tipos enum Oen %-t#pesR. El tipo System.)num =ereda del tipo System.Ualue1y&e O[4.1.1R, el cual, a su ve1, =ereda del tipo object. En tiempo de e$ecuci-n, un valor de tipo System.)num puede ser null o una re0erencia a un valor con conversi-n boxing de cual?uier tipo enum.

1!.# Valores y operaciones de enumeracin


Cada tipo enum de0ine un tipo distintivoV es necesaria una conversi-n expl5cita de enumeraci-n O[#.2.2R para convertir un tipo enum a un tipo integral, o para convertir dos tipos enum. El con$unto de valores ?ue puede tomar un tipo enum no est( limitado por sus miembros de enumeraci-n. En concreto, cual?uier valor del tipo subyacente de una enumeraci-n puede convertirse en el tipo enum, y es un valor aceptado y distintivo de dic=o tipo enum. 8os miembros de enumeraci-n tienen el tipo de su tipo enum contenedor Osalvo dentro de otros iniciali1adores de miembros de enumeraci-nG vea la secci-n [14.3R. El valor de un miembro de enumeraci-n declarado en el tipo enum ) con un valor v asociado es ())v. 8os operadores siguientes se pueden utili1ar en los valores de tipos enumG ++, @+, D, E, D+, E+ O[*.+. R, binario < O[*.*.4R, binario = O[*.*. R, G, F, H O[*.1".2R, A O[*.#.4R, << y == O[*. .+ y [*.#. R. Cada tipo de enum autom(ticamente deriva de la clase System.)num O?ue, a su ve1, deriva de System.Ualue1y&e y objectR. &s5, los m)todos =eredados y propiedades de esta clase se pueden utili1ar en los valores de un tipo de enumeraci-n.

#1$

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

1#. /elegados
8os delegados =abilitan escenarios de programaci-n ?ue otros lengua$es, como CSS, 'ascal y %odula, =an resuelto mediante punteros a 0unci-n. & di0erencia de los punteros a 0unci-n de CSS, los delegados est(n completamente orientados a ob$etos y, a di0erencia de los punteros a 0unciones miembro de CSS, los delegados encapsulan a la ve1 una instancia de ob$eto y un m)todo. 7na declaraci-n de delegado de0ine una clase ?ue se deriva de la clase System.6elegate. 7na instancia de delegado encapsula una lista de llamadas, ?ue consiste en una lista de uno o varios m)todos, a cada uno de los ?ue se =ace re0erencia como una entidad invocable. 'ara m)todos de instancia, una entidad invocable consta de una instancia y un m)todo de la instancia. 'ara los m)todos est(ticos, una entidad invocable est( 0ormada solamente por un m)todo. !nvocar a una instancia delegada con un con$unto adecuado de argumentos, =ace ?ue se invo?ue a cada una de las entidades del delegado invocables, con el con$unto de argumentos dado. 7na propiedad interesante y Htil de una instancia de delegado es ?ue no necesita conocer las clases de los m)todos a los ?ue encapsulaV lo Hnico ?ue importa es ?ue los m)todos sean compatibles O[1 .1R con el tipo del delegado. Esto =ace ?ue los delegados sean per0ectos para una invocaci-n Pan-nimaQ.

1#.1 /eclaraciones de delegados


7na declaraci-n de delegado Odele&ate-declarationR es una declaraci-n de tipo Ot#pe-declarationR O[+.#R ?ue declara un nuevo tipo delegado. dele&ate-declaration1 attri- tesopt dele&ate-%odifiersopt delegate ret rn-t#pe identifier t#pe-para%eter-listopt ( for%al-para%eter-listopt ) t#pe-para%eter-constraints-cla sesopt ; dele&ate-%odifiers1 dele&ate-%odifier dele&ate-%odifiers dele&ate-%odifier dele&ate-%odifier1
ne, &ublic &rotected internal &rivate

Cuando el mismo modi0icador aparece varias veces en una declaraci-n de delegado, se produce un error en tiempo de compilaci-n. El modi0icador ne, s-lo est( permitido en delegados declarados dentro de otro tipo, en cuyo caso, )ste especi0ica ?ue tal delegado oculta un miembro =eredado con el mismo nombre, como se describe en la secci-n [1".3.4. 8os modi0icadores &ublic, &rotected, internal y &rivate controlan el acceso del tipo delegado. 2ependiendo del contexto en el ?ue ocurra la declaraci-n de delegado, algunos de estos modi0icadores pueden no estar permitidos O[3. .1R. El nombre del tipo delegado es el identi0icador OidentifierR.

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

#1"

Especificacin del lenguaje C#

8a lista opcional de par(metros 0ormales Ofor%al-para%eter-listR especi0ica los par(metros del delegado, y el tipo de valor devuelto Oret rn-t#peR corresponde al delegado. 8a lista opcional de par(metros de tipo Ot#pe-para%eter-listR especi0ica los par(metros de tipo ?ue corresponden al propio delegado. 8os tipos delegados en C# son e?uivalentes en su denominaci-n, no estructuralmente. En concreto, dos tipos delegados di0erentes con la misma lista de par(metros y el mismo tipo de valor devuelto se consideran di0erentes. .in embargo, las instancias de dos tipos delegados distintos pero estructuralmente e?uivalentes se pueden considerar iguales O[*.+.8R. 'or e$emploG
delegate int 62(int i double d); class ' { &ublic static int M2(int a ! class : { delegate int 68(int c

double b) {...!

double d); double g) {...! double l) {...!

&ublic static int M2(int &ublic static void M8(int (

&ublic static int M9(int g) {...! &ublic static void MJ(int g) {...! !

8os tipos delegados 62 y 68 son compatibles con los m)todos '.M2 y :.M2, ya ?ue poseen el mismo tipo de valor devuelto y la misma lista de par(metrosV sin embargo, son tipos di0erentes, por lo cual no son intercambiables entre s5. 8os tipos delegados 62 y 68 son incompatibles con los m)todos :.M8, :.M9 y :.MJ, ya ?ue poseen di0erentes tipos de valor devuelto o di0erentes listas de par(metros. &l igual ?ue otras declaraciones de tipo gen)rico, se deben proporcionar argumentos de tipo para crear un tipo de delegado construido. 8os tipos de par(metro y el tipo de valor devuelto de un tipo de delegado construido se crean sustituyendo, para cada par(metro de tipo de la declaraci-n de delegado, el argumento de tipo correspondiente del tipo de delegado construido. El tipo de valor devuelto resultante y los tipos de par(metros se utili1an para determinar los m)todos compatibles con un tipo de delegado construido. 'or e$emploG
delegate bool *redicateD1E(1 value); class I { static bool V(int i) {...! static bool S(string s) {...! !

El tipo delegado *redicateDintE es compatible con el m)todo I.V y el tipo delegado *redicateDstringE es compatible con el m)todo I.S. 8a Hnica 0orma de declarar un tipo delegado es a trav)s de una declaraci-n de delegado Odele&ate-declarationR. 7n tipo delegado es un tipo de clase derivada de System.6elegate. 8os tipos delegados son sealed de manera impl5cita, por lo ?ue no est( permitido derivar ningHn tipo de un tipo delegado. Tampoco se permite derivar un tipo de clase no delegado a partir de System.6elegate. /bserve ?ue System.6elegate no es en s5 mismo un tipo delegadoV es un tipo de clase del cual se derivan todos los tipos delegados. C# proporciona una sintaxis especial para la creaci-n y llamada de instancias de delegado. .alvo para la creaci-n de instancias, cual?uier operaci-n ?ue pueda aplicarse a una clase o instancia de clase tambi)n puede

#2'

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

aplicarse a una clase o instancia de delegado, respectivamente. En particular, es posible obtener acceso a los miembros del tipo System.6elegate a trav)s de la sintaxis =abitual de acceso a miembros. El con$unto de m)todos encapsulados por una instancia de delegado se denomina lista de llamadas. Cuando se crea una instancia de delegado O[1 .2R a partir de un Hnico m)todo, encapsula el m)todo y su lista de llamadas contiene una sola entrada. .in embargo, cuando se combinan dos instancias de delegado no null, sus listas de llamadas se concatenan, por orden de operando i1?uierdo a operando derec=o, para 0ormar una nueva lista de llamadas, ?ue contiene dos o m(s entradas. 8os delegados se combinan utili1ando los operadores binarios < O[*.*.4R y <+ O[*.1#.2R. .e puede ?uitar un delegado de una combinaci-n de delegados utili1ando los operadores binarios = O[*.*. R y =+ O[*.1#.2R. 8os delegados se pueden comparar para comprobar si =ay igualdad O[*.+.8R. El e$emplo siguiente muestra la creaci-n de instancias de un nHmero de delegados y sus correspondientes listas de llamadasG
delegate void 6(int #); class C { &ublic static void M2(int i) {...! &ublic static void M8(int i) {...! ! class 1est { static void Main() { 6 cd2 + ne, 6(C.M2); 6 cd8 + ne, 6(C.M8); 6 cd9 + cd2 < cd8; 6 cdJ + cd9 < cd2; 6 cdK + cdJ < cd9; ! !

.. .. .. .. ..

M2 M8 M2 < M8 M2 < M8 < M2 M2 < M8 < M2 < M2 < M8

&l crear instancias de cd2 y cd8, cada una de ellas encapsula un m)todo. Cuando se crea una instancia de cd9, tiene una lista de llamadas de dos m)todos, M2 y M8, por ese orden. 8a lista de llamadas de cdJ contiene M2, M8 y M2, por ese orden. 'or Hltimo, la lista de llamadas de cdK contiene M2, M8, M2, M2 y M8, por ese orden. 'ara ver m(s e$emplos de combinaci-n Oy supresi-nR de delegados, vea la secci-n [1 .4.

1#.2 %ompatibilidad de delegados


7n m)todo o delegado M es co pati/le con un tipo delegado 6 si se cumplen las siguientes condicionesG
6 y M tienen el mismo nHmero de par(metros y cada par(metro de 6 tiene los mismos modi0icadores re- u out ?ue el par(metro correspondiente en M.

'ara cada par(metro de valor Oun par(metro sin un modi0icador re- u outR, existe una conversi-n de identidad O[#.1.1R o una conversi-n de re0erencia impl5cita O[#.1.#R desde el tipo de par(metro 6 al tipo de par(metro correspondiente en M. 'ara cada par(metro re- u out, el tipo de par(metro en 6 es el mismo ?ue el tipo de par(metro en M. Existe una conversi-n de identidad o de re0erencia impl5cita desde el tipo de valor devuelto de M al tipo de valor devuelto de 6.

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

#21

Especificacin del lenguaje C#

1#.3 %reacin de instancias de delegados


7na instancia de un delegado se crea mediante una expresi-n de creaci-n de delegados Odele&ate-creatione2pressionR O[R o una conversi-n a un tipo delegado. 8a instancia de delegado reci)n creada =ace re0erencia a alguno de los siguientesG El m)todo est(tico a ?ue se =ace re0erencia en la expresi-n de creaci-n de delegados Odele&ate-creatione2pressionR, o bien El ob$eto de destino O?ue no puede ser nullR y el m)todo de instancia a ?ue se =ace re0erencia en la expresi-n de creaci-n de delegados Odele&ate-creation-e2pressionR, o bien /tro delegado.
delegate void 6(int #); class C { &ublic static void M2(int i) {...! &ublic void M8(int i) {...! ! class 1est { static void Main() { 6 cd2 + ne, 6(C.M2); C t + ne, C(); 6 cd8 + ne, 6(t.M8); 6 cd9 + ne, 6(cd8); ! !

'or e$emploG

.. static met"od .. instance met"od .. anot"er delegate

7na ve1 creadas las instancias de delegado, )stas siempre =acen re0erencia al mismo ob$eto de destino y m)todo. ;ecuerde ?ue, cuando se combinan dos delegados, o se ?uita uno de ellos en el otro, el resultado es un nuevo delegado con su propia lista de llamadasV las listas de llamadas de los delegados combinados o eliminados permanecen sin cambios.

1#.! In ocacin de delegados


C# proporciona una sintaxis especial para invocar un delegado. Cuando se invoca una instancia de delegado no null cuya lista de llamadas contiene un sola entrada, llama a ese m)todo con los mismos argumentos ?ue recibi-, y devuelve el mismo valor ?ue el m)todo a ?ue se =ace re0erencia. O>ea la secci-n [*. . .3 para obtener in0ormaci-n detallada sobre la invocaci-n de delegados.R .i se produce una excepci-n durante la llamada a un delegado y no se captura dentro del m)todo invocado, la bHs?ueda de una cl(usula de excepci-n catc= continHa en el m)todo ?ue llam- al delegado, como si ese m)todo =ubiera llamado directamente al m)todo al ?ue =ac5a re0erencia el delegado. 8a invocaci-n de una instancia de delegado cuya lista de llamadas contiene varias entradas continHa llamando a cada uno de los m)todos de la lista, de 0orma sincr-nica, por orden. & cada uno de los m)todos as5 llamados se le pasa el mismo con$unto de argumentos pasados a la instancia de delegado. .i tal invocaci-n de delegado incluye par(metros de re0erencia O[1".#.1.2R, cada invocaci-n de m)todo incluir( una re0erencia a la misma variableV los cambios en dic=a variable ?ue realice un m)todo de la lista de llamadas ser(n visibles para todos los m)todos situados a continuaci-n en la lista. .i la invocaci-n de delegado incluye par(metros de salida o un valor devuelto, su valor 0inal vendr( dado por la invocaci-n del Hltimo delegado de la lista. .i se produce una excepci-n durante la llamada a dic=o delegado y no se captura dentro del m)todo invocado, la bHs?ueda de una cl(usula de excepci-n catc= continHa en el m)todo ?ue llam- al delegado, y no se invoca ninguno de los m)todos situados a continuaci-n en la lista de llamadas.

#22

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

!ntentar invocar una instancia de delegado cuyo valor es null provoca una excepci-n del tipo System.NullOe-erence)#ce&tion. En el siguiente e$emplo se muestra c-mo crear instancias, combinar, ?uitar e invocar delegadosG
using System; delegate void 6(int #); class C { &ublic static void M2(int i) { Console.WriteLine("C.M2/ " < i); ! &ublic static void M8(int i) { Console.WriteLine("C.M8/ " < i); ! &ublic void M9(int i) { Console.WriteLine("C.M9/ " < i); ! ! class 1est { static void Main() { 6 cd2 + ne, 6(C.M2); cd2(=2); .. call M2 6 cd8 + ne, 6(C.M8); cd8(=8); .. call M8 6 cd9 + cd2 < cd8; cd9(23); .. call M2 t"en M8 cd9 <+ cd2; cd9(83); .. call M2 M8 t"en M2

C c + ne, C(); 6 cdJ + ne, 6(c.M9); cd9 <+ cdJ; cd9(93); .. call M2 cd9 =+ cd2; cd9(J3); cd9 =+ cdJ; cd9(K3); cd9 =+ cd8; cd9(X3); cd9 =+ cd8; cd9(X3); cd9 =+ cd2; .. ! ! cd9(M3); cd9 =+ cd2;

M8

M2

t"en M9

.. remove last M2 .. call M2 M8 t"en M9 .. call M2 t"en M8 .. call M2 .. im&ossible removal is benign .. call M2 .. invocation list is em&ty so cd9 is null .. System.NullOe-erence)#ce&tion t"ro,n .. im&ossible removal is benign

Tal como se muestra en la instrucci-n cd9 <+ cd2;, un delegado puede aparecer varias veces en una lista de llamadas. En este caso, se le llama una ve1 por cada aparici-n. En una lista de llamadas como esta, cuando se ?uita el delegado, la Hltima aparici-n en la lista es la ?ue se elimina realmente.

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

#23

Especificacin del lenguaje C#

!nmediatamente antes de la e$ecuci-n de la instrucci-n 0inal, cd9 =+ cd2; el delegado cd9 =ace re0erencia a una lista de llamadas vac5a. !ntentar ?uitar un delegado de una lista vac5a Oo ?uitar un delegado no existente de una lista ?ue no est( vac5aR no es ningHn error. El resultado producido es el siguienteG
C.M2/ C.M8/ C.M2/ C.M8/ C.M2/ C.M8/ C.M2/ C.M2/ C.M8/ C.M2/ C.M9/ C.M2/ C.M8/ C.M9/ C.M2/ C.M8/ C.M2/ C.M2/ =2 =8 23 23 83 83 83 93 93 93 93 J3 J3 J3 K3 K3 X3 X3

#2#

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

1$. E"cepciones
8as excepciones de C# proporcionan una 0orma estructurada, uni0orme y con seguridad de tipos de controlar situaciones de error del sistema y de las aplicaciones. El mecanismo de excepciones de C# es bastante similar al de CSS, pero con unas cuantas di0erencias importantesG En C#, todas las excepciones deben estar representadas por una instancia de un tipo de clase derivado de System.)#ce&tion. En CSS, cual?uier valor de cual?uier tipo puede utili1arse para representar una excepci-n. En C#, puede utili1arse un blo?ue 0inally O[8.1"R para crear c-digo de terminaci-n ?ue se e$ecute en condiciones normales y excepcionales. Ese tipo de c-digo es di05cil de escribir en CSS sin duplicar c-digo. En C#, las excepciones del nivel de sistema, como desbordamiento, divisi-n por cero o eliminaciones de re0erencia nulas, tienen clases de excepci-n bien de0inidas y est(n al mismo nivel ?ue los escenarios de error de aplicaciones.

1$.1 %ausas de e"cepciones


7na excepci-n se puede iniciar de dos 0ormas di0erentes. 7na instrucci-n t"ro, O[8.+. R inicia una excepci-n de manera inmediata e incondicional. El control nunca llega a la instrucci-n ?ue sigue inmediatamente a t"ro,. &lgunas situaciones excepcionales ?ue pueden surgir durante el procesamiento de instrucciones y expresiones de C# provocan una excepci-n en ciertas circunstancias cuando no es posible completar normalmente una operaci-n. 'or e$emplo, una operaci-n de divisi-n de enteros O[*.*.2R inicia una excepci-n System.6ivide:yPero)#ce&tion si el denominador es cero. >ea la [1#.4 para obtener una lista de las di0erentes excepciones ?ue pueden producirse de esta 0orma.

1$.2 %lase 4ystem.E"ception


8a clase System.)#ce&tion es el tipo base de todas las excepciones. Esta clase tiene unas cuantas propiedades a resaltar ?ue comparten todas las excepcionesG
Message es una propiedad de s-lo lectura de tipo string ?ue contiene una descripci-n legible por el

=ombre de la causa ?ue provoc- la excepci-n.


$nner)#ce&tion es una propiedad de s-lo lectura de tipo )#ce&tion. .i su valor no es null, se re0iere a

la excepci-n ?ue caus- la excepci-n actual, es decir, ?ue la excepci-n actual se inici- en un blo?ue catc= ?ue controlaba la excepci-n $nner)#ce&tion. En cual?uier otro caso, su valor es null, lo ?ue indica ?ue esta excepci-n no 0ue causada por otra excepci-n. El nHmero de ob$etos de excepci-n encadenados de esta 0orma puede ser arbitrario.

El valor de estas propiedades puede especi0icarse en las llamadas al constructor de instancia de System.)#ce&tion.

1$.3 %mo controlar e"cepciones


8as excepciones se controlan mediante una excepci-n try O[8.1"R.

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

#2!

Especificacin del lenguaje C#

Cuando se produce una excepci-n, el sistema busca la cl(usula catc" m(s pr-xima ?ue controla la excepci-n, segHn lo determina el tipo de la excepci-n en tiempo de e$ecuci-n. En primer lugar, se busca una instrucci-n try contenedora en el m)todo actual, y se consideran las cl(usulas catc= asociadas de la instrucci-n try segHn su ordenaci-n. .i ese primer paso no se produce, se busca el m)todo ?ue llam- al m)todo actual en una instrucci-n try ?ue contenga el punto de la llamada al m)todo actual. Esta bHs?ueda continHa =asta encontrar una cl(usula catc" ?ue puede controlar la excepci-n actual, denominando una clase de excepci-n ?ue sea de la misma clase o clase base del tipo en tiempo de e$ecuci-n de la excepci-n iniciada. 7na cl(usula catc" ?ue no denomina ninguna clase de excepci-n puede controlar cual?uier excepci-n. 7na ve1 =allada una cl(usula catc= coincidente, el sistema se prepara para trans0erir el control a la primera instrucci-n de la cl(usula catc=. &ntes de comen1ar la e$ecuci-n de la cl(usula catc=, el sistema e$ecuta, por orden, todas las cl(usulas -inally asociadas a instrucciones try cuyo nivel de anidamiento sea mayor ?ue el de la ?ue captur- la excepci-n. 2e no encontrarse ninguna cl(usula catc= coincidente, se produce una de estas dos circunstanciasG .i la bHs?ueda de una cl(usula catc= coincidente llega =asta un constructor est(tico O[1".12R o un iniciali1ador de campo est(tico, se inicia una excepci-n System.1y&e$nitiali?ation)#ce&tion en el punto donde se desencaden- la llamada al constructor est(tico. 8a excepci-n interna de System.1y&e$nitiali?ation)#ce&tion contiene la excepci-n iniciada en un principio. .i la bHs?ueda de cl(usulas catc= coincidentes llega =asta el c-digo ?ue inici- el subproceso, termina la e$ecuci-n del mismo. El impacto de esta terminaci-n se de0ine segHn la implementaci-n.

8as excepciones ?ue se producen durante la e$ecuci-n de un destructor merecen especial atenci-n. .i se produce una excepci-n durante la e$ecuci-n de un destructor y la excepci-n no es capturada, se termina la e$ecuci-n de dic=o destructor y se llama al destructor de la clase base Osi existeR. .i no =ay clase base Ocomo ocurre con el tipo objectR o no =ay un destructor de clase base, se descarta la excepci-n.

1$.! %lases de e"cepcin comunes


& continuaci-n se muestran las excepciones iniciadas por algunas operaciones de C#.

#26

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

System.'rit"metic)#ce&tion

Clase base de las excepciones producidas durante operaciones aritm)ticas, como System.6ivide:yPero)#ce&tion y System.%ver-lo,)#ce&tion. .e inicia cuando una operaci-n de almacenamiento en una matri1 da error por?ue el tipo real del elemento almacenado es incompatible con el tipo de la matri1. .e inicia cuando se produce un intento de dividir un valor integral por cero. .e inicia cuando se produce un intento de indi1ar una matri1 por medio de un 5ndice menor ?ue cero o situado 0uera de los l5mites de la matri1. .e inicia cuando una conversi-n expl5cita de un tipo o inter0a1 base a un tipo derivado da un error en tiempo de e$ecuci-n. .e inicia cuando se utili1a una re0erencia null de manera ?ue =ace obligatorio el ob$eto al ?ue se =ace re0erencia. .e inicia cuando =ay problemas al intentar asignar memoria a trav)s de ne,. .e inicia cuando una operaci-n aritm)tica en un contexto c"ec(ed produce un desbordamiento. .e inicia cuando se agota la pila de excepciones debido a la existencia de demasiadas llamadas de m)todo pendientesV suele indicar un nivel de recursividad muy pro0undo o ilimitado. .e inicia cuando un constructor est(tico inicia una excepci-n sin ?ue =aya cl(usulas catc" para capturarla.

System.'rray1y&eMismatc")#ce&tion

System.6ivide:yPero)#ce&tion System.$nde#%ut%-Oange)#ce&tion

System.$nvalidCast)#ce&tion

System.NullOe-erence)#ce&tion

System.%ut%-Memory)#ce&tion System.%ver-lo,)#ce&tion System.Stac(%ver-lo,)#ce&tion

System.1y&e$nitiali?ation)#ce&tion

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

#2(

Especificacin del lenguaje C#

1+. 'tributos
3ran parte del lengua$e C# permite al programador especi0icar in0ormaci-n declarativa acerca de las entidades ?ue se de0inen en el programa. 'or e$emplo, la accesibilidad de un m)todo en una clase se especi0ica al decorarlo con los modi0icadores de m)todo O%ethod-%odifiersR &ublic, &rotected, internal y &rivate. C# permite a los programadores inventar nuevas clases de in0ormaci-n declarativa, denominadas atri/!tos. 8os programadores pueden entonces asociar atributos a varias entidades de programa y recuperar la in0ormaci-n de atributos en un entorno en tiempo de e$ecuci-n. 'or e$emplo, un marco de traba$o podr5a de0inir un atributo Hel&'ttribute ?ue se pueda colocar en ciertos elementos del programa, como clases y m)todos, para proporcionar una asignaci-n o correspondencia entre dic=os elementos y su documentaci-n. 8os atributos se de0inen mediante la declaraci-n de clases de atributo O[1*.1R, ?ue pueden contener par(metros posicionales y con nombre O[1*.1.2R. 8os atributos se asocian a entidades de un programa de C# mediante las especi0icaciones de atributos O[1*.2R, y pueden recuperarse en tiempo de e$ecuci-n como instancias de atributo O[1*.3R.

1+.1 %lases de atributos


7na clase de atri/!to es una clase ?ue se deriva de la clase abstracta System.'ttribute, ya sea directa o indirectamente. 8a declaraci-n de una clase de atributo de0ine un nuevo tipo de atri/!to ?ue se puede insertar en una declaraci-n. 'or convenci-n, las clases de atributos se denominan con el su0i$o 'ttribute. 8os usos de un atributo pueden incluir u omitir este su0i$o. 1+.1.1 5so de los atributos El atributo 'ttribute;sage O[1*.4.1R se utili1a para describir c-mo se puede utili1ar una clase de atributo.
'ttribute;sage posee un par(metro posicional O[1*.1.2R ?ue =abilita a una clase de atributo para especi0icar

los tipos de declaraciones en ?ue se puede utili1ar. En el e$emplo


using System; 4'ttribute;sage('ttribute1argets.Class H 'ttribute1argets.$nter-ace)5 &ublic class Sim&le'ttribute/ 'ttribute { ... !

se de0ine una clase de atributo denominada Sim&le'ttribute ?ue se puede colocar en declaraciones de clase Oclass-declarationsR y en declaraciones de inter0a1 Ointerface-declarationsR. El e$emplo
4Sim&le5 class Class2 {...! 4Sim&le5 inter-ace $nter-ace2 {...!

muestra varios usos del atributo Sim&le. .i bien el atributo se de0ine con el nombre Sim&le'ttribute, cuando se utili1a puede omitirse el su0i$o 'ttribute, dando como resultado el nombre corto Sim&le. &s5, el e$emplo anterior es sem(nticamente e?uivalente al ?ue se muestra a continuaci-nG
4Sim&le'ttribute5 class Class2 {...! 4Sim&le'ttribute5 inter-ace $nter-ace2 {...! 'ttribute;sage tiene un par(metro con nombre O[1*.1.2R denominado 'llo,Multi&le, ?ue indica si puede especi0icarse el atributo m(s de una ve1 para una entidad dada. .i 'llo,Multi&le para una clase de atributo es

#2$

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

true, se trata de una clase de atri/!to de !so 7ltiple y se puede especi0icar m(s de una ve1 en una entidad. .i 'llo,Multi&le para una clase de atributo es 0alse o no est( especi0icado, se trata de una clase de atri/!to de !so 7nico y se puede especi0icar como muc=o una ve1 en una entidad. El e$emplo
using System; 4'ttribute;sage('ttribute1argets.Class 'llo,Multi&le + true)5 &ublic class 'ut"or'ttribute/ 'ttribute { &rivate string name; &ublic 'ut"or'ttribute(string name) { t"is.name + name; ! &ublic string Name { get { return name; ! ! !

de0ine una clase de atributo de uso mHltiple de nombre 'ut"or'ttribute. El e$emplo


4'ut"or(":rian aernig"an") class Class2 { ... ! 'ut"or("6ennis Oitc"ie")5

muestra una declaraci-n de clase con dos usos del atributo 'ut"or.
'ttribute;sage tiene otro par(metro con nombre denominado $n"erited, ?ue especi0ica si el atributo,

cuando se especi0ica en una clase base, tambi)n es =eredado por las clases ?ue se derivan de esta clase base. .i $n"erited para una clase de atributo es true, se =ereda dic=o atributo. .i $n"erited para una clase de atributo es 0alse, dic=o atributo no se =ereda. .i no se especi0ica, su valor predeterminado es true. 7na clase de atributo I sin atributo 'ttribute;sage asociado, como en
using System; class I/ 'ttribute {...!

e?uivale a lo siguienteG
using System; 4'ttribute;sage( 'ttribute1argets.'ll 'llo,Multi&le + -alse $n"erited + true) 5 class I/ 'ttribute {...!

1+.1.2 (ar)metros posicionales y con nombre 8as clases de atributo pueden tener par5 etros posicionales y par5 etros con no /re. Cada constructor de instancia pHblico de una clase de atributo de0ine una secuencia v(lida de par(metros posicionales para esa clase de atributo. Cada campo o propiedad de lectura y escritura pHblica y no est(tica de una clase de atributo de0ine un par(metro con nombre para la clase de atributo. En el e$emplo
using System;

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

#2"

Especificacin del lenguaje C# 4'ttribute;sage('ttribute1argets.Class)5 &ublic class Hel&'ttribute/ 'ttribute { &ublic Hel&'ttribute(string url) { ... ! &ublic string 1o&ic { get {...! set {...! ! &ublic string ;rl { get {...! ! !

.. *ositional &arameter

.. Named &arameter

se de0ine una clase de atributo denominada Hel&'ttribute ?ue posee un par(metro posicional, url y un par(metro con nombre, 1o&ic. .i bien es no est(tica y pHblica, la propiedad ;rl no de0ine un par(metro con nombre por?ue no es de lectura y escritura. Esta clase de atributo podr5a utili1arse de la manera siguienteG
4Hel&(""tt&/..,,,.mycom&any.com.....Class2."tm")5 class Class2 { ... ! 4Hel&(""tt&/..,,,.mycom&any.com.....Misc."tm" class Class8 { ... ! 1o&ic + "Class8")5

1+.1.3 Tipos de par)metros de atributos 8os tipos de los par(metros posicionales y con nombre de una clase de atributo se limitan a los tipos de par5 etros de atri/!tos, ?ue sonG 7no de los tipos siguientesG bool, byte, c"ar, double, -loat, int, long, sbyte, s"ort, string, uint, ulong, us"ort. El tipo object. El tipo System.1y&e. 7n tipo enum, con la condici-n de ?ue )ste y los tipos en los ?ue est) anidado Osi los =ubieraR tengan acceso pHblico O[1*.2R. %atrices unidimensionales de los tipos anteriores. 7n argumento de constructor o un campo pHblico ?ue no tenga uno de estos tipos no se puede usar como par(metro con nombre o posicional en una especi0icaci-n de atributo.

1+.2 Especificacin de atributos


8a especificaci,n de atri/!tos es la aplicaci-n de un atributo previamente de0inido a una declaraci-n. 7n atributo es una parte de in0ormaci-n declarativa adicional ?ue se especi0ica en una declaraci-n. 8os atributos pueden especi0icarse en un (mbito global Opara especi0icar atributos en el ensamblado o m-dulo ?ue los contienenR y para declaraciones de tipo Ot#pe-declarationsR O[+.#R, declaraciones de miembros de clase Oclass%e%-er-declarationsR O[1".1. R, declaraciones de miembros de inter0a1 Ointerface-%e%-er-declarationsR O[13.2R, declaraciones de miembros de estructura Ostr ct-%e%-er-declarationsR O[11.2R, declaraciones de

#3'

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

miembros de enumeraci-n Oen %-%e%-er-declarationsR O[14.3R, declaraciones de descriptores de acceso Oaccessor-declarationsR O[1".*.2R, declaraciones de descriptores de acceso a eventos Oevent-accessordeclarationsR O[1".8.1R y listas de par(metros 0ormales Ofor%al-para%eter-listsR O[1".#.1R. 8os atributos se especi0ican en secciones de atri/!tos. 7na secci-n de atributos se compone de un par de corc=etes, ?ue encierran una lista separada por comas de uno o varios atributos. 4i el orden de los atributos en la lista, ni el de las secciones ad$untas a la misma entidad de programa son signi0icativos. 'or e$emplo, las especi0icaciones de atributos 4'54:5, 4:54'5, 4', :5 y 4:, '5 son e?uivalentes. &lo-al-attri- tes1 &lo-al-attri- te-sections &lo-al-attri- te-sections1 &lo-al-attri- te-section &lo-al-attri- te-sections &lo-al-attri- te-section &lo-al-attri- te-section1 4 &lo-al-attri- te-tar&et-specifier attri- te-list 5 4 &lo-al-attri- te-tar&et-specifier attri- te-list 5 &lo-al-attri- te-tar&et-specifier1 &lo-al-attri- te-tar&et / &lo-al-attri- te-tar&et1
assembly module

attri- tes1 attri- te-sections attri- te-sections1 attri- te-section attri- te-sections attri- te-section attri- te-section1 4 attri- te-tar&et-specifieropt attri- te-list 5 4 attri- te-tar&et-specifieropt attri- te-list 5 attri- te-tar&et-specifier1 attri- te-tar&et / attri- te-tar&et1
-ield event met"od &aram &ro&erty return ty&e

attri- te-list1 atri- to attri- te-list

attri- te

attri- te1 attri- te-na%e attri- te-ar& %entsopt attri- te-na%e1 t#pe-na%e
Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

#31

Especificacin del lenguaje C#

attri- te-ar& %ents1 ( positional-ar& %ent-listopt ) ( positional-ar& %ent-list na%ed-ar& %ent-list ) ( na%ed-ar& %ent-list ) positional-ar& %ent-list1 positional-ar& %ent positional-ar& %ent-list

positional-ar& %ent

positional-ar& %ent1 attri- te-ar& %ent-e2pression na%ed-ar& %ent-list1 na%ed-ar& %ent na%ed-ar& %ent-list

na%ed-ar& %ent

na%ed-ar& %ent1 identifier + attri- te-ar& %ent-e2pression attri- te-ar& %ent-e2pression1 e2pression 7n atributo se compone de un nombre de atributo Oattri- te-na%eR y una lista opcional de argumentos posicionales y con nombre. 8os argumentos posicionales Osi los =ayR preceden a los argumentos con nombre. 7n argumento posicional se compone de una expresi-n de argumentos de atributo Oattri- te-ar& %ent-e2pressionR. 7n argumento con nombre consta de un nombre seguido por el signo igual, seguido de una expresi-n de argumentos de atributo Oattri- te-ar& %ent-e2pressionR ?ue, en con$unto, est(n restringidos por las mismas reglas ?ue la asignaci-n simple. El orden de los argumentos con nombre no es signi0icativo. El nombre de atributo Oattri- te-na%eR identi0ica una clase de atributo. .i la 0orma del nombre de atributo Oattri- te-na%eR es un nombre de tipo Ot#pe-na%eR, este nombre debe =acer re0erencia a una clase de atributo. En caso contrario, se producir( un error en tiempo de compilaci-n. En el e$emplo
class Class2 {! 4Class25 class Class8 {! .. )rror

se produce un error en tiempo de compilaci-n, por?ue se intenta utili1ar Class2 como clase de atributo a pesar de no serlo. &lgunos contextos permiten especi0icar un atributo en m(s de un destino. 7n programa puede especi0icar expl5citamente el destino incluyendo un especi0icador de destino de atributo Oattri- te-tar&et-specifierR. Cuando se coloca un atributo en el nivel global, es necesario un especi0icador de destino de atributo global O&lo-alattri- te-tar&et-specifierR. En todas las dem(s ubicaciones, se aplica un valor predeterminado ra1onable, pero es posible utili1ar un especi0icador de destino de atributo Oattri- te-tar&et-specifierR para a0irmar o invalidar el valor predeterminado en ciertos casos ambiguos Oo s-lo para a0irmar el valor predeterminado, en casos en ?ue no =aya ambigIedadR. 2e esta 0orma, pueden omitirse =abitualmente los especi0icadores de destino de atributo Oattri- te-tar&et-specifiersR. 8os contextos potencialmente ambiguos se resuelven de esta 0ormaG 7n atributo especi0icado en el (mbito global se puede aplicar tanto al ensamblado de destino como al m-dulo de destino. 4o existe un valor predeterminado para este contexto, por lo ?ue siempre se re?uiere un especi0icador de destino de atributo Oattri- te-tar&et-specifierR. 8a presencia del especi0icador de destino de atributo Oattri- te-tar&et-specifierR a continuaci-n de assembly indica ?ue el atributo se aplica al ensamblado de destinoV la presencia del mismo especi0icador a continuaci-n de module indica ?ue el atributo se aplica al m-dulo de destino. 7n atributo especi0icado en una declaraci-n de delegado se puede aplicar al delegado ?ue se est( declarando o a su valor devuelto. En ausencia del especi0icador de destino de atributo Oattri- te-tar&et-specifierR, el

#32

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

atributo se aplica al delegado. 8a presencia del especi0icador de destino de atributo Oattri- te-tar&etspecifierR a continuaci-n de ty&e indica ?ue el atributo se aplica al delegadoV la presencia del mismo especi0icador a continuaci-n de return indica ?ue el atributo se aplica al valor devuelto. 7n atributo especi0icado en una declaraci-n de m)todo se puede aplicar al m)todo ?ue se est( declarando o a su valor devuelto. En ausencia del especi0icador de destino de atributo Oattri- te-tar&et-specifierR, el atributo se aplica al m)todo. 8a presencia del especi0icador de destino de atributo Oattri- te-tar&et-specifierR a continuaci-n de met"od indica ?ue el atributo se aplica al m)todoV la presencia del mismo especi0icador a continuaci-n de return indica ?ue el atributo se aplica al valor devuelto. 7n atributo especi0icado en una declaraci-n de operador se puede aplicar al operador ?ue se est( declarando o a su valor devuelto. En ausencia del especi0icador de destino de atributo Oattri- te-tar&et-specifierR, el atributo se aplica al operador. 8a presencia del especi0icador de destino de atributo Oattri- te-tar&etspecifierR a continuaci-n de met"od indica ?ue el atributo se aplica al operadorV la presencia del mismo especi0icador a continuaci-n de return indica ?ue el atributo se aplica al valor devuelto. 7n atributo especi0icado en una declaraci-n de evento ?ue omite los descriptores de acceso de eventos se puede aplicar al evento ?ue se est( declarando, al campo asociado Osi el evento no es abstractoR o a los m)todos add y remove. En ausencia del especi0icador de destino de atributo Oattri- te-tar&et-specifierR, el atributo se aplica al evento. 8a presencia del especi0icador de destino de atributo Oattri- te-tar&et-specifierR a continuaci-n de event indica ?ue el atributo se aplica al eventoV la presencia del especi0icador a continuaci-n de -ield indica ?ue el atributo se aplica al campoV y la presencia del mismo especi0icador a continuaci-n de met"od indica ?ue el atributo se aplica a los m)todos. 7n atributo especi0icado en una declaraci-n de descriptor de acceso get para una propiedad o una declaraci-n de indi1ador se puede aplicar al m)todo asociado o a su valor devuelto. En ausencia del especi0icador de destino de atributo Oattri- te-tar&et-specifierR, el atributo se aplica al m)todo. 8a presencia del especi0icador de destino de atributo Oattri- te-tar&et-specifierR a continuaci-n de met"od indica ?ue el atributo se aplica al m)todoV la presencia del mismo especi0icador a continuaci-n de return indica ?ue el atributo se aplica al valor devuelto. 7n atributo especi0icado en una declaraci-n de descriptor de acceso set para una propiedad o una declaraci-n de indi1ador se puede aplicar al m)todo asociado o a su par(metro impl5cito solo. En ausencia del especi0icador de destino de atributo Oattri- te-tar&et-specifierR, el atributo se aplica al m)todo. 8a presencia del especi0icador de destino de atributo Oattri- te-tar&et-specifierR a continuaci-n de met"od indica ?ue el atributo se aplica al m)todoV la presencia del especi0icador de destino de atributo &aram indica ?ue el atributo se aplica al par(metroV y la presencia del especi0icador de destino de atributo return indica ?ue el atributo se aplica al valor devuelto. 7n atributo especi0icado en una declaraci-n de descriptor de acceso add o remove para una declaraci-n de evento se aplica al m)todo asociado o a su par(metro. En ausencia del especi0icador de destino de atributo Oattri- te-tar&et-specifierR, el atributo se aplica al m)todo. 8a presencia del especi0icador de destino de atributo Oattri- te-tar&et-specifierR a continuaci-n de met"od indica ?ue el atributo se aplica al m)todoV la presencia del especi0icador de destino de atributo &aram indica ?ue el atributo se aplica al par(metroV y la presencia del especi0icador de destino de atributo return indica ?ue el atributo se aplica al valor devuelto.

En otros contextos se permite la inclusi-n de un especi0icador de destino de atributo Oattri- te-tar&et-specifierR, pero no es necesaria. 'or e$emplo, una declaraci-n de clase puede incluir u omitir el especi0icador ty&eG
4ty&e/ 'ut"or(":rian aernig"an")5 class Class2 {! 4'ut"or("6ennis Oitc"ie")5 class Class8 {!

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

#33

Especificacin del lenguaje C#

.upone un error especi0icar un especi0icador de destino de atributo Oattri- te-tar&et-specifierR no v(lido. 'or e$emplo, el especi0icador &aram no se puede utili1ar en una declaraci-n de claseG
4&aram/ 'ut"or(":rian aernig"an")5 class Class2 {! .. )rror

'or convenci-n, las clases de atributos se denominan con el su0i$o 'ttribute. 7n nombre de atributo Oattri- te-na%eR con la estructura de nombre de tipo Ot#pe-na%eR puede incluir u omitir este su0i$o. .i se encuentra una clase de atributo tanto con este su0i$o como sin )l, existe una ambigIedad y se produce un error de tiempo de compilaci-n. .i el nombre de atributo Oattri- te-na%eR se escribe de manera ?ue su identi0icador OidentifierR situado m(s a la derec=a es un identi0icador literal O[2.4.2R, s-lo se corresponder( con un atributo sin su0i$o, lo ?ue supondr( una ambigIedad ?ue se debe resolver. En el e$emplo
using System; 4'ttribute;sage('ttribute1argets.'ll)5 &ublic class I/ 'ttribute {! 4'ttribute;sage('ttribute1argets.'ll)5 &ublic class I'ttribute/ 'ttribute {! 4I5 class Class2 {! 4I'ttribute5 class Class8 {! 4[I5 class Class9 {! 4[I'ttribute5 class ClassJ {! .. )rror/ ambiguity .. Oe-ers to I'ttribute .. Oe-ers to I .. Oe-ers to I'ttribute

se muestran dos clases de atributos denominadas I y I'ttribute. El atributo 4I5 es ambiguo, puesto ?ue podr5a re0erirse tanto a I como a I'ttribute. El uso de un identi0icador literal permite especi0icar la intenci-n exacta en estos casos poco 0recuentes. El atributo 4I'ttribute5 no es ambiguo Oaun?ue lo ser5a si =ubiera una clase de atributo denominada I'ttribute'ttributeR. .i se ?uita la declaraci-n de la clase I, ambos atributos =acen re0erencia a la clase de atributo Iattribute, de la manera siguienteG
using System; 4'ttribute;sage('ttribute1argets.'ll)5 &ublic class I'ttribute/ 'ttribute {! 4I5 class Class2 {! 4I'ttribute5 class Class8 {! 4[I5 class Class9 {! .. Oe-ers to I'ttribute .. Oe-ers to I'ttribute .. )rror/ no attribute named "I"

.upone un error en tiempo de compilaci-n utili1ar un atributo de uso Hnico m(s de una ve1 en la misma entidad. En el e$emplo
using System; 4'ttribute;sage('ttribute1argets.Class)5 &ublic class Hel&String'ttribute/ 'ttribute { string value;

#3#

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases &ublic Hel&String'ttribute(string value) { t"is.value + value; ! &ublic string Ualue { get {...! ! ! 4Hel&String("6escri&tion o- Class2")5 4Hel&String("'not"er descri&tion o- Class2")5 &ublic class Class2 {!

se produce un error en tiempo de compilaci-n, por?ue intenta utili1ar Hel&String, una clase de atributo de uso Hnico, m(s de una ve1 en la declaraci-n de Class2. 7na expresi-n ) es una expresi-n de argumentos de atributo Oattri- te-ar& %ent-e2pressionR si todas las instrucciones siguientes son verdaderasG El tipo de ) es un tipo de par(metro de atributo O[1*.1.3R. En tiempo de compilaci-n, el valor de ) se puede calcular a trav)s deG o o o 7n valor constante. 7n ob$eto System.1y&e. 7na matri1 unidimensional de expresiones de argumento de atributo Oattri- te-ar& %ent-e2pressionsR.
using System; 4'ttribute;sage('ttribute1argets.Class)5 &ublic class 1est'ttribute/ 'ttribute { &ublic int *2 { get {...! set {...! ! &ublic 1y&e *8 { get {...! set {...! ! &ublic object *9 { get {...! set {...! ! ! 41est(*2 + 289J *9 + ne, int45 {2 class MyClass {! 9 K! *8 + ty&eo-(-loat))5

'or e$emploG

7na expresi-n typeo0 Ot#peof-e2pressionR O[*. .11R utili1ada como una expresi-n de argumentos de atributo puede =acer re0erencia a un tipo no gen)rico, un tipo construido cerrado o un tipo gen)rico independiente, pero no puede =acer re0erencia a un tipo abierto. &s5 se garanti1a ?ue la expresi-n no se puede resolver en tiempo de compilaci-n.
class '/ 'ttribute { &ublic '(1y&e t) {...! !

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

#3!

Especificacin del lenguaje C# class SD1E { 4'(ty&eo-(1))5 1 t; ! class I { 4'(ty&eo-(ListDintE))5 int #; 4'(ty&eo-(ListDE))5 int y; !

.. )rror

o&en ty&e in attribute

.. %( .. %(

closed constructed ty&e unbound generic ty&e

1+.3 Instancias de atributo


7na instancia de atri/!to es una instancia ?ue representa un atributo en tiempo de e$ecuci-n. 7n atributo se de0ine mediante una clase de atributo, argumentos posicionales y argumentos con nombre. 7na instancia de atributo es una instancia de la clase de atributo ?ue se iniciali1a con los argumentos posicionales y con nombre. 8a recuperaci-n de la instancia de atributo comprende el procesamiento en tiempo de compilaci-n y e$ecuci-n, tal como se describe en las siguientes seccionesG 1+.3.1 %ompilacin de un atributo 8a compilaci-n de un atributo Oattri- teR con clase de atributo 1, una lista de argumentos posicionales Opositional-ar& %ent-listR * y una lista de argumentos con nombre Ona%ed-ar& %ent-listR N se compone de los siguientes pasosG 'ara compilar una expresi-n de creaci-n de ob$eto de la 0orma ne, 1(*), se siguen los pasos del procesamiento en tiempo de compilaci-n. Estos pasos pueden producir un error en tiempo de compilaci-n o determinar un constructor de instancia C en 1, ?ue se puede invocar en tiempo de e$ecuci-n. .i C no tiene acceso pHblico, se produce un error en tiempo de compilaci-n. 'ara cada argumento con nombre 'rg de NG o o
Name ser( el identi0icador OidentifierR del argumento con nombre Ona%ed-ar& %entR 'rg. Name debe identi0icar a una propiedad o un campo pHblico de lectura y escritura no est(tico en 1. .i 1

no tiene dic=o campo o propiedad, se produce una excepci-n en tiempo de compilaci-n. %antenga la siguiente in0ormaci-n para la creaci-n de instancias del atributo en tiempo de e$ecuci-nG la clase de atributo 1, el constructor de instancia C de 1, la lista de argumentos posicionales Opositionalar& %ent-listR * y la lista de argumentos con nombre Ona%ed-ar& %ent-listR N.

1+.3.2 9ecuperacin en tiempo de ejecucin de una instancia de atributo 8a compilaci-n de un atributo Oattri- teR da como resultado una clase de atributo 1, un constructor de instancia C en 1, una lista de argumentos posicionales Opositional-ar& %ent-listR * y una lista de argumentos con nombre Ona%ed-ar& %ent-listR N. 2ada esta in0ormaci-n, se puede recuperar una instancia de atributo en tiempo de e$ecuci-n siguiendo estos pasosG .e siguen los pasos de procesamiento en tiempo de e$ecuci-n para e$ecutar una expresi-n de creaci-n de ob$eto Oo->ect-creation-e2pressionR de la 0orma ne, 1(*), utili1ando el constructor de instancia C tal como se determina en tiempo de compilaci-n. Estos pasos dan como resultado una excepci-n, o producen una instancia % de 1. 'ara cada argumento con nombre Ona%ed-ar& %entR 'rg de N, con el ordenG

#36

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases Name ser( el identi0icador OidentifierR del argumento con nombre Ona%ed-ar& %entR 'rg. .i Name no identi0ica a un campo o propiedad de lectura y escritura, pHblico y no est(tico en %, se inicia una

excepci-n. o o o o
Ualue ser( el resultado de evaluar la expresi-n de argumentos de atributo Oattri- te-ar& %ente2pressionR de 'rg.

.i Name identi0ica a un campo en %, estable1ca este campo en Ualue. En cual?uier otro caso, Name identi0ica a una propiedad en %. Estable1ca esta propiedad en Ualue. El resultado es %, una instancia de la clase de atributo 1 iniciali1ada con la lista de argumentos posicionales Opositional-ar& %ent-listR * y la lista de argumentos con nombre Ona%ed-ar& %ent-listR N.

1+.! 'tributos reser ados


7n pe?ueUo nHmero de atributos a0ectan al lengua$e de alguna 0orma. Estos atributos incluyenG
System.'ttribute;sage'ttribute O[1*.4.1R, ?ue se utili1a para describir las 0ormas en ?ue puede

usarse una clase de atributo.


System.6iagnostics.Conditional'ttribute O[1*.4.2R, ?ue se utili1a para de0inir m)todos

condicionales.
System.%bsolete'ttribute O[1*.4.3R, ?ue se utili1a para marcar un miembro como obsoleto.

1+.!.1 'tributo 'ttribute5sage El atributo 'ttribute;sage se utili1a para describir la manera en ?ue se puede utili1ar la clase de atributo. 7na clase decorada con el atributo 'ttribute;sage debe derivarse de System.'ttribute, directa o indirectamente. En caso contrario, se producir( un error en tiempo de compilaci-n.
names&ace System { 4'ttribute;sage('ttribute1argets.Class)5 &ublic class 'ttribute;sage'ttribute/ 'ttribute { &ublic 'ttribute;sage'ttribute('ttribute1argets valid%n) {...! &ublic virtual bool 'llo,Multi&le { get {...! set {...! ! &ublic virtual bool $n"erited { get {...! set {...! ! &ublic virtual 'ttribute1argets Ualid%n { get {...! ! ! &ublic enum 'ttribute1argets { 'ssembly + 3#3332 Module + 3#3338 Class + 3#333J Struct + 3#333Y )num + 3#3323 Constructor + 3#3383 Met"od + 3#33J3 *ro&erty + 3#33Y3 Vield + 3#3233 )vent + 3#3833 $nter-ace + 3#3J33 *arameter + 3#3Y33 6elegate + 3#2333 OeturnUalue + 3#8333

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

#3(

Especificacin del lenguaje C# 'll + 'ssembly H Module H Class H Struct H )num H Constructor H Met"od H *ro&erty H Vield H )vent H $nter-ace H *arameter H 6elegate H OeturnUalue ! !

1+.!.2 'tributo %onditional El atributo Conditional permite la de0inici-n de 6todos condicionales y clases de atri/!to condicional.
names&ace System.6iagnostics { 4'ttribute;sage('ttribute1argets.Met"od H 'ttribute1argets.Class 'llo,Multi&le + true)5 &ublic class Conditional'ttribute/ 'ttribute { &ublic Conditional'ttribute(string conditionString) {...! &ublic string ConditionString { get {...! ! ! !

1#.4.2.1 Mtodos condicionales 7n m)todo decorado con el atributo Conditional es un m)todo condicional. El atributo Conditional indica una condici-n cuando se comprueba un s5mbolo de compilaci-n condicional. 8as llamadas a un m)todo condicional se incluyen u omiten dependiendo de si est( de0inido este s5mbolo en el punto de la llamada. .i el s5mbolo se de0ine, la llamada se incluyeV en caso contrario, la llamada Oincluida la evaluaci-n de los par(metros de la llamadaR se omite. 7n m)todo condicional est( su$eto a las siguientes restriccionesG El m)todo condicional debe ser un m)todo perteneciente a una declaraci-n de clase Oclass-declarationR o de estructura Ostr ct-declarationR. .i se especi0ica el atributo Conditional en un m)todo de declaraci-n de inter0a1, se produce un error en tiempo de compilaci-n. El m)todo condicional debe tener un tipo de valor devuelto void. El m)todo condicional no debe estar marcado con el modi0icador override. .in embargo, un m)todo condicional puede marcarse con el modi0icador virtual. 8as invalidaciones de dic=o m)todo son condicionales de 0orma impl5cita, y no se deben marcar expl5citamente con un atributo Conditional. El m)todo condicional no debe ser una implementaci-n de un m)todo de inter0a1. En caso contrario, se producir( un error en tiempo de compilaci-n.

&simismo, se produce un error en tiempo de compilaci-n si se utili1a un m)todo condicional en una expresi-n de creaci-n de delegados Odele&ate-creation-e2pressionR. En el e$emplo
0de-ine 6):;S using System; using System.6iagnostics; class Class2 { 4Conditional("6):;S")5 &ublic static void M() { Console.WriteLine(")#ecuted Class2.M"); ! !

#3$

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases class Class8 { &ublic static void 1est() { Class2.M(); ! !

se declara Class2.M como m)todo condicional. El m)todo 1est de Class8 llama a este m)todo. 2ado ?ue se de0ine el s5mbolo de compilaci-n condicional 6):;S, si se llama a Class8.1est )ste llamar( a M. .i no se de0ine el s5mbolo 6):;S, Class8.1est no llamar( a Class2.M. Es importante observar ?ue la inclusi-n o exclusi-n de una llamada a un m)todo condicional est( controlada por los s5mbolos de compilaci-n condicional existentes en el lugar de la llamada. En el e$emplo &rc=ivo class2.csG
using System.6iagnostics; class Class2 { 4Conditional("6):;S")5 &ublic static void V() { Console.WriteLine(")#ecuted Class2.V"); ! !

&rc=ivo class8.csG
0de-ine 6):;S class Class8 { &ublic static void S() { Class2.V(); .. V is called ! !

&rc=ivo class9.csG
0unde- 6):;S class Class9 { &ublic static void H() { Class2.V(); .. V is not called ! !

las clases Class8 y Class9 contienen llamadas al m)todo condicional Class2.V, ?ue ser( o no condicional, en 0unci-n de si 6):;S est( de0inido o no. 2ado ?ue este s5mbolo est( de0inido en el contexto de Class8 pero no de Class9, la llamada a V en Class8 se mantiene, mientras ?ue se omite la llamada a V en Class9. El uso de m)todos condicionales en una cadena de =erencia puede resultar con0uso. 8as llamadas reali1adas a un m)todo condicional mediante base, de la 0orma base.M, est(n su$etas a las reglas normales de llamadas a m)todos condicionales. En el e$emplo &rc=ivo class2.csG
using System; using System.6iagnostics;

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

#3"

Especificacin del lenguaje C# class Class2 { 4Conditional("6):;S")5 &ublic virtual void M() { Console.WriteLine("Class2.M e#ecuted"); ! !

&rc=ivo class8.csG
using System; class Class8/ Class2 { &ublic override void M() { Console.WriteLine("Class8.M e#ecuted"); base.M(); .. base.M is not called@ ! !

&rc=ivo class9.csG
0de-ine 6):;S using System; class Class9 { &ublic static void 1est() { Class8 c + ne, Class8(); c.M(); ! !

.. M is called

Class8 incluye una llamada al m)todo M de0inido en su clase base. Esta llamada se omite por?ue el m)todo base es condicional debido a la presencia del s5mbolo 6):;S, ?ue no est( de0inido. &s5, el m)todo s-lo escribe en la consola PClass8.M e#ecutedQ. 7n uso $uicioso de las declaraciones pp Opp-declarationsR puede

eliminar tales problemas. 1#.4.2.2 Clases de atributo condicional 7na clase de atributo O[1*.1R decorada con uno o m(s atributos Conditional es una clase de atri/!to condicional. 7na clase de atributo condicional se asocia, por lo tanto, con los s5mbolos de compilaci-n condicional declarados en sus atributos Conditional. Este e$emploG
using System; using System.6iagnostics; 4Conditional("'L*H'")5 4Conditional(":)1'")5 &ublic class 1est'ttribute / 'ttribute {!

declara 1est'ttribute como una clase de atributo condicional asociado a los s5mbolos de compilaciones condicionales 'L*H' y :)1'. 8as especi0icaciones de atributos O[1*.2R de un atributo condicional se incluyen si uno o m(s de sus s5mbolos de compilaci-n condicional asociado se de0ine en el lugar de la especi0icaci-nV de lo contrario, se omite la especi0icaci-n de atributos. Es importante observar ?ue la inclusi-n o exclusi-n de la especi0icaci-n de un atributo de una clase de atributo condicional est( controlada por los s5mbolos de compilaci-n condicional existentes en el lugar de la especi0icaci-n. En el e$emplo &rc=ivo test.csG

##'

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases using System; using System.6iagnostics; 4Conditional(R6):;ST)5 &ublic class 1est'ttribute / 'ttribute {!

&rc=ivo class2.csG
0de-ine 6):;S 41est5 class Class2 {! .. 1est'ttribute is s&eci-ied

&rc=ivo class8.csG
0unde- 6):;S 41est5 class Class8 {! .. 1est'ttribute is not s&eci-ied

las clases Class2 y Class8 est(n decoradas con el atributo 1est, ?ue es condicional en 0unci-n de si 6):;S est( o no de0inido. 2ado ?ue este s5mbolo est( de0inido en el contexto de Class2 pero no de Class8, se incluye la especi0icaci-n del atributo 1est de Class2, mientras ?ue se omite la especi0icaci-n del atributo 1est en Class8.

1+.!.3 'tributo ,bsolete El atributo %bsolete se utili1a para marcar tipos y miembros de tipos ?ue ya no se deber5an utili1ar.
names&ace System { 4'ttribute;sage( 'ttribute1argets.Class H 'ttribute1argets.Struct H 'ttribute1argets.)num H 'ttribute1argets.$nter-ace H 'ttribute1argets.6elegate H 'ttribute1argets.Met"od H 'ttribute1argets.Constructor H 'ttribute1argets.*ro&erty H 'ttribute1argets.Vield H 'ttribute1argets.)vent $n"erited + -alse) 5 &ublic class %bsolete'ttribute/ 'ttribute { &ublic %bsolete'ttribute() {...! &ublic %bsolete'ttribute(string message) {...! &ublic %bsolete'ttribute(string message &ublic string Message { get {...! ! &ublic bool $s)rror { get {...! ! ! ! bool error) {...!

.i un programa utili1a un tipo o miembro decorado con el atributo %bsolete, el compilador emite una advertencia o genera un error. En concreto, si no se proporciona ningHn par(metro de error, o si se proporciona y su valor es -alse, el compilador emite una advertencia. .i se especi0ica un par(metro de error y su valor es true, el compilador genera un error.

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

##1

Especificacin del lenguaje C#

En el e$emplo
4%bsolete("1"is class is obsolete; use class : instead")5 class ' { &ublic void V() {! ! class : { &ublic void V() {! ! class 1est { static void Main() { ' a + ne, '(); a.V(); ! !

.. Warning

la clase ' est( decorada con el atributo %bsolete. Cada uso de ' en Main da como resultado una advertencia ?ue incluye el mensa$e especi0icado en el c-digo anterior, PT=is class is obsoleteV use class A instead.Q

1+.# 'tributos para interoperabilidad


8ote1 'sta secci/n s/lo se aplica a la i%ple%entaci/n de C" de Microsoft .8'B. 1+.#.1 Interoperabilidad con componentes %,& y Bin32 El motor de tiempo de e$ecuci-n de .4ET proporciona un gran nHmero de atributos ?ue permiten ?ue los programas de C# interactHen con componentes escritos mediante bibliotecas .dll C/% y @in32. 'or e$emplo, el atributo 6ll$m&ort puede utili1arse en un m)todo static e#tern para indicar ?ue la implementaci-n del m)todo se encuentra en una biblioteca 288 @in32. Estos atributos se encuentran en el espacio de nombres System.Ountime.$ntero&ServicesV se puede encontrar in0ormaci-n detallada re0erente a estos atributos en la documentaci-n del motor de tiempo de e$ecuci-n .4ET. 1+.#.2 Interoperabilidad con otros lenguajes .1ET 1#. .2.1 Ftributo $nde2erEame 8os indi1adores se implementan en .4ET utili1ando propiedades indi1adas y tienen un nombre en los metadatos .4ET. .i no =ay ningHn atributo $nde#erName presente para un indi1ador, se utili1a de 0orma predeterminada el nombre $tem. El atributo $nde#erName permite al programador invalidar este valor predeterminado y especi0icar un nombre distinto.
names&ace System.Ountime.Com&ilerServices.CS"ar& { 4'ttribute;sage('ttribute1argets.*ro&erty)5 &ublic class $nde#erName'ttribute/ 'ttribute { &ublic $nde#erName'ttribute(string inde#erName) {...! &ublic string Ualue { get {...! ! ! !

##2

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

1-. %digo no seguro


El lengua$e C# b(sico, tal como se de0ine en los cap5tulos precedentes, di0iere notablemente de C y CSS en su omisi-n de los punteros como un tipo de datos. C# proporciona en su lugar re0erencias, as5 como la capacidad de crear ob$etos administrados por un recolector de elementos no utili1ados. Este diseUo, unido a otras caracter5sticas, =ace de C# un lengua$e muc=o m(s seguro ?ue C o CSS. En el lengua$e b(sico de C# no es posible usar una variable no iniciali1ada, un puntero PpendienteQ o una expresi-n ?ue indice una matri1 m(s all( de sus l5mites. 2e esta manera se eliminan categor5as enteras de errores ?ue suelen a0ectar a los programas desarrollados en C y CSS. .i bien casi todas las construcciones de tipos de puntero en C o CSS poseen un tipo de re0erencia e?uivalente en C#, =ay situaciones donde el acceso a tipos de puntero se convierte en una necesidad. 'or e$emplo, al desear interactuar con el sistema operativo subyacente, obtener acceso a un dispositivo asignado a memoria o implementar un algoritmo sensible al tiempo puede no lograrse nuestro ob$etivo sin disponer de acceso a punteros. 'ara solucionar esta necesidad, C# proporciona la capacidad de crear c,digo no seg!ro. En el c-digo no seguro es posible declarar y operar con punteros, reali1ar conversiones de punteros a tipos integrales, tomar las direcciones de variables, etc. En cierto sentido, escribir c-digo no seguro se parece muc=o a escribir c-digo C dentro de un programa en C#. El c-digo no seguro es, en realidad, una caracter5stica PseguraQ desde el punto de vista tanto de programadores como de usuarios. El c-digo no seguro debe estar marcado con claridad mediante el modi0icador unsa-e, de manera ?ue los programadores no puedan usar caracter5sticas no seguras por accidente, y el motor de e$ecuci-n garantice ?ue no se pueda e$ecutar el c-digo no seguro en un entorno ?ue no sea de con0ian1a.

1-.1 %onte"tos no seguros


8as caracter5sticas no seguras de C# est(n disponibles s-lo en contextos no seguros O nsafe conte2tsR. .e introduce un contexto no seguro incluyendo un modi0icador unsa-e en la declaraci-n de un tipo o miembro, o utili1ando una instrucci-n unsa0e O nsafe-state%entR. 7na declaraci-n de una clase, estructura, inter0a1 o delegado puede incluir un modi0icador unsa-e, en cuyo caso toda la extensi-n textual de la declaraci-n Oincluido el cuerpo de la clase, estructura o inter0a1R se considera como contexto no seguro. 7na declaraci-n de un campo, m)todo, propiedad, evento, indi1ador, operador, constructor de instancia, constructor est(tico o destructor puede incluir el modi0icador unsa-e, en cuyo caso toda la extensi-n textual de dic=a declaraci-n de miembro se considera como contexto no seguro. 7na instrucci-n unsa0e O nsafe-state%entR =abilita el uso de un contexto no seguro dentro de un blo?ue O-loc3R. Toda la extensi-n textual del blo?ue O-loc3R asociado se considera como contexto no seguro.

8as extensiones de gram(tica asociadas se muestran a continuaci-n. 'ara mayor brevedad, se utili1an puntos suspensivos O...R para representar elementos ?ue aparecen explicados en cap5tulos anteriores. class-%odifier1 ...
unsa-e

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

##3

Especificacin del lenguaje C#

str ct-%odifier1 ...


unsa-e

interface-%odifier1 ...
unsa-e

dele&ate-%odifier1 ...
unsa-e

field-%odifier1 ...
unsa-e

%ethod-%odifier1 ...
unsa-e

propert#-%odifier1 ...
unsa-e

event-%odifier1 ...
unsa-e

inde2er-%odifier1 ...
unsa-e

operator-%odifier1 ...
unsa-e

constr ctor-%odifier1 ...


unsa-e

destr ctor-declaration1 attri- tesopt e#ternopt unsa-eopt A identifier ( ) destr ctor--od# attri- tesopt unsa-eopt e#ternopt A identifier ( ) destr ctor--od# static-constr ctor-%odifiers1
e#ternopt unsa-eopt static unsa-eopt e#ternopt static e#ternopt static unsa-eopt unsa-eopt static e#ternopt static e#ternopt unsa-eopt static unsa-eopt e#ternopt

e%-edded-state%ent1 ... nsafe-state%ent nsafe-state%ent1 unsa-e -loc3

###

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

En el e$emplo
&ublic unsa-e struct Node { &ublic int Ualue; &ublic Node> Le-t; &ublic Node> Oig"t; !

el modi0icador unsa-e especi0icado en la declaraci-n de estructura =ace ?ue toda la extensi-n textual de la declaraci-n sea un contexto no seguro. &s5, es posible declarar los campos Le-t y Oig"t como tipo de puntero. El e$emplo anterior tambi)n se puede escribir de la siguiente 0ormaG
&ublic struct Node { &ublic int Ualue; &ublic unsa-e Node> Le-t; &ublic unsa-e Node> Oig"t; !

&?u5, los modi0icadores unsa-e de las declaraciones de campo convierten a )stas en contextos no seguros. &parte de establecer un contexto no seguro, ?ue permite as5 el uso de tipos de puntero, el modi0icador unsa-e no tiene ningHn e0ecto en un tipo o miembro. En el e$emplo
&ublic class ' { &ublic unsa-e virtual void V() { c"ar> &; ... ! ! &ublic class :/ ' { &ublic override void V() { base.V(); ... ! !

el modi0icador unsa-e del m)todo V en ' simplemente =ace ?ue la extensi-n textual de V se convierta en un contexto no seguro en el cual pueden utili1arse las caracter5sticas no seguras del lengua$e. En la invalidaci-n de V de :, no =ay necesidad de volver a especi0icar el modi0icador unsa-e, a menos ?ue el propio m)todo V de : re?uiera el acceso a caracter5sticas no seguras. Esta situaci-n es ligeramente di0erente cuando un tipo de puntero 0orma parte de la 0irma del m)todo.
&ublic unsa-e class ' { &ublic virtual void V(c"ar> &) {...! ! &ublic class :/ ' { &ublic unsa-e override void V(c"ar> &) {...! !

&?u5, debido a ?ue la 0irma de V incluye un tipo de puntero, s-lo se puede escribir en un contexto no seguro. .in embargo, el contexto no seguro se puede introducir convirtiendo toda la clase en no segura, como en el caso de ', o al incluir un modi0icador unsa-e en la declaraci-n de m)todo, como en el caso de :.

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

##!

Especificacin del lenguaje C#

1-.2 Tipos de punteros


En un contexto no seguro, un tipo Ot#peR O[4R puede ser un tipo de puntero Opointer-t#peR, as5 como un tipo de valor Oval e-t#peR o un tipo de re0erencia Oreference-t#peR. .in embargo, un tipo de puntero Opointer-t#peR tambi)n puede utili1arse en una expresi-n ty&eo- O[*. .1".#R 0uera de un contexto no seguro ya ?ue dic=o uso no es no seguro. t#pe1 ... pointer-t#pe 7n tipo de puntero Opointer-t#peR se escribe como tipo no administrado O n%ana&ed-t#peR o como la palabra clave void seguida de un s5mbolo Oto6enR >G pointer-t#pe1 n%ana&ed-t#pe >
void >

n%ana&ed-t#pe1 t#pe El tipo especi0icado antes del asterisco O>R en un tipo de puntero se denomina tipo referente del tipo de puntero. ;epresenta el tipo de la variable a la ?ue seUala un valor del tipo de puntero. &l contrario ?ue las re0erencias Ovalores de tipos de re0erenciaR, los punteros no est(n sometidos al seguimiento del recolector de elementos no utili1ados, el cual no conoce los punteros ni los datos a los ?ue estos apuntan. 'or este motivo, un puntero no puede seUalar a una re0erencia o una estructura ?ue contenga re0erencias, y el tipo re0erente de un puntero debe ser un tipo no administrado O n%ana&ed-t#peR. 7n tipo no administrado O n%ana&ed-t#peR es cual?uier tipo ?ue no sea un tipo de re0erencia Oreference-t#peR y no contenga campos de tipo de re0erencia en ningHn nivel de anidamiento. En otras palabras, un tipo no administrado O n%ana&ed-t#peR es uno de los siguientesG
sbyte, byte, s"ort, us"ort, int, uint, long, ulong, c"ar, -loat, double, decimal o bool.

Cual?uier tipo enum Oen %-t#peR. Cual?uier tipo de puntero Opointer-t#peR. Cual?uier tipo struct Ostr ct-t#peR de0inido por el usuario ?ue contenga Hnicamente campos de tipos no administrados O n%ana&ed-t#pesR.

8a regla intuitiva para me1clar punteros y re0erencias es ?ue los re0erentes de las re0erencias Oob$etosR pueden contener punteros, pero los re0erentes de punteros no pueden contener re0erencias. En la tabla siguiente se dan algunos e$emplos de tipos de punterosG Eje)plo
byte> c"ar> int>> int>45 void>

+escripcin 'untero a byte 'untero a c"ar 'untero a un puntero a int %atri1 unidimensional de punteros a int 'untero a un tipo desconocido

'ara una implementaci-n dada, todos los tipos de puntero deben tener el mismo tamaUo y representaci-n.

##6

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

& di0erencia de C y CSS, cuando se declaran mHltiples punteros en una misma declaraci-n, en C# el car(cter > se escribe $unto al tipo subyacente Hnicamente, no como puntuaci-n de pre0i$o en cada nombre de puntero. 'or e$emploG
int> &i &j; .. N%1 as int >&i >&j;

El valor de un puntero de tipo 1> representa la direcci-n OaddressR de una variable de tipo 1. El operador de direccionamiento indirecto de puntero > O[18. .1R puede usarse para obtener acceso a esta variable. 'or e$emplo dada una variable * de tipo int>, la expresi-n >* denota la variable int =allada en la direcci-n contenida en
*.

&l igual ?ue una re0erencia de ob$eto, un puntero puede ser null. &plicar el operador de direccionamiento indirecto a un puntero null da como resultado un comportamiento de0inido segHn la implementaci-n. 7n puntero con el valor null se representa por medio de todos los bits cero. El tipo void> representa un puntero a un tipo desconocido. 2ado ?ue el tipo re0erente es desconocido, el operador de direccionamiento indirecto no se puede aplicar a un puntero de tipo void>, ni se pueden reali1ar operaciones aritm)ticas en este tipo de puntero. .in embargo, un puntero de tipo void> se puede convertir a cual?uier otro tipo de puntero Oy viceversaR. 8os tipos de puntero 0orman una categor5a independiente de tipos. & di0erencia de los tipos de re0erencia y los tipos de valor, los tipos de puntero no se derivan de object y no existen conversiones entre tipos de puntero y object. En particular, las operaciones -o2in& y n-o2in& O[4.3R no se permiten en punteros. .in embargo, se permiten las conversiones entre di0erentes tipos de punteros y entre tipos de punteros y tipos integrales. Este proceso se describe en [18.4. 7n tipo de puntero Opointer-t#peR no se puede usar como argumento de tipo O[4.4R y la in0erencia de tipos O[*.4.2R da error en llamadas de m)todos gen)ricos ?ue =abr5an in0erido un argumento de tipo para ?ue 0uera un tipo de puntero. 'uede utili1arse un tipo de puntero Opointer-t#peR como tipo de un campo vol(til O[1". .3R. .i bien pueden pasarse punteros como par(metros re- u out, =acerlo puede causar un comportamiento inde0inido, ya ?ue un puntero puede seUalar a una variable local ?ue ya no existe cuando el m)todo llamado devuelve un valor, o el ob$eto 0i$o al ?ue apuntaba ya no es de tipo 0i$ado. 'or e$emploG
using System; class 1est { static int value + 83; unsa-e static void V(out int> &i2 int i + 23; &i2 + Fi; -i#ed (int> &j + Fvalue) { .. ... &i8 + &j; ! ! static void Main() { int i + 23; unsa-e { int> &#2; int> &#8 + Fi; V(out &#2 re- &#8); re- int> &i8) {

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

##(

Especificacin del lenguaje C# Console.WriteLine(">&#2 + {3! >&#8 + {2!" >&#2 >&#8); .. unde-ined be"avior ! ! !

7n m)todo puede devolver un valor de un tipo, y ese tipo puede ser un puntero. 'or e$emplo, dado un puntero a una secuencia contigua de valores int, el nHmero de elementos de la secuencia y otro valor int, el m)todo siguiente devuelve la direcci-n del valor indicado en la secuencia, si se encuentra una coincidenciaV en cual?uier otro caso devuelve nullG
unsa-e static int> Vind(int> &i int si?e -or (int i + 3; i D si?e; <<i) { i- (>&i ++ value) return &i; <<&i; ! return null; ! int value) {

En un contexto no seguro, =ay varias construcciones disponibles para operar con punterosG 'uede utili1arse el operador > para reali1ar direccionamiento indirecto de punteros O[18. .1R. 'uede utili1arse el operador =E para obtener acceso a un miembro de una estructura a trav)s de un puntero O[18. .2R. 'uede utili1arse el operador 45 para indi1ar un puntero O[18. .3R. 'uede utili1arse el operador F para obtener la direcci-n de una variable O[18. .4R. 'ueden utili1arse los operadores << y == para incrementar y disminuir punteros O[18. . R. .e pueden utili1ar los operadores < y = para reali1ar aritm)tica de punteros O[18. .#R. 'ueden utili1arse los operadores ++, @+, D, E, D+ y +E para comparar punteros O[18. .*R. El operador stac(alloc puede utili1arse para asignar memoria de la pila de llamadas O[18.*R. 'uede utili1arse la instrucci-n -i#ed para 0i$ar temporalmente una variable y obtener su direcci-n O[18.#R.

1-.3 Variables fijas y m iles


El operador de direcci-n O[18. .4R y la instrucci-n -i#ed O[18.#R dividen las variables en dos categor5asG varia/les fi1as y varia/les ,viles. 8as variables 0i$as se encuentran en ubicaciones de almacenamiento ?ue no se ven a0ectadas por el 0uncionamiento del recolector de elementos no utili1ados. 8os e$emplos de variables 0i$as incluyen variables locales, par(metros de valor y variables creados mediante punteros de eliminaci-n de re0erencias. 8as variables m-viles, por otro lado, se encuentran en ubicaciones de almacenamiento su$etas a la reubicaci-n o eliminaci-n por parte del recolector de elementos no utili1ados. 8os e$emplos de variables m-viles incluyen campos de ob$etos y elementos de matrices. El operador F O[18. .4R permite obtener la direcci-n de una variable 0i$a sin restricciones. .in embargo, debido a ?ue una variable m-vil est( su$eta a la reubicaci-n o eliminaci-n por el recolector de elementos no utili1ados, s-lo se puede obtener su direcci-n mediante una instrucci-n -i#ed O[R, y la direcci-n es v(lida s-lo durante el ciclo de duraci-n de esa instrucci-n -i#ed. En t)rminos precisos, una variable 0i$a es una de las siguientesG 7na variable resultante de un nombre simple Osi%ple-na%eR O[*. .2R ?ue =ace re0erencia a una variable local o un par(metro de valor, a menos ?ue la variable sea capturada por una 0unci-n an-nima.

##$

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

7na variable resultante de un acceso a miembro O%e%-er-accessR O[R de la 0orma U.$, donde U es una variable 0i$a de tipo struct Ostr ct-t#peR. 7na variable resultante de una expresi-n de direccionamiento indirecto de puntero Opointer-indirectione2pressionR O[18. .1R de la 0orma >*, un acceso a miembro de puntero Opointer-%e%-er-accessR O[18. .2R de la 0orma *=E$ o un acceso a elemento de puntero Opointer-ele%ent-accessR O[18. .3R de la 0orma *4)5.

Todas las dem(s variables se clasi0ican como variables m-viles. /bserve ?ue un campo est(tico se clasi0ica tambi)n como variable m-vil. /bserve, igualmente, ?ue un par(metro re- u out se clasi0ica como variable m-vil, aun cuando el argumento dado para ese par(metro sea una variable 0i$a. 'or Hltimo, debe seUalarse ?ue una variable producida mediante la eliminaci-n de re0erencia a un puntero siempre se clasi0ica como una variable 0i$a.

1-.! %on ersiones de puntero


En un contexto no seguro, el con$unto de conversiones impl5citas disponibles O[#.1R se extiende =asta incluir las siguientes conversiones impl5citas de punteroG 2e cual?uier tipo de puntero Opointer-t#peR al tipo void>. 2el literal null a cual?uier tipo de puntero Opointer-t#peR.

En un contexto no seguro, el con$unto de conversiones expl5citas disponibles O[#.2R se extiende =asta incluir las siguientes conversiones expl5citas de punteroG 2e cual?uier tipo de puntero Opointer-t#peR a cual?uier otro tipo de puntero. 2e sbyte, byte, s"ort, us"ort, int, uint, long o ulong a cual?uier tipo de puntero Opointer-t#peR. 2e cual?uier tipo de puntero Opointer-t#peR a sbyte, byte, s"ort, us"ort, int, uint, long o ulong.

'or Hltimo, en un contexto no seguro, el con$unto de conversiones impl5citas est(ndar O[#.3.1R incluye la siguiente conversi-n de punteroG 2e cual?uier tipo de puntero Opointer-t#peR al tipo void>. 8as conversiones entre dos tipos de puntero nunca a0ectan al valor real del puntero. En otras palabras, una conversi-n de un tipo de puntero a otro no tiene e0ecto en la direcci-n subyacente dada por el puntero. Cuando se convierte un tipo de puntero a otro, si el puntero resultante no est( correctamente alineado para el tipo a ?ue se apunta, el comportamiento ser( inde0inido si se elimina la re0erencia al resultado. En general, el concepto Pcorrectamente alineadoQ es transitivoG si un puntero a un tipo ' est( correctamente alineado para un puntero a un tipo : ?ue, a su ve1, est( correctamente alineado para un puntero a un tipo C, entonces un puntero a un tipo ' est( correctamente alineado para un puntero a un tipo C. Consid)rese el siguiente caso en el ?ue se obtiene acceso a una variable de un tipo determinado mediante un puntero a otro tipoG
c"ar c + W'W; c"ar> &c + Fc; void> &v + &c; int> &i + (int>)&v; int i + >&i; .. unde-ined >&i + 289JKX; .. unde-ined

Cuando se convierte un tipo de puntero a un puntero a byte, el resultado apunta al byte de direcci-n in0erior de la variable. 8os sucesivos incrementos del resultado, =asta alcan1ar el tamaUo de la variable, dan como resultado punteros a los bytes restantes de dic=a variable. 'or e$emplo, el m)todo siguiente muestra cada uno de los oc=o bytes de un tipo double como un valor =exadecimalG

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

##"

Especificacin del lenguaje C# using System; class 1est { unsa-e static void Main() { double d + 289.JKXe89; unsa-e { byte> &b + (byte>)Fd; -or (int i + 3; i D si?eo-(double); <<i) Console.Write("{3/I8! " >&b<<); Console.WriteLine(); ! ! !

'or supuesto, los resultados producidos dependen del car(cter bigBendian o little endian. 8as asignaciones entre punteros y enteros se de0inen segHn su implementaci-n. .in embargo, en ar?uitecturas de C'7 de 32 y #4 bits, con un espacio de direcciones lineal, las conversiones de punteros a o desde tipos integrales tienen lugar exactamente igual ?ue las conversiones de valores uint o ulong, respectivamente, a o desde dic=os tipos integrales. 1-.!.1 &atrices de punteros En un contexto no seguro, se pueden construir matrices de punteros. En matrices de punteros, solamente se permiten algunas de las conversiones ?ue se aplican a otros tipos de matricesG 8a conversi-n de re0erencia impl5cita O[#.1.#R desde cual?uier tipo de matri1 Oarra#-t#peR a System.'rray y las inter0aces ?ue implementa tambi)n se aplica a matrices de punteros. 4o obstante, cual?uier intento de acceso a los elementos de la matri1 a trav)s de System.'rray o las inter0aces ?ue implementa provocar( una excepci-n en tiempo de e$ecuci-n, ya ?ue los tipos de puntero no son convertibles a object. 8as conversiones de re0erencia impl5cita y expl5cita O[#.1.#, [#.2.4R desde un tipo de matri1 unidimensional S45 a System.Collections.Seneric.$ListD1E y sus inter0aces base nunca se aplican a matrices de punteros, ya ?ue los tipos de puntero no se pueden usar como argumentos de tipo y no =ay conversiones desde tipos de puntero a tipos ?ue no son puntero. 8a conversi-n de re0erencia expl5cita O[#.2.4R desde cual?uier tipo de matri1 Oarra#-t#peR a System.'rray y las inter0aces ?ue implementa a cual?uier tipo de matri1 Oarra#-t#peR se aplica a matrices de punteros. 8as conversiones de re0erencia expl5cita O[#.2.4R desde System.Collections.Seneric.$ListDSE a un tipo de matri1 unidimensional 145 nunca se aplican a matrices de punteros, ya ?ue los tipos de puntero no se pueden usar como argumentos de tipo y no =ay conversiones desde tipos de puntero a tipos ?ue no son puntero.

Estas restricciones signi0ican ?ue la expansi-n para la instrucci-n -oreac" sobre matrices descrita en [8.8.4 no se puede aplicar a matrices de punteros. En su lugar una instrucci-n 0oreac= con la siguiente estructuraG
-oreac" (U v in #) instr cci/n incr stada

donde el tipo de # es un tipo de matri1 con la estructura 14 b 5, n es el nHmero de dimensiones menos 1 y 1 o U es un tipo de puntero, se expande usando bucles 0or anidados de la siguiente maneraG
{ 14 b 5 a + #; U v; -or (int i3 + a.SetLo,er:ound(3); i3 D+ a.Set;&&er:ound(3); i3<<) -or (int i2 + a.SetLo,er:ound(2); i2 D+ a.Set;&&er:ound(2); i2<<) b -or (int in + a.SetLo,er:ound(n); in D+ a.Set;&&er:ound(n); in<<) { v + (U)a.SetUalue(i3 i2 b in);

#!'

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

e%-edded-state%ent
! !

8as variables a i3, i2, f in no son visible ni accesibles para la expresi-n # o la instr cci/n incr stada o cual?uier otro c-digo 0uente del programa. 8a variable v es de s-lo lectura en la instrucci-n incrustada. .i no =ay una conversi-n expl5cita O[18.4R desde 1 Otipo de elementoR a U, se produce un error y no se reali1an m(s pasos. .i # tiene el valor null, se inicia una System.NullOe-erence)#ce&tion en tiempo de e$ecuci-n.

1-.# (unteros en e"presiones


En un contexto no seguro, una expresi-n puede dar como resultado un tipo de puntero, pero 0uera de ese contexto supone un error en tiempo de compilaci-n ?ue una expresi-n sea del tipo de puntero. En t)rminos m(s precisos, 0uera de un contexto no seguro se produce un error en tiempo de compilaci-n si cual?uier nombre simple Osi%ple-na%eR O[*. .2R, acceso a miembro O%e%-er-accessR O[*. .4R, expresi-n de invocaci-n Oinvocation-e2pressionR O[*. . R o acceso a elemento Oele%ent-accessR O[*. .#R es de un tipo de puntero. En un contexto no seguro, una expresi-n primaria sin creaci-n de matri1 Opri%ar#-no-arra#-creatione2pressionR O[*. R y una expresi-n unaria O nar#-e2pressionR O[*.#R permiten las siguientes construcciones adicionalesG pri%ar#-no-arra#-creation-e2pression1 ... pointer-%e%-er-access pointer-ele%ent-access si0eof-e2pression nar#-e2pression1 ... pointer-indirection-e2pression addressof-e2pression Estas construcciones se describen en las siguientes secciones. 8a precedencia y asociatividad de los operadores no seguros est( implicada en la gram(tica del lengua$e. 1-.#.1 /ireccionamiento indirecto de punteros 7na expresi-n de direccionamiento indirecto de punteros Opointer-indirection-e2pressionR se compone de un asterisco O>R seguido de una expresi-n unaria O nar#-e2pressionR. pointer-indirection-e2pression1 > nar#-e2pression El operador unario > indica el direccionamiento indirecto de punteros Opointer indirectionR y se utili1a para obtener la variable a la ?ue apunta un puntero. El resultado de evaluar >*, donde * es una expresi-n de un tipo de puntero 1>, es una variable de tipo 1. .e produce un error en tiempo de compilaci-n al aplicar el operador unario > a una expresi-n de tipo void> o a una expresi-n ?ue no sea de tipo de puntero. El e0ecto de aplicar el operador unario > a un puntero null se de0ine por su implementaci-n. En particular, no =ay garant5a de ?ue esta operaci-n inicie una excepci-n System.NullOe-erence)#ce&tion. .i se asign- un valor no v(lido al puntero, el comportamiento del operador unario > es inde0inido. Entre los valores no v(lidos para eliminar la re0erencia a un puntero desde un operador unario > se encuentran una direcci-n incorrectamente alineada para el tipo al ?ue se apunta Ovea el e$emplo de la [18.4R y la direcci-n de una variable despu)s de 0inali1ar su vigencia. & los e0ectos del an(lisis de0initivo de asignaciones, una variable producida al evaluar una expresi-n de la 0orma >* se considera inicialmente asignada O[ .3.1R.
Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

#!1

Especificacin del lenguaje C#

1-.#.2 'cceso a miembros de puntero 7n acceso a miembros de puntero Opointer-%e%-er-accessR se compone de una expresi-n primaria Opri%ar#e2pressionR, seguida de un to6en P=EQ, ?ue a su ve1 viene seguido de un identi0icador OidentifierR. pointer-%e%-er-access1 pri%ar#-e2pression =E identifier En un acceso a miembro de puntero de la 0orma *=E$, * debe ser una expresi-n de un tipo de puntero di0erente de void>, e $ debe denotar un miembro accesible del tipo al ?ue apunta *. 7n acceso a miembro de puntero de la 0orma *=E$ se evalHa exactamente como (>*).$. 'ara obtener una descripci-n del operador de direccionamiento indirecto de puntero O>R, vea la secci-n [18. .1. 'ara obtener una descripci-n del operador de acceso a miembros O.R, vea la secci-n [*. .4. En el e$emplo
using System; struct *oint { &ublic int #; &ublic int y; &ublic override string 1oString() { return "(" < # < " " < y < ")"; ! ! class 1est { static void Main() { *oint &oint; unsa-e { *oint> & + F&oint; &=E# + 23; &=Ey + 83; Console.WriteLine(&=E1oString()); ! ! !

el operador =E se utili1a para obtener acceso a campos e invocar un m)todo de una estructura a trav)s de un puntero. 2ado ?ue la operaci-n *=E$ es precisamente e?uivalente a (>*).$, podr5a =aberse escrito igualmente el m)todo MainG
class 1est { static void Main() { *oint &oint; unsa-e { *oint> & + F&oint; (>&).# + 23; (>&).y + 83; Console.WriteLine((>&).1oString()); ! ! !

1-.#.3 'cceso a elementos de puntero 7n acceso a elementos de puntero Opointer-ele%ent-accessR se compone de una expresi-n primaria sin creaci-n de matri1 seguida de una expresi-n Opri%ar#-no-arra#-creation-e2pressionR delimitada por P4Q y P5Q.

#!2

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

pointer-ele%ent-access1 pri%ar#-no-arra#-creation-e2pression 4 e2pression 5 En un acceso a elemento de puntero de la 0orma *4)5, * debe ser una expresi-n de un tipo de puntero di0erente de void>, y ) debe ser una expresi-n de un tipo ?ue pueda convertirse impl5citamente a int, uint, long o ulong. 7n acceso a elemento de puntero de la 0orma *4)5 se evalHa exactamente como >(* < )). 'ara obtener una descripci-n del operador de direccionamiento indirecto de puntero O>R, vea la secci-n [18. .1. 'ara obtener una descripci-n del operador de suma de punteros O<R, vea la secci-n [18. .#. En el e$emplo
class 1est { static void Main() { unsa-e { c"ar> & + stac(alloc c"ar48KX5; -or (int i + 3; i D 8KX; i<<) &4i5 + (c"ar)i; ! ! !

se utili1a un acceso a elemento de puntero para iniciali1ar el bH0er de caracteres de un bucle -or. 2ado ?ue la operaci-n *4)5 es precisamente e?uivalente a >(* < )), el e$emplo podr5a =aberse escrito igualmente de esta 0ormaG
class 1est { static void Main() { unsa-e { c"ar> & + stac(alloc c"ar48KX5; -or (int i + 3; i D 8KX; i<<) >(& < i) + (c"ar)i; ! ! !

El operador de acceso a elementos de puntero no comprueba errores de tipo ^0uera de l5mite^, por otro lado, el comportamiento al obtener acceso a un elemento 0uera de l5mites no est( de0inido. /curre lo mismo en C y CSS. 1-.#.! ,perador de direccin 7na expresi-n de direcci-n Oaddressof-e2pressionR se compone de un s5mbolo de K comercial OFR seguido de una expresi-n unaria O nar#-e2pressionR. addressof-e2pression1 F nar#-e2pression 2ada una expresi-n ) ?ue es del tipo 1 y se clasi0ica como una variable 0i$a O[18.3R, la construcci-n F) calcula la direcci-n de la variable proporcionada por ). El tipo del resultado es 1> y se clasi0ica como un valor. .e produce un error en tiempo de compilaci-n si no se clasi0ica ) como una variable, si se clasi0ica ) como una variable local de s-lo lectura o si ) denota una variable m-vil. En este Hltimo caso, se puede usar una instrucci-n 0i$a O[18.#R para P0i$arQ temporalmente la variable antes de obtener su direcci-n. Como se a0irmaba en la secci-n [*. .4, 0uera de un constructor de instancia o constructor est(tico de una clase o estructura ?ue de0ine un campo readonly, dic=o campo se considera un valor, no una variable. Como tal, no se puede capturar su direcci-n. !gualmente, no se puede tomar la direcci-n de una constante. El operador F no re?uiere ?ue su argumento est) asignado de0initivamente, pero despu)s de una operaci-n F, la variable a la ?ue se aplica el operador se considera de0initivamente asignada en la ruta de e$ecuci-n donde tiene

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

#!3

Especificacin del lenguaje C#

lugar la operaci-n. Es responsabilidad del programador asegurarse de ?ue se produce una correcta iniciali1aci-n de la variable en esta situaci-n. En el e$emplo
using System; class 1est { static void Main() { int i; unsa-e { int> & + Fi; >& + 289; ! Console.WriteLine(i); ! ! i se considera de0initivamente asignada despu)s de la operaci-n Fi utili1ada para iniciali1ar &. 8a asignaci-n a >& tiene como resultado la iniciali1aci-n de i, pero la inclusi-n de esta iniciali1aci-n corresponde al

programador, y no =abr( ningHn error en tiempo de compilaci-n si se ?uita la asignaci-n. 8as reglas de asignaci-n de0initiva para el operador F permiten evitar tal iniciali1aci-n redundante de variables locales. 'or e$emplo, muc=as inter0aces &'! externas toman un puntero a una estructura ?ue rellena la &'!. 8as llamadas a esas &'! suelen pasar la direcci-n de una variable de estructura local, y sin esta regla, se re?uerir5a una iniciali1aci-n redundante de la variable. 1-.#.# Incremento y decremento de punteros En un contexto no seguro, los operadores << y == O[*. .+ y [*.#. R se pueden aplicar a las variables de todos los tipos de puntero excepto void>. &s5, por cada tipo de puntero 1>, se de0inen de manera impl5cita los siguientes operadoresG
1> o&erator <<(1> #); 1> o&erator ==(1> #);

8os operadores generan los mismos resultados ?ue #<2 y #=2, respectivamente O[18. .#R. En otras palabras, para una variable de puntero de tipo 1>, el operador << agrega si?eo-(1) a la direcci-n contenida en la variable, y el operador == resta si?eo-(1) de la direcci-n contenida en la variable. .i una operaci-n de incremento o disminuci-n de puntero desborda el dominio del tipo de puntero, se de0ine dependiendo de la implementaci-n, pero no se producen excepciones. 1-.#.$ 'ritm*tica con punteros En un contexto no seguro, los operadores < y = O[*.*.4 y [*.*. R se pueden aplicar a los valores de todos los tipos de puntero excepto void>. &s5, por cada tipo de puntero 1>, se de0inen de manera impl5cita los siguientes operadoresG
1> 1> 1> 1> 1> 1> 1> 1> o&erator o&erator o&erator o&erator o&erator o&erator o&erator o&erator <(1> <(1> <(1> <(1> # # # # int y); uint y); long y); ulong y);

<(int # 1> y); <(uint # 1> y); <(long # 1> y); <(ulong # 1> y);

#!#

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases 1> 1> 1> 1> o&erator o&erator o&erator o&erator C(1> C(1> C(1> C(1> # # # # int y); uint y); long y); ulong y); 1> y);

long o&erator C(1> #

2ada una expresi-n * de un tipo de puntero 1> y una expresi-n N de tipo int, uint, long o ulong, las expresiones * < N y N < * calculan el valor de puntero de tipo 1> ?ue resulta de agregar N > si?eo-(1) a la direcci-n dada por *. 2e igual 0orma, la expresi-n * = N calcula el valor de puntero de tipo 1> ?ue resulta de restar N > si?eo-(1) de la direcci-n dada por *. 2adas dos expresiones, * y ^, de un tipo de puntero 1>, la expresi-n * C ^ calcula la di0erencia entre las direcciones dadas por * y ^ y a continuaci-n divide la di0erencia por si?eo-(1). El tipo del resultado siempre es long. En e0ecto, * = ^ se calcula como ((long)(*) = (long)(^)) . si?eo-(1). 'or e$emploG
using System; class 1est { static void Main() { unsa-e { int> values + stac(alloc int4835; int> & + Fvalues425; int> Q + Fvalues42K5; Console.WriteLine("& = Q + {3!" & = Q); Console.WriteLine("Q = & + {3!" Q = &); ! ! !

produce el resultadoG
& = Q + =2J Q = & + 2J

.i una operaci-n de aritm)tica de punteros desborda el dominio del tipo de puntero, se trunca el resultado dependiendo de la implementaci-n, pero no se producen excepciones. 1-.#.+ %omparacin de punteros En un contexto no seguro, los operadores ++, @+, D, E, D+ y +E O[*.+R pueden aplicarse a valores de todos los tipos de puntero. 8os operadores de comparaci-n de punteros sonG
bool o&erator ++(void> # bool o&erator @+(void> # bool o&erator D(void> # bool o&erator E(void> # bool o&erator D+(void> # bool o&erator E+(void> # void> y); void> y); void> y); void> y); void> y); void> y);

2ado ?ue existe una conversi-n impl5cita entre cual?uier tipo de puntero y el tipo void>, pueden compararse operandos de cual?uier tipo de puntero mediante estos operadores. 8os operadores de comparaci-n comparan las direcciones proporcionadas por los dos operandos como si 0ueran enteros sin signo.

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

#!!

Especificacin del lenguaje C#

1-.#.- ,perador 4i8eof El operador si?eo- devuelve el nHmero de bytes ocupados por una variable de un tipo dado. El tipo especi0icado como operando para si?eo- debe ser de un tipo no administrado O n%ana&ed-t#peR O[R. si0eof-e2pression1
si?eo- (

n%ana&ed-t#pe )

El resultado del operador si?eo- es un valor de tipo int. 'ara ciertos tipos prede0inidos, el operador si?eoproduce un valor constante, como se muestra en la tabla siguiente. Expresin
si?eo-(sbyte) si?eo-(byte) si?eo-(s"ort) si?eo-(us"ort) si?eo-(int) si?eo-(uint) si?eo-(long) si?eo-(ulong) si?eo-(c"ar) si?eo-(-loat) si?eo-(double) si?eo-(bool)

/esultado
2 2 8 8 J J Y Y 8 J Y 2

'ara todos los dem(s tipos, el resultado del operador si?eo- se de0ine segHn la implementaci-n y se clasi0ica como un valor, no como una constante. El orden en ?ue se empa?uetan los miembros en una estructura no est( especi0icado. 'ara 0ines de alineaci-n, puede =aber un relleno sin nombre al comien1o de una estructura, dentro de una estructura y al 0inal de una estructura. El contenido de los bits utili1ados para el relleno es indeterminado. &l aplicarse a un operando con tipo de estructura, el resultado es el nHmero total de bytes de una variable de ese tipo, incluidos los bytes de relleno.

1-.$ Instruccin fi"ed


En un contexto no seguro, la instrucci-n incrustada Oe%-edded-state%entR O[R permite una construcci-n adicional, la instrucci-n -i#ed, ?ue se utili1a para P0i$arQ una variable m-vil de manera ?ue su direcci-n permanece constante en toda la duraci-n de la instrucci-n. e%-edded-state%ent1 ... fi2ed-state%ent fi2ed-state%ent1 -i#ed ( pointer-t#pe fi2ed-pointer-declarators ) e%-edded-state%ent fi2ed-pointer-declarators1 fi2ed-pointer-declarator fi2ed-pointer-declarators

fi2ed-pointer-declarator

#!6

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

fi2ed-pointer-declarator1 identifier + fi2ed-pointer-initiali0er fi2ed-pointer-initiali0er1 F varia-le-reference e2pression Cada declarador de puntero 0i$o Ofi2ed-pointer-declaratorR declara una variable local del tipo de puntero Opointer-t#peR dado e iniciali1a dic=a variable con la direcci-n calculada por el iniciali1ador de puntero 0i$o Ofi2ed-pointer-initiali0erR correspondiente. 7na variable local declarada en una instrucci-n -i#ed es accesible en cual?uier iniciali1ador de puntero 0i$o Ofi2ed-pointer-initiali0ersR situado a la derec=a de la declaraci-n de la variable, y en la instrucci-n incrustada Oe%-edded-state%entR de la instrucci-n -i#ed. 7na variable local declarada por una instrucci-n -i#ed se considera de s-lo lectura. .e producir( un error en tiempo de compilaci-n si la instrucci-n incrustada intenta modi0icar esta variable local Opor medio de asignaci-n o utili1ando los operadores << y ==R o bien si la pasa como un par(metro re- u out. 7n iniciali1ador de puntero 0i$o Ofi2ed-pointer-initiali0erR puede ser uno de los siguientesG El s5mbolo Oto6enR PFQ seguido de una re0erencia de variable Ovaria-le-referenceR O[R a una variable m-vil O[R de un tipo no administrado 1, siempre ?ue el tipo 1> sea impl5citamente convertible al tipo de puntero proporcionado en la instrucci-n -i#ed. En este caso, el iniciali1ador calcula la direcci-n de la variable dada, y se garanti1a ?ue )sta permanecer( en una direcci-n 0i$a durante toda la e$ecuci-n de la instrucci-n -i#ed. 7na expresi-n de un tipo de matri1 Oarra#-t#peR con elementos de un tipo no administrado 1, siempre ?ue el tipo 1> sea impl5citamente convertible al tipo de puntero proporcionado por la instrucci-n -i#ed. En este caso, el iniciali1ador calcula la direcci-n del primer elemento de la matri1, y se garanti1a ?ue toda la matri1 permanecer( en una direcci-n 0i$a durante toda la e$ecuci-n de la instrucci-n -i#ed. El comportamiento de la instrucci-n -i#ed se de0ine segHn sea su implementaci-n si la expresi-n de matri1 es nula o la matri1 contiene cero elementos. 7na expresi-n de tipo string, siempre ?ue el tipo c"ar> sea impl5citamente convertible al tipo de puntero proporcionado en la instrucci-n -i#ed. En este caso, el iniciali1ador calcula la direcci-n del primer car(cter de la cadena, y se garanti1a ?ue toda la cadena permanecer( en una direcci-n 0i$a durante toda la e$ecuci-n de la instrucci-n -i#ed. El comportamiento de la instrucci-n -i#ed se de0ine segHn sea su implementaci-n si la expresi-n de cadena es nula. 7na expresi-n de nombre simple Osi%ple-na%eR o acceso a miembro O%e%-er-accessR ?ue =ace re0erencia a un miembro de bH0er 0i$o de una variable m-vil, siempre ?ue el tipo del miembro de bH0er 0i$o sea impl5citamente convertible al tipo de puntero dado en la instrucci-n -i#ed. En este caso, el iniciali1ador calcula un puntero en el primer elemento del bH0er 0i$o O[18.*.2R y se garanti1a ?ue el bH0er 0i$o permanecer( en una direcci-n 0i$a para la duraci-n de la instrucci-n -i#ed.

'or cada direcci-n calculada por un iniciali1ador de puntero 0i$o Ofi2ed-pointer-initiali0erR, la instrucci-n -i#ed garanti1a ?ue la variable a la ?ue =ace re0erencia la direcci-n no est( su$eta a reubicaci-n o eliminaci-n por el recolector de elementos no utili1ados en toda la duraci-n de la instrucci-n -i#ed. 'or e$emplo, si la direcci-n calculada por un iniciali1ador de puntero 0i$o Ofi2ed-pointer-initiali0erR =ace re0erencia a un campo de un ob$eto o un elemento de una instancia de matri1, la instrucci-n -i#ed garanti1a ?ue la instancia de ob$eto contenedora no se reubicar( ni eliminar( en toda la duraci-n de la instrucci-n. Es responsabilidad del programador asegurarse de ?ue los punteros creados mediante instrucciones -i#ed no permanecen tras la e$ecuci-n de dic=as instrucciones. 'or e$emplo, cuando se pasan punteros creados con instrucciones -i#ed a inter0aces &'! externas, es responsabilidad del programador asegurarse de ?ue las &'! no retienen memoria de estos punteros.

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

#!(

Especificacin del lenguaje C#

8os ob$etos 0i$os pueden provocar la 0ragmentaci-n del mont-n al no poder moverse. 'or este motivo, los ob$etos deben ser 0i$os s-lo cuando sea absolutamente necesario y por el menor tiempo posible. En el e$emplo
class 1est { static int #; int y; unsa-e static void V(int> &) { >& + 2; ! static void Main() { 1est t + ne, 1est(); int45 a + ne, int4235; unsa-e { -i#ed (int> & + F#) V(&); -i#ed (int> & + Ft.y) V(&); -i#ed (int> & + Fa435) V(&); -i#ed (int> & + a) V(&); ! ! !

se muestran varios usos de la instrucci-n -i#ed. 8a primera instrucci-n 0i$a y obtiene la direcci-n de un campo est(tico, la segunda 0i$a y obtiene la direcci-n de un campo de instancia, y la tercera 0i$a y obtiene la direcci-n de un elemento de matri1. En cada caso =ubiera sido un error utili1ar el operador F =abitual, ya ?ue las variables se clasi0ican todas como variables m-viles. 8a tercera y cuarta instrucci-n -i#ed del e$emplo anterior producen id)nticos resultados. En general, para una instancia de matri1 a, especi0icar Fa435 en una instrucci-n -i#ed es lo mismo ?ue especi0icar simplemente a. En este e$emplo de la instrucci-n -i#ed se usa stringG
class 1est { static string name + "##"; unsa-e static void V(c"ar> &) { -or (int i + 3; &4i5 @+ WZ3W; <<i) Console.WriteLine(&4i5); ! static void Main() { unsa-e { -i#ed (c"ar> & + name) V(&); -i#ed (c"ar> & + "##") V(&); ! ! !

En una matri1 de contexto no seguro, los elementos de matrices unidimensionales se almacenan por orden de 5ndice creciente, comen1ando con el 5ndice 3 y terminando con el 5ndice Lengt" C 2. 8os elementos de matrices multidimensionales se almacenan de manera ?ue los 5ndices de la dimensi-n del extremo derec=o se incrementan en primer lugar, a continuaci-n la dimensi-n situada inmediatamente a su i1?uierda, etc., siguiendo por la i1?uierda. 2entro de una instrucci-n -i#ed ?ue obtiene un puntero & para una instancia de matri1 a, los valores de puntero comprendidos entre & y & < a.Lengt" = 2 representan direcciones de los elementos de la matri1. 2e igual 0orma, las variables comprendidas en el intervalo de &435 a &4a.Lengt" = 25 representan los propios elementos de la matri1. 2ada la 0orma en ?ue se almacenan las matrices, se puede tratar una matri1 de cual?uier dimensi-n como si 0uera lineal. 'or e$emploG

#!$

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases using System; class 1est { static void Main() { int4 5 a + ne, int48 9 J5; unsa-e { -i#ed (int> & + a) { -or (int i + 3; i D a.Lengt"; <<i) &4i5 + i; ! !

.. treat as linear

-or (int i + 3; i D 8; <<i) -or (int j + 3; j D 9; <<j) { -or (int ( + 3; ( D J; <<() Console.Write("4{3! {2! {8!5 + {9 8! " Console.WriteLine(); ! ! !

a4i j (5);

produce el resultadoG
43 43 43 42 42 42 3 2 8 3 2 8 35 35 35 35 35 35 + 3 43 3 + J 43 2 + Y 43 8 + 28 42 3 + 2X 42 2 + 83 42 8 25 25 25 25 25 25 + 2 43 3 + K 43 2 + L 43 8 + 29 42 3 + 2M 42 2 + 82 42 8 85 85 85 85 85 85 + + + + + + 8 X 23 2J 2Y 88 43 43 43 42 42 42 3 2 8 3 2 8 95 95 95 95 95 95 + + + + + + 9 M 22 2K 2L 89

En el e$emplo
class 1est { unsa-e static void Vill(int> & int count int value) { -or (; count @+ 3; count==) >&<< + value; ! static void Main() { int45 a + ne, int42335; unsa-e { -i#ed (int> & + a) Vill(& ! ! !

233

=2);

se utili1a una instrucci-n -i#ed para 0i$ar una matri1 de manera ?ue pueda pasarse su direcci-n a un m)todo ?ue toma un puntero. En el siguiente e$emploG
unsa-e struct Vont { &ublic int si?e; &ublic -i#ed c"ar name4985; ! class 1est { unsa-e static void *utString(string s c"ar> bu--er int bu-Si?e) { int len + s.Lengt"; i- (len E bu-Si?e) len + bu-Si?e; -or (int i + 3; i D len; i<<) bu--er4i5 + s4i5; -or (int i + len; i D bu-Si?e; i<<) bu--er4i5 + (c"ar)3; ! Vont -;

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

#!"

Especificacin del lenguaje C# unsa-e static void Main() { 1est test + ne, 1est(); test.-.si?e + 23; -i#ed (c"ar> & + test.-.name) { *utString("1imes Ne, Ooman" & ! ! !

98);

se utili1a una instrucci-n -i#ed para 0i$ar una matri1 de bH0er 0i$o de manera ?ue pueda utili1arse como un puntero. 7n valor c"ar> producido al 0i$ar una instancia de cadena siempre apunta a una cadena terminada en null. 2entro de una instrucci-n 0ixed ?ue obtiene un puntero & a una instancia de cadena s, los valores de puntero comprendidos entre & y & < s.Lengt" = 2 representan direcciones de los caracteres de la cadena, y el valor de puntero & < s.Lengt" siempre apunta a un car(cter null Oel car(cter con valor WZ3WR. 8a modi0icaci-n de ob$etos de tipo administrado mediante punteros 0i$os puede producir un comportamiento inde0inido. 'or e$emplo, dado ?ue las cadenas son invariables, es responsabilidad del programador asegurarse de ?ue los caracteres de una cadena 0i$a a los ?ue =ace re0erencia un puntero no se modi0i?uen. 8a terminaci-n autom(tica en null de cadenas es especialmente c-moda al llamar a inter0aces &'! externas ?ue esperan cadenas Pde estilo CQ. /bserve, sin embargo, ?ue no se permite una instancia de cadena ?ue contenga caracteres null. .i se detectan dic=os caracteres null, la cadena aparecer( truncada al tratarla como c"ar> terminada en null.

1-.+ <=feres fijos


8os bH0eres 0i$os se utili1an para declarar matrices en l5nea Pde estilo CQ como miembros de estructuras, y son Htiles principalmente para interactuar con &'! no administradas. 1-.+.1 /eclaraciones de b=feres fijos 7n /7fer fi1o es un miembro ?ue representa el almacenamiento para un bH0er de longitud 0i$a de variables de un tipo determinado. 7na declaraci-n de bH0er 0i$o introduce uno o m(s bH0eres 0i$os de un tipo de elemento dado. 8os bH0eres 0i$os s-lo se permiten en declaraciones de estructuras y s-lo pueden darse en contextos no seguros O[18.1R. str ct-%e%-er-declaration1 A fi2ed-si0e-- ffer-declaration fi2ed-si0e-- ffer-declaration1 attri- tesopt fi2ed-si0e-- ffer-%odifiersopt -i#ed - ffer-ele%ent-t#pe fi2ed-si0e-- ffer-declarators ; fi2ed-si0e-- ffer-%odifiers1 fi2ed-si0e-- ffer-%odifier fi2ed-si0e-- ffer-%odifier fi2ed-si0e-- ffer-%odifiers fi2ed-si0e-- ffer-%odifier1
ne, &ublic &rotected internal &rivate unsa-e

#6'

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

- ffer-ele%ent-t#pe1 t#pe fi2ed-si0e-- ffer-declarators1 fi2ed-si0e-- ffer-declarator fi2ed-si0e-- ffer-declarator fi2ed-si0e-- ffer-declarators fi2ed-si0e-- ffer-declarator1 identifier 4 const-e2pression 5 Es posible ?ue una declaraci-n de bH0er 0i$o incluya un con$unto de atributos O[1*R, un modi0icador ne, O[1".2.2R, una combinaci-n v(lida de los cuatro modi0icadores de acceso O[1".2.3R y un modi0icador unsa-e O[18.1R. 8os atributos y modi0icadores se aplican a todos los miembros declarados por la declaraci-n de bH0er 0i$o. Es un error ?ue el mismo modi0icador apare1ca varias veces en una declaraci-n de bH0er 0i$o. 7na declaraci-n de bH0er 0i$o no puede incluir el modi0icador static. El tipo de elemento de bH0er de una declaraci-n de bH0er 0i$o especi0ica el tipo de elemento del bH0er o de los bH0eres introducido por la declaraci-n. El tipo de elemento de bH0er debe ser uno de los tipos prede0inidos sbyte, byte, s"ort, us"ort, int, uint, long, ulong, c"ar, -loat, double o bool. El tipo de elemento de bH0er viene seguido de una lista de declaradores de bH0er 0i$o, cada uno de los cuales introduce un nuevo miembro. 7n declarador de bH0er 0i$o est( 0ormado por un identi0icador ?ue denomina al miembro, seguido de una expresi-n constante entre los s5mbolos Oto6enR 4 y 5. 8a expresi-n constante denota el nHmero de elementos del miembro introducido por el declarador de bH0er 0i$o. El tipo de la expresi-n constante se debe convertir impl5citamente en el tipo int y el valor debe ser un entero positivo distinto de cero. .e garanti1a ?ue los elementos de un bH0er 0i$o se organicen de manera secuencial en memoria. 7na declaraci-n de bH0er 0i$o ?ue declara varios bH0eres 0i$os e?uivale a varias declaraciones de una declaraci-n de bH0er 0i$o con los mismos atributos y tipos de elementos. 'or e$emploG
unsa-e struct ' { &ublic -i#ed int #4K5 ! y4235 ?42335;

e?uivale a
unsa-e struct ' { &ublic -i#ed int #4K5; &ublic -i#ed int y4235; &ublic -i#ed int ?42335; !

1-.+.2 <=feres fijos en e"presiones 8a bHs?ueda de miembros O[*.3R de un miembro de bH0er 0i$o procede exactamente de la misma manera ?ue la bHs?ueda de miembros de un campo. .e puede =acer re0erencia a un bH0er 0i$o en una expresi-n con un nombre simple Osi%ple-na%eR O[*. .2R o un acceso a miembro O%e%-er-accessR O[*. .4R. Cuando se =ace re0erencia a un miembro de bH0er 0i$o como un nombre simple, el e0ecto es el mismo ?ue un acceso a miembro con la estructura t"is.$, donde $ es el miembro de bH0er 0i$o. En un acceso a miembro de la estructura ).$, si ) es de un tipo struct y una bHs?ueda de miembros de $ ).$ en dic=o tipo struct identi0ica un miembro 0i$o, ).$ se evalHa y clasi0ica de la siguiente maneraG .i la expresi-n ).$ no ocurre en un contexto no seguro, se genera un error en tiempo de compilaci-n.

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

#61

Especificacin del lenguaje C#

.i ) se clasi0ica como un valor, se genera un error de compilaci-n. 2e lo contrario, si ) es una variable m-vil O[18.3R y la expresi-n ).$ no es un iniciali1ador de puntero 0i$o Ofi2ed-pointer-initiali0erR O[18.#R, se genera un error en tiempo de compilaci-n. 2e lo contrario, ) =ace re0erencia a una variable 0i$a y el resultado de la expresi-n es un puntero al primer elemento del miembro de bH0er 0i$o $ en ). El resultado es del tipo S>, donde S es el tipo de elemento de $ y se clasi0ica como un valor.

& los elementos subsiguientes del bH0er 0i$o se puede obtener acceso con operaciones de puntero desde el primer elemento. &l contrario ?ue ocurre con el acceso a matrices, el acceso a los elementos de un bH0er 0i$o es una operaci-n no segura y su intervalo no se comprueba. En el siguiente e$emplo se declara y utili1a una estructura con un miembro de bH0er 0i$o.
unsa-e struct Vont { &ublic int si?e; &ublic -i#ed c"ar name4985; ! class 1est { unsa-e static void *utString(string s c"ar> bu--er int bu-Si?e) { int len + s.Lengt"; i- (len E bu-Si?e) len + bu-Si?e; -or (int i + 3; i D len; i<<) bu--er4i5 + s4i5; -or (int i + len; i D bu-Si?e; i<<) bu--er4i5 + (c"ar)3; ! unsa-e static void Main() { Vont -; -.si?e + 23; *utString("1imes Ne, Ooman" ! !

-.name

98);

1-.+.3 %omprobacin de asignacin definiti a El bH0er 0i$o no est( su$eto a una comprobaci-n de asignaci-n de0initiva O[ .3R y los miembros de bH0er 0i$o se omiten con el 0in de comprobar la asignaci-n de0initiva de variables de tipo struct. Cuando la variable de estructura m(s externa de un miembro de bH0er 0i$o es una variable est(tica, una variable de instancia de una instancia de clase o un elemento de array, los elementos de bH0er 0i$o se iniciali1an autom(ticamente a sus valores predeterminados O[ .2R. En el resto de casos, el contenido inicial de un bH0er 0i$o no est( de0inido.

1-.- 'signacin de pila


En un contexto no seguro, una declaraci-n de variable local O[8. .1R puede incluir un iniciali1ador de asignaci-n de pila ?ue asigne memoria de la pila de llamadas. local-varia-le-initiali0er1 A stac3alloc-initiali0er stac3alloc-initiali0er1 stac(alloc n%ana&ed-t#pe 4 e2pression 5 El tipo no administrado O n%ana&ed-t#peR indica el tipo de los elementos ?ue se almacenar(n en la ubicaci-n reci)n asignada, y la expresi-n Oe2pressionR indica el nHmero de estos elementos. Tomados $untos, especi0ican el
#62
Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases

tamaUo de asignaci-n re?uerido. 2ado ?ue el tamaUo de una asignaci-n de pila no puede ser negativo, supone un error en tiempo de compilaci-n especi0icar el nHmero de elementos como una expresi-n constante Oconstante2pressionR ?ue se evalHa como un nHmero negativo. 7n iniciali1ador de asignaci-n de pila de la 0orma stac(alloc 14)5 re?uiere ?ue 1 sea un tipo no administrado O[18.2R y ) sea una expresi-n de tipo int. 8a construcci-n asigna ) > si?eo-(1) bytes de la pila de llamadas y devuelve un puntero de tipo 1> al blo?ue reci)n asignado. .i ) es un valor negativo, el comportamiento es inde0inido. .i ) es cero, no se reali1a ninguna asignaci-n, y el puntero devuelto se de0ine segHn su implementaci-n. .i no =ay memoria su0iciente disponible para asignar un blo?ue del tamaUo dado, se inicia una excepci-n System.Stac(%ver-lo,)#ce&tion. El contenido de la memoria reci)n asignada es inde0inido. 4o se permiten los iniciali1adores de asignaci-n de pila en blo?ues catc" o -inally O[8.1"R. 4o =ay 0orma de liberar expl5citamente la memoria asignada con stac(alloc. Todos los blo?ues asignados de memoria de la pila y creados durante la e$ecuci-n de un miembro de 0unci-n se descartan autom(ticamente cuando )ste devuelve un valor. Esto se corresponde con la 0unci-n alloca, una extensi-n =abitual en las implementaciones de C y CSS. En el e$emplo
using System; class 1est { static string $nt1oString(int value) { int n + value E+ 37 value/ =value; unsa-e { c"ar> bu--er + stac(alloc c"ar42X5; c"ar> & + bu--er < 2X; do { >==& + (c"ar)(n B 23 < W3W); n .+ 23; ! ,"ile (n @+ 3); i- (value D 3) >==& + W=W; return ne, string(& 3 (int)(bu--er < 2X = &)); ! ! static void Main() { Console.WriteLine($nt1oString(289JK)); Console.WriteLine($nt1oString(=LLL)); ! !

un iniciali1ador stac(alloc se utili1a en el m)todo $nt1oString para asignar un bH0er de 1# caracteres en la pila. El bH0er ?ueda descartado autom(ticamente cuando el m)todo devuelve un valor.

1-.. 'signacin din)mica de memoria


.alvo por el operador stac(alloc, C# no proporciona construcciones prede0inidas para administrar memoria no recolectada por el recolector de elementos no utili1ados. Tales servicios suelen proporcionarlos bibliotecas de clases auxiliares o importadas directamente del sistema operativo subyacente. 'or e$emplo, la clase Memory de aba$o muestra c-mo es posible obtener acceso desde C# a las 0unciones del mont-n de un sistema operativo subyacenteG
using System; using System.Ountime.$ntero&Services;

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

#63

Especificacin del lenguaje C# &ublic unsa-e class Memory { .. Handle -or t"e &rocess "ea&. 1"is "andle is used in all calls to t"e .. Hea&III '*$s in t"e met"ods belo,. static int &" + Set*rocessHea&(); .. *rivate instance constructor to &revent instantiation. &rivate Memory() {! .. 'llocates a memory bloc( o- t"e given si?e. 1"e allocated memory is .. automatically initiali?ed to ?ero. &ublic static void> 'lloc(int si?e) { void> result + Hea&'lloc(&" H)'*\P)O%\M)M%O` si?e); i- (result ++ null) t"ro, ne, %ut%-Memory)#ce&tion(); return result; ! .. Co&ies count bytes -rom src to dst. 1"e source and destination .. bloc(s are &ermitted to overla&. &ublic static void Co&y(void> src void> dst int count) { byte> &s + (byte>)src; byte> &d + (byte>)dst; i- (&s E &d) { -or (; count @+ 3; count==) >&d<< + >&s<<; ! else i- (&s D &d) { -or (&s <+ count &d <+ count; count @+ 3; count==) >==&d + >==&s; ! ! .. Vrees a memory bloc(. &ublic static void Vree(void> bloc() { i- (@Hea&Vree(&" 3 bloc()) t"ro, ne, $nvalid%&eration)#ce&tion(); ! .. Oe=allocates a memory bloc(. $- t"e reallocation reQuest is -or a .. larger si?e t"e additional region o- memory is automatically .. initiali?ed to ?ero. &ublic static void> Oe'lloc(void> bloc( int si?e) { void> result + Hea&Oe'lloc(&" H)'*\P)O%\M)M%O` bloc( i- (result ++ null) t"ro, ne, %ut%-Memory)#ce&tion(); return result; ! .. Oeturns t"e si?e o- a memory bloc(. &ublic static int Si?e%-(void> bloc() { int result + Hea&Si?e(&" 3 bloc(); i- (result ++ =2) t"ro, ne, $nvalid%&eration)#ce&tion(); return result; ! .. Hea& '*$ -lags const int H)'*\P)O%\M)M%O` + 3#3333333Y; .. Hea& '*$ -unctions 46ll$m&ort("(ernel98")5 static e#tern int Set*rocessHea&(); 46ll$m&ort("(ernel98")5 static e#tern void> Hea&'lloc(int "Hea& 46ll$m&ort("(ernel98")5 static e#tern bool Hea&Vree(int "Hea& int -lags int -lags int si?e); void> bloc(); si?e);

#6#

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

Cap0tulo 1' Clases 46ll$m&ort("(ernel98")5 static e#tern void> Hea&Oe'lloc(int "Hea& void> bloc( int si?e); 46ll$m&ort("(ernel98")5 static e#tern int Hea&Si?e(int "Hea& !

int -lags

int -lags

void> bloc();

& continuaci-n se muestra un e$emplo ?ue utili1a la clase MemoryG


class 1est { static void Main() { unsa-e { byte> bu--er + (byte>)Memory.'lloc(8KX); try { -or (int i + 3; i D 8KX; i<<) bu--er4i5 + (byte)i; byte45 array + ne, byte48KX5; -i#ed (byte> & + array) Memory.Co&y(bu--er & 8KX); ! -inally { Memory.Vree(bu--er); ! -or (int i + 3; i D 8KX; i<<) Console.WriteLine(array4i5); ! ! !

El e$emplo asigna 2 # bytes de memoria mediante Memory.'lloc e iniciali1a el blo?ue de memoria con valores crecientes de " a 2 . & continuaci-n, asigna una matri1 de bytes de 2 # elementos y utili1a Memory.Co&y para copiar el contenido del blo?ue de memoria en la matri1 de bytes. 'or Hltimo, se libera el blo?ue de memoria mediante Memory.Vree y se env5a el contenido de la matri1 de bytes como resultado a la consola.

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

#6!

Especificacin del lenguaje C#

'. %omentarios de documentacin


C# proporciona un mecanismo para ?ue los programadores puedan documentar el c-digo mediante una sintaxis de comentarios ?ue contiene texto N%8. En los arc=ivos de c-digo 0uente, es posible utili1ar comentarios con cierto 0ormato para indicar a una =erramienta ?ue genere texto N%8 a partir de estos comentarios y de los elementos de c-digo 0uente a los ?ue precede. 8os comentarios ?ue utili1an esta sintaxis se denominan co entarios de doc! entaci,n. 2eben preceder inmediatamente a un tipo de0inido por el usuario Ocomo una clase, una estructura o una inter0a1R o a un miembro Ocomo un campo, un evento, una propiedad o un m)todoR. 8a =erramienta de generaci-n de N%8 se denomina generador de doc! entaci,n. OEste generador podr5a ser, pero no es necesario ?ue as5 sea, el propio compilador de C#.R El resultado producido por el generador de documentaci-n se denomina archivo de doc! entaci,n. 7n arc=ivo de documentaci-n se utili1a como entrada a un visor de doc! entaci,nV una =erramienta pensada para generar alguna ordenaci-n de presentaci-n visual de in0ormaci-n de tipo y su documentaci-n asociada. Esta especi0icaci-n sugiere el uso de un con$unto de eti?uetas en los comentarios de esta clase de documentaci-n, sin embargo, siempre ?ue se respete la correcta sintaxis del lengua$e N%8, se puede utili1ar el con$unto de eti?uetas ?ue se desee para este 0in.

'.1 Introduccin
Es posible utili1ar comentarios con un 0ormato determinado para indicar a una =erramienta ?ue genere texto N%8 a partir de los mismos y de los elementos de c-digo 0uente a los ?ue preceden. Tales comentarios pueden serG comentarios de una sola l5nea ?ue comien1an con tres barras diagonales O...R, o comentarios delimitados ?ue van precedidos de una barra diagonal y dos asteriscos O.>>R. 2eben preceder inmediatamente al tipo de0inido por el usuario Ocomo una clase, un delegado o una inter0a1R o al miembro Ocomo un campo, un evento, una propiedad o un m)todoR al ?ue =acen re0erencia los comentarios. 8as secciones de atributos O[1*.2R se consideran parte de las declaracionesV por lo tanto, los comentarios de documentaci-n deben preceder a los atributos ?ue se aplican a un tipo o a un miembro. 3intaxis8 sin&le-line-doc-co%%ent1 ... inp t-charactersopt deli%ited-doc-co%%ent1 .>> deli%ited-co%%ent-charactersopt >. En un comentario de una sola l5nea Osin&le-line-doc-co%%entR, si aparece un car(cter de espacio en blanco OwhitespaceR a continuaci-n de los caracteres ... en cada uno de los comentarios de documentaci-n de una sola l5nea Osin&le-line-doc-co%%entsR, adyacentes al comentario de documentaci-n de una sola l5nea Osin&le-linedoc-co%%entR actual, el car(cter de espacio en blanco OwhitespaceR no se incluir( en los resultados N%8. En un comentario de documentaci-n delimitado Odeli%ited-doc-co%%entR, si el primer car(cter distinto del espacio en blanco OwhitespaceR es un asterisco y el mismo patr-n de caracteres opcionales de espacio en blanco y un car(cter de asterisco se repite al principio de cada una de las l5neas dentro del comentario de documentaci-n delimitado Odeli%ited-doc-co%%entR, entonces los caracteres del patr-n repetido no se incluyen en el c-digo N%8 resultante. El patr-n puede incluir caracteres de espacio en blanco OwhitespaceR antes y despu)s del car(cter de asterisco.

#66

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

,pndice , Co)entarios de docu)entacin

Eje)plo8
... DsummaryEClass DcE*ointD.cE models a &oint in a t,o=dimensional ... &lane.D.summaryE ... &ublic class *oint { ... DsummaryEmet"od DcEdra,D.cE renders t"e &oint.D.summaryE void dra,() {b! !

El texto de los comentarios de documentaci-n debe estar correctamente estructurado segHn las reglas del lengua$e N%8 O=ttpGTT999.93.orgTT;T;ECBxmlR. .i =ay incorrecciones en el texto N%8, se generar( una advertencia y el arc=ivo de documentaci-n incluir( un comentario ?ue =ar( re0erencia al error encontrado. &un?ue los desarrolladores pueden crear su propio $uego de eti?uetas, existe un $uego recomendado en la secci-n [18.+. &lgunas de las eti?uetas recomendadas tienen signi0icados especialesG 8a eti?ueta D&aramE se utili1a para describir par(metros. .i se utili1a dic=a eti?ueta, el generador de documentaci-n deber( comprobar ?ue el par(metro especi0icado existe y ?ue todos los par(metros se encuentran descritos en los comentarios de documentaci-n. .i esta comprobaci-n encuentra algHn error, el generador de documentaci-n emitir( una advertencia. El atributo cre- se puede asociar a cual?uier eti?ueta para proporcionar una re0erencia a un elemento de c-digo. El generador de documentaci-n debe comprobar si existe dic=o elemento de c-digo. .i la comprobaci-n no tiene )xito, el generador de documentaci-n emite una advertencia. &l buscar un nombre descrito en un atributo cre-, el generador de la documentaci-n debe respetar la visibilidad de espacio de nombres segHn las instrucciones using ?ue aparecen dentro del c-digo 0uente. 'ara los elementos de c-digo ?ue son gen)ricos, la sintaxis gen)rica normal Oes decir, PListD1EQR no se puede usar por?ue produce N%8 no v(lido. .e pueden usar llaves en lugar de corc=etes Oes decir, PList{1!QR, o se puede usar la sintaxis de escape N%8 Oes decir, PListFlt;1Fgt;QR. 8a eti?ueta DsummaryE est( pensada para su uso en un visor de documentaci-n con el 0in de mostrar in0ormaci-n adicional sobre un tipo o un miembro. 8a eti?ueta DincludeE incluye in0ormaci-n de un arc=ivo N%8 externo.

/bserve ?ue el arc=ivo de documentaci-n no proporciona in0ormaci-n completa sobre el tipo y los miembros Opor e$emplo, no contiene ninguna in0ormaci-n de tiposR. 'ara obtener tal in0ormaci-n acerca de un tipo o un miembro, el arc=ivo de documentaci-n debe utili1arse con$untamente con el mecanismo de re0lexi-n sobre el tipo o el miembro real.

'.2 Eti;uetas recomendadas


El generador de documentaci-n debe aceptar y procesar todas a?uellas eti?uetas ?ue sean v(lidas segHn las reglas de N%8. 8as siguientes eti?uetas proporcionan la 0uncionalidad =abitual en la documentaci-n de usuario. O'or supuesto, se pueden utili1ar otras eti?uetasR.

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

#6(

Especificacin del lenguaje C#

Eti9ueta
DcE DcodeE De#am&leE De#ce&tionE DincludeE DlistE D&araE D&aramE D&aramre-E D&ermissionE Dremar(E DreturnsE DseeE DseealsoE DsummaryE DvalueE Dty&e&aramE Dty&e&aramre-E

3eccin
2Y.L 2Y.L 2Y.L 2Y.L 2Y.L 2Y.L 2Y.L 2Y.L 2Y.L 2Y.L 2Y.L 2Y.L 2Y.L 2Y.L 2Y.L 2Y.L

:inalidad Establecer un tipo de 0uente de c-digo para un texto Establecer una o m(s l5neas de c-digo 0uente o indicar el 0inal de un programa !ndicar un e$emplo !denti0ica las excepciones ?ue pueden iniciar un m)todo !ncluye N%8 procedente de un arc=ivo externo Crear una lista o una tabla 'ermite agregar una estructura al texto 2escribe un par(metro para un m)todo o constructor !denti0ica una palabra como nombre de par(metro 2ocumenta la accesibilidad de seguridad de un miembro 2escribe in0ormaci-n adicional acerca de un tipo 2escribe el valor devuelto de un m)todo Especi0ica un v5nculo 3enera una entrada de tipo Vea ta%-i?n 2escribe un tipo o un miembro de un tipo 2escribe una propiedad 2escribe un par(metro de tipo gen)rico !denti0ica una palabra como nombre de par(metro de tipo

'.2.1 FcG Esta eti?ueta proporciona un mecanismo para indicar ?ue se debe establecer una 0uente especial para un 0ragmento de texto dentro de una descripci-n, tal como la ?ue se usa para un blo?ue de c-digo. 'ara l5neas de c-digo real, utilice DcodeE O[18.+R. 3intaxis8
DcEte#tD.cE

Eje)plo8
... DsummaryEClass DcE*ointD.cE models a &oint in a t,o=dimensional ... &lane.D.summaryE &ublic class *oint { .. ... !

'.2.2 FcodeG Esta eti?ueta se utili1a para establecer una o m(s l5neas de c-digo 0uente o para indicar el 0inal de un programa en alguna 0uente especial. 'ara pe?ueUos 0ragmentos de c-digo en texto narrativo, utilice DcE O[18.+R.

#6$

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

,pndice , Co)entarios de docu)entacin

3intaxis8
DcodeEsource code or &rogram out&utD.codeE

Eje)plo8
... ... ... ... ... ... ... ... ... ... DsummaryE1"is met"od c"anges t"e &ointWs location by t"e given #= and y=o--sets. De#am&leEVor e#am&le/ DcodeE *oint & + ne, *oint(9 K); &.1ranslate(=2 9); D.codeE results in DcE&D.cEWs "aving t"e value (8 Y). D.e#am&leE D.summaryE int yor) {

&ublic void 1ranslate(int #or I <+ #or; ` <+ yor; !

'.2.3 Fe"ampleG Esta eti?ueta permite c-digo de e$emplo dentro de un comentario, para especi0icar c-mo puede utili1arse un m)todo u otro miembro de biblioteca. 3eneralmente, esto tambi)n supone la utili1aci-n de la eti?ueta DcodeE O[18.+R. 3intaxis8
De#am&leEdescri&tionD.e#am&leE

Eje)plo8 >ea DcodeE( [18.+) para obtener un e$emplo. '.2.! Fe"ceptionG Esta eti?ueta proporciona un medio para documentar las excepciones ?ue puede iniciar un m)todo. 3intaxis8
De#ce&tion cre-+"member"Edescri&tionD.e#ce&tionE

donde
cre-+"member"

El nombre de un miembro. El generador de documentaci-n comprueba si el miembro en cuesti-n existe y traduce %e%-er al nombre del elemento can-nico en el arc=ivo de documentaci-n.
descri&tion

2escripci-n de las circunstancias en las ?ue se inicia la excepci-n.

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

#6"

Especificacin del lenguaje C#

Eje)plo8
&ublic class 6ata:ase%&erations { ... De#ce&tion cre-+"MasterVileVormatCorru&t)#ce&tion"ED.e#ce&tionE ... De#ce&tion cre-+"MasterVileLoc(ed%&en)#ce&tion"ED.e#ce&tionE &ublic static void OeadOecord(int -lag) { i- (-lag ++ 2) t"ro, ne, MasterVileVormatCorru&t)#ce&tion(); else i- (-lag ++ 8) t"ro, ne, MasterVileLoc(ed%&en)#ce&tion(); .. b ! !

'.2.# FincludeG Esta eti?ueta permite incluir in0ormaci-n de un documento N%8 externo al arc=ivo de c-digo 0uente. El arc=ivo externo debe ser un documento N%8 sin erroresV al documento se aplica una expresi-n I*at" para especi0icar ?u) parte de la sintaxis N%8 del documento debe incluirse. 8a eti?ueta DincludeE se sustituye entonces por el texto N%8 seleccionado del documento externo. 3intaxis8
Dinclude -ile+"-ilename" &at"+"#&at"" .E

donde
-ile+"-ilename"

4ombre de un arc=ivo N%8 externo. El nombre del arc=ivo se interpreta en relaci-n con el arc=ivo ?ue contiene la eti?ueta include.
&at"+"#&at""

7na expresi-n N'at= ?ue selecciona parte del c-digo N%8 del arc=ivo N%8 externo. Eje)plo8 .i el c-digo 0uente contuviera una declaraci-n como la siguienteG
... Dinclude -ile+"docs.#ml" &at"+We#tradoc.class4[name+"$ntList"5.>W .E &ublic class $ntList { b !

y el arc=ivo externo Pdocs.xmlQ tuviera el siguiente contenidoG


D7#ml version+"2.3"7E De#tradocE Dclass name+"$ntList"E DsummaryE Contains a list o- integers. D.summaryE D.classE Dclass name+"StringList"E DsummaryE Contains a list o- integers. D.summaryE D.classE D.e#tradocE

entonces la documentaci-n resultante ser5a la misma ?ue si el c-digo 0uente contuvieraG


... DsummaryE ... Contains a list o- integers. ... D.summaryE &ublic class $ntList { b !

#('

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

,pndice , Co)entarios de docu)entacin

'.2.$ FlistG Esta eti?ueta se utili1a para crear una lista o tabla de elementos. 'uede contener un blo?ue Dlist"eaderE para de0inir la 0ila de encabe1ado de una tabla o de una lista de de0iniciones. OCuando se de0ine una tabla, s-lo es necesario suministrar una entrada para term en el encabe1ado.R Cada elemento de la lista se especi0ica con un blo?ue DitemE. &l crear una lista de de0iniciones, es necesario especi0icar tanto term como descri&tion. .in embargo, para una tabla, lista con viUetas o lista numerada, s-lo es necesario especi0icar descri&tion. 3intaxis8
Dlist ty&e+"bullet" H "number" H "table"E Dlist"eaderE DtermEtermD.termE Ddescri&tionEdescri&tionD.descri&tionE D.list"eaderE DitemE DtermEtermD.termE Ddescri&tionEdescri&tionD.descri&tionE D.itemE b DitemE DtermEtermD.termE Ddescri&tionEdescri&tionD.descri&tionE D.itemE D.listE

donde
term

El t)rmino ?ue se desea de0inir, cuya de0inici-n se encuentra en descri&tion.


descri&tion

'uede ser el elemento de una lista numerada o con viUetas, o la de0inici-n de un term. Eje)plo8
&ublic class MyClass { ... DsummaryEHere is an e#am&le o- a bulleted list/ ... Dlist ty&e+"bullet"E ... DitemE ... Ddescri&tionE$tem 2.D.descri&tionE ... D.itemE ... DitemE ... Ddescri&tionE$tem 8.D.descri&tionE ... D.itemE ... D.listE ... D.summaryE &ublic static void Main () { .. ... ! !

'.2.+ FparaG Este eti?ueta debe utili1arse dentro de otras, como DsummaryE O[18.+R o DreturnsE O[18.+R y permite agregar la estructura al texto. 3intaxis8
D&araEcontentD.&araE

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

#(1

Especificacin del lenguaje C#

donde
content

Texto del p(rra0o. Eje)plo8


... DsummaryE1"is is t"e entry &oint o- t"e *oint class testing &rogram. ... D&araE1"is &rogram tests eac" met"od and o&erator and ... is intended to be run a-ter any non=trvial maintenance "as ... been &er-ormed on t"e *oint class.D.&araED.summaryE &ublic static void Main() { .. ... !

'.2.- FparamG Esta eti?ueta se utili1a para describir un par(metro para un m)todo, constructor o indi1ador. 3intaxis8
D&aram name+"name"Edescri&tionD.&aramE

donde
nombre

4ombre del par(metro.


descri&tion

7na descripci-n del par(metro. Eje)plo8


... DsummaryE1"is met"od c"anges t"e &ointWs location to ... t"e given coordinates.D.summaryE ... D&aram name+"#or"Et"e ne, #=coordinate.D.&aramE ... D&aram name+"yor"Et"e ne, y=coordinate.D.&aramE &ublic void Move(int #or int yor) { I + #or; ` + yor; !

'.2.. FparamrefG Esta eti?ueta se utili1a para indicar ?ue una palabra es un par(metro. El arc=ivo de documentaci-n se puede procesar de manera ?ue apli?ue un 0ormato di0erente a este par(metro. 3intaxis8
D&aramre- name+"name".E

donde
nombre

4ombre del par(metro. Eje)plo8


... DsummaryE1"is constructor ... (D&aramre- name+"#or".E ... D&aram name+"#or"Et"e ne, ... D&aram name+"yor"Et"e ne, initiali?es t"e ne, *oint to D&aramre- name+"yor".E).D.summaryE *ointWs #=coordinate.D.&aramE *ointWs y=coordinate.D.&aramE

#(2

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

,pndice , Co)entarios de docu)entacin &ublic *oint(int #or I + #or; ` + yor; ! int yor) {

'.2.10 FpermissionG Esta eti?ueta permite documentar la accesibilidad de seguridad de un miembro. 3intaxis8
D&ermission cre-+"member"Edescri&tionD.&ermissionE

donde
cre-+"member"

El nombre de un miembro. El generador de documentaci-n comprueba si el elemento de c-digo dado existe y traduce %e%-er al nombre del elemento can-nico en el arc=ivo de documentaci-n.
descri&tion

2escripci-n del acceso al miembro. Eje)plo8


... D&ermission cre-+"System.Security.*ermissionSet"E)veryone can ... access t"is met"od.D.&ermissionE &ublic static void 1est() { .. ... !

'.2.11 Fremar3G Esta eti?ueta se utili1a para especi0icar in0ormaci-n adicional sobre un tipo. O7se DsummaryE O[18.+R para describir el propio tipo y los miembros de un tipo.R 3intaxis8
Dremar(Edescri&tionD.remar(E

donde
descri&tion

El texto de la nota. Eje)plo8


... DsummaryEClass DcE*ointD.cE models a &oint in a ... t,o=dimensional &lane.D.summaryE ... Dremar(E;ses &olar coordinatesD.remar(E &ublic class *oint { .. ... !

'.2.12 FreturnsG Esta eti?ueta se utili1a para describir el valor devuelto de un m)todo. 3intaxis8
DreturnsEdescri&tionD.returnsE

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

#(3

Especificacin del lenguaje C#

donde
descri&tion

2escripci-n del valor devuelto. Eje)plo8


... DsummaryEOe&ort a &ointWs location as a string.D.summaryE ... DreturnsE' string re&resenting a &ointWs location in t"e -orm (# y) ... ,it"out any leading trailing or embedded ,"ites&ace.D.returnsE &ublic override string 1oString() { return "(" < I < " " < ` < ")"; !

'.2.13 FseeG Esta eti?ueta permite especi0icar un v5nculo dentro del texto. 7tilice DseealsoE O[18.+R para indicar el texto ?ue debe aparecer en una secci-n Vea ta%-i?n. 3intaxis8
Dsee cre-+"member".E

donde
cre-+"member"

El nombre de un miembro. El generador de documentaci-n comprueba si el elemento de c-digo dado existe y cambia %e%-er por el nombre del elemento en el arc=ivo de documentaci-n generado. Eje)plo8
... DsummaryE1"is met"od c"anges t"e &ointWs location to ... t"e given coordinates.D.summaryE ... Dsee cre-+"1ranslate".E &ublic void Move(int #or int yor) { I + #or; ` + yor; ! ... DsummaryE1"is met"od c"anges t"e &ointWs location by ... t"e given #= and y=o--sets. ... D.summaryE ... Dsee cre-+"Move".E &ublic void 1ranslate(int #or int yor) { I <+ #or; ` <+ yor; !

'.2.1! FseealsoG Esta eti?ueta permite generar una entrada para la secci-n Vea ta%-i?n. 7tilice DseeE O[18.+R para especi0icar un v5nculo desde dentro del texto. 3intaxis8
Dseealso cre-+"member".E

donde
cre-+"member"

El nombre de un miembro. El generador de documentaci-n comprueba si el elemento de c-digo dado existe y cambia %e%-er por el nombre del elemento en el arc=ivo de documentaci-n generado.

#(#

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

,pndice , Co)entarios de docu)entacin

Eje)plo8
... DsummaryE1"is met"od determines ,"et"er t,o *oints "ave t"e same ... location.D.summaryE ... Dseealso cre-+"o&erator++".E ... Dseealso cre-+"o&erator@+".E &ublic override bool )Quals(object o) { .. ... !

'.2.1# FsummaryG Esta eti?ueta se utili1a para describir un tipo o un miembro de un tipo. 7tilice Dremar(E O[18.+R para describir el propio tipo. 3intaxis8
DsummaryEdescri&tionD.summaryE

donde
descri&tion

;esumen del tipo o miembro. Eje)plo8


... DsummaryE1"is constructor initiali?es t"e ne, *oint to (3 3).D.summaryE &ublic *oint() / t"is(3 3) { !

'.2.1$ F alueG Esta eti?ueta permite describir una propiedad. 3intaxis8


DvalueE&ro&erty descri&tionD.valueE

donde
&ro&erty descri&tion

2escripci-n de la propiedad. Eje)plo8


... DvalueE*ro&erty DcEID.cE re&resents t"e &ointWs #=coordinate.D.valueE &ublic int I { get { return #; ! set { # + value; ! !

'.2.1+ FtypeparamG Esta eti?ueta se utili1a para describir un par(metro de tipo gen)rico para un m)todo, delegado, inter0a1, estructura o clase. 3intaxis8
Dty&e&aram name+"name"Edescri&tionD.ty&e&aramE

donde
nombre

4ombre del par(metro de tipo.


Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

#(!

Especificacin del lenguaje C#

descri&tion

2escripci-n del par(metro de tipo. Eje)plo8


... DsummaryE' generic list class.D.summaryE ... Dty&e&aram name+"1"E1"e ty&e stored by t"e list.D.ty&e&aramE &ublic class MyListD1E { ... !

'.2.1- FtypeparamrefG Esta eti?ueta se utili1a para indicar ?ue una palabra es un par(metro de tipo. El arc=ivo de documentaci-n se puede procesar de manera ?ue apli?ue un 0ormato di0erente a este par(metro de tipo. 3intaxis8
Dty&e&aramre- name+"name".E

donde
nombre

4ombre del par(metro de tipo. Eje)plo8


... DsummaryE1"is met"od -etc"es data and returns a list o- Dty&e&aramrename+T1TE T.ETE .D.summaryE ... D&aram name+"string"EQuery to e#ecuteD.&aramE &ublic ListD1E Vetc"6ataD1E(string Query) { ... !

'.3 (rocesar el arc?i o de documentacin


El generador de documentaci-n genera una cadena de id. para cada elemento del c-digo 0uente marcado con un comentario de documentaci-n. Esta cadena de id. identi0ica de 0orma Hnica un elemento 0uente. 7n visor de documentaci-n puede utili1ar una cadena de id. para identi0icar el correspondiente elemento de metadatosTre0lexi-n al ?ue se aplica la documentaci-n. El arc=ivo de documentaci-n no es una representaci-n $er(r?uica del c-digo 0uente, es una lista sencilla con una cadena de id. generada para cada elemento. '.3.1 7ormato de cadena de Id. El generador de documentaci-n cumple las siguientes reglas cuando genera las cadenas de id.G 4o se coloca ningHn espacio en blanco en la cadena. 8a primera parte de la cadena identi0ica el tipo de miembro ?ue se desea documentar por medio de un Hnico car(cter seguido de dos puntos. .e de0inen los siguientes tipos de miembrosG

#(6

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

,pndice , Co)entarios de docu)entacin

Car cter E : % 4 ' T E

+escripcin Evento Campo %)todo Oincluidos constructores, destructores y operadoresR Espacio de nombres 'ropiedad Oincluidos los indi1adoresR Tipo Otal como class, delegate, enum, inter0ace y structR Cadena de errorV el resto de la cadena proporciona in0ormaci-n acerca del error. 'or e$emplo, el generador de documentaci-n genera in0ormaci-n de error para v5nculos ?ue no se pueden resolver.

8a segunda parte de la cadena es el nombre completo del elemento, empe1ando en la ra51 del espacio de nombres. El nombre del elemento, los tipos contenedores y el espacio de nombres se separan mediante puntos. .i el nombre del elemento ya contiene puntos, )stos se reempla1an por caracteres 0 O;<3389R. O.e asume ?ue ningHn elemento tiene este car(cter en su nombreR. 'ara los m)todos y propiedades con argumentos, sigue la lista de argumentos entre par)ntesis. .i no existen argumentos, los par)ntesis se omiten. 8os argumentos se separan por comas. 8a codi0icaci-n de cada argumento es la misma ?ue la 0irma C8!, como se indica a continuaci-nG :or met=ods and properties 9it= arguments, t=e argument list 0ollo9s, enclosed in parent=eses. :or t=ose 9it=out arguments, t=e parent=eses are omitted. T=e arguments are separated by commas. T=e encoding o0 eac= argument is t=e same as a C8! signature, as 0ollo9sG o 8os argumentos aparecen representados por su nombre de documentaci-n, ?ue se basa en su nombre completo, modi0icado como se indica a continuaci-nG 8os argumentos ?ue representan tipos gen)ricos tienen un car(cter PaQ anexo seguido por el nHmero de par(metros de tipo 8os argumentos ?ue contienen el modi0icador out o re- llevan un signo [ tras su nombre de tipo. 8os argumentos ?ue se pasan por valor o a trav)s de &arams no tienen una notaci-n especial. 8os argumentos ?ue son matrices se representan como 4 lower-o nd / si0e f lower-o nd / si0e 5, donde el nHmero de comas es el rango menos 1, y los l5mites in0eriores y tamaUos de cada dimensi-n, si se conocen, se representan en 0ormato decimal. .i no se especi0ica un l5mite in0erior ni un tamaUo, se omite. .i el l5mite in0erior Olower-o ndR y el tamaUo Osi0eR de una dimensi-n particular se omiten, tambi)n se omite el signo P/Q. 8as matrices escalonadas se representan con un P45Q por nivel. 8os argumentos con tipos de puntero distintos de void se representan con un > a continuaci-n del nombre de tipo. 7n puntero void se representa mediante un nombre de tipo de System.Uoid. 8os argumentos ?ue =acen re0erencia a par(metros de tipos gen)ricos de0inidos en tipos se codi0ican mediante el car(cter PjQ seguido por el 5ndice de base cero del par(metro de tipo. 8os argumentos ?ue usan par(metros de tipos gen)ricos de0inidos en m)todos utili1an una doble marca inversa PjjQ en lugar de PjQ, ?ue se usa para los tipos.

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

#((

Especificacin del lenguaje C#

8os argumentos ?ue =acen re0erencia a tipos gen)ricos construidos se codi0ican mediante el tipo gen)rico, seguido por PdP, seguido por una lista separada por comas de los argumentos de tipo, seguida por PeQ.

'.3.2 Ejemplos de cadena de Id. 8os siguientes e$emplos muestran cada uno un 0ragmento de c-digo C#, $unto con la cadena de id. ?ue se produce a partir de cada elemento de c-digo 0uente ?ue puede tener un comentario de documentaci-nG 8os tipos se representan con su nombre completo, incrementado con in0ormaci-n gen)rica.
enum Color { Oed :lue Sreen ! names&ace 'cme { inter-ace $*rocess {...! struct Ualue1y&e {...! class Widget/ $*rocess { &ublic class NestedClass {...! &ublic inter-ace $Menu$tem {...! &ublic delegate void 6el(int i); &ublic enum 6irection { Nort" ! class MyListD1E { class Hel&erD; UE {...! ! ! "1/Color" "1/'cme.$*rocess" "1/'cme.Ualue1y&e" "1/'cme.Widget" "1/'cme.Widget.NestedClass" "1/'cme.Widget.$Menu$tem" "1/'cme.Widget.6el" "1/'cme.Widget.6irection" T1/'cme.MyListd2T T1/'cme.MyListd2.Hel&erd8T Sout" )ast West !

8os campos se representan con su nombre completoG


names&ace 'cme { struct Ualue1y&e { &rivate int total; ! class Widget/ $*rocess { &ublic class NestedClass { &rivate int value; !

#($

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

,pndice , Co)entarios de docu)entacin &rivate string message; &rivate static Color de-aultColor; &rivate const double *$ + 9.2J2KL; &rotected readonly double mont"ly'verage; &rivate long45 array2; &rivate Widget4 5 array8; &rivate unsa-e int >&Count; &rivate unsa-e -loat >>&&Ualues; ! ! "V/'cme.Ualue1y&e.total" "V/'cme.Widget.NestedClass.value" "V/'cme.Widget.message" "V/'cme.Widget.de-aultColor" "V/'cme.Widget.*$" "V/'cme.Widget.mont"ly'verage" "V/'cme.Widget.array2" "V/'cme.Widget.array8" "V/'cme.Widget.&Count" "V/'cme.Widget.&&Ualues"

Constructores.
names&ace 'cme { class Widget/ $*rocess { static Widget() {...! &ublic Widget() {...! &ublic Widget(string s) {...! ! ! "M/'cme.Widget.0cctor" "M/'cme.Widget.0ctor" "M/'cme.Widget.0ctor(System.String)"

2estructores.
names&ace 'cme { class Widget/ $*rocess { AWidget() {...! ! ! "M/'cme.Widget.Vinali?e"

%)todos.
names&ace 'cme { struct Ualue1y&e { &ublic void M(int i) {...! ! class Widget/ $*rocess { &ublic class NestedClass { &ublic void M(int i) {...! !

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

#("

Especificacin del lenguaje C# &ublic &ublic &ublic &ublic &ublic &ublic &ublic ! class MyListD1E { &ublic void 1est(1 t) { ! ! class ;seList { &ublic void *rocess(MyListDintE list) { ! &ublic MyListD1E SetUaluesD1E(1 in&utUalue) { return null; ! ! ! "M/'cme.Ualue1y&e.M(System.$nt98)" "M/'cme.Widget.NestedClass.M(System.$nt98)" "M/'cme.Widget.M3" "M/'cme.Widget.M2(System.C"ar System.Single[ 'cme.Ualue1y&e[)" "M/'cme.Widget.M8(System.$nt2X45 System.$nt9843/ 3/5 System.$ntXJ4545)" "M/'cme.Widget.M9(System.$ntXJ4545 'cme.Widget43/ 3/ 3/545)" "M/'cme.Widget.MJ(System.C"ar> Color>>)" "M/'cme.Widget.MK(System.Uoid> System.6ouble>43/ 3/545)" "M/'cme.Widget.MX(System.$nt98 System.%bject45)" TM/'cme.MyListd2.1est(d3)T TM/'cme.;seList.*rocess('cme.MyList{System.$nt98!)T TM/'cme.;seList.SetUaluesdd(dd3)T static void M3() {...! void M2(c"ar c out -loat - re- Ualue1y&e v) {...! void M8(s"ort45 #2 int4 5 #8 long4545 #9) {...! void M9(long4545 #9 Widget454 5 #J) {...! unsa-e void MJ(c"ar >&c Color >>&-) {...! unsa-e void MK(void >&v double >454 5 &d) {...! void MX(int i &arams object45 args) {...!

'ropiedades e indi1adores.
names&ace 'cme { class Widget/ { &ublic int &ublic int &ublic int ! ! $*rocess Widt" { get {...! set {...! ! t"is4int i5 { get {...! set {...! ! t"is4string s int i5 { get {...! set {...! !

"*/'cme.Widget.Widt"" "*/'cme.Widget.$tem(System.$nt98)" "*/'cme.Widget.$tem(System.String System.$nt98)"

Eventos.
names&ace 'cme { class Widget/ $*rocess { &ublic event 6el 'n)vent; ! ! ")/'cme.Widget.'n)vent"

#$'

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

,pndice , Co)entarios de docu)entacin

/peradores unarios.
names&ace 'cme { class Widget/ $*rocess { &ublic static Widget o&erator<(Widget #) {...! ! ! "M/'cme.Widget.o&\;nary*lus('cme.Widget)"

El con$unto completo de nombres de 0unci-n de operadores unarios es el siguienteG o&\;nary*lus, o&\;naryNegation, o&\LogicalNot, o&\%nesCom&lement, o&\$ncrement, o&\6ecrement, o&\1rue y o&\Valse. /peradores binarios.
names&ace 'cme { class Widget/ $*rocess { &ublic static Widget o&erator<(Widget #2 ! !

Widget #8) {...!

"M/'cme.Widget.o&\'ddition('cme.Widget 'cme.Widget)"

El con$unto completo de nombres de 0unciones de operadores binarios es el siguienteG o&\'ddition, o&\Subtraction, o&\Multi&ly, o&\6ivision, o&\Modulus, o&\:it,ise'nd, o&\:it,ise%r, o&\)#clusive%r, o&\Le-tS"i-t, o&\Oig"tS"i-t, o&\)Quality, o&\$neQuality, o&\Less1"an, o&\Less1"an%r)Qual, o&\Sreater1"an y o&\Sreater1"an%r)Qual. 8os operadores de conversi-n tienen un car(cter 0inal PAQ seguido del tipo de valor devuelto.
names&ace 'cme { class Widget/ $*rocess { &ublic static e#&licit o&erator int(Widget #) {...! &ublic static im&licit o&erator long(Widget #) {...! ! ! "M/'cme.Widget.o&\)#&licit('cme.Widget)ASystem.$nt98" "M/'cme.Widget.o&\$m&licit('cme.Widget)ASystem.$ntXJ"

'.! 5n ejemplo
'.!.1 %digo fuente %H El e$emplo siguiente muestra el c-digo 0uente de una clase *ointG
names&ace Sra&"ics { ... DsummaryEClass DcE*ointD.cE models a &oint in a t,o=dimensional &lane. ... D.summaryE &ublic class *oint { ... DsummaryE$nstance variable DcE#D.cE re&resents t"e &ointWs ... #=coordinate.D.summaryE &rivate int #;

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

#$1

Especificacin del lenguaje C# ... DsummaryE$nstance variable DcEyD.cE re&resents t"e &ointWs ... y=coordinate.D.summaryE &rivate int y; ... DvalueE*ro&erty DcEID.cE re&resents t"e &ointWs #=coordinate.D.valueE &ublic int I { get { return #; ! set { # + value; ! ! ... DvalueE*ro&erty DcE`D.cE re&resents t"e &ointWs y=coordinate.D.valueE &ublic int ` { get { return y; ! set { y + value; ! ! ... DsummaryE1"is constructor initiali?es t"e ne, *oint to ... (3 3).D.summaryE &ublic *oint() / t"is(3 3) {! ... DsummaryE1"is constructor initiali?es t"e ne, *oint to ... (D&aramre- name+"#or".E D&aramre- name+"yor".E).D.summaryE ... D&aramEDcE#orD.cE is t"e ne, *ointWs #=coordinate.D.&aramE ... D&aramEDcEyorD.cE is t"e ne, *ointWs y=coordinate.D.&aramE &ublic *oint(int #or int yor) { I + #or; ` + yor; ! ... DsummaryE1"is met"od c"anges t"e &ointWs location to ... t"e given coordinates.D.summaryE ... D&aramEDcE#orD.cE is t"e ne, #=coordinate.D.&aramE ... D&aramEDcEyorD.cE is t"e ne, y=coordinate.D.&aramE ... Dsee cre-+"1ranslate".E &ublic void Move(int #or int yor) { I + #or; ` + yor; ! ... DsummaryE1"is met"od c"anges t"e &ointWs location by ... t"e given #= and y=o--sets. ... De#am&leEVor e#am&le/ ... DcodeE ... *oint & + ne, *oint(9 K); ... &.1ranslate(=2 9); ... D.codeE ... results in DcE&D.cEWs "aving t"e value (8 Y). ... D.e#am&leE ... D.summaryE ... D&aramEDcE#orD.cE is t"e relative #=o--set.D.&aramE ... D&aramEDcEyorD.cE is t"e relative y=o--set.D.&aramE ... Dsee cre-+"Move".E &ublic void 1ranslate(int #or int yor) { I <+ #or; ` <+ yor; !

#$2

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

,pndice , Co)entarios de docu)entacin ... DsummaryE1"is met"od determines ,"et"er t,o *oints "ave t"e same ... location.D.summaryE ... D&aramEDcEoD.cE is t"e object to be com&ared to t"e current object. ... D.&aramE ... DreturnsE1rue i- t"e *oints "ave t"e same location and t"ey "ave ... t"e e#act same ty&e; ot"er,ise -alse.D.returnsE ... Dseealso cre-+"o&erator++".E ... Dseealso cre-+"o&erator@+".E &ublic override bool )Quals(object o) { i- (o ++ null) { return -alse; ! i- (t"is ++ o) { return true; ! i- (Set1y&e() ++ o.Set1y&e()) { *oint & + (*oint)o; return (I ++ &.I) FF (` ++ &.`); ! return -alse; ! ... DsummaryEOe&ort a &ointWs location as a string.D.summaryE ... DreturnsE' string re&resenting a &ointWs location in t"e -orm (# y) ... ,it"out any leading training or embedded ,"ites&ace.D.returnsE &ublic override string 1oString() { return "(" < I < " " < ` < ")"; ! ... DsummaryE1"is o&erator determines ,"et"er t,o *oints "ave t"e same ... location.D.summaryE ... D&aramEDcE&2D.cE is t"e -irst *oint to be com&ared.D.&aramE ... D&aramEDcE&8D.cE is t"e second *oint to be com&ared.D.&aramE ... DreturnsE1rue i- t"e *oints "ave t"e same location and t"ey "ave ... t"e e#act same ty&e; ot"er,ise -alse.D.returnsE ... Dseealso cre-+")Quals".E ... Dseealso cre-+"o&erator@+".E &ublic static bool o&erator++(*oint &2 *oint &8) { i- ((object)&2 ++ null HH (object)&8 ++ null) { return -alse; ! i- (&2.Set1y&e() ++ &8.Set1y&e()) { return (&2.I ++ &8.I) FF (&2.` ++ &8.`); ! return -alse; ! ... DsummaryE1"is o&erator determines ,"et"er t,o *oints "ave t"e same ... location.D.summaryE ... D&aramEDcE&2D.cE is t"e -irst *oint to be com&ared.D.&aramE ... D&aramEDcE&8D.cE is t"e second *oint to be com&ared.D.&aramE ... DreturnsE1rue i- t"e *oints do not "ave t"e same location and t"e ... e#act same ty&e; ot"er,ise -alse.D.returnsE ... Dseealso cre-+")Quals".E ... Dseealso cre-+"o&erator++".E &ublic static bool o&erator@+(*oint &2 *oint &8) { return @(&2 ++ &8); !

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

#$3

Especificacin del lenguaje C# ... DsummaryE1"is is t"e entry &oint o- t"e *oint class testing ... &rogram. ... D&araE1"is &rogram tests eac" met"od and o&erator and ... is intended to be run a-ter any non=trvial maintenance "as ... been &er-ormed on t"e *oint class.D.&araED.summaryE &ublic static void Main() { .. class test code goes "ere ! ! !

'.!.2 I&6 resultante Zste es el resultado producido por un generador de documentaci-n =abi)ndose proporcionado al mismo el c-digo 0uente para la clase *oint, como se mostr- anteriormenteG
D7#ml version+"2.3"7E DdocE DassemblyE DnameE*ointD.nameE D.assemblyE DmembersE Dmember name+"1/Sra&"ics.*oint"E DsummaryEClass DcE*ointD.cE models a &oint in a t,o=dimensional &lane. D.summaryE D.memberE Dmember name+"V/Sra&"ics.*oint.#"E DsummaryE$nstance variable DcE#D.cE re&resents t"e &ointWs #=coordinate.D.summaryE D.memberE Dmember name+"V/Sra&"ics.*oint.y"E DsummaryE$nstance variable DcEyD.cE re&resents t"e &ointWs y=coordinate.D.summaryE D.memberE Dmember name+"M/Sra&"ics.*oint.0ctor"E DsummaryE1"is constructor initiali?es t"e ne, *oint to (3 3).D.summaryE D.memberE Dmember name+"M/Sra&"ics.*oint.0ctor(System.$nt98 System.$nt98)"E DsummaryE1"is constructor initiali?es t"e ne, *oint to (D&aramre- name+"#or".E D&aramre- name+"yor".E).D.summaryE D&aramEDcE#orD.cE is t"e ne, *ointWs #=coordinate.D.&aramE D&aramEDcEyorD.cE is t"e ne, *ointWs y=coordinate.D.&aramE D.memberE Dmember name+"M/Sra&"ics.*oint.Move(System.$nt98 System.$nt98)"E DsummaryE1"is met"od c"anges t"e &ointWs location to t"e given coordinates.D.summaryE D&aramEDcE#orD.cE is t"e ne, #=coordinate.D.&aramE D&aramEDcEyorD.cE is t"e ne, y=coordinate.D.&aramE Dsee cre-+"M/Sra&"ics.*oint.1ranslate(System.$nt98 System.$nt98)".E D.memberE

#$#

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

,pndice , Co)entarios de docu)entacin Dmember name+"M/Sra&"ics.*oint.1ranslate(System.$nt98 System.$nt98)"E DsummaryE1"is met"od c"anges t"e &ointWs location by t"e given #= and y=o--sets. De#am&leEVor e#am&le/ DcodeE *oint & + ne, *oint(9 K); &.1ranslate(=2 9); D.codeE results in DcE&D.cEWs "aving t"e value (8 Y). D.e#am&leE D.summaryE D&aramEDcE#orD.cE is t"e relative #=o--set.D.&aramE D&aramEDcEyorD.cE is t"e relative y=o--set.D.&aramE Dsee cre-+"M/Sra&"ics.*oint.Move(System.$nt98 System.$nt98)".E D.memberE Dmember name+"M/Sra&"ics.*oint.)Quals(System.%bject)"E DsummaryE1"is met"od determines ,"et"er t,o *oints "ave t"e same location.D.summaryE D&aramEDcEoD.cE is t"e object to be com&ared to t"e current object. D.&aramE DreturnsE1rue i- t"e *oints "ave t"e same location and t"ey "ave t"e e#act same ty&e; ot"er,ise -alse.D.returnsE Dseealso cre-+"M/Sra&"ics.*oint.o&\)Quality(Sra&"ics.*oint Sra&"ics.*oint)".E Dseealso cre-+"M/Sra&"ics.*oint.o&\$neQuality(Sra&"ics.*oint Sra&"ics.*oint)".E D.memberE Dmember name+"M/Sra&"ics.*oint.1oString"E DsummaryEOe&ort a &ointWs location as a string.D.summaryE DreturnsE' string re&resenting a &ointWs location in t"e -orm (# y) ,it"out any leading training or embedded ,"ites&ace.D.returnsE D.memberE Dmember name+"M/Sra&"ics.*oint.o&\)Quality(Sra&"ics.*oint Sra&"ics.*oint)"E DsummaryE1"is o&erator determines ,"et"er t,o *oints "ave t"e same location.D.summaryE D&aramEDcE&2D.cE is t"e -irst *oint to be com&ared.D.&aramE D&aramEDcE&8D.cE is t"e second *oint to be com&ared.D.&aramE DreturnsE1rue i- t"e *oints "ave t"e same location and t"ey "ave t"e e#act same ty&e; ot"er,ise -alse.D.returnsE Dseealso cre-+"M/Sra&"ics.*oint.)Quals(System.%bject)".E Dseealso cre-+"M/Sra&"ics.*oint.o&\$neQuality(Sra&"ics.*oint Sra&"ics.*oint)".E D.memberE Dmember name+"M/Sra&"ics.*oint.o&\$neQuality(Sra&"ics.*oint Sra&"ics.*oint)"E DsummaryE1"is o&erator determines ,"et"er t,o *oints "ave t"e same location.D.summaryE D&aramEDcE&2D.cE is t"e -irst *oint to be com&ared.D.&aramE D&aramEDcE&8D.cE is t"e second *oint to be com&ared.D.&aramE DreturnsE1rue i- t"e *oints do not "ave t"e same location and t"e e#act same ty&e; ot"er,ise -alse.D.returnsE Dseealso cre-+"M/Sra&"ics.*oint.)Quals(System.%bject)".E Dseealso cre-+"M/Sra&"ics.*oint.o&\)Quality(Sra&"ics.*oint Sra&"ics.*oint)".E D.memberE

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

#$!

Especificacin del lenguaje C# Dmember name+"M/Sra&"ics.*oint.Main"E DsummaryE1"is is t"e entry &oint o- t"e *oint class testing &rogram. D&araE1"is &rogram tests eac" met"od and o&erator and is intended to be run a-ter any non=trvial maintenance "as been &er-ormed on t"e *oint class.D.&araED.summaryE D.memberE Dmember name+"*/Sra&"ics.*oint.I"E DvalueE*ro&erty DcEID.cE re&resents t"e &ointWs #=coordinate.D.valueE D.memberE Dmember name+"*/Sra&"ics.*oint.`"E DvalueE*ro&erty DcE`D.cE re&resents t"e &ointWs y=coordinate.D.valueE D.memberE D.membersE D.docE

#$6

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

,pndice C /eferencias

<. 0ram)tica
Este ap)ndice contiene resHmenes de las gram(ticas l)xicas y sint(cticas ?ue pertenecen al documento principal, as5 como de las extensiones de gram(tica del c-digo no seguro. 8as construcciones de gram(tica aparecen a?u5 en el mismo orden en ?ue aparecen en el documento principal.

<.1 0ram)tica l*"ica


inp t1 inp t-sectionopt inp t-section1 inp t-section-part inp t-section inp t-section-part inp t-section-part1 inp t-ele%entsopt new-line pp-directive inp t-ele%ents1 inp t-ele%ent inp t-ele%ents inp t-ele%ent inp t-ele%ent1 whitespace co%%ent to3en <.1.1 Terminadores de l2nea new-line1 Car,cter de retorno de carro 4;<33365 Car,cter de salto de l*nea 4;<333'5 Car,cter de retorno de carro 4;<33365 se& ido de n car,cter de salto de l*nea 4;<333'5 Car,cter de l*nea si& iente 4;<33YK5 Car,cter separador de l*nea 4;<838Y5 Car,cter separador de p,rrafo 4;<838L5 <.1.2 %omentarios co%%ent1 sin&le-line-co%%ent deli%ited-co%%ent sin&le-line-co%%ent1 .. inp t-charactersopt inp t-characters1 inp t-character inp t-characters inp t-character

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

#$(

Especificacin del lenguaje C#

inp t-character1 C al6 ier car,cter (nicode e2cepto n new-line-character 4car,cter de n eva l*neaR new-line-character1 Car,cter de retorno de carro 4;<33365 Car,cter de salto de l*nea 4;<333'5 Car,cter de l*nea si& iente 4;<33YK5 Car,cter separador de l*nea 4;<838Y5 Car,cter separador de p,rrafo 4;<838L5 deli%ited-co%%ent1 .> deli%ited-co%%ent-te2topt asteris3s . deli%ited-co%%ent-te2t1 deli%ited-co%%ent-section deli%ited-co%%ent-te2t deli%ited-co%%ent-section deli%ited-co%%ent-section1
.

asteris3sopt not-slash-or-asteris3 asteris3s1


>

asteris3s > not-slash-or-asteris31 C al6 ier car,cter (nicode e2cepto . o > <.1.3 Espacio en blanco whitespace1 C al6 ier car,cter con clase (nicode 7s Car,cter de ta- laci/n hori0ontal 4;<333L5 Car,cter de ta- laci/n vertical 4;<333:5 Car,cter de avance de p,&ina 4;<333C5 <.1.! To3ens to3en1 identificador 3e#word inte&er-literal real-literal character-literal strin&-literal operator-or-p nct ator <.1.# 4ecuencias de escape de caracteres 5nicode nicode-escape-se6 ence1 Zu he2-di&it he2-di&it he2-di&it he2-di&it Z; he2-di&it he2-di&it he2-di&it he2-di&it he2-di&it he2-di&it he2-di&it he2-di&it

#$$

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

,pndice C /eferencias

<.1.$ Identificadores identifier1 availa-le-identifier [ identifier-or-3e#word availa-le-identifier1 (n identifier-or-3e#word 4identificador o pala-ra clave5 6 e no es na 3e#word Opalabra claveR identifier-or-3e#word1 identifier-start-character identifier-part-charactersopt identifier-start-character1 letter-character \ 4el car,cter de s -ra#ado ;<33KV5 identifier-part-characters1 identifier-part-character identifier-part-characters identifier-part-character identifier-part-character1 letter-character deci%al-di&it-character connectin&-character co%-inin&-character for%attin&-character letter-character1 (n car,cter (nicode de las clases + , +l, +t, +%, +o o 8l (na sec encia de escape (nicode 4 nicode-escape-se6 ence) 6 e representa a n car,cter de clases + , +l, +t, +%, +o o 8l co%-inin&-character1 (n car,cter (nicode de las clases Mn o Mc (na sec encia de escape (nicode 4 nicode-escape-se6 ence5 6 e representa n car,cter de clases Mn o Mc deci%al-di&it-character1 (n car,cter (nicode de la clase 8d. (na sec encia de escape (nicode 4 nicode-escape-se6 ence5 6 e representa n car,cter de la clase 8d connectin&-character1 (n car,cter (nicode de la clase 9c (na sec encia de escape (nicode 4 nicode-escape-se6 ence5 6 e representa n car,cter de la clase 9c for%attin&-character1 (n car,cter (nicode de la clase Cf (na sec encia de escape (nicode 4 nicode-escape-se6 ence5 6 e representa n car,cter de la clase Cf

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

#$"

Especificacin del lenguaje C#

<.1.+ (alabras cla e palabra clave O3e#wordRG una de


abstract byte class delegate event -i#ed iinternal ne, override readonly s"ort struct try unsa-e volatile as case const do e#&licit -loat im&licit es null &arams resi?eos,itc" ty&eous"ort ,"ile base catc" continue double e#tern -or in loc( object &rivate return stac(alloc t"is uint using bool c"ar decimal else -alse -oreac" int long o&erator &rotected sbyte static t"ro, ulong virtual brea( c"ec(ed de-ault enum -inally goto inter-ace names&ace out &ublic sealed string true unc"ec(ed void

<.1.- 6iterales literal1 -oolean-literal inte&er-literal real-literal character-literal strin&-literal n ll-literal -oolean-literal1
true -alse

inte&er-literal1 deci%al-inte&er-literal he2adeci%al-inte&er-literal deci%al-inte&er-literal1 deci%al-di&its inte&er-t#pe-s ffi2opt deci%al-di&its1 deci%al-di&it deci%al-di&its deci%al-di&it deci%al-di&it1 no de
3 ; 2 u 8 L 9 l J ;L K ;l X M uL Y ul L L; Lu l; lu

inte&er-t#pe-s ffi21 no de he2adeci%al-inte&er-literal1 3# he2-di&its inte&er-t#pe-s ffi2opt 3I he2-di&its inte&er-t#pe-s ffi2opt

#"'

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

,pndice C /eferencias

he2-di&its1 he2-di&it he2-di&its he2-di&it he2-di&it1 no de


3 2 8 9 J K X M Y L ' : C 6 ) V a b c d e -

real-literal1 deci%al-di&its . deci%al-di&its e2ponent-partopt real-t#pe-s ffi2opt . deci%al-di&its e2ponent-partopt real-t#pe-s ffi2opt deci%al-di&its e2ponent-part real-t#pe-s ffi2opt deci%al-di&its real-t#pe-s ffi2 e2ponent-part1 e si&nopt deci%al-di&its ) si&nopt deci%al-di&its si&n1 no de
< V = 6 d M m

real-t#pe-s ffi21 no de character-literal1 W character W character1 sin&le-character si%ple-escape-se6 ence he2adeci%al-escape-se6 ence nicode-escape-se6 ence sin&le-character1 C al6 ier car,cter e2ceptoW 4;<338M5, Z 4;<33KC5 # n new-line-character 4car,cter de n eva l*neaR si%ple-escape-se6 ence1 no de
ZW Z" ZZ Z3 Za Zb ZZn Zr Zt Zv

he2adeci%al-escape-se6 ence1 Z# he2-di&it he2-di&itopt he2-di&itopt he2-di&itopt strin&-literal1 re& lar-strin&-literal ver-ati%-strin&-literal re& lar-strin&-literal1 " re& lar-strin&-literal-charactersopt " re& lar-strin&-literal-characters1 re& lar-strin&-literal-character re& lar-strin&-literal-characters re& lar-strin&-literal-character re& lar-strin&-literal-character1 sin&le-re& lar-strin&-literal-character si%ple-escape-se6 ence he2adeci%al-escape-se6 ence nicode-escape-se6 ence

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

#"1

Especificacin del lenguaje C#

sin&le-re& lar-strin&-literal-character1 C al6 ier car,cter e2cepto" 4;<33885, Z 4;<33KC5 # n new-line-character 4car,cter de n eva l*neaR ver-ati%-strin&-literal1 [" ver-ati% -strin&-literal-charactersopt " ver-ati%-strin&-literal-characters1 ver-ati%-strin&-literal-character ver-ati%-strin&-literal-characters ver-ati%-strin&-literal-character ver-ati%-strin&-literal-character1 sin&le-ver-ati%-strin&-literal-character 6 ote-escape-se6 ence sin&le-ver-ati%-strin&-literal-character1 C al6 ier car,cter e2cepto " 6 ote-escape-se6 ence1
""

n ll-literal1
null

<.1.. ,peradores y signos de puntuacin operator-or-p nct ator1 no de


{ < + =E F+ ! = D ++ H+ 4 > E @+ G+ 5 . 7 D+ DD ( B 77 E+ DD+ ) F // <+ +E . H << =+ G == >+ / @ FF .+ ; A HH B+

ri&ht-shift1 E=E ri&ht-shift-assi&n%ent1 E=E+ <.1.10 /irecti as de preprocesamiento pp-directive1 pp-declaration pp-conditional pp-line pp-dia&nostic pp-re&ion pp-pra&%a conditional-s#%-ol1 C al6 ier identificador o pala-ra clave 4identifier-or-3e#word5 e2cepto true o -alse pp-e2pression1 whitespaceopt pp-or-e2pression whitespaceopt pp-or-e2pression1 pp-and-e2pression pp-or-e2pression whitespaceopt HH whitespaceopt pp-and-e2pression

#"2

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

,pndice C /eferencias

pp-and-e2pression1 pp-e6 alit#-e2pression pp-and-e2pression whitespaceopt FF whitespaceopt pp-e6 alit#-e2pression pp-e6 alit#-e2pression1 pp- nar#-e2pression pp-e6 alit#-e2pression whitespaceopt ++ whitespaceopt pp- nar#-e2pression pp-e6 alit#-e2pression whitespaceopt @+ whitespaceopt pp- nar#-e2pression pp- nar#-e2pression1 pp-pri%ar#-e2pression @ whitespaceopt pp- nar#-e2pression pp-pri%ar#-e2pression1
true -alse

conditional-s#%-ol ( whitespaceopt pp-e2pression whitespaceopt ) pp-declaration1 whitespaceopt 0 whitespaceopt de-ine whitespace conditional-s#%-ol pp-new-line whitespaceopt 0 whitespaceopt unde- whitespace conditional-s#%-ol pp-new-line pp-new-line1 whitespaceopt sin&le-line-co%%entopt new-line pp-conditional1 pp-if-section pp-elif-sectionsopt pp-else-sectionopt pp-endif pp-if-section1 whitespaceopt 0 whitespaceopt i- whitespace pp-e2pression pp-new-line conditionalsectionopt pp-elif-sections1 pp-elif-section pp-elif-sections pp-elif-section pp-elif-section1 whitespaceopt 0 whitespaceopt eli- whitespace pp-e2pression pp-new-line conditionalsectionopt pp-else-section1 whitespaceopt 0 whitespaceopt else pp-new-line conditional-sectionopt pp-endif1 whitespaceopt 0 whitespaceopt endi- pp-new-line conditional-section1 inp t-section s3ipped-section s3ipped-section1 s3ipped-section-part s3ipped-section s3ipped-section-part s3ipped-section-part1 s3ipped-charactersopt new-line pp-directive

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

#"3

Especificacin del lenguaje C#

s3ipped-characters1 whitespaceopt not-n %-er-si&n inp t-charactersopt not-n %-er-si&n1 C al6 ier car,cter de entrada 4inp t-character5 e2cepto 0 pp-dia&nostic1 whitespaceopt 0 whitespaceopt error pp-%essa&e whitespaceopt 0 whitespaceopt ,arning pp-%essa&e pp-%essa&e1 new-line whitespace inp t-charactersopt new-line pp-re&ion1 pp-start-re&ion conditional-sectionopt pp-end-re&ion pp-start-re&ion1 whitespaceopt 0 whitespaceopt region pp-%essa&e pp-end-re&ion1 whitespaceopt 0 whitespaceopt endregion pp-%essa&e pp-line1 whitespaceopt 0 whitespaceopt line whitespace line-indicator pp-new-line line-indicator1 deci%al-di&its whitespace file-na%e deci%al-di&its
de-ault "idden

file-na%e1 " file-na%e-characters " file-na%e-characters1 file-na%e-character file-na%e-characters file-na%e-character file-na%e-character1 C al6 ier car,cter de entrada 4inp t-character5 e2cepto " pp-pra&%a1 whitespaceopt 0 whitespaceopt &ragma whitespace pra&%a--od# pp-new-line pra&%a--od#1 pra&%a-warnin&--od# pra&%a-warnin&--od#1 ,arning whitespace warnin&-action ,arning whitespace warnin&-action whitespace warnin&-list warnin&-action1
disable restore

warnin&-list1 deci%al-di&its warnin&-list whitespaceopt

whitespaceopt deci%al-di&its

#"#

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

,pndice C /eferencias

<.2 0ram)tica sint)ctica


<.2.1 %onceptos b)sicos na%espace-na%e1 na%espace-or-t#pe-na%e t#pe-na%e1 na%espace-or-t#pe-na%e na%espace-or-t#pe-na%e1 identifier t#pe-ar& %ent-listopt na%espace-or-t#pe-na%e . identifier t#pe-ar& %ent-listop 6 alified-alias-%e%-er <.2.2 Tipos t#pe1 val e-t#pe reference-t#pe t#pe-para%eter val e-t#pe1 str ct-t#pe en %-t#pe str ct-t#pe1 t#pe-na%e si%ple-t#pe n lla-le-t#pe si%ple-t#pe1 n %eric-t#pe
bool

n %eric-t#pe1 inte&ral-t#pe floatin&-point-t#pe


decimal

inte&ral-t#pe1
sbyte byte s"ort us"ort int uint long ulong c"ar

floatin&-point-t#pe1
-loat double

n lla-le-t#pe1 non-n lla-le-val e-t#pe 7

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

#"!

Especificacin del lenguaje C#

non-n lla-le-val e-t#pe1 t#pe en %-t#pe1 t#pe-na%e reference-t#pe1 class-t#pe interface-t#pe arra#-t#pe dele&ate-t#pe class-t#pe1 t#pe-na%e
object string

interface-t#pe1 t#pe-na%e arra#-t#pe1 non-arra#-t#pe ran3-specifiers non-arra#-t#pe1 t#pe ran3-specifiers1 ran3-specifier ran3-specifiers ran3-specifier ran3-specifier1 4 di%-separatorsopt 5 di%-separators1 di%-separators dele&ate-t#pe1 t#pe-na%e t#pe-ar& %ent-list1 D t#pe-ar& %ents E t#pe-ar& %ents1 t#pe-ar& %ent t#pe-ar& %ents t#pe-ar& %ent1 t#pe t#pe-para%eter1 identificador <.2.3 Variables varia-le-reference1 e2pression

t#pe-ar& %ent

#"6

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

,pndice C /eferencias

<.2.! E"presiones ar& %ent-list1 ar& %ent ar& %ent-list

ar& %ent

ar& %ent1 e2pression re- varia-le-reference out varia-le-reference pri%ar#-e2pression1 pri%ar#-no-arra#-creation-e2pression arra#-creation-e2pression pri%ar#-no-arra#-creation-e2pression1 literal si%ple-na%e parenthesi0ed-e2pression %e%-er-access invocation-e2pression ele%ent-access this-access -ase-access post-incre%ent-e2pression post-decre%ent-e2pression o->ect-creation-e2pression dele&ate-creation-e2pression anon#%o s-o->ect-creation-e2pression t#peof-e2pression chec3ed-e2pression nchec3ed-e2pression defa lt-val e-e2pression anon#%o s-%ethod-e2pression si%ple-na%e1 identifier t#pe-ar& %ent-listopt parenthesi0ed-e2pression1 ( e2pression ) %e%-er-access1 pri%ar#-e2pression . identifier t#pe-ar& %ent-listopt predefined-t#pe . identifier t#pe-ar& %ent-listopt 6 alified-alias-%e%-er . identificador predefined-t#pe1
bool object

no de
c"ar s"ort decimal string double uint -loat ulong int us"ort long

byte sbyte

invocation-e2pression1 pri%ar#-e2pression ( ar& %ent-listopt ) ele%ent-access1 pri%ar#-no-arra#-creation-e2pression 4 e2pression-list 5

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

#"(

Especificacin del lenguaje C#

e2pression-list1 e2pression e2pression-list this-access1


t"is

e2pression

-ase-access1
base . identificador base 4 e2pression-list 5

post-incre%ent-e2pression1 pri%ar#-e2pression << post-decre%ent-e2pression1 pri%ar#-e2pression == o->ect-creation-e2pression1 ne, t#pe ( ar& %ent-listopt ) o->ect-or-collection-initiali0eropt ne, t#pe o->ect-or-collection-initiali0er o->ect-or-collection-initiali0er1 o->ect-initiali0er collection-initiali0er o->ect-initiali0er1 { %e%-er-initiali0er-listopt ! { %e%-er-initiali0er-list ! %e%-er-initiali0er-list1 %e%-er-initiali0er %e%-er-initiali0er-list

%e%-er-initiali0er

%e%-er-initiali0er1 identifier @ initiali0er-val e initiali0er-val e1 e2pression o->ect-or-collection-initiali0er collection-initiali0er1 { ele%ent-initiali0er-list ! { ele%ent-initiali0er-list ! ele%ent-initiali0er-list1 ele%ent-initiali0er ele%ent-initiali0er-list ele%ent-initiali0er1 non-assi&n%ent-e2pression { e2pression-list ! arra#-creation-e2pression1 ne, non-arra#-t#pe 4 e2pression-list 5 ran3-specifiersopt arra#-initiali0eropt ne, arra#-t#pe arra#-initiali0er ne, ran3-specifier arra#-initiali0er dele&ate-creation-e2pression1 ne, dele&ate-t#pe ( e2pression )

ele%ent-initiali0er

#"$

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

,pndice C /eferencias

anon#%o s-o->ect-creation-e2pression1 ne, anon#%o s-o->ect-initiali0er anon#%o s-o->ect-initiali0er1 { %e%-er-declarator-listopt ! { %e%-er-declarator-list ! %e%-er-declarator-list1 %e%-er-declarator %e%-er-declarator-list %e%-er-declarator1 si%ple-na%e %e%-er-access identifier @ e2pression t#peof-e2pression1 ty&eo- ( t#pe ) ty&eo- ( n-o nd-t#pe-na%e )
ty&eo- ( void )

%e%-er-declarator

n-o nd-t#pe-na%e1 identifier &eneric-di%ension-specifieropt identifier // identifier &eneric-di%ension-specifieropt n-o nd-t#pe-na%e . identifier &eneric-di%ension-specifieropt &eneric-di%ension-specifier1 D co%%asopt E co%%as1 co%%as chec3ed-e2pression1 c"ec(ed ( e2pression ) nchec3ed-e2pression1 unc"ec(ed ( e2pression ) defa lt-val e-e2pression1 de-ault ( t#pe ) nar#-e2pression1 pri%ar#-e2pression < nar#-e2pression = nar#-e2pression @ nar#-e2pression A nar#-e2pression pre-incre%ent-e2pression pre-decre%ent-e2pression cast-e2pression pre-incre%ent-e2pression1 << nar#-e2pression pre-decre%ent-e2pression1 == nar#-e2pression

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

#""

Especificacin del lenguaje C#

cast-e2pression1 ( t#pe ) nar#-e2pression % ltiplicative-e2pression1 nar#-e2pression % ltiplicative-e2pression > % ltiplicative-e2pression . % ltiplicative-e2pression B

nar#-e2pression nar#-e2pression nar#-e2pression

additive-e2pression1 % ltiplicative-e2pression additive-e2pression < % ltiplicative-e2pression additive-e2pression C % ltiplicative-e2pression shift-e2pression1 additive-e2pression shift-e2pression DD additive-e2pression shift-e2pression ri&ht-shift additive-e2pression relational-e2pression1 shift-e2pression relational-e2pression relational-e2pression relational-e2pression relational-e2pression relational-e2pression relational-e2pression

D shift-e2pression E shift-e2pression D+ shift-e2pression E+ shift-e2pression is t#pe as t#pe

e6 alit#-e2pression1 relational-e2pression e6 alit#-e2pression ++ relational-e2pression e6 alit#-e2pression @+ relational-e2pression and-e2pression1 e6 alit#-e2pression and-e2pression F e6 alit#-e2pression e2cl sive-or-e2pression1 and-e2pression e2cl sive-or-e2pression G and-e2pression incl sive-or-e2pression1 e2cl sive-or-e2pression incl sive-or-e2pression H e2cl sive-or-e2pression conditional-and-e2pression1 incl sive-or-e2pression conditional-and-e2pression FF incl sive-or-e2pression conditional-or-e2pression1 conditional-and-e2pression conditional-or-e2pression HH conditional-and-e2pression n ll-coalescin&-e2pression1 conditional-or-e2pression conditional-or-e2pression 77 n ll-coalescin&-e2pression

!''

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

,pndice C /eferencias

conditional-e2pression1 n ll-coalescin&-e2pression n ll-coalescin&-e2pression 7 e2pression / e2pression la%-da-e2pression1 anon#%o s-f nction-si&nat re +E anon#%o s-f nction--od# anon#%o s-%ethod-e2pression1 delegate e2plicit-anon#%o s-f nction-si&nat reopt -loc3 anon#%o s-f nction-si&nat re1 e2plicit-anon#%o s-f nction-si&nat re i%plicit-anon#%o s-f nction-si&nat re e2plicit-anon#%o s-f nction-si&nat re1 ( e2plicit-anon#%o s-f nction-para%eter-listopt ) e2plicit-anon#%o s-f nction-para%eter-list e2plicit-anon#%o s-f nction-para%eter e2plicit-anon#%o s-f nction-para%eter-list

e2plicit-anon#%o s-f nction-para%eter

e2plicit-anon#%o s-f nction-para%eter1 anon#%o s-f nction-para%eter-%odifieropt t#pe identifier anon#%o s-f nction-para%eter-%odifier1
reout

i%plicit-anon#%o s-f nction-si&nat re1 ( i%plicit-anon#%o s-f nction-para%eter-listopt ) i%plicit-anon#%o s-f nction-para%eter i%plicit-anon#%o s-f nction-para%eter-list i%plicit-anon#%o s-f nction-para%eter i%plicit-anon#%o s-f nction-para%eter-list i%plicit-anon#%o s-f nction-para%eter1 identificador anon#%o s-f nction--od#1 e2pression -loc3 6 er#-e2pression1 fro%-cla se 6 er#--od# fro%-cla se1 -rom t#peopt identifier in e2pression 6 er#--od#1 6 er#--od#-cla sesopt select-or-&ro p-cla se 6 er#-contin ationopt 6 er#--od#-cla ses1 6 er#--od#-cla se 6 er#--od#-cla ses 6 er#--od#-cla se

i%plicit-anon#%o s-f nction-para%eter

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

!'1

Especificacin del lenguaje C#

6 er#--od#-cla se1 fro%-cla se let-cla se where-cla se >oin-cla se >oin-into-cla se order-#-cla se let-cla se1 let identifier + e2pression where-cla se1 ,"ere -oolean-e2pression >oin-cla se1 join t#peopt identifier in e2pression on e2pression eQuals e2pression >oin-into-cla se1 join t#peopt identifier in e2pression on e2pression eQuals e2pression into identifier order-#-cla se1 orderby orderin&s orderin&s1 orderin& orderin&s orderin&1 e2pression

orderin& orderin&-directionopt

orderin&-direction1
ascending descending

select-or-&ro p-cla se1 select-cla se &ro p-cla se select-cla se1


select e2pression

&ro p-cla se1 grou& e2pression by e2pression 6 er#-contin ation1 into identifier 6 er#--od# assi&n%ent1 nar#-e2pression assi&n%ent-operator e2pression

!'2

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

,pndice C /eferencias

assi&n%ent-operator1
+ <+ =+ >+ .+ B+ F+ H+ G+ DD+

ri&ht-shift-assi&n%ent e2pression1 non-assi&n%ent-e2pression assi&n%ent non-assi&n%ent-e2pression1 conditional-e2pression la%-da-e2pression 6 er#-e2pression constant-e2pression1 e2pression -oolean-e2pression1 e2pression <.2.# Instrucciones state%ent1 la-eled-state%ent declaration-state%ent e%-edded-state%ent e%-edded-state%ent1 -loc3 e%pt#-state%ent e2pression-state%ent selection-state%ent iteration-state%ent > %p-state%ent tr#-state%ent chec3ed-state%ent nchec3ed-state%ent loc3-state%ent sin&-state%ent #ield-state%ent -loc31
{ state%ent-listopt !

state%ent-list1 state%ent state%ent-list state%ent

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

!'3

Especificacin del lenguaje C#

e%pt#-state%ent1
;

la-eled-state%ent1 identifier / state%ent declaration-state%ent1 local-varia-le-declaration ; local-constant-declaration ; local-varia-le-declaration1 local-varia-le-t#pe local-varia-le-declarators local-varia-le-t#pe1 t#pe
var

local-varia-le-declarators1 local-varia-le-declarator local-varia-le-declarators

local-varia-le-declarator

local-varia-le-declarator1 identificador identifier @ local-varia-le-initiali0er local-varia-le-initiali0er1 e2pression arra#-initiali0er local-constant-declaration1 const t#pe constant-declarators constant-declarators1 constant-declarator constant-declarators

constant-declarator

constant-declarator1 identifier @ constant-e2pression e2pression-state%ent1 state%ent-e2pression ; state%ent-e2pression1 invocation-e2pression o->ect-creation-e2pression assi&n%ent post-incre%ent-e2pression post-decre%ent-e2pression pre-incre%ent-e2pression pre-decre%ent-e2pression selection-state%ent1 if-state%ent switch-state%ent if-state%ent1 i- ( -oolean-e2pression ) e%-edded-state%ent i- ( -oolean-e2pression ) e%-edded-state%ent else e%-edded-state%ent

!'#

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

,pndice C /eferencias

switch-state%ent1 s,itc" ( e2pression ) switch--loc3 switch--loc31 { switch-sectionsopt ! switch-sections1 switch-section switch-sections switch-section switch-section1 switch-la-els state%ent-list switch-la-els1 switch-la-el switch-la-els switch-la-el switch-la-el1 case constant-e2pression /
de-ault /

iteration-state%ent1 while-state%ent do-state%ent for-state%ent foreach-state%ent while-state%ent1 ,"ile ( -oolean-e2pression ) e%-edded-state%ent do-state%ent1 do e%-edded-state%ent ,"ile ( -oolean-e2pression ) ; for-state%ent1 -or ( for-initiali0eropt ; for-conditionopt ; for-iteratoropt ) e%-edded-state%ent for-initiali0er1 local-varia-le-declaration state%ent-e2pression-list for-condition1 -oolean-e2pression for-iterator1 state%ent-e2pression-list state%ent-e2pression-list1 state%ent-e2pression state%ent-e2pression-list

state%ent-e2pression

foreach-state%ent1 -oreac" ( local-varia-le-t#pe identifier in e2pression ) e%-edded-state%ent > %p-state%ent1 -rea3-state%ent contin e-state%ent &oto-state%ent ret rn-state%ent throw-state%ent

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

!'!

Especificacin del lenguaje C#

-rea3-state%ent1
brea( ;

contin e-state%ent1
continue ;

&oto-state%ent1 goto identifier ; goto case constant-e2pression C


goto de-ault ;

ret rn-state%ent1 return e2pressionopt ; throw-state%ent1 t"ro, e2pressionopt ; tr#-state%ent1 try -loc3 catch-cla ses try -loc3 finall#-cla se try -loc3 catch-cla ses finall#-cla se catch-cla ses1 specific-catch-cla ses &eneral-catch-cla seopt specific-catch-cla sesopt &eneral-catch-cla se specific-catch-cla ses1 specific-catch-cla se specific-catch-cla ses specific-catch-cla se specific-catch-cla se1 catc" ( class-t#pe identifieropt ) -loc3 &eneral-catch-cla se1 catc" -loc3 finall#-cla se1
-inally -loc3

chec3ed-state%ent1 c"ec(ed -loc3 nchec3ed-state%ent1 unc"ec(ed -loc3 loc3-state%ent1 loc( ( e2pression ) e%-edded-state%ent sin&-state%ent1
using (

reso rce-ac6 isition ) e%-edded-state%ent

reso rce-ac6 isition1 local-varia-le-declaration e2pression #ield-state%ent1


yield return e2pression ; yield brea( ;

!'6

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

,pndice C /eferencias

<.2.$ Espacio de nombres co%pilation- nit1 e2tern-alias-directivesopt sin&-directivesopt &lo-al-attri- tesopt na%espace-%e%-er-declarationsopt na%espace-declaration1 names&ace 6 alified-identifier na%espace--od# ;opt 6 alified-identifier1 identificador 6 alified-identifier . identificador na%espace--od#1 { e2tern-alias-directivesopt sin&-directivesopt na%espace-%e%-er-declarationsopt !

e2tern-alias-directives1 e2tern-alias-directive e2tern-alias-directives e2tern-alias-directive e2tern-alias-directive1


e#tern alias identifier ;

sin&-directives1 sin&-directive sin&-directives

sin&-directive

sin&-directive1 sin&-alias-directive sin&-na%espace-directive sin&-alias-directive1 using identifier + na%espace-or-t#pe-na%e ; sin&-na%espace-directive1 using na%espace-na%e ; na%espace-%e%-er-declarations1 na%espace-%e%-er-declaration na%espace-%e%-er-declarations na%espace-%e%-er-declaration na%espace-%e%-er-declaration1 na%espace-declaration t#pe-declaration t#pe-declaration1 class-declaration str ct-declaration interface-declaration en %-declaration dele&ate-declaration 6 alified-alias-%e%-er1 identifier // identifier t#pe-ar& %ent-listopt

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

!'(

Especificacin del lenguaje C#

<.2.+ %lases class-declaration1 attri- tesopt class-%odifiersopt &artialopt class identifier t#pe-para%eter-listopt class--aseopt t#pe-para%eter-constraints-cla sesopt class--od# ;opt class-%odifiers1 class-%odifier class-%odifiers class-%odifier class-%odifier1
ne, &ublic &rotected internal &rivate abstract sealed static

t#pe-para%eter-list1 D t#pe-para%eters E t#pe-para%eters1 attri- tesopt t#pe-para%eter t#pe-para%eters attri- tesopt t#pe-para%eter t#pe-para%eter1 identificador class--ase1 / class-t#pe / interface-t#pe-list / class-t#pe interface-t#pe-list interface-t#pe-list1 interface-t#pe interface-t#pe-list

interface-t#pe

t#pe-para%eter-constraints-cla ses1 t#pe-para%eter-constraints-cla se t#pe-para%eter-constraints-cla ses t#pe-para%eter-constraints-cla se t#pe-para%eter-constraints-cla se1 ,"ere t#pe-para%eter / t#pe-para%eter-constraints t#pe-para%eter-constraints1 pri%ar#-constraint secondar#-constraints constr ctor-constraint pri%ar#-constraint secondar#-constraints pri%ar#-constraint constr ctor-constraint secondar#-constraints constr ctor-constraint pri%ar#-constraint secondar#-constraints constr ctor-constraint

!'$

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

,pndice C /eferencias

pri%ar#-constraint1 class-t#pe
class struct

secondar#-constraints1 interface-t#pe t#pe-para%eter secondar#-constraints secondar#-constraints constr ctor-constraint1


ne, ( )

interface-t#pe t#pe-para%eter

class--od#1 { class-%e%-er-declarationsopt ! class-%e%-er-declarations1 class-%e%-er-declaration class-%e%-er-declarations class-%e%-er-declaration class-%e%-er-declaration1 constant-declaration field-declaration %ethod-declaration propert#-declaration event-declaration inde2er-declaration operator-declaration constr ctor-declaration destr ctor-declaration static-constr ctor-declaration t#pe-declaration constant-declaration1 attri- tesopt constant-%odifiersopt const t#pe constant-declarators ; constant-%odifiers1 constant-%odifier constant-%odifiers constant-%odifier constant-%odifier1
ne, &ublic &rotected internal &rivate

constant-declarators1 constant-declarator constant-declarators

constant-declarator

constant-declarator1 identifier @ constant-e2pression field-declaration1 attri- tesopt field-%odifiersopt t#pe varia-le-declarators ;

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

!'"

Especificacin del lenguaje C#

field-%odifiers1 field-%odifier field-%odifiers field-%odifier field-%odifier1


ne, &ublic &rotected internal &rivate static readonly volatile

varia-le-declarators1 varia-le-declarator varia-le-declarators

varia-le-declarator

varia-le-declarator1 identificador identifier @ varia-le-initiali0er varia-le-initiali0er1 e2pression arra#-initiali0er %ethod-declaration1 %ethod-header %ethod--od# %ethod-header1 attri- tesopt %ethod-%odifiersopt &artialopt ret rn-t#pe %e%-er-na%e t#pe-para%eter-listopt ( for%al-para%eter-listopt ) t#pe-para%eter-constraints-cla sesopt %ethod-%odifiers1 %ethod-%odifier %ethod-%odifiers %ethod-%odifier %ethod-%odifier1
ne, &ublic &rotected internal &rivate static virtual sealed override abstract e#tern

ret rn-t#pe1 t#pe


void

%e%-er-na%e1 identificador interface-t#pe . identificador


!1'
Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

,pndice C /eferencias

%ethod--od#1 -loc3
;

for%al-para%eter-list1 fi2ed-para%eters fi2ed-para%eters para%eter-arra# fi2ed-para%eters1 fi2ed-para%eter fi2ed-para%eters

para%eter-arra#

fi2ed-para%eter

fi2ed-para%eter1 attri- tesopt para%eter-%odifieropt t#pe identifier para%eter-%odifier1


reout t"is

para%eter-arra#1 attri- tesopt &arams arra#-t#pe identifier propert#-declaration1 attri- tesopt propert#-%odifiersopt t#pe %e%-er-na%e { accessor-declarations ! propert#-%odifiers1 propert#-%odifier propert#-%odifiers propert#-%odifier propert#-%odifier1
ne, &ublic &rotected internal &rivate static virtual sealed override abstract e#tern

%e%-er-na%e1 identificador interface-t#pe . identificador accessor-declarations1 &et-accessor-declaration set-accessor-declarationopt set-accessor-declaration &et-accessor-declarationopt &et-accessor-declaration1 attri- tesopt accessor-%odifieropt get accessor--od# set-accessor-declaration1 attri- tesopt accessor-%odifieropt set accessor--od#

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

!11

Especificacin del lenguaje C#

accessor-%odifier1
&rotected internal &rivate &rotected internal internal &rotected

accessor--od#1 -loc3
;

event-declaration1 attri- tesopt event-%odifiersopt event t#pe varia-le-declarators ; attri- tesopt event-%odifiersopt event t#pe %e%-er-na%e { event-accessor-declarations ! event-%odifiers1 event-%odifier event-%odifiers event-%odifier event-%odifier1
ne, &ublic &rotected internal &rivate static virtual sealed override abstract e#tern

event-accessor-declarations1 add-accessor-declaration re%ove-accessor-declaration re%ove-accessor-declaration add-accessor-declaration add-accessor-declaration1 attri- tesopt add -loc3 re%ove-accessor-declaration1 attri- tesopt remove -loc3 inde2er-declaration1 attri- tesopt inde2er-%odifiersopt inde2er-declarator { accessor-declarations ! inde2er-%odifiers1 inde2er-%odifier inde2er-%odifiers inde2er-%odifier

!12

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

,pndice C /eferencias

inde2er-%odifier1
ne, &ublic &rotected internal &rivate virtual sealed override abstract e#tern

inde2er-declarator1 t#pe t"is 4 for%al-para%eter-list 5 t#pe interface-t#pe . t"is 4 for%al-para%eter-list 5 operator-declaration1 attri- tesopt operator-%odifiers operator-declarator operator--od# operator-%odifiers1 operator-%odifier operator-%odifiers operator-%odifier operator-%odifier1
&ublic static e#tern

operator-declarator1 nar#-operator-declarator -inar#-operator-declarator conversion-operator-declarator nar#-operator-declarator1 t#pe o&erator overloada-le- nar#-operator ( t#pe identifier ) overloada-le- nar#-operator1 no de
< = @ A << == true -alse

-inar#-operator-declarator1 t#pe o&erator overloada-le--inar#-operator ( t#pe identifier

t#pe identifier )

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

!13

Especificacin del lenguaje C#

overloada-le--inar#-operator1
< = > . B F H G DD

ri&ht-shift
++ @+ E D E+ D+

conversion-operator-declarator1 im&licit o&erator t#pe ( t#pe identifier ) e#&licit o&erator t#pe ( t#pe identifier ) operator--od#1 -loc3
;

constr ctor-declaration1 attri- tesopt constr ctor-%odifiersopt constr ctor-declarator constr ctor--od# constr ctor-%odifiers1 constr ctor-%odifier constr ctor-%odifiers constr ctor-%odifier constr ctor-%odifier1
&ublic &rotected internal &rivate e#tern

constr ctor-declarator1 identifier ( for%al-para%eter-listopt ) constr ctor-initiali0eropt constr ctor-initiali0er1 / base ( ar& %ent-listopt ) / t"is ( ar& %ent-listopt ) constr ctor--od#1 -loc3
;

static-constr ctor-declaration1 attri- tesopt static-constr ctor-%odifiers identifier ( ) static-constr ctor--od# static-constr ctor-%odifiers1
e#ternopt static static e#ternopt
!1#
Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

,pndice C /eferencias

static-constr ctor--od#1 -loc3


;

destr ctor-declaration1 attri- tesopt e#ternopt A identifier ( ) destr ctor--od# destr ctor--od#1 -loc3
;

<.2.- Estructuras str ct-declaration1 attri- tesopt str ct-%odifiersopt &artialopt struct identifier t#pe-para%eter-listopt str ct-interfacesopt t#pe-para%eter-constraints-cla sesopt str ct--od# ;opt str ct-%odifiers1 str ct-%odifier str ct-%odifiers str ct-%odifier str ct-%odifier1
ne, &ublic &rotected internal &rivate

str ct-interfaces1 / interface-t#pe-list str ct--od#1 { str ct-%e%-er-declarationsopt ! str ct-%e%-er-declarations1 str ct-%e%-er-declaration str ct-%e%-er-declarations str ct-%e%-er-declaration str ct-%e%-er-declaration1 constant-declaration field-declaration %ethod-declaration propert#-declaration event-declaration inde2er-declaration operator-declaration constr ctor-declaration static-constr ctor-declaration t#pe-declaration <.2.. &atrices arra#-t#pe1 non-arra#-t#pe ran3-specifiers non-arra#-t#pe1 t#pe

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

!1!

Especificacin del lenguaje C#

ran3-specifiers1 ran3-specifier ran3-specifiers ran3-specifier ran3-specifier1 4 di%-separatorsopt 5 di%-separators1 di%-separators arra#-initiali0er1 { varia-le-initiali0er-listopt ! { varia-le-initiali0er-list ! varia-le-initiali0er-list1 varia-le-initiali0er varia-le-initiali0er-list varia-le-initiali0er1 e2pression arra#-initiali0er <.2.10 Interfaces interface-declaration1 attri- tesopt interface-%odifiersopt &artialopt inter-ace identifier t#pe-para%eter-listopt interface--aseopt t#pe-para%eter-constraints-cla sesopt interface--od# ;opt interface-%odifiers1 interface-%odifier interface-%odifiers interface-%odifier interface-%odifier1
ne, &ublic &rotected internal &rivate

varia-le-initiali0er

interface--ase1 / interface-t#pe-list interface--od#1 { interface-%e%-er-declarationsopt ! interface-%e%-er-declarations1 interface-%e%-er-declaration interface-%e%-er-declarations interface-%e%-er-declaration interface-%e%-er-declaration1 interface-%ethod-declaration interface-propert#-declaration interface-event-declaration interface-inde2er-declaration

!16

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

,pndice C /eferencias

interface-%ethod-declaration1 attri- tesopt ne,opt ret rn-t#pe identifier t#pe-para%eter-list ( for%al-para%eter-listopt ) t#pe-para%eter-constraints-cla sesopt ; interface-propert#-declaration1 attri- tesopt ne,opt t#pe identifier { interface-accessors ! interface-accessors1 attri- tesopt get attri- tesopt set attri- tesopt get attri- tesopt set
; ; ; attri- tesopt set ; ; attri- tesopt get ;

interface-event-declaration1 attri- tesopt ne,opt event t#pe identifier ; interface-inde2er-declaration1 attri- tesopt ne,opt t#pe t"is 4 for%al-para%eter-list 5 { interface-accessors ! <.2.11 Enumeraciones en %-declaration1 attri- tesopt en %-%odifiersopt enum identifier en %--aseopt en %--od# ;opt en %--ase1 / inte&ral-t#pe en %--od#1 { en %-%e%-er-declarationsopt ! { en %-%e%-er-declarations ! en %-%odifiers1 en %-%odifier en %-%odifiers en %-%odifier en %-%odifier1
ne, &ublic &rotected internal &rivate

en %-%e%-er-declarations1 en %-%e%-er-declaration en %-%e%-er-declarations

en %-%e%-er-declaration

en %-%e%-er-declaration1 attri- tesopt identifier attri- tesopt identifier + constant-e2pression <.2.12 /elegados dele&ate-declaration1 attri- tesopt dele&ate-%odifiersopt delegate ret rn-t#pe identifier t#pe-para%eter-listopt ( for%al-para%eter-listopt ) t#pe-para%eter-constraints-cla sesopt ;

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

!1(

Especificacin del lenguaje C#

dele&ate-%odifiers1 dele&ate-%odifier dele&ate-%odifiers dele&ate-%odifier dele&ate-%odifier1


ne, &ublic &rotected internal &rivate

<.2.13 'tributos &lo-al-attri- tes1 &lo-al-attri- te-sections &lo-al-attri- te-sections1 &lo-al-attri- te-section &lo-al-attri- te-sections &lo-al-attri- te-section &lo-al-attri- te-section1 4 &lo-al-attri- te-tar&et-specifier attri- te-list 5 4 &lo-al-attri- te-tar&et-specifier attri- te-list 5 &lo-al-attri- te-tar&et-specifier1 &lo-al-attri- te-tar&et / &lo-al-attri- te-tar&et1
assembly module

attri- tes1 attri- te-sections attri- te-sections1 attri- te-section attri- te-sections attri- te-section attri- te-section1 4 attri- te-tar&et-specifieropt attri- te-list 5 4 attri- te-tar&et-specifieropt attri- te-list 5 attri- te-tar&et-specifier1 attri- te-tar&et / attri- te-tar&et1
-ield event met"od &aram &ro&erty return ty&e

attri- te-list1 atri- to attri- te-list

attri- te

!1$

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

,pndice C /eferencias

attri- te1 attri- te-na%e attri- te-ar& %entsopt attri- te-na%e1 t#pe-na%e attri- te-ar& %ents1 ( positional-ar& %ent-listopt ) ( positional-ar& %ent-list na%ed-ar& %ent-list ) ( na%ed-ar& %ent-list ) positional-ar& %ent-list1 positional-ar& %ent positional-ar& %ent-list

positional-ar& %ent

positional-ar& %ent1 attri- te-ar& %ent-e2pression na%ed-ar& %ent-list1 na%ed-ar& %ent na%ed-ar& %ent-list

na%ed-ar& %ent

na%ed-ar& %ent1 identifier + attri- te-ar& %ent-e2pression attri- te-ar& %ent-e2pression1 e2pression

<.3 E"tensiones de la gram)tica para el cdigo no seguro


class-%odifier1 ...
unsa-e

str ct-%odifier1 ...


unsa-e

interface-%odifier1 ...
unsa-e

dele&ate-%odifier1 ...
unsa-e

field-%odifier1 ...
unsa-e

%ethod-%odifier1 ...
unsa-e

propert#-%odifier1 ...
unsa-e

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

!1"

Especificacin del lenguaje C#

event-%odifier1 ...
unsa-e

inde2er-%odifier1 ...
unsa-e

operator-%odifier1 ...
unsa-e

constr ctor-%odifier1 ...


unsa-e

destr ctor-declaration1 attri- tesopt e#ternopt unsa-eopt A identifier ( ) destr ctor--od# attri- tesopt unsa-eopt e#ternopt A identifier ( ) destr ctor--od# static-constr ctor-%odifiers1
e#ternopt unsa-eopt static unsa-eopt e#ternopt static e#ternopt static unsa-eopt unsa-eopt static e#ternopt static e#ternopt unsa-eopt static unsa-eopt e#ternopt

e%-edded-state%ent1 ... nsafe-state%ent nsafe-state%ent1 unsa-e -loc3 t#pe1 ... pointer-t#pe pointer-t#pe1 n%ana&ed-t#pe >
void >

n%ana&ed-t#pe1 t#pe pri%ar#-no-arra#-creation-e2pression1 ... pointer-%e%-er-access pointer-ele%ent-access si0eof-e2pression nar#-e2pression1 ... pointer-indirection-e2pression addressof-e2pression

!2'

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

,pndice C /eferencias

pointer-indirection-e2pression1 > nar#-e2pression pointer-%e%-er-access1 pri%ar#-e2pression =E identifier pointer-ele%ent-access1 pri%ar#-no-arra#-creation-e2pression 4 e2pression 5 addressof-e2pression1 F nar#-e2pression si0eof-e2pression1
si?eo- (

n%ana&ed-t#pe )

e%-edded-state%ent1 ... fi2ed-state%ent fi2ed-state%ent1 -i#ed ( pointer-t#pe fi2ed-pointer-declarators ) e%-edded-state%ent fi2ed-pointer-declarators1 fi2ed-pointer-declarator fi2ed-pointer-declarators

fi2ed-pointer-declarator

fi2ed-pointer-declarator1 identifier + fi2ed-pointer-initiali0er fi2ed-pointer-initiali0er1 F varia-le-reference e2pression str ct-%e%-er-declaration1 A fi2ed-si0e-- ffer-declaration fi2ed-si0e-- ffer-declaration1 attri- tesopt fi2ed-si0e-- ffer-%odifiersopt -i#ed - ffer-ele%ent-t#pe fi2ed-si0e-- ffer-declarators ; fi2ed-si0e-- ffer-%odifiers1 fi2ed-si0e-- ffer-%odifier fi2ed-si0e-- ffer-%odifier fi2ed-si0e-- ffer-%odifiers fi2ed-si0e-- ffer-%odifier1
ne, &ublic &rotected internal &rivate unsa-e

- ffer-ele%ent-t#pe1 t#pe fi2ed-si0e-- ffer-declarators1 fi2ed-si0e-- ffer-declarator fi2ed-si0e-- ffer-declarator fi2ed-si0e-- ffer-declarators

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

!21

Especificacin del lenguaje C#

fi2ed-si0e-- ffer-declarator1 identifier 4 const-e2pression 5 local-varia-le-initiali0er1 A stac3alloc-initiali0er stac3alloc-initiali0er1 stac(alloc n%ana&ed-t#pe 4 e2pression 5

!22

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

,pndice C /eferencias

%. 9eferencias
7nicode Consortium. Bhe (nicode :tandard, Version ;.0 OEl Est(ndar 7nicode, >ersi-n 3."R. &ddisonB@esley, ;eading, %assac=usetts OEE.77.R, 2""", !.A4 "B2"1B#1#33 B . !EEE. D''' :tandard for !inar# <loatin&-9oint Erith%etic OEst(ndar !EEE para &ritm)tica Ainaria de 'unto :lotanteR. &4.!T!EEE .tandard * 4B1+8 . 2isponible en =ttpGTT999.ieee.org. !./T!EC. C$$. &4.!T!./T!EC 14882G1++8.

Copyright Microsoft Corporation 1999-2008. Reservados todos los derechos.

!23

También podría gustarte