C Language Specification 1.2

  • Published on
    12-Jun-2015

  • View
    183

  • Download
    6

Transcript

1 2 3 4 5 6

7

# CEspecificacin del lenguajeVersin 1.2

8 9

1

2

Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos. Enve sus correcciones u otros comentarios a sharp@microsoft.com

1 Aviso 2 1999-2003 Microsoft Corporation. Reservados todos los derechos. 3 Microsoft, Windows, Visual Basic, Visual C# y Visual C++ son marcas registradas o marcas comerciales de Microsoft 4 Corporation en los EE.UU. y/o en otros pases o regiones. 5 Los dems productos y nombres de compaas mencionados en esta publicacin pueden ser marcas comerciales de sus 6 respectivos propietarios.

3

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

4

Tabla de contenido

1Tabla de contenido 21. Introduccin.............................................................................................................................. ......................1 3 1.1 Hola a todos............................................................................................................................... .................2 4 1.2 Estructura del programa................................................................................................................ ..............2 5 1.3 Tipos y variables........................................................................................................................ .................4 6 1.4 Expresiones.......................................................................................................................................... .......8 7 1.5 Instrucciones............................................................................................................................. ................10 8 1.6 Clases y objetos............................................................................................................. ...........................13 9 1.6.1 Miembros.............................................................................................................................. .............14 10 1.6.2 Accesibilidad................................................................................................................................ ......15 11 1.6.3 Clases base.............................................................................................................................. ...........15 12 1.6.4 Campos......................................................................................................................... .....................15 13 1.6.5 Mtodos..................................................................................................................... ........................16 14 1.6.5.1 Parmetros................................................................................................................................. ...16 15 1.6.5.2 Cuerpo del mtodo y variables locales...................................................................... ...................18 16 1.6.5.3 Mtodos estticos y de instancia........................................................................ ..........................18 17 1.6.5.4 Mtodos virtuales, de reemplazo y abstractos...................................................... ........................19 18 1.6.5.5 Sobrecarga de mtodos........................................................................................................... ......22 19 1.6.6 Otros miembros de funcin.................................................................................................. ..............22 20 1.6.6.1 Constructores.................................................................................................... ...........................24 21 1.6.6.2 Propiedades.................................................................................................................. ................25 22 1.6.6.3 Indizadores...................................................................................................................... .............25 23 1.6.6.4 Eventos..................................................................................................................................... ....26 24 1.6.6.5 Operadores................................................................................................................ ...................27 25 1.6.6.6 Destructores....................................................................................................... ..........................28 26 1.7 Estructuras......................................................................................................................... .......................28 27 1.8 Matrices............................................................................................................................... .....................29 28 1.9 Interfaces................................................................................................................................................... 30 29 1.10 Enumeraciones............................................................................................................................... .........33 30 1.11 Delegados............................................................................................................................................. ...34 31 1.12 Atributos....................................................................................................................... ..........................36 322. Estructura lxica........................................................................................................................ ...................38 33 2.1 Programas............................................................................................................................. ....................38 34 2.2 Gramticas............................................................................................................................... .................38 35 2.2.1 Notacin gramatical......................................................................................................... ..................38 36 2.2.2 Gramtica lxica....................................................................................................... .........................39 37 2.2.3 Gramtica sintctica............................................................................................................... ............39 38 2.3 Anlisis lxico.................................................................................................................................... .......40 39 2.3.1 Terminadores de lnea................................................................................................. .......................40 40 2.3.2 Comentarios........................................................................................................................ ...............41 41 2.3.3 Espacio en blanco.............................................................................................................................. .42 42 2.4 Smbolos................................................................................................................................ ...................42 43 2.4.1 Secuencias de escape de caracteres Unicode............................................................................ ..........43 44 2.4.2 Identifiers.............................................................................................................................. .............43 45 2.4.3 Palabras clave.................................................................................................................................... .45 46 2.4.4 Literales..................................................................................................................... ........................46 47 2.4.4.1 Literales booleanos................................................................................................................... ....46 48 2.4.4.2 Literales enteros....................................................................................................... ....................46 49 2.4.4.3 Literales reales.................................................................................................... .........................475Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

iii

6Especificacin del lenguaje C#

1 2.4.4.4 Literales de carcter........................................................................................... ..........................48 2 2.4.4.5 Literales de cadena.......................................................................................................... .............49 3 2.4.4.6 El literal null............................................................................................................................... ..51 4 2.4.5 Operadores y signos de puntuacin......................................................................................... ...........51 5 2.5 Directivas de preprocesamiento........................................................................................... .....................51 6 2.5.1 Smbolos de compilacin condicional...................................................................................... ..........53 7 2.5.2 Expresiones de preprocesamiento............................................................................... .......................53 8 2.5.3 Directivas de declaracin................................................................................................ ...................54 9 2.5.4 Directivas de compilacin condicional............................................................................................. ..56 10 2.5.5 Directivas de diagnstico................................................................................................ ...................58 11 2.5.6 Directivas de regin...................................................................................................... .....................59 12 2.5.7 Directivas de lnea.......................................................................................................................... ....59 133. Conceptos bsicos...................................................................................................................................... ....61 14 3.1 Inicio de la aplicacin........................................................................................................... ....................61 15 3.2 Finalizacin de la aplicacin........................................................................................................ .............62 16 3.3 Declaraciones..................................................................................................................................... .......62 17 3.4 Miembros........................................................................................................................................ ..........65 18 3.4.1 Miembros de espacio de nombres............................................................................... .......................65 19 3.4.2 Miembros de estructura.............................................................................................................. ........65 20 3.4.3 Miembros de enumeraciones........................................................................................................ ......66 21 3.4.4 Miembros de clase................................................................................................... ..........................66 22 3.4.5 Miembros de interfaz................................................................................................... ......................66 23 3.4.6 Miembros de matriz...................................................................................................... .....................66 24 3.4.7 Miembros de delegados.................................................................................................................... ..66 25 3.5 Acceso a miembros.............................................................................................................. .....................66 26 3.5.1 Accesibilidad declarada................................................................................................................. .....67 27 3.5.2 Dominios de accesibilidad....................................................................................... ..........................67 28 3.5.3 Acceso protegido para miembros de instancia................................................................................ ....71 29 3.5.4 Restricciones de accesibilidad..................................................................................................... .......72 30 3.6 Firmas y sobrecargas............................................................................................................................ .....73 31 3.7 mbitos......................................................................................................................... ...........................74 32 3.7.1 Ocultar nombres........................................................................................................................ .........76 33 3.7.1.1 Ocultar mediante anidacin................................................................................................ ..........77 34 3.7.1.2 Ocultar mediante herencia.................................................................................................. ..........78 35 3.8 Espacios de nombres y nombres de tipos.................................................................................. ................80 36 3.8.1 Nombres completos.......................................................................................................................... ..81 37 3.9 Administracin automtica de la memoria............................................................................... .................82 38 3.10 Orden de ejecucin..................................................................................................... ............................85 394. Tipos..................................................................................................................................................... ..........86 40 4.1 Tipos de valor........................................................................................................................................... .86 41 4.1.1 Tipo System.ValueType................................................................................................................... ...87 42 4.1.2 Constructores predeterminados......................................................................................... .................87 43 4.1.3 Tipos de estructura......................................................................................................... ....................88 44 4.1.4 Tipos simples............................................................................................................ .........................88 45 4.1.5 Tipos integrales................................................................................................................. .................89 46 4.1.6 Tipos de punto flotante................................................................................................................ .......90 47 4.1.7 Tipo decimal.......................................................................................................... ............................91 48 4.1.8 Tipo bool................................................................................................................................ ............92 49 4.1.9 Tipos de enumeracin.............................................................................................. ..........................92

7iv

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

8

Tabla de contenido

1 4.2 Tipos de referencia......................................................................................................................... ...........92 2 4.2.1 Tipos de clase........................................................................................................................... ..........93 3 4.2.2 Tipo object.................................................................................................................. .......................93 4 4.2.3 Tipo string............................................................................................................................. .............94 5 4.2.4 Tipos de interfaz........................................................................................................................... ......94 6 4.2.5 Tipos de matriz.............................................................................................................................. .....94 7 4.2.6 Tipos de delegados............................................................................................................... ..............94 8 4.3 Boxing y Unboxing........................................................................................................................... ........94 9 4.3.1 Conversiones boxing................................................................................................................. .........94 10 4.3.2 Conversiones Unboxing...................................................................................................... ...............96 115. Variables................................................................................................................................ ........................97 12 5.1 Categoras de variables..................................................................................................... ........................97 13 5.1.1 Variables estticas........................................................................................................ ......................97 14 5.1.2 Variables de instancia............................................................................................................. ............97 15 5.1.2.1 Variables de instancia en clases..................................................................................... ...............98 16 5.1.2.2 Variables de instancia en estructuras................................................................... .........................98 17 5.1.3 Elementos matriciales................................................................................................. .......................98 18 5.1.4 Parmetros de valor....................................................................................................................... .....98 19 5.1.5 Parmetros de referencia.................................................................................................... ................98 20 5.1.6 Parmetros de salida........................................................................................................................ ...99 21 5.1.7 Variables locales............................................................................................................................ .....99 22 5.2 Valores predeterminados...................................................................................................... ...................100 23 5.3 Estado de asignacin definitiva...................................................................................................... .........100 24 5.3.1 Variables asignadas inicialmente.......................................................................................... ............101 25 5.3.2 Variables no asignadas inicialmente.................................................................................. ...............101 26 5.3.3 Reglas precisas para determinar asignaciones definitivas...................................... ..........................102 27 5.3.3.1 Reglas generales para instrucciones................................................................... ........................102 28 5.3.3.2 Instrucciones de bloques e instrucciones checked y unchecked...................... ...........................103 29 5.3.3.3 Instrucciones de expresiones.................................................................................... ..................103 30 5.3.3.4 Instrucciones de declaracin.................................................................................................... ...103 31 5.3.3.5 Instrucciones If................................................................................................................... ........103 32 5.3.3.6 Instrucciones Switch....................................................................................... ...........................103 33 5.3.3.7 Instrucciones While.......................................................................................................... ..........105 34 5.3.3.8 Instrucciones Do...................................................................................................................... ...105 35 5.3.3.9 Instrucciones For............................................................................................................ ............105 36 5.3.3.10 Instrucciones Break, Continue y Goto........................................................................... ...........105 37 5.3.3.11 Instrucciones Throw.............................................................................................. ...................106 38 5.3.3.12 Instrucciones Return.......................................................................................................... .......106 39 5.3.3.13 Instrucciones Try-catch.................................................................................... ........................106 40 5.3.3.14 Instrucciones Try-finally................................................................................. .........................106 41 5.3.3.15 Instrucciones Try-finally-catch......................................................................................... ........107 42 5.3.3.16 Instrucciones Foreach....................................................................................................... ........108 43 5.3.3.17 Instrucciones Using................................................................................................... ...............108 44 5.3.3.18 Instrucciones Lock........................................................................................... ........................108 45 5.3.3.19 Reglas generales para expresiones simples............................................................................. ..108 46 5.3.3.20 Reglas generales para expresiones con expresiones incrustadas......................................... ......109 47 5.3.3.21 Expresiones de invocacin y expresiones de creacin de objetos...................................... .......109 48 5.3.3.22 Expresiones de asignacin simples...................................................................................... .....109 49 5.3.3.23 Expresiones &&................................................................................................... ....................110 50 5.3.3.24 Expresiones ||................................................................................................................. ...........1119Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

v

10Especificacin del lenguaje C#

1 5.3.3.25 ! Expresiones !................................................................................................................ ..........111 2 5.3.3.26 Expresiones ?:.............................................................................................. ............................112 3 5.4 Referencias de variables.................................................................................................................. ........112 4 5.5 Atomicidad de las referencias de variable......................................................................... ......................113 56. Conversiones...................................................................................................................................... ..........114 6 6.1 Conversiones implcitas................................................................................................... .......................114 7 6.1.1 Conversiones de identidad............................................................................................................. ...114 8 6.1.2 Conversiones numricas implcitas............................................................................ ......................114 9 6.1.3 Conversiones de enumeracin implcitas.............................................................. ...........................115 10 6.1.4 Conversiones de referencia implcitas............................................................................... ...............115 11 6.1.5 Conversiones boxing.......................................................................................................... ..............116 12 6.1.6 Conversiones implcitas de expresin constante........................................................................... ....116 13 6.1.7 Conversiones definidas por el usuario implcitas................................................... ..........................116 14 6.2 Conversiones explcitas.................................................................................................................... .......116 15 6.2.1 Conversiones explcitas numricas............................................................................................ .......117 16 6.2.2 Conversiones de enumeracin explcitas............................................................................... ...........118 17 6.2.3 Conversiones explcitas de referencia................................................................... ...........................119 18 6.2.4 Conversiones Unboxing............................................................................................... ....................119 19 6.2.5 Conversiones explcitas definidas por el usuario................................................................... ...........119 20 6.3 Conversiones estndar........................................................................................................................... ..120 21 6.3.1 Conversiones implcitas estndar................................................................................. ....................120 22 6.3.2 Conversiones explcitas estndar.................................................................................................. ....120 23 6.4 Conversiones definidas por el usuario................................................................................................ .....120 24 6.4.1 Conversiones permitidas definidas por el usuario........................................................ ....................120 25 6.4.2 Evaluacin de conversiones definidas por el usuario................................................ .......................120 26 6.4.3 Conversiones explcitas definidas por el usuario....................................................................... .......121 27 6.4.4 Conversiones explcitas definidas por el usuario....................................................................... .......122 287. Expresiones....................................................................................................................................... ...........124 29 7.1 Clasificaciones de expresin................................................................................................... ................124 30 7.1.1 Valores de expresiones................................................................................................. ....................125 31 7.2 Operadores.................................................................................................................................. ............125 32 7.2.1 Prioridad y asociatividad de los operadores............................................................ .........................126 33 7.2.2 Sobrecarga de operadores............................................................................................................. ....127 34 7.2.3 Resolucin de sobrecarga de operador unario............................................................... ...................128 35 7.2.4 Resolucin de sobrecarga de operador binario................................................................ .................128 36 7.2.5 Operadores candidatos definidos por el usuario............................................................... ................129 37 7.2.6 Promociones numricas.................................................................................................................... 129 38 7.2.6.1 Promociones numricas unarias ........................................................................ ........................129 39 7.2.6.2 Promociones numricas binarias........................................................................... .....................130 40 7.3 Bsqueda de miembros........................................................................................................ ...................130 41 7.3.1 Tipos base.............................................................................................................. ..........................131 42 7.4 Miembros de funcin.......................................................................................................... ....................132 43 7.4.1 Listas de argumentos............................................................................................................... .........135 44 7.4.2 Resolucin de sobrecargas........................................................................................ .......................137 45 7.4.2.1 Miembro de funcin aplicable.......................................................................................... ..........138 46 7.4.2.2 Mejor miembro de funcin.............................................................................................. ...........138 47 7.4.2.3 Mejor conversin........................................................................................... ............................139 48 7.4.3 Invocacin de miembros de funcin............................................................................................. ....139 49 7.4.3.1 Invocaciones en instancias de conversin boxing.................................................................... ...141

11vi

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

12

Tabla de contenido

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51

7.5 Expresiones primarias............................................................................................................... ..............141 7.5.1 Literales.................................................................................................................. .........................142 7.5.2 Nombres sencillos.............................................................................................................. ..............142 7.5.2.1 Significado invariable en bloques............................................................................................ ...143 7.5.3 Expresiones entre parntesis.................................................................................. ..........................144 7.5.4 Acceso a miembros................................................................................................. .........................144 7.5.4.1 Nombres simples y nombres de tipos idnticos............................................................ ..............146 7.5.5 Expresiones de llamada........................................................................................................... .........147 7.5.5.1 Invocaciones de mtodo........................................................................................... ..................147 7.5.5.2 Invocaciones de delegados..................................................................................... ....................148 7.5.6 Acceso a elementos:......................................................................................................... ................148 7.5.6.1 Acceso a matrices.......................................................................................................... .............149 7.5.6.2 Acceso al indizador............................................................................................ ........................149 7.5.7 Acceso a this.......................................................................................................... ..........................150 7.5.8 Acceso a bases................................................................................................................................ ..151 7.5.9 Operadores postfijos de incremento y decremento................................................................ ...........151 7.5.10 El operador new......................................................................................................... ....................152 7.5.10.1 Expresiones de creacin de objetos........................................................................ ..................153 7.5.10.2 Expresiones de creacin de matrices.................................................................... ....................155 7.5.10.3 Expresiones de creacin de delegados.............................................................................. ........156 7.5.11 Operador typeof.................................................................................................. ...........................158 7.5.12 Los operadores checked y unchecked................................................................ ............................159 7.6 Operadores unarios........................................................................................................ .........................161 7.6.1 Operador unario de signo ms.................................................................................................. ........162 7.6.2 Operador unario de signo menos............................................................................................ ..........162 7.6.3 Operador de negacin lgica................................................................................................. ...........164 7.6.4 Operador de complemento de bit a bit............................................................................................ ..164 7.6.5 Operadores prefijos de incremento y decremento.................................................. ..........................164 7.6.6 Expresiones de conversin................................................................................................ ...............165 7.7 Operadores aritmticos............................................................................................... ............................166 7.7.1 Operador de multiplicacin.................................................................................................. ............166 7.7.2 Operador de divisin........................................................................................................... .............167 7.7.3 Operador de resto............................................................................................................... ..............168 7.7.4 Operador de suma.................................................................................................... ........................169 7.7.5 Operador de resta......................................................................................................... ....................171 7.8 Operadores de desplazamiento....................................................................................................... .........173 7.9 Operadores de comprobacin de tipos y relacionales...................................................................... ........174 7.9.1 Operadores de comparacin de enteros............................................................................ ................175 7.9.2 Operadores de comparacin de punto flotante...................................................... ...........................176 7.9.3 Operadores de comparacin decimales................................................................... .........................176 7.9.4 Operadores de igualdad booleanos....................................................................................... ............177 7.9.5 Operadores de comparacin de tipo de enumeracin................................................ .......................177 7.9.6 Operadores de igualdad de tipos de referencia............................................................... ..................177 7.9.7 Operadores de igualdad de cadenas............................................................................................ ......179 7.9.8 Operadores de igualdad de delegados................................................................... ...........................180 7.9.9 Operador Is.......................................................................................................... ............................180 7.9.10 Operador As............................................................................................................... ....................181 7.10 Operadores lgicos............................................................................................................................ ....181 7.10.1 Operadores lgicos enteros.................................................................................. ..........................182 7.10.2 Operadores lgicos de enumeracin....................................................................................... ........182 7.10.3 Operadores lgicos booleanos............................................................................................... .........182

13Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

vii

14Especificacin del lenguaje C#

1 2 3 4 5 6 7 8 9 10 11

7.11 Operadores lgicos condicionales...................................................................................... ...................182 7.11.1 Operadores lgicos condicionales booleanos........................................................ .........................183 7.11.2 Operadores lgicos condicionales definidos por el usuario........................................... .................183 7.12 Operador condicional................................................................................................................ ............184 7.13 Operadores de asignacin......................................................................................... ............................185 7.13.1 Asignacin simple........................................................................................................... ...............185 7.13.2 Asignacin compuesta.............................................................................................................. ......187 7.13.3 Asignacin de eventos........................................................................................................... .........188 7.14 Expresin............................................................................................................................ ..................188 7.15 Expresiones constantes......................................................................................................................... .189 7.16 Expresiones booleanas....................................................................................................... ...................190

128. Instrucciones............................................................................................................................................ ....191 13 8.1 Puntos finales y alcance....................................................................................................... ...................191 14 8.2 Bloques................................................................................................................................ ...................193 15 8.2.1 Listas de instrucciones............................................................................................. ........................193 16 8.3 Instruccin vaca.................................................................................................................... .................194 17 8.4 Instrucciones con etiqueta......................................................................................................... ..............194 18 8.5 Instrucciones de declaracin............................................................................................ .......................195 19 8.5.1 Declaraciones de variables locales................................................................................. ..................195 20 8.5.2 Declaraciones de constantes locales.................................................................................... .............196 21 8.6 Instrucciones de expresiones......................................................................................................... ..........197 22 8.7 Instrucciones de seleccin............................................................................................................... ........197 23 8.7.1 Instruccin If.......................................................................................................................... ..........197 24 8.7.2 Instruccin Switch.......................................................................................................................... ..198 25 8.8 Instrucciones de iteracin................................................................................................................... .....203 26 8.8.1 Instruccin While................................................................................................................ .............203 27 8.8.2 Instruccin Do............................................................................................................................. .....203 28 8.8.3 Instruccin For.................................................................................................................. ...............204 29 8.8.4 Instruccin Foreach................................................................................................................. .........205 30 8.9 Instrucciones Jump............................................................................................................................... ...207 31 8.9.1 Instruccin Break............................................................................................................ .................208 32 8.9.2 Instruccin Statement............................................................................................................... ........209 33 8.9.3 Instruccin Goto........................................................................................................................... ....209 34 8.9.4 Instruccin Return.................................................................................................................... ........210 35 8.9.5 Instruccin Throw........................................................................................................ ....................211 36 8.10 Instruccin Try......................................................................................................................... .............212 37 8.11 Instrucciones Checked y Unchecked......................................................................................... ............216 38 8.12 Instruccin Lock........................................................................................................... ........................216 39 8.13 Instruccin Using................................................................................................................... ...............217 409. Espacios de nombres................................................................................................................... ................220 41 9.1 Unidades de compilacin....................................................................................................... .................220 42 9.2 Declaraciones de espacio de nombres................................................................................... ..................220 43 9.3 Directivas Using..................................................................................................................................... .222 44 9.3.1 Directivas Using alias........................................................................................... ...........................222 45 9.3.2 Directivas Using espacio de nombres.......................................................................................... .....225 46 9.4 Miembros de espacio de nombres...................................................................................... .....................227 47 9.5 Declaraciones de tipo................................................................................................................ ..............227 4810. Clases.............................................................................................................................. ...........................229 49 10.1 Declaraciones de clases................................................................................................................. ........22915viiiCopyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

16

Tabla de contenido

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51

10.1.1 Modificadores de clase............................................................................................................ .......229 10.1.1.1 Clases abstractas................................................................................................................... ....230 10.1.1.2 Clases Sealed........................................................................................................................ ....230 10.1.2 Especificacin de clase base......................................................................................................... ..230 10.1.2.1 Clases base............................................................................................................. ..................231 10.1.2.2 Implementaciones de interfaces............................................................................................. ...233 10.1.3 Cuerpo de clase............................................................................................................. .................233 10.2 Miembros de clase....................................................................................................... .........................233 10.2.1 Herencia........................................................................................................................... ..............235 10.2.2 Modificador New......................................................................................................... ..................235 10.2.3 Modificadores de acceso............................................................................................... .................235 10.2.4 Tipos constituyentes.......................................................................................................... .............235 10.2.5 Miembros estticos y de instancia...................................................................................... ............236 10.2.6 Tipos anidados................................................................................................... ............................237 10.2.6.1 Nombre completo.......................................................................................................... ...........237 10.2.6.2 Accesibilidad declarada................................................................................................ ............237 10.2.6.3 Ocultar.................................................................................................................................... ..238 10.2.6.4 Acceso this....................................................................................................... ........................239 10.2.6.5 Acceso a miembros privados y protegidos del tipo contenedor........................... .....................239 10.2.7 Nombres de miembro reservados................................................................................. ..................240 10.2.7.1 Nombres de miembros reservados para propiedades................................................ ................242 10.2.7.2 Nombres de miembros reservados para eventos....................................................... ................242 10.2.7.3 Nombres de miembros reservados para indizadores.................................................... .............242 10.2.7.4 Nombres de miembros reservados para destructores................................................ ................243 10.3 Constantes.................................................................................................................................... .........243 10.4 Campos............................................................................................................................. ....................244 10.4.1 Campos estticos y de instancia................................................................................. ....................246 10.4.2 Campos de slo lectura........................................................................................ ..........................246 10.4.2.1 Utilizar campos de slo lectura estticos para constantes............................................... ..........247 10.4.2.2 Versiones de constantes y campos de slo lectura estticos.............................................. ........247 10.4.3 Campos volatile............................................................................................................................. .248 10.4.4 Inicializacin de campos.............................................................................................. ..................249 10.4.5 Inicializadores de variables........................................................................................ ....................249 10.4.5.1 Inicializacin de campos estticos.................................................................................... ........250 10.4.5.2 Inicializacin de campos de instancia.................................................................................. .....252 10.5 Mtodos......................................................................................................................... .......................252 10.5.1 Parmetros de mtodos.................................................................................................................. .254 10.5.1.1 Parmetros de valor...................................................................................................... ............255 10.5.1.2 Parmetros de referencia................................................................................... .......................256 10.5.1.3 Parmetros de salida....................................................................................................... ..........257 10.5.1.4 Matrices de parmetros................................................................................ ............................258 10.5.2 Mtodos estticos y de instancia............................................................................. .......................261 10.5.3 Mtodos virtuales............................................................................................................... ............261 10.5.4 Mtodos de reemplazo.......................................................................................... .........................264 10.5.5 Mtodos sellados.................................................................................................................... ........265 10.5.6 Mtodos abstractos.................................................................................................................. .......266 10.5.7 Mtodos externos......................................................................................................... ..................267 10.5.8 Cuerpo del mtodo......................................................................................................... ................268 10.5.9 Sobrecarga de mtodos................................................................................................................ ...269 10.6 Propiedades................................................................................................................................. ..........269 10.6.1 Propiedades estticas y de instancia.............................................................................. .................270

17Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

ix

18Especificacin del lenguaje C#

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22

10.6.2 Descriptores de acceso................................................................................................ ...................270 10.6.3 Descriptores de acceso virtual, sellado, de reemplazo y abstracto............................................ ......275 10.7 Eventos....................................................................................................................... ..........................277 10.7.1 Eventos como campos........................................................................................................... .........279 10.7.2 Descriptores de acceso de evento .................................................................................. ................281 10.7.3 Eventos estticos y de instancia........................................................................... ..........................282 10.7.4 Descriptores de acceso virtual, sellado, de reemplazo y abstracto............................................ ......282 10.8 Indizadores..................................................................................................................................... .......283 10.8.1 Sobrecarga de indizadores...................................................................................................... ........287 10.9 Operadores............................................................................................................................... .............287 10.9.1 Operadores unarios........................................................................................................................ .288 10.9.2 Operadores binarios............................................................................................. ..........................289 10.9.3 Operadores de conversin........................................................................................... ...................290 10.10 Constructores de instancia............................................................................................................... ....291 10.10.1 Inicializadores de constructor................................................................................................ .......292 10.10.2 Inicializadores de variables de instancia.................................................................................... ...293 10.10.3 Ejecucin de constructores................................................................................................ ...........293 10.10.4 Constructores predeterminados................................................................................ ....................295 10.10.5 Constructores Private............................................................................................. ......................296 10.10.6 Parmetros de constructor de instancia opcionales............................................................... ........296 10.11 Constructores static........................................................................................................... ..................297 10.12 Destructores................................................................................................................... .....................299

2311. Estructuras................................................................................................................................................ .302 24 11.1 Declaraciones de estructuras........................................................................................... ......................302 25 11.1.1 Modificadores de estructuras.................................................................................................... ......302 26 11.1.2 Interfaces Struct.................................................................................................. ...........................303 27 11.1.3 Cuerpo de estructura.................................................................................................................... ...303 28 11.2 Miembros de estructura.............................................................................................................. ...........303 29 11.3 Diferencias entre clase y estructura......................................................................................... ..............303 30 11.3.1 Semnticas de valor................................................................................................................... .....304 31 11.3.2 Herencia....................................................................................................................... ..................305 32 11.3.3 Asignacin.................................................................................................................................. ....305 33 11.3.4 Valores predeterminados..................................................................................... ...........................305 34 11.3.5 Boxing y Unboxing....................................................................................................... .................306 35 11.3.6 Significado de This..................................................................................................................... ....306 36 11.3.7 Inicializadores de campo................................................................................................ ................306 37 11.3.8 Constructores.................................................................................................................................. 308 38 11.3.9 Destructores........................................................................................................ ...........................309 39 11.3.10 Constructores Static................................................................................................................... ...309 40 11.4 Ejemplos de estructuras.................................................................................................................... .....309 41 11.4.1 Tipo entero de base de datos..................................................................................................... ......309 42 11.4.2 Tipo booleano de base de datos................................................................................. .....................311 4312. Matrices.............................................................................................................................. .......................314 44 12.1 Tipos de matriz.................................................................................................................................. ....314 45 12.1.1 Tipo System.Array.................................................................................................... .....................315 46 12.2 Creacin de matrices................................................................................................................. ............315 47 12.3 Acceso a los elementos de matriz................................................................................................. .........315 48 12.4 Miembros de matriz.......................................................................................................... ....................315 49 12.5 Covarianza de matrices..................................................................................................... ....................315

19x

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

20

Tabla de contenido

1 12.6 Inicializadores de matrices....................................................................................................... .............316 213. Interfaces........................................................................................................................... ........................318 3 13.1 Declaraciones de interfaz.................................................................................................... ..................318 4 13.1.1 Modificadores de interfaz............................................................................................................ ...318 5 13.1.2 Interfaces base.......................................................................................................................... ......319 6 13.1.3 Cuerpo de interfaz.............................................................................................................. ............319 7 13.2 Miembros de interfaz....................................................................................................... .....................319 8 13.2.1 Mtodos de interfaz................................................................................................................. .......321 9 13.2.2 Propiedades de interfaz........................................................................................... .......................321 10 13.2.3 Eventos de interfaz............................................................................................................... ..........321 11 13.2.4 Indizadores de interfaz................................................................................................ ...................321 12 13.2.5 Acceso a miembros de interfaz................................................................................................ .......322 13 13.3 Nombres completos de miembros de interfaz........................................................... ............................324 14 13.4 Implementaciones de interfaces..................................................................................... .......................324 15 13.4.1 Implementaciones de miembro de interfaz explcitas............................................................ .........325 16 13.4.2 Asignacin de interfaces............................................................................................................... ..328 17 13.4.3 Herencia de implementacin de interfaces..................................................................... ................331 18 13.4.4 Reimplementacin de interfaces................................................................................................... ..333 19 13.4.5 Interfaces y clases abstractas............................................................................................... ...........334 2014. Enumeraciones...................................................................................................................... ....................336 21 14.1 Declaraciones de enumeracin.................................................................................................... ..........336 22 14.2 Modificadores de enumeracin......................................................................................... ....................337 23 14.3 Miembros de enumeracin....................................................................................................... .............337 24 14.4 Tipo System.Enum................................................................................................................... .............339 25 14.5 Valores y operaciones de enumeracin............................................................................................ ......339 2615. Delegados................................................................................................................................. ..................341 27 15.1 Declaraciones de delegados........................................................................................ ..........................341 28 15.2 Creacin de instancias de delegados............................................................................. ........................343 29 15.3 Invocacin de delegados.................................................................................................. .....................345 3016. Excepciones............................................................................................................................................ ....347 31 16.1 Causas de excepciones.......................................................................................................... ................347 32 16.2 Clase System.Exception............................................................................................................. ...........347 33 16.3 Cmo controlar excepciones............................................................................................... ..................348 34 16.4 Clases de excepcin comunes......................................................................................... ......................348 3517. Atributos................................................................................................................................ ....................350 36 17.1 Clases de atributo...................................................................................................................... ............350 37 17.1.1 Uso de los atributos.............................................................................................................. ..........350 38 17.1.2 Parmetros posicionales y con nombre........................................................................................... 351 39 17.1.3 Tipos de parmetros de atributos......................................................................................... ...........353 40 17.2 Especificacin de atributos................................................................................................................... .353 41 17.3 Instancias de atributo................................................................................................. ...........................360 42 17.3.1 Compilacin de un atributo............................................................................................ ................360 43 17.3.2 Recuperacin en tiempo de ejecucin de una instancia de atributo................................ ................360 44 17.4 Atributos reservados......................................................................................................................... .....361 45 17.4.1 Atributo AttributeUsage.......................................................................................... .......................362 46 17.4.2 Atributo Conditional...................................................................................................................... .362 47 17.4.2.1 Mtodos condicionales.............................................................................................. ...............363

21Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

xi

22Especificacin del lenguaje C#

1 17.4.2.2 Clases de atributo condicional....................................................................................... ...........365 2 17.4.3 Atributo Obsolete......................................................................................................... ..................367 3 17.5 Atributos para interoperabilidad................................................................................................. ...........368 4 17.5.1 Interoperabilidad con componentes COM y Win32............................................. ..........................368 5 17.5.2 Interoperabilidad con otros lenguajes .NET............................................................... ....................368 6 17.5.2.1 Atributo IndexerName................................................................................................... ...........368 718. Cdigo no seguro......................................................................................................................... ..............369 8 18.1 Contextos no seguros....................................................................................................... .....................369 9 18.2 Tipos de punteros................................................................................................................ ..................372 10 18.3 Variables fijas y mviles.............................................................................................. .........................374 11 18.4 Conversiones de puntero......................................................................................................... ..............375 12 18.5 Punteros en expresiones....................................................................................................... .................377 13 18.5.1 Direccionamiento indirecto de punteros.............................................................................. ...........377 14 18.5.2 Acceso a miembros de puntero................................................................................................ .......378 15 18.5.3 Acceso a elementos de puntero...................................................................................................... .379 16 18.5.4 Operador de direccin.................................................................................................... ................380 17 18.5.5 Incremento y decremento de punteros................................................................................... .........380 18 18.5.6 Aritmtica con punteros....................................................................................... ..........................381 19 18.5.7 Comparacin de punteros...................................................................................................... .........383 20 18.5.8 Operador Sizeof...................................................................................................... .......................383 21 18.6 Instruccin fixed........................................................................................................... ........................384 22 18.7 Asignacin de pila........................................................................................................................ .........388 23 18.8 Asignacin dinmica de memoria................................................................................ .........................389 24A. Comentarios de documentacin............................................................................................ ....................392 25 A.1 Introduccin.......................................................................................................................... .................392 26 A.2 Etiquetas recomendadas........................................................................................................ .................393 27 A.2.1 ................................................................................................................................. .................394 28 A.2.2 .................................................................................................................. ..........................394 29 A.2.3 ...................................................................................................................................... .395 30 A.2.4 ................................................................................................................................... ..395 31 A.2.5 .................................................................................................................. ......................396 32 A.2.6 ................................................................................................................................ ...............397 33 A.2.7 ............................................................................................................................. ................398 34 A.2.8 ........................................................................................................................... ...............399 35 A.2.9 ................................................................................................................................. .....399 36 A.2.10 ............................................................................................................................. ....400 37 A.2.11 .......................................................................................................... .........................400 38 A.2.12 .......................................................................................................................... .............400 39 A.2.13 ................................................................................................................................... ..........402 40 A.2.14 ...................................................................................................................................... .402 41 A.2.15 .............................................................................................................. .....................403 42 A.2.16 ................................................................................................................ .........................403 43 A.3 Procesar el archivo de documentacin.......................................................................... .........................403 44 A.3.1 Formato de cadena de Id...................................................................................... ...........................404 45 A.3.2 Ejemplos de cadena de Id.................................................................................................... ............404 46 A.4 Un ejemplo....................................................................................................................................... ......410 47 A.4.1 Cdigo fuente C#.................................................................................................... ........................410 48 A.4.2 XML resultante..................................................................................................... ..........................413 49B. Gramtica........................................................................................................................... ........................41623xiiCopyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

24

Tabla de contenido

1 B.1 Gramtica lxica................................................................................................................................ .....416 2 B.1.1 Terminadores de lnea................................................................................................................ ......416 3 B.1.2 Espacio en blanco................................................................................................................ ............416 4 B.1.3 Comentarios.......................................................................................................... ..........................416 5 B.1.4 Smbolos...................................................................................................................................... ....417 6 B.1.5 Secuencias de escape de caracteres Unicode............................................................... ....................417 7 B.1.6 Identifiers................................................................................................................ ........................418 8 B.1.7 Palabras clave...................................................................................................................... ............419 9 B.1.8 Literales.................................................................................................................................... .......419 10 B.1.9 Operadores y signos de puntuacin........................................................................... ......................421 11 B.1.10 Directivas de preprocesamiento............................................................................................. ........421 12 B.2 Gramtica sintctica........................................................................................................... ....................423 13 B.2.1 Conceptos bsicos................................................................................................... ........................423 14 B.2.2 Tipos......................................................................................................................................... .......423 15 B.2.3 Variables.............................................................................................................................. ............425 16 B.2.4 Expresiones............................................................................................................... ......................425 17 B.2.5 Instrucciones................................................................................................................................... .428 18 B.2.6 Espacios de nombres................................................................................................ .......................431 19 B.2.7 Clases......................................................................................................................... .....................432 20 B.2.8 Estructuras.............................................................................................................................. .........438 21 B.2.9 Matrices.................................................................................................................................... .......438 22 B.2.10 Interfaces........................................................................................................................ ...............439 23 B.2.11 Enumeraciones................................................................................................... ...........................440 24 B.2.12 Delegados......................................................................................................................... .............440 25 B.2.13 Atributos............................................................................................................................. ...........441 26 B.3 Extensiones de la gramtica para el cdigo no seguro................................................................... .........442 27C. Referencias............................................................................................................................................. .....445

25Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

xiii

26

Captulo 18 Cdigo no seguro

1

1.Introduccin

2C# (C sharp) es un lenguaje de programacin sencillo y moderno, orientado a objetos y con seguridad de 3tipos. C# tiene su raz en la familia de lenguajes C y resultar inmediatamente familiar a programadores de C, 4C++ y Java. ECMA International estandariza C# como el estndar ECMA-334, e ISO/CEI como el estndar 5ISO/CEI 23270. El compilador de C# de Microsoft para .NET Framework es una implementacin compatible 6de ambos estndares. 7C# es un lenguaje de programacin orientado a objetos, pero tambin es compatible con la programacin 8orientada a componentes. El diseo de software contemporneo se basa cada vez ms en componentes de 9software en forma de paquetes de funcionalidad autodescriptivos y autosuficientes. La clave de dichos 10componentes reside en que presentan un modelo de programacin con propiedades, mtodos y eventos, en que 11tienen atributos que facilitan informacin declarativa sobre el componente y en que incorporan su propia 12documentacin. C# proporciona construcciones de lenguaje para que se admitan directamente estos conceptos, 13haciendo de C# un lenguaje muy natural en el que crear y utilizar los componentes de software. 14Algunas de las caractersticas de C# ayudan en la construccin de aplicaciones slidas y duraderas: la 15recoleccin de elementos no utilizados reclama automticamente la memoria ocupada por objetos no utilizados; 16el control de excepciones proporciona un enfoque extensible y estructurado de la deteccin y recuperacin de 17errores; y el diseo con seguridad de tipos del lenguaje hace que sea imposible tener variables no inicializadas, 18indizar las matrices ms all de sus lmites o realizar conversiones de tipo no comprobado. 19C# tiene un sistema de tipos unificado. Todos los tipos de C#, incluidos tipos primitivos como i n ty doub le, 20heredan de un tipo raz object nico. Por lo tanto, todos los tipos comparten un conjunto de operaciones 21comunes, y se pueden almacenar, transportar y tratar valores de cualquier tipo de una manera coherente. 22Adems, C# admite tipos de referencia definidos por el usuario y tipos de valor, y permite la asignacin 23dinmica de objetos as como el almacenamiento en lnea de estructuras ligeras. 24Para asegurarse de que los programas y bibliotecas de C# evolucionan con el tiempo de forma compatible, se ha 25dado mucha importancia al control de versiones en el diseo de C#. Muchos lenguajes de programacin apenas 26prestan atencin a este problema y, en consecuencia, los programas escritos en estos lenguajes se interrumpen 27ms de lo necesario cuando se incluyen versiones ms recientes de bibliotecas dependientes. Los aspectos del 28diseo de C# con influencia directa de las consideraciones sobre el control de versiones incluyen los 29modificadores virtual y override, las reglas de la resolucin de sobrecarga de mtodos y la compatibilidad con 30declaraciones explcitas de miembros de interfaz. 31En el resto de este captulo se explican las caractersticas esenciales del lenguaje C#. Mientras que en captulos 32posteriores se describen las reglas y las excepciones de una forma muy detallada e incluso a veces matemtica, 33este captulo se ha redactado dando prioridad a la claridad y la brevedad, a veces incluso a expensas de la 34integridad. El propsito es proporcionar al lector una introduccin al lenguaje que pueda facilitarle la 35programacin de sus primeros programas y la lectura de posteriores captulos.

27Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

1

28Especificacin del lenguaje C#

11.1 Hola a todos 2El programa Hola a todos (Hello, World) se utiliza tradicionalmente para presentar un lenguaje de 3programacin. Aqu est en C#:4 5 6 7 8 9 10

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

11Normalmente, la extensin de los archivos de cdigo fuente de C# es . c s Suponiendo que Hello, World se . 12almacena en el archivo he l l o . c s programa se puede compilar con el compilador de Microsoft C#, utilizando , el 13la lnea de comandos14 16

csc he l l o . c s He l l o , W ld or

15que genera un ensamblado ejecutable denominado he l l o . exe resultado de la ejecucin de esta aplicacin es . El 17El programa Hello, World se inicia con una directiva us ingque hace referencia al espacio de nombres 18Sys tem. Los espacios de nombres proporcionan una jerarqua que permite organizar programas y bibliotecas de 19C#. Los espacios de nombres contienen tipos y otros espacios de nombres, por ejemplo, el espacio de nombres 20System contiene varios tipos, como la clase Console, a la que se hace referencia en el programa, y otros 21espacios de nombres, como IO y Collections. Una directiva using que hace referencia a un espacio de nombres 22determinado permite el uso no calificado de los tipos que son miembros del espacio de nombres. Debido a la 23directiva using, el programa puede utilizar Console.WriteLine como forma abreviada para 24System.Console.WriteLine. 25La clase Hello declarada por el programa Hello, World tiene un nico miembro, el mtodo denominado Main. 26El mtodo Main se declara con el modificador static. A diferencia de los mtodos de instancia, que hacen 27referencia a una instancia de objeto determinada utilizando la palabra clave this, los mtodos estticos 28funcionan sin referencia a un objeto determinado. Por convencin, un mtodo esttico denominado Main sirve 29como punto de entrada de un programa. 30El mtodo WriteLine genera el resultado del programa en la clase Console del espacio de nombres System. 31Esta clase es proporcionada por las bibliotecas de clases de .NET Framework, a las que de forma 32predeterminada hace referencia automticamente el compilador de Microsoft C#. Observe que el propio C# no 33tiene una biblioteca en tiempo de ejecucin independiente. En su lugar, .NET Framework es la biblioteca en 34tiempo de ejecucin de C#. 351.2 Estructura del programa 36Los conceptos clave de organizacin en C# son programas, espacios de nombres, tipos, miembros y 37ensamblados. Los programas de C# constan de uno o varios archivos de cdigo fuente. Los programas declaran 38tipos, que contienen los miembros y pueden organizarse en los espacios de nombres. Las clases y las interfaces 39son ejemplos de tipos. Los campos, mtodos, propiedades y eventos son ejemplos de miembros. Cuando se 40compilan programas de C#, se empaquetan fsicamente en ensamblados. Normalmente la extensin de los 41ensamblados es .exe o .dll, dependiendo de si implementan aplicaciones o bibliotecas.

292

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

30

Captulo 18 Cdigo no seguro

1En el ejemplo 2 3 4 5 6 8 7 9 10 11 12 13 14 17 15using System; namespace Acme.Collections { public class Stack public void Push(object data) { top = new Entry(top, data); public object Pop() { if (top == null) throw new InvalidOperationException(); object result = top.data; class Entry { public Entry next; public Entry(Entry next, object data) { this.next = next; this.data = data; } top = top.next;

18 16 19 21 20 22 23 24

25declara una clase denominada Stack en un espacio de nombres llamado Acme.Co l l ec t i ons nombre } 28 . El 29completo de esta clase es Acme.Collections.Stack. La clase contiene varios miembros: un campo denominado 26 30top, dos mtodos denominados Push y Pop, y una clase anidada denominada Entry. La clase Entry contiene 31 27tres miembros ms: un campo denominado next, un campo denominado data y un constructor. Suponiendo que 32el cdigo fuente del ejemplo se almacena en el archivo acme.cs, la lnea de comandos 33 csc /t:library acme.cs 34compila el ejemplo como una biblioteca (cdigo sin un punto de entrada Main) y genera un ensamblado 35denominado acme.dll. 36Los ensamblados contienen cdigo ejecutable en forma de instrucciones de Lenguaje intermedio (IL) e 37informacin simblica en forma de metadatos. Antes de ejecutarse, el cdigo IL de un ensamblado se convierte 38automticamente en cdigo especfico del procesador mediante el compilador Just-In-Time (JIT) de .NET 39Common Language Runtime. 40Dado que un ensamblado es una unidad autodescriptiva de funcionalidad que contiene cdigo y metadatos, las 41directivas #include y los archivos de encabezado no son necesarios en C#. Los tipos y miembros pblicos 42contenidos en un ensamblado determinado estarn disponibles en un programa de C# haciendo referencia a 43dicho ensamblado al compilar el programa. Por ejemplo, este programa utiliza la clase 44Acme.Collections.Stack desde el ensamblado acme.dll: 45 46using System; using Acme.Collections;

31Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

3

32Especificacin del lenguaje C#

1 2 3 4 5 6 7

class Test { static void Main() { Stack s = new Stack(); s.Push(1); s.Push(10); s.Push(100);

13Si el programa se almacena en el archivo tes t . c,scuando se compila tes t . c s puede hacer referencia al se 8 14ensamblado acme.dll utilizando la opcin del compilador /r: 9 15 csc /r:acme.dll test.cs 10 16De este modo se crea un ensamblado ejecutable denominado test.exe que, cuando se ejecuta, genera el 17 11resultado: 12 18100

19 10 21 20C# permite el almacenamiento del texto de origen de un programa en varios archivos de cdigo fuente. Cuando 22se compila un programa de C# de varios archivos, se procesan todos los archivos de cdigo fuente juntos, y 23stos pueden hacer referencia libremente unos a otros. Conceptualmente, es como si todos los archivos de 24cdigo fuente se concatenaran en un gran archivo antes de procesarse. En C# nunca son necesarias las 25declaraciones adelantadas porque, salvo alguna excepcin, el orden de la declaracin no es significativo. C# no 26limita un archivo de cdigo fuente a declarar un nico tipo pblico ni exige que el nombre del archivo de cdigo 27fuente coincida con un tipo declarado en el archivo de cdigo fuente. 281.3 Tipos y variables 29Hay dos clases de tipos en C#: tipos de valor y tipos de referencia. Las variables de tipos de valor contienen 30directamente sus datos mientras que las variables de tipos de referencia almacenan las referencias a sus datos, 31que se conocen como objetos. En el caso de los tipos de referencia, es posible que dos variables hagan referencia 32al mismo objeto y, por tanto, que las operaciones en una variable afecten al objeto al que hace referencia la otra 33variable. En el caso de los tipos de valor, cada variable tiene su propia copia de los datos, de manera que no es 34posible que las operaciones de una afecten a la otra (exceptuando las variables de los parmetros ref y out). 35Los tipos de valor de C# se dividen a su vez en tipos simples, tipos de enumeracin y tipos de estructura, y los 36tipos de referencia de C# en tipos de clase, tipos de interfaz, tipos de matriz y tipos de delegado. 37La tabla siguiente proporciona informacin general sobre el sistema de tipos de C#.38

334

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

34

Captulo 18 Cdigo no seguro

Categora Tipos de valor Tipos simples

Descripcin Integrales con signo: sby te, shor t int, long , Integrales sin signo: byte, ushort, uint, ulong Caracteres Unicode: char Punto flotante IEEE: float, double Decimal de gran precisin: decimal Booleano: bool Tipos de enumeracin Tipos de estructura User-defined types of the form enum E { . . . } User-defined types of the form s t ruc t S { . . . } Clase base ltima de los dems tipos: object Cadenas de Unicode: string Tipos definidos por el usuario en forma classC{...} Tipos de interfaz Tipos de matriz Tipos de delegados User-defined types of the form i n te r face I { . . . } Unidimensional y multidimensional, por ejemplo, int[] e int[,] User-defined types of the form de legate T D( . . . )

Tipos de referencia

Tipos de clase

39 40Los ocho tipos integrales admiten los valores de 8 bits, 16 bits, 32 bits y 64 bits, con y sin signo. 41Los dos tipos de punto flotante float y double se representan utilizando los formatos IEEE 754 de 32 bits de 42precisin simple y de 64 bits de doble precisin. 43El tipo decimal es un tipo de datos de 128 bits apto para clculos financieros y monetarios. 44El tipo boo l de C# permite representar valores booleanos, que son t rueo false. 45El procesamiento de caracteres y cadenas en C# utiliza la codificacin Unicode. El tipo char representa una 46unidad de cdigo Unicode de 16 bits y el tipo string representa una secuencia de unidades de cdigo Unicode 47de 16 bits. 48La tabla siguiente resume los tipos numricos de C#.49

35Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

5

36Especificacin del lenguaje C#

Categora Integral con signo

Bits 8 16 32 64

Tiposbyte short int long byte ushort uint ulong float double decimal

Intervalo/precisin 128...127 32,768...32,767 2,147,483,648...2,147,483,647 9,223,372,036,854,775,808...9,223,372,036,854,775,807 0...255 0...65,535 0...4,294,967,295 0...18,446,744,073,709,551,615 1,5 10.45 a 3,4 1038, con precisin de 7 dgitos 5,0 10324 a 1,7 10308, con precisin de 15 dgitos 1,0 1028 a 7,9 1028, con precisin de 28 dgitos

Integral sin signo

8 16 32 64

Punto flotante Decimal

32 64 128

50 51Los programas de C# utilizan declaraciones de tipo para crear nuevos tipos. Una declaracin de tipo especifica 52el nombre y los miembros del nuevo tipo. Cinco de las categoras de tipos de C# son definibles por el usuario: 53tipos de clase, tipos de estructura, tipos de interfaz, tipos de enumeracin y tipos de delegado. 54Un tipo de clase define una estructura de datos que contiene miembros de datos (campos) y miembros de 55funcin (mtodos, propiedades y otros). Los tipos de clase admiten la herencia y el polimorfismo, mecanismos 56mediante los que las clases derivadas pueden ampliar y especializar clases base. 57Un tipo de estructura es similar a un tipo de clase en cuanto a que ambas representan una estructura con 58miembros de datos y miembros de funcin. No obstante, a diferencia de las clases, las estructuras son tipos de 59valores y no requieren asignacin del montn. Los tipos de estructura no admiten la herencia especificada por el 60usuario y heredan implcitamente del tipo ob jec t . 61Un tipo de interfaz define un contrato como un conjunto con nombre de miembros de funcin. Una clase o 62estructura que implementa una interfaz debe proporcionar implementaciones de los miembros de funcin de la 63interfaz. Una interfaz puede derivarse de varias interfaces base, y una clase o estructura puede implementar 64varias interfaces. 65Un tipo de enumeracin es un tipo distinto con constantes con nombre. Todos los tipos de enumeracin tienen 66un tipo subyacente, que debe ser uno de los ocho tipos integrales. El conjunto de valores de un tipo de 67enumeracin es el mismo que el del conjunto de valores del tipo subyacente. 68Un tipo de valor delegado representa las referencias a los mtodos con una lista de parmetros y un valor 69devuelto determinados. Los delegados permiten tratar mtodos como entidades, que se pueden asignar a las 70variables y pasarse como parmetros. Los delegados son similares al concepto de punteros a funcin de otros 71lenguajes, pero al contrario de los punteros a funcin, los delegados estn orientados a objetos y proporcionan 72seguridad de tipos. 73C# admite matrices unidimensionales y multidimensionales de cualquier tipo. Al contrario que otros tipos, los 74tipos de matriz no tienen que ser declarados antes de poder utilizarse. En su lugar, los tipos de matriz se crean 75mediante un nombre de tipo seguido de corchetes. Por ejemplo, i n t [ es una matriz unidimensional de i n t int[,] ] , 76es una matriz bidimensional de int e int[][] es una matriz unidimensional de matrices unidimensionales de int. 77El sistema de tipos de C# est unificado, de manera que un valor de cualquier tipo pueda tratarse como un 78objeto. Todos los tipos de C# se derivan directa o indirectamente del tipo de clase object, que es la clase base

376

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

38

Captulo 18 Cdigo no seguro

1definitiva de todos los tipos. Los valores de los tipos de referencia se tratan como objetos considerndolos 2sencillamente como del tipo ob jec t Los valores de los tipos de valor se tratan como objetos mediante la . 3realizacin de operaciones de conversin boxing y unboxing. En el ejemplo siguiente, se convierte un valor i n t 4en object y de nuevo en int. 5 6 7 8 9using System; class Test { static void Main() { int i = 123;

10 object o = i; // Boxing 14Cuando un valor de un tipo de valor se convierte en el tipo object, se asigna una instancia de objeto, tambin 11 15denominada box, para que contenga el valor, y ste se copia en dicha instancia. A la inversa, cuando se 16 12convierte una referencia object en un tipo de valor, se comprueba que el objeto al que se hace referencia es un 17cuadro del tipo de valor correcto, y si la comprobacin se lleva a cabo con xito, el valor del cuadro se copia 13externamente. 18 19El sistema de tipos unificado de C# significa en la prctica que los tipos de valor pueden convertirse en objetos 20a peticin. Debido a la unificacin, las bibliotecas de uso general que utilizan el tipo object, como las clases 21de coleccin en .NET Framework, pueden utilizarse tanto con los tipos de referencia como con los tipos de 22valor. 23Hay varios tipos de variables en C#, entre los que se incluyen campos, elementos de matriz, variables locales y 24parmetros. Las variables representan ubicaciones de almacenamiento, y cada variable tiene un tipo que 25determina qu valores se pueden almacenar en ella, como se muestra en la tabla siguiente.26

Tipo de variable Tipo de valorobject

Posible contenido Un valor de ese tipo exacto Una referencia nula, una referencia a un objeto de cualquier tipo de referencia o una referencia a un valor de tipo box de cualquier tipo de valor Una referencia nula, una referencia a una instancia de ese tipo de clase o una referencia a una instancia de una clase derivada de dicho tipo de clase Una referencia nula, una referencia a una instancia de un tipo de clase que implemente dicho tipo de interfaz o una referencia a un valor de tipo box que implemente dicho tipo de interfaz Una referencia nula, una referencia a una instancia de dicho tipo de matriz o una referencia a una instancia de un tipo de matriz compatible Una referencia nula o una referencia a una instancia de dicho tipo delegado

Tipo de clase

Tipo de interfaz

Tipo de matriz Tipo delegado

27

39Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

7

40Especificacin del lenguaje C#

11.4 Expresiones 2Las expresiones se construyen a partir de operandos y operadores. Los operadores de una expresin indican 3qu operaciones se aplican a los operandos. Entre los ejemplos de operadores se incluyen +, -, *, / y new. Son 4ejemplos de operandos los literales, campos, variables locales y expresiones. 5Cuando una expresin contiene varios operadores, la prioridad de los operadores controla el orden de 6evaluacin de los operadores individuales. Por ejemplo, la expresin x + y * z se evala como x + (y * z) 7porque el operador * tiene prioridad sobre +. 8La mayora de los operadores se pueden sobrecargar. La sobrecarga de operadores permite utilizar 9implementaciones de operadores definidas por el usuario en operaciones en las que al menos uno de los 10operandos es de un tipo estructura o clase definido por el usuario. 11En la tabla siguiente se resumen los operadores de C#, enumerando las categoras en orden de prioridad de 12mayor a menor: Los operadores de la misma categora tienen la misma prioridad.13

418

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

42

Captulo 18 Cdigo no seguro

Categora Principal

Expresinx.m x(...) x[...] x++ x-new T(...) new T[...] typeof(T) checked(x) unchecked(x)

Descripcin Acceso a miembros Invocacin de mtodos y delegados Matriz y acceso del indizador Incremento posterior Decremento posterior Creacin de objetos y de delegados Creacin de matrices Obtiene el objeto Sys tem. Typepara T Evala la expresin en contexto comprobado Evala la expresin en contexto no comprobado Identidad Negacin Negacin lgica Negacin bit a bit Incremento previo Decremento previo Convertir explcitamente x en el tipo T Multiplicacin Divisin Resto Suma, concatenacin de cadenas, combinacin de delegados Resta, eliminacin de delegados Desplazamiento a la izquierda Desplazamiento a la derecha Menor que Mayor que Menor o igual que Mayor o igual que Devuelve t ruesi x es T, de lo contrario, false Devuelve x escrito como T o null si x no es un T Igual No igual

Unario

+x -x !x ~x ++x --x (T)x

Multiplicativo

x*y x/y x%y

Sumatorio

x+y xy

Desplazamiento Comprobacin de tipos y relacionales

x > y xy x = y x is T x as T

Igualdad

x == y x != y

43Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

9

44Especificacin del lenguaje C#

AND lgico XOR lgico OR lgico AND condicional OR condicional Condicional Asignacin

x&y x^y x|y x && y x || y x?y:z x=y x op= y

AND bit a bit entero, AND lgico booleano XOR bit a bit entero, XOR lgico booleano OR bit a bit entero, OR lgico booleano Evaluates y only if x is true Evaluates y only if x is false Evala y si x es true, z si x es false Asignacin Asignacin compuesta; los operadores compatibles son*= /= %= += -= = &= ^= |=

14

151.5 Instrucciones 16Las acciones de un programa se expresan utilizando instrucciones. C# admite varios tipos de instrucciones, 17algunos de los cuales se definen en trminos de instrucciones incrustadas. 18Un bloque permite escribir varias instrucciones en contextos donde se admite una nica instruccin. Un bloque 19se compone de una lista de instrucciones escrita entre delimitadores { y }. 20Las instrucciones de declaracin se utilizan para declarar constantes y variables locales. 21Las instrucciones de expresin se utilizan para evaluar las expresiones. Las expresiones que pueden utilizarse 22como instrucciones incluyen invocaciones de mtodo, asignaciones de objetos utilizando el operador new, 23asignaciones utilizando =, operadores de asignacin compuesta y operadores de incremento y decremento 24utilizando los operadores ++ y --. 25Las instrucciones de seleccin seleccionan una de las instrucciones que se van a ejecutar en funcin del valor de 26alguna expresin. En este grupo estn las instrucciones if y switch. 27Las instrucciones de iteracin se utilizan para ejecutar repetidamente una instruccin incrustada. En este grupo 28estn las instrucciones while, do, for y foreach. 29Las instrucciones de salto se utilizan para transferir el control. En este grupo estn las instrucciones break, 30continue, goto, throw y return. 31La instruccin try...catch se utiliza para detectar las excepciones que se producen durante la ejecucin de un 32bloque y la instruccin try...finally se usa para especificar el cdigo de finalizacin que siempre se ejecuta, 33aparezca o no una excepcin. 34Las instrucciones checked y unchecked se utilizan con el fin de controlar el contexto de comprobacin de 35desbordamiento para operaciones aritmticas y conversiones. 36La instruccin lock se utiliza para bloquear un objeto determinado mediante exclusin mutua, ejecutar una 37instruccin y, a continuacin, liberar el bloqueo. 38La instruccin using se utiliza para obtener un recurso, ejecutar una instruccin y, a continuacin, eliminar 39dicho recurso. 40La tabla siguiente muestra las instrucciones de C# y proporciona un ejemplo para cada una.41

4510

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

46

Captulo 18 Cdigo no seguro

Instruccin Declaraciones de variables locales

Ejemplostatic void Main() { int a; int b = 2, c = 3; a = 1; Console.WriteLine(a + b + c); } static void Main() { const float pi = 3.1415927f; const int r = 25; Console.WriteLine(pi * r * r); } static void Main() { int i; i = 123; // Expression statement Console.WriteLine(i); // Expression statement i++; // Expression statement Console.WriteLine(i); // Expression statement } static void Main(string[] args) { if (args.Length == 0) { Console.WriteLine("No arguments"); } else { Console.WriteLine("One or more arguments"); } } static void Main(string[] args) { int n = args.Length; switch (n) { case 0: Console.WriteLine("No arguments"); break; case 1: Console.WriteLine("One argument"); break; default: Console.WriteLine("{0} arguments", n); break; } } } static void Main(string[] args) { int i = 0; while (i < args.Length) { Console.WriteLine(args[i]); i++; } }

Declaraciones de constantes locales

Instrucciones de expresiones

Instruccin i f

Instruccin sw i t ch

Instruccin whi le

47Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

11

48Especificacin del lenguaje C#

Instruccin do

static void Main() { string s; do { s = Console.ReadLine(); if (s != null) Console.WriteLine(s); } while (s != null); } static void Main(string[] args) { for (int i = 0; i < args.Length; i++) { Console.WriteLine(args[i]); } } static void Main(string[] args) { foreach (string s in args) { Console.WriteLine(s); } } static void Main() { while (true) { string s = Console.ReadLine(); if (s == null) break; Console.WriteLine(s); } } for (int i = 0; i < args.Length; i++) { if (args[i].StartsWith("/")) continue; Console.WriteLine(args[i]); }

Instruccin f o r

Instruccin f o reach

Instruccin break

Instruccin cont inue static void Main(string[] args) {

}

Instruccin goto

static void Main(string[] args) { int i = 0; goto check; loop: Console.WriteLine(args[i++]); check: if (i < args.Length) goto loop; } static int Add(int a, int b) { return a + b; } static void Main() { Console.WriteLine(Add(1, 2)); return; }

Instruccin re tu rn

4912

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

50

Captulo 18 Cdigo no seguro

Instrucciones th row y t ry

static double Divide(double x, double y) { if (y == 0) throw new DivideByZeroException(); return x / y; } static void Main(string[] args) { try { if (args.Length != 2) { throw new Exception("Two numbers required"); } double x = double.Parse(args[0]); double y = double.Parse(args[1]); Console.WriteLine(Divide(x, y)); } catch (Exception e) { Console.WriteLine(e.Message); } }

Instrucciones checked yunchecked

static void Main() { int i = int.MaxValue; checked { Console.WriteLine(i + 1); } unchecked { Console.WriteLine(i + 1); } } class Account { decimal balance;

// Exception // Overflow

l ockstatement

} us ingstatement

public void Withdraw(decimal amount) { lock (this) { if (amount > balance) { throw new Exception("Insufficient funds"); } balance -= amount; } }

42

static void Main() { using (TextWriter w = File.CreateText("test.txt")) { w.WriteLine("Line one"); w.WriteLine("Line two"); w.WriteLine("Line three"); } }

431.6 Clases y objetos 44Las clases son el tipo ms importante de C#. Una clase es una estructura de datos que combina estados (campos) 45y acciones (mtodos y otros miembros de funcin) en una unidad nica. Una clase proporciona una definicin 46para las instancias de la clase creadas dinmicamente, tambin conocidas como objetos. Las clases admiten la

51Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

13

52Especificacin del lenguaje C#

1herencia y el polimorfismo, mecanismos mediante los que una clase derivada puede ampliar y especializar una 2clase base. 2Las clases nuevas se crean utilizando declaraciones de clase. Las declaraciones de clase se inician con un 3encabezado que especifica los atributos y modificadores de la clase, el nombre, la clase base (si existe) y las 4interfaces implementadas por ella. El encabezado va seguido por el cuerpo de la clase, que consiste en una lista 5de declaraciones de miembros escritas entre los delimitadores { y }. 3La siguiente es una declaracin de una clase simple denominada Po in t : 4 5 6 5 6public class Point { public Point(int x, int y) { this.x = x;

7 this.y = y; 6 8Las instancias de clases se crean utilizando el operador new , que asigna memoria para una nueva instancia, 7invoca un constructor para inicializar la instancia y devuelve una referencia a la misma. Las instrucciones 9siguientes crean dos objetos Po in ty almacenan las referencias a dichos objetos en dos variables: 8 7Point p1 = new Point(0, 0);

8La memoria ocupada por un Point(10, 20); Point p2 = new objeto se reclama automticamente cuando el objeto deja de estar en uso. No es 8 9posible ni necesario desasignar explcitamente objetos en C#. 91.6.1 Miembros 10Los miembros de una clase son o miembros estticos o miembros de instancia. Los miembros estticos 11pertenecen a las clases y los miembros de instancia pertenecen a los objetos (instancias de clases). 11La tabla siguiente proporciona informacin general sobre los tipos de miembros que puede contener una clase.12

Miembro Constantes Campos Mtodos Propiedades Indizadores Eventos Operadores Constructores Destructores Tipos

Descripcin Los valores constantes asociados a la clase Las variables de la clase Los clculos y acciones que puede realizar la clase Las acciones asociadas a la lectura y escritura de propiedades con nombre de la clase Las acciones asociadas a instancias de indizacin de la clase como una matriz Las notificaciones que pueden ser generadas por la clase Las conversiones y operadores de expresin admitidos por la clase Las acciones requeridas para inicializar instancias de la clase o la propia clase Acciones que hay que llevar a cabo antes de que las instancias de la clase sean descartadas de forma permanente Tipos anidados declarados por la clase

135314

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

54

Captulo 18 Cdigo no seguro

11.6.2 Accesibilidad 2Cada miembro de una clase tiene asociada una accesibilidad, que controla las regiones del texto del programa a 3las que tiene acceso el miembro. Existen cinco formas posibles de accesibilidad. stas se resumen en la 4siguiente tabla.5

Accesibilidadpublic protected internal protected internal private

Significado Acceso no limitado Acceso limitado a esta clase y a las clases derivadas de la misma Acceso limitado a este programa Acceso limitado a este programa y a las clases derivadas de la misma Acceso limitado a esta clase

6

71.6.3 Clases base 8Una declaracin de clase puede especificar una clase base si a continuacin del nombre de clase se colocan dos 9puntos y el nombre de la clase base. Omitir una especificacin de clase base es igual que derivar del tipo ob jec t . 10En el ejemplo siguiente, la clase base de Po in t3Des Point, y la clase base de Point es object:11 12 13 14 15 16 17 18 19 20 21 22 23 24 25

pub l i c c lass Po in t { pub l i c i n t x , y ; pub l i c Po in t ( i n t x , i n t y ) { th i s . x = x ; th i s . y = y ; }

}

pub l i c c lass Po in t3D: Po in t { pub l i c i n t z ; pub l i c Po in t3D( in t x , i n t y , i n t z ) : Po in t (x , y ) { th i s . z = z ; } }

26Las clases heredan los miembros de sus clases base. La herencia significa que una clase contiene implcitamente 27todos los miembros de su clase base, salvo los constructores de la clase base. Una clase derivada puede agregar 28nuevos miembros a los heredados, pero no puede quitar la definicin de un miembro heredado. En el ejemplo 29anterior, Point3D hereda los campos x e y de Point, y cada instancia de Point3D contiene tres campos x, y, y z. 30Existe una conversin implcita desde un tipo de clase a cualquiera de sus tipos de clase base. Por consiguiente, 31una variable de un tipo de clase puede hacer referencia a una instancia de dicha clase o a una instancia de 32cualquier clase derivada. Por ejemplo, teniendo en cuenta las declaraciones de clase anteriores, una variable de 33tipo Point puede hacer referencia a un Point o a un Point3D:34 35

Po in t a = new Po in t (10 , 20) ; Po in t b = new Po in t3D(10 , 20 , 30) ;

361.6.4 Campos 37Un campo es una variable que est asociada a una clase o a una instancia de una clase.55Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

15

56Especificacin del lenguaje C#

1Un campo declarado con el modificador s ta t i c define un campo esttico. Un campo esttico identifica 2exactamente una ubicacin de almacenamiento. Independientemente del nmero de instancias que se creen de 3una clase, slo habr una copia de un campo esttico. 4Un campo declarado sin el modificador s ta t i c define un campo de instancia. Todas las instancias de una clase 5contienen una copia independiente de todos los campos de instancia de esa clase. 6En el ejemplo siguiente, cada instancia de la clase Co lo rtiene una copia independiente de los campos de 7instancia r, g y b, pero slo hay una copia de los campos estticos Black, White, Red, Green y Blue: 8 9 10 11 12 15 13 16 14 17 18public class Color { public static readonly Color Black = new Color(0, 0, 0); public static readonly Color White = new Color(255, 255, 255); public static readonly Color Red = new Color(255, 0, 0); private byte r, g, b; public Color(byte r, byte g, byte b) { this.r = r; this.g = g;

19 this.b = b; 22Como se puede ver en el ejemplo anterior, los campos de slo lectura se pueden declarar con un modificador 20readonly. Solamente se pueden realizar asignaciones a un campo readonly como parte de la declaracin del 23 24campo o en un constructor de instancias o un constructor esttico en la misma clase. 21 251.6.5 Mtodos 26Un mtodo es un miembro que implementa un clculo o una accin que puede realizar un objeto o una clase. El 27acceso a los mtodos estticos se obtiene a travs de la clase. Se tiene acceso a los mtodos de instancia a travs 28de las instancias de la clase. 29Los mtodos tienen una lista (posiblemente vaca) de parmetros, que representa valores o referencias variables 30que se pasan al mtodo y un tipo de valor devuelto que especifica el tipo del valor calculado y devuelto por el 31mtodo. El tipo de valor devuelto de un mtodo es void si no devuelve ningn valor. 32La firma de un mtodo debe ser nica en la clase en la que se declara el mtodo. La firma de un mtodo se 33compone del nombre del mtodo y del nmero, los modificadores y los tipos de sus parmetros. La firma de un 34mtodo no incluye el tipo de valor devuelto. 351.6.5.1 Parmetros 36Los parmetros se utilizan para pasar valores o referencias variables a los mtodos. Los parmetros de un 37mtodo reciben sus valores reales de los argumentos que se especifican cuando se invoca el mtodo. Existen 38cuatro clases de parmetros: parmetros de valores, parmetros de referencias, parmetros de salida y matrices 39de parmetros. 40Para pasar el parmetro de entrada se utiliza un parmetro de valor. Un parmetro de valor corresponde a una 41variable local que obtiene su valor inicial del argumento proporcionado para el parmetro. Las modificaciones 42de un parmetro de valor no afectan al argumento proporcionado para el parmetro. 43Un parmetro de referencia se utiliza tanto para proporcionar parmetros de entrada como de salida. El 44argumento pasado para un parmetro de referencia debe ser una variable, y durante la ejecucin del mtodo, el

5716

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

58

Captulo 18 Cdigo no seguro

1parmetro de referencia representa la misma ubicacin de almacenamiento que la variable del argumento. Los 2parmetros de referencia se declaran con el modificador re f El ejemplo siguiente ilustra el uso de los . 3parmetros re f . 2 3 4 5 6 7 4 8 5 9 6using System; class Test { static void Swap(ref int x, ref int y) { int temp = x; x = y; static void Main() { int i = 1, j = 2; Swap(ref i, ref j);

7 Console.WriteLine("{0} {1}", i, j); // Outputs "2 1" 5Para pasar parmetros de salida se utiliza un parmetro de salida. Un parmetro de salida es similar a un 8parmetro de referencia, excepto en que el valor inicial del argumento suministrado por el llamador no es 6 7importante. Los parmetros de salida se declaran con un modificador out. El ejemplo siguiente ilustra el uso de 9 8los parmetros out . 6 7 8 9 10 8 11using System; class Test { static void Divide(int x, int y, out int result, out int remainder) { static void Main() { int res, rem; Divide(10, 3, out res, out rem); result = x / y;

9 12 10

11 Console.WriteLine("{0} {1}", res, rem); // Outputs "3 1" 9Una matriz de parmetros permite pasar un nmero variable de argumentos a un mtodo. Un parmetro de 12matriz se declara con un modificador params . Slo el ltimo parmetro de un mtodo puede ser una matriz de 10 11 13parmetros y el tipo de una matriz de parmetros debe ser un tipo de matriz unidimensional. Los mtodos Wr i te 12y WriteLine de la clase System.Console son buenos ejemplos del uso de una matriz de parmetros. Se 13declaran del siguiente modo: 10 11 12 11 12public class Console { public static void WriteLine(string fmt, params object[] args) {...} ...

13Dentro de un mtodo que utiliza una matriz de parmetros, la matriz de parmetros se comporta exactamente } 13 14como un parmetro normal de un tipo de matriz. Sin embargo, en una invocacin de un mtodo con una matriz 15de parmetros, es posible pasar un argumento nico del tipo de matriz de parmetros o cualquier nmero de59Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

17

60Especificacin del lenguaje C#

1argumentos del tipo elemento de la matriz de parmetros. En este ltimo caso, se crea automticamente una 2instancia de matriz y se inicializa con los argumentos especificados. Este ejemplo 2 Console.WriteLine("x={0} y={1} z={2}", x, y, z); 3equivale a escribir lo siguiente. 4 5 6object[] args = new object[3]; args[0] = x; args[1] = y;

71.6.5.2 Cuerpo del mtodo y variables locales 5 8El cuerpo de un mtodo especifica las instrucciones que se deben ejecutar cuando se invoque el mtodo. 6 7Un cuerpo del mtodo puede declarar variables especficas para la invocacin del mtodo. Tales variables se 8denominan variables locales. Una declaracin de variable local especifica un nombre de tipo, un nombre de 9variable y posiblemente un valor inicial. El ejemplo siguiente declara una variable local i con un valor inicial de 10cero y una variable local j sin valor inicial. 8 9 10 11 12 13 14 15using System; class Squares { static void Main() { int i = 0; int j; while (i < 10) { j = i * i;

10C# exige que las variables locales estn definitivamente asignadas para que se puedan obtener sus valores. Por 16 11ejemplo, si la declaracin de i anterior no incluyera un valor inicial, el compilador notificara un error para la 17 12utilizacin subsiguiente de i ,porque i no estara definitivamente asignada en dichos puntos del programa. 18Un mtodo puede utilizar instrucciones return para devolver el control a su llamador. En un mtodo que 11 12devuelve void , las instrucciones return no pueden especificar una expresin. En un mtodo que no devuelve 19 13void, las instrucciones return deben incluir una expresin que calcule el valor devuelto. 20 121.6.5.3 Mtodos estticos y de instancia 13Un mtodo declarado con un modificador static es un mtodo esttico. Un mtodo esttico no funciona en una 14instancia especfica y slo tiene acceso a miembros estticos. 14Un mtodo declarado sin un modificador static es un mtodo de instancia. Los mtodos de instancia funcionan 15en instancias especficas y pueden tener acceso tanto a miembros estticos como a los de instancia. Se puede 16tener acceso explcitamente a la instancia en la que se invoc un mtodo de instancia como this. Es incorrecto 17hacer referencia a this en un mtodo esttico. 15La clase Entity siguiente tiene tanto miembros estticos como de instancia. 16 17 186118

class Entity {Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

62

Captulo 18 Cdigo no seguro

1 2 3 4 5 6 7 8 9 10 11 12

int serialNo; public Entity() { serialNo = nextSerialNo++; public int GetSerialNo() { return serialNo; public static int GetNextSerialNo() { return nextSerialNo; public static void SetNextSerialNo(int value) { nextSerialNo = value;

13 } 15Cada instancia Ent i t y contiene un nmero de serie (y probablemente alguna otra informacin que no se muestra 16aqu). El constructor Ent i t y (que es como un mtodo de instancia) inicializa la nueva instancia con el siguiente 14 17nmero de serie disponible. Dado que el constructor es un miembro de instancia, se puede tener acceso tanto al 18campo de instancia serialNo como al campo esttico nextSerialNo. 19Los mtodos estticos GetNextSerialNo y SetNextSerialNo pueden tener acceso al campo esttico 20nextSerialNo, pero sera incorrecto que tuvieran acceso al campo de instancia serialNo. 21En el ejemplo siguiente se muestra el uso de la clase Entity. 22 23 24 25 27 26 28 29 30using System; class Test { static void Main() { Entity e1 = new Entity(); Entity e2 = new Entity(); Console.WriteLine(e1.GetSerialNo()); Console.WriteLine(e2.GetSerialNo()); // Outputs "1000" // Outputs "1001"

31 Console.WriteLine(Entity.GetNextSerialNo()); // Outputs "1002" 34 32Tenga en cuenta que los mtodos estticos SetNextSerialNo y GetNextSerialNo se invocan en la clase, 35mientras que el mtodo de instancia GetSerialNo se invoca en las instancias de la clase. 33 361.6.5.4 Mtodos virtuales, de reemplazo y abstractos 37Cuando una declaracin de mtodo de instancia incluye un modificador virtual, se dice que el mtodo es un 38mtodo virtual. Si no existe un modificador virtual, se dice que el mtodo es un mtodo no virtual. 39En la invocacin de un mtodo virtual, el tipo en tiempo de ejecucin de la instancia para la que tiene lugar la 40invocacin determina la implementacin del mtodo real que se va a invocar. Cuando se invoca a un mtodo no 41virtual, el factor determinante es el tipo en tiempo de compilacin de la instancia. 42En las clases derivadas, los mtodos virtuales se pueden reemplazar. Cuando una declaracin del mtodo de 43instancia incluye un modificador override, el mtodo reemplaza un mtodo virtual heredado con la misma 44firma. Mientras que una declaracin de mtodo virtual introduce un mtodo nuevo, una declaracin de mtodo

63Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

19

64Especificacin del lenguaje C#

1de reemplazo especializa un mtodo virtual heredado existente proporcionando una nueva implementacin de 2ese mtodo. 3Un mtodo abstract es un mtodo virtual sin implementacin. Los mtodos abstractos se declaran con el 4modificador abs t rac t slo se permiten en una clase que tambin se declare como abs t rac.tLos mtodos y 5abstractos deben reemplazarse en cada clase derivada no abstracta. 4El ejemplo siguiente declara una clase abstracta, Express ionque representa un nodo de rbol de expresin y , 5tres clases derivadas Cons tan t, VariableReference y Operation, que implementan los nodos de rbol de 6expresin para las constantes, referencias variables y operaciones aritmticas. 5 6 6 7 8 7 9 8 9 8 9 10 9 10 11 10 12 11 12 11 12 13 12 13 14 15 16 13 17 14 18 15 19 16 14 17 15 16 17 1820 65Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

using System; using System.Collections; public abstract class Expression { public abstract double Evaluate(Hashtable vars); public class Constant: Expression { public Constant(double value) { this.value = value; public override double Evaluate(Hashtable vars) { return value; } public class VariableReference: Expression { public VariableReference(string name) { this.name = name; public override double Evaluate(Hashtable vars) { object value = vars[name]; if (value == null) { throw new Exception("Unknown variable: " + name); } public class Operation: Expression { Expression left; public Operation(Expression left, char op, Expression right) { this.left = left; this.op = op;

66

Captulo 18 Cdigo no seguro

1 2 3 4 5 6 7

public override double Evaluate(Hashtable vars) { double x = left.Evaluate(vars); double y = right.Evaluate(vars); switch (op) { case '+': return x + y; case '-': return x - y; case '*': return x * y;

16 new VariableReference("x"), 11 17 '+', 12El mtodo Eva lua tede una instancia Express ion invoca para evaluar la expresin determinada y generar un 19 se 20valor double. El mtodo toma como argumento un Hashtable que contiene nombres de variable (como claves 18 21de las entradas) y valores (como valores de las entradas). El mtodo Evaluate es un mtodo abstracto virtual, lo 22que significa que deben reemplazarlo las clases derivadas no abstractas para proporcionar una implementacin 23real. 24Una implementacin de Constant de Evaluate simplemente devuelve la constante almacenada. Una 25implementacin de VariableReference busca el nombre de la variable en la tabla hash y devuelve el valor 26resultante. Una implementacin de Operation evala primero los operandos izquierdo y derecho (invocando de 27forma recursiva sus mtodos Evaluate) y, a continuacin, lleva a cabo la operacin aritmtica correspondiente. 28El programa siguiente utiliza las clases Expression para evaluar la expresin x*(y+2) para distintos valores de 29x e y. 30 31 32 33 34 35 36 37 38 39 40 44 41 45 42 46 43 47using System; using System.Collections; class Test { Expression e = new Operation( new VariableReference("x"), '*', new Operation( new VariableReference("y"), '+', Hashtable vars = new Hashtable(); vars["x"] = 3; vars["y"] = 5;

13Las cuatro clases anteriores se pueden utilizar para modelar expresiones aritmticas. Por ejemplo, utilizando 8 14instancias de estas clases, la expresin x+3 se puede representar como sigue. 9 15 Expression e = new Operation( 10

67Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

21

68Especificacin del lenguaje C#

1 2 3

vars["x"] = 1.5; vars["y"] = 9; Console.WriteLine(e.Evaluate(vars)); // Outputs "16.5"

41.6.5.5 Sobrecarga de mtodos 6 5La sobrecarga del mtodo permite que varios mtodos de la misma clase tengan el mismo nombre siempre que 7 8sus firmas sean nicas. Al compilar una invocacin de un mtodo sobrecargado, el compilador utiliza la 9resolucin de sobrecarga para determinar el mtodo concreto que se va a invocar. La resolucin de sobrecarga 10busca el mtodo que mejor se ajusta a los argumentos o informa de un error si no se puede encontrar ningn 11ajuste adecuado. El ejemplo siguiente muestra la resolucin de sobrecarga en vigor. El comentario para cada 12invocacin en el mtodo Main muestra qu mtodo se ha invocado. 13 14 15 16 18 17 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34class Test { static void F() {...} static void F(object x) { Console.WriteLine("F(object)"); static void F(int x) { Console.WriteLine("F(int)"); static void F(double x) { Console.WriteLine("F(double)"); static void F(double x, double y) { Console.WriteLine("F(double, double)"); static void Main() { F(); F(1); F(1.0); F("abc"); // Invokes F() // Invokes F(int) // Invokes F(double) // Invokes F(object)

35 F((double)1); // Invokes F(double) 40Como muestra el ejemplo, un mtodo determinado siempre puede ser seleccionado convirtiendo explcitamente 36 41los argumentos en los tipos de parmetros exactos. 37 421.6.6 Otros miembros de funcin 38 43Los miembros que contienen cdigo ejecutable se conocen colectivamente como miembros de funcin de una 39 44clase. La seccin anterior describe mtodos, que son el tipo primario de miembros de funcin. En esta seccin se 45describen los otros tipos de miembros de funcin admitidos por C#: constructores, propiedades, indizadores, 46eventos, operadores y destructores.

6922

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

70

Captulo 18 Cdigo no seguro

1La tabla siguiente muestra una clase llamada L i s tque implementa una lista creciente de objetos. La clase 2contiene varios ejemplos de los tipos ms comunes de miembros de funcin.3

public class List { const int defaultCapacity = 4; object[] items; int count; public List(): List(defaultCapacity) {} public List(int capacity) { items = new object[capacity]; } public int Count { get { return count; } } public string Capacity { get { return items.Length; } set { if (value < count) value = count; if (value != items.Length) { object[] newItems = new object[value]; Array.Copy(items, 0, newItems, 0, count); items = newItems; } } } public object this[int index] { get { return items[index]; } set { items[index] = value; OnListChange(); } }

Constante Campos Constructores

Propiedades

Indizador

71Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

23

72Especificacin del lenguaje C#

public void Add(object item) { if (count == Capacity) Capacity = count * 2; items[count] = item; count++; OnChanged(); } protected virtual void OnChanged() { if (Changed != null) Changed(this, EventArgs.Empty); } public override bool Equals(object other) { return Equals(this, other as List); } static bool Equals(List a, List b) { if (a == null) return b == null; if (b == null || a.count != b.count) return false; for (int i = 0; i < a.count; i++) { if (!object.Equals(a.items[i], b.items[i])) { return false; } } return true; } public event EventHandler Changed; public static bool operator ==(List a, List b) { return Equals(a, b); } public static bool operator !=(List a, List b) { return !Equals(a, b); }

Mtodos

Evento Operadores

4

}

51.6.6.1 Constructores 6C# admite tanto constructores de instancia como estticos. Un constructor de instancia es un miembro que 7implementa las acciones que se requieren para inicializar una instancia de una clase. Un constructor esttico es 8un miembro que implementa las acciones exigidas para inicializar una clase cuando se carga por primera vez. 9Un constructor se declara como mtodo sin devolucin de tipo y con el mismo nombre que la clase contenedora. 10Si una declaracin de un constructor incluye un modificador s ta t i,cdeclara un constructor esttico. De lo 11contrario, declara un constructor de instancia. 12Los constructores de instancia se pueden sobrecargar. Por ejemplo, la clase L i s tdeclara dos constructores de 13instancia, uno sin parmetros y otro que toma un parmetro i n t Los constructores de instancia se invocan . 14utilizando el operador new. Las siguientes instrucciones asignan dos instancias List utilizando cada uno de los 15constructores de la clase List.16 17

L i s t l i s t1 = new L i s t ( ) ; L i s t l i s t2 = new L i s t (10 ) ;

18Al contrario que otros miembros, los constructores de instancia no se heredan, y una clase slo tiene los 19constructores de instancia realmente declarados en la clase. Si no se suministra ningn constructores de instancia 20para una clase, se proporcionar automticamente uno vaco sin parmetros.7324Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

74

Captulo 18 Cdigo no seguro

11.6.6.2 Propiedades 2Las propiedades son una extensin natural de los campos. Los dos son miembros denominados con tipos 3asociados, y la sintaxis que se utiliza para el acceso a campos y propiedades es la misma. No obstante, a 4diferencia de los campos, las propiedades no denotan ubicaciones de almacenamiento. Las propiedades tienen 5descriptores de acceso que especifican las instrucciones que deben ejecutarse para leer o escribir sus valores. 6Una propiedad se declara como un campo, slo que la declaracin finaliza con un descriptor de acceso get y/o 7un descriptor de acceso se t escrito entre los delimitadores { y } en lugar de finalizar con un punto y coma. Una 8propiedad que tiene un descriptor de acceso get y un set es una propiedad de lectura y escritura, una propiedad 9que tiene slo un descriptor de acceso get es una propiedad de slo lectura, y una propiedad que tiene slo un 10descriptor de acceso set es una propiedad de slo escritura. 11Un descriptor de acceso get corresponde a un mtodo sin parmetros que devuelve un valor del tipo de la 12propiedad. Exceptuando cuando se trata del destino de una asignacin, al hacer referencia a una propiedad en 13una expresin, se invoca al descriptor de acceso get de la propiedad para calcular su valor. 14Un descriptor de acceso set corresponde a un mtodo con un parmetro nico denominado value y ningn tipo 15de valor devuelto. Cuando se hace referencia a una propiedad como el destino de una asignacin o como el 16operando de ++ o --, se invoca al descriptor de acceso set con un argumento que proporciona el nuevo valor. 17La clase List declara dos propiedades, Count y Capacity; la primera de ellas es de slo lectura y la segunda de 18lectura y escritura. El siguiente es un ejemplo del uso de estas propiedades. 19 20List names = new List(); names.Capacity = 100; // Invokes set accessor

21 int i = names.Count; // Invokes get accessor 23Al igual que los campos y mtodos, C# admite tanto las propiedades de instancia como las propiedades 24 22estticas. Las propiedades estticas se declaran con el modificador static, y las propiedades de instancias, sin l. 25Los descriptores de acceso de una propiedad pueden ser virtuales. Cuando una declaracin de propiedad incluye 26un modificador virtual, abstract u override, se aplica a los descriptores de acceso de la propiedad. 271.6.6.3 Indizadores 28Un indizador es un miembro que permite indizar objetos de la misma manera que una matriz. Un indizador se 29declara como una propiedad, salvo en que el nombre del miembro es this seguido de una lista de parmetros 30escritos entre delimitadores [ y ]. Los parmetros estn disponibles en los descriptores de acceso del indizador. 31Al igual que las propiedades, los indizadores pueden ser de lectura y escritura, de slo lectura y de slo 32escritura, y los descriptores de acceso de un indizador pueden ser virtuales. 33La clase List declara un indizador de lectura y escritura nico que toma un parmetro int. El indizador permite 34indizar instancias List con valores int. Por ejemplo: 35 36 37 38List numbers = new List(); names.Add("Liz"); names.Add("Martha"); names.Add("Beth");

39 for (int i = 0; i < names.Count; i++) { 43Los indizadores se pueden sobrecargar, lo que significa que pueden declararse varios indizadores siempre y 40 44cuando sus parmetros difieran en nmero o tipos. 41 4275Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

25

76Especificacin del lenguaje C#

11.6.6.4 Eventos 2Un evento es un miembro que permite a una clase u objeto proporcionar notificaciones. Un evento se declara 3como un campo, salvo que la declaracin incluye una palabra clave event y el tipo debe ser un tipo delegado. 4En una clase que declara un miembro de evento, el evento se comporta como un campo de un tipo delegado 5(siempre que el evento no sea abstracto y no declare descriptores de acceso). El campo almacena una referencia 6a un delegado que representa los controladores de eventos que se han agregado al evento. Si no hay ningn 7controlador de eventos presente, el campo es nu l .l 8La clase L i s tdeclara un miembro de evento nico llamado Changed , que indica que se ha agregado un nuevo 9elemento a la lista. El mtodo virtual OnChanged inicia el evento Changed, comprobando previamente que el 10evento es null (lo que significa que no hay ningn controlador presente). La nocin de iniciar un evento 11equivale exactamente a invocar el delegado representado por el evento; por lo tanto, no hay construcciones 12especiales del lenguaje para producir eventos. 13Los clientes reaccionan a los eventos a travs de los controladores de eventos. Los controladores de eventos se 14asocian utilizando el operador += y se eliminan utilizando el operador -=. El ejemplo siguiente asocia un 15controlador de eventos al evento Changed de List.

7726

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

78

Captulo 18 Cdigo no seguro

1 2 3 4 5 6 7 8 9 10 11 12

using System; class Test { static void ListChanged(object sender, EventArgs e) { changeCount++; static void Main() { List names = new List(); names.Changed += new EventHandler(ListChanged); names.Add("Liz"); names.Add("Martha");

13Para escenarios avanzados donde se busca el control del almacenamiento subyacente de un evento, una names.Add("Beth"); 17 18declaracin de evento puede proporcionar explcitamente descriptores de acceso add y remove , que en cierto 14 19modo son similares al descriptor de acceso set de una propiedad. 15 201.6.6.5 Operadores 16 21Un operador es un miembro que define el significado de aplicar un operador de expresin determinado a las 22instancias de una clase. Pueden definirse tres categoras de operadores: operadores unarios, operadores binarios 23y operadores de conversin. Todos los operadores debern declararse como public y static. 24La clase List declara dos operadores operator== y operator!=, proporcionando de este modo un nuevo 25significado a expresiones que aplican dichos operadores a instancias List. Especficamente, los operadores 26definen la igualdad de dos instancias List comparando todos los objetos contenidos que utilizan sus mtodos 27Equals. El ejemplo siguiente utiliza el operador == para comparar dos instancias List. 28 29 30 31 32 33 34 35 36using System; class Test { static void Main() { List a = new List(); a.Add(1); a.Add(2); List b = new List(); b.Add(1);

37 b.Add(2); 43El resultado del primer Console.WriteLine es True porque las dos listas contienen el mismo nmero de objetos 44con los mismos valores. Si List no definiera operator==, el primer Console.WriteLine habra generado False 38 45porque a y b hacen referencia a dos instancias List diferentes. 39 40 41 4279Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

27

80Especificacin del lenguaje C#

11.6.6.6 Destructores 2Un destructor es un miembro que implementa las acciones necesarias para destruir una instancia de una clase. 3Los destructores no pueden tener parmetros, no pueden tener modificadores de accesibilidad y no se pueden 4invocar de forma explcita. El destructor de una instancia se invoca automticamente durante la recoleccin de 5elementos no utilizados. 6El recolector de elementos no utilizados tiene una amplia libertad para decidir cundo debe recolectar objetos y 7ejecutar destructores. En concreto, el control de tiempo de las invocaciones del destructor no es determinista y 8los destructores se pueden ejecutar en cualquier subproceso. Por estas y otras razones, las clases slo deberan 9implementar los destructores cuando no es factible ninguna otra solucin. 101.7 Estructuras 11Como las clases, las estructuras son estructuras de datos que pueden contener miembros de datos y miembros 12de funcin, pero al contrario que las clases, las estructuras son tipos de valor y no requieren asignacin del 13montn. Una variable de un tipo de estructura almacena directamente los datos de la estructura, mientras que 14una variable de un tipo de clase almacena una referencia a un objeto dinmicamente asignado. Los tipos de 15estructura no admiten la herencia especificada por el usuario y heredan implcitamente del tipo ob jec t . 16Las estructuras son particularmente tiles para estructuras de datos pequeas que tienen semnticas de valor. Los 17nmeros complejos, los puntos de un sistema de coordenadas o los pares de valores clave de un diccionario son 18buenos ejemplos de estructuras. El uso de estructuras en lugar de clases para estructuras de datos pequeas 19puede suponer una diferencia sustancial en el nmero de asignaciones de memoria que realiza una aplicacin. 20Por ejemplo, el programa siguiente crea e inicializa una matriz de 100 puntos. Con Po in timplementada como 21una clase, se inicializan 101 objetos separados, uno para la matriz y uno para cada uno de los 100 elementos. 22 c lass Po in t 23 { 24 pub l i c i n t x , y ; 25 pub l i c Po in t ( i n t x , i n t y ) { 26 th i s . x = x ; 27 th i s . y = y ; 28 } 29 30 c lass Tes t 31 { 32 s ta t i c vo id Main ( ) { 33 Po in t [ ] po in ts = new Po in t [100 ] ; 34 f o r ( i n t i = 0 ; i < 100 ; i++) po in ts [ i ] = new Po in t ( i , i ) ; 35 } 37Una alternativa es convertir Po in ten una estructura. 36 38 s t ruc t Po in t 39 { 40 pub l i c i n t x , y ; 41 pub l i c Po in t ( i n t x , i n t y ) { 42 th i s . x = x ; 43 th i s . y = y ; 44 } 45Ahora, slo se crea una instancia de un objeto, el del array, y las instancias de Po in tse almacenan en lnea en el 46 47array.8128Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

82

Captulo 18 Cdigo no seguro

1Los constructores de estructuras se invocan con el operador new, pero esto no implica que se est asignando la 2memoria. En lugar de asignar dinmicamente un objeto y devolver una referencia al mismo, un constructor de 3estructuras simplemente devuelve el propio valor de la estructura (normalmente en una ubicacin temporal en la 4pila) y a continuacin se copia este valor como sea necesario. 5En el caso de las clases, es posible que dos variables hagan referencia al mismo objeto y, por tanto, que las 6operaciones en una variable afecten al objeto al que hace referencia la otra variable. En el caso de las 7estructuras, cada variable tiene su propia copia de los datos, de manera que no es posible que las operaciones de 8una afecten a la otra. Por ejemplo, el resultado generado por el fragmento de cdigo siguiente depende de si 9Po in tes una clase o una estructura. 10 Po in t a = new Po in t (10 , 10) ; 11 Po in t b = a ; 12 a .x = 20 ; 13Si Po in Conso le .Wr i teL ine (b .x ) ; porque a y b hacen referencia al mismo objeto. Si Point es una 14 tes una clase, el resultado es 20 15estructura, el resultado es 10 porque la asignacin de a a b crea una copia del valor y esta copia no resulta 16afectada por la subsiguiente asignacin a a.x. 17El ejemplo anterior resalta dos de las limitaciones de estructuras. En primer lugar, copiar una estructura 18completa normalmente es menos eficaz que copiar una referencia a un objeto, por lo que la asignacin y el modo 19de pasar parmetros de valor puede ser ms costoso con estructuras que con tipos de referencia. En segundo 20lugar, salvo en el caso de los parmetros ref y out, no es posible crear referencias a estructuras, que descarta su 21uso en varias situaciones. 221.8 Matrices 23Una matriz es una estructura de datos que contiene una serie de variables a las que se obtiene acceso a travs de 24ndices calculados. Las variables contenidas en una matriz, tambin conocidas como elementos de la matriz, son 25todas del mismo tipo, que se denomina tipo de elemento de la matriz. 26Los tipos de matriz son tipos de referencia, por lo que la declaracin de una variable matricial solamente reserva 27espacio para una instancia de matriz. Las instancias de matriz reales se crean dinmicamente en tiempo de 28ejecucin utilizando el operador new. La operacin new especifica la longitud de la nueva instancia de matriz, 29que se establece para el perodo de duracin de la instancia. Los ndices de los elementos de una matriz pueden 30ir desde 0 a Length-1. El operador new inicializa automticamente los elementos de una matriz con su valor 31predeterminado que, por ejemplo, es cero para todos los tipos numricos y null para todos los tipos de 32referencia. 33El ejemplo siguiente crea una matriz de elementos int, inicializa la matriz e imprime su contenido. 34 us ing Sys tem; 35 c lass Tes t 36 { 37 s ta t i c vo id Main ( ) { 38 i n t [ ] a = new i n t [10 ] ; 39 f o r ( i n t i = 0 ; i < a .Length ; i++) a[ i ] = i * i ; 40 f o r ( i n t i = 0 ; i < a .Length ; i++) { 41 Conso le .Wr i teL ine ( "a [{0}] = {1}" , i , a[ i ] ) ; 42 } 45Este ejemplo crea y funciona en una matriz unidimensional. C# tambin admite las matrices 43 46 44multidimensionales. El nmero de dimensiones de un tipo de matriz, tambin conocido como el rango del tipo83Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

29

84Especificacin del lenguaje C#

1de matriz, es uno ms el nmero de comas escrito entre los corchetes del tipo de matriz. El ejemplo siguiente 2asigna una matriz unidimensional, una bidimensional y una tridimensional. 3int[] a1 = new int[10];

4 int[,] a2 = new int[10, 5]; 6La matriz a1 contiene 10 elementos, la matriz a2 contiene 50 (10 5) elementos y la matriz a3 contiene 100 5 7(10 5 2) elementos. 8Los elementos de una matriz pueden ser de cualquier tipo, incluido un tipo de matriz. Una matriz con elementos 9de tipo de matriz a veces se denomina matriz escalonada porque las longitudes de las matrices de elementos no 10tienen que ser siempre las mismas. El ejemplo siguiente asigna una matriz de matrices de int: 11 12int[][] a = new int[3][]; a[0] = new int[10];

13 a[1] = new int[5]; 15La primera lnea crea una matriz con tres elementos, cada uno de tipo int[] y cada uno con un valor inicial null. 16A continuacin, las lneas subsiguientes inicializan los tres elementos con referencias a instancias de matriz 14 17individuales de longitudes diversas. 18El operador new permite especificar los valores iniciales de los elementos de matriz utilizando un inicializador 19de matrices, que es una lista de expresiones escrita entre los delimitadores { y }. El ejemplo siguiente asigna e 20inicializa un int[] con tres elementos. 21 int[] a = new int[] {1, 2, 3}; 22Observe que la longitud de la matriz se deduce del nmero de expresiones existentes entre { y }. La variable 23local y las declaraciones de campo se pueden acortar ms, de tal modo que no es necesario volver a especificar 24el tipo de matriz. 25 int[] a = {1, 2, 3}; 26Los dos ejemplos anteriores son equivalentes a lo siguiente: 27 28int[] a = new int[3]; a[0] = 1;

29 a[1] = 2; 31 301.9 Interfaces 32Una interfaz define un contrato que puede ser implementado por clases y estructuras. Una interfaz puede 33contener mtodos, propiedades, eventos e indizadores. Una interfaz no proporciona implementaciones de los 34miembros que define, simplemente especifica los miembros que deben proporcionar las clases o estructuras que 35implementan la interfaz. 36Las interfaces pueden utilizar una herencia mltiple. En el ejemplo siguiente, la interfaz IComboBox hereda de 37ITextBox y de IListBox. 38 39 40 41interface IControl { void Paint();

8530

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

86

Captulo 18 Cdigo no seguro

1 2 3 5 4 6 7 9 8

interface ITextBox: IControl { void SetText(string text); interface IListBox: IControl { void SetItems(string[] items); interface IComboBox: ITextBox, IListBox {}

87Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

31

88Especificacin del lenguaje C#

1Las clases y las estructuras pueden implementar varias interfaces. En el ejemplo siguiente, la clase Ed i tBox 2implementa I Con t ro e IDataBound. l 3 4 5 7 6 8 9 10interface IDataBound { void Bind(Binder b); public class EditBox: IControl, IDataBound { public void Bind(Binder b) {...}

11 12Cuando } clase o estructura implementa una interfaz determinada, las instancias de dicha clase o estructura se una 13pueden convertir implcitamente en dicho tipo de interfaz. Por ejemplo: 14EditBox editBox = new EditBox();

15 IControl control = editBox; 17En los casos en los que no se sabe estticamente que una interfaz pueda implementar una interfaz determinada, 16 18se pueden utilizar conversiones de tipo dinmicas. Por ejemplo, las instrucciones siguientes utilizan 19conversiones de tipo dinmicas para obtener implementaciones de interfaces IControl y IDataBound de un 20objeto. Dado que el tipo real del objeto es EditBox, las conversiones se realizaron con xito. 21object obj = new EditBox();

22 IControl control = (IControl)obj; 24En la clase EditBox anterior, el mtodo Paint de la interfaz IControl y el mtodo Bind de la interfaz 23 25IDataBound se implementan utilizando miembros public. C# tambin admite implementaciones explcitas de 26miembro de la interfaz y, al utilizarlas la clase o la estructura, se puede evitar que los miembros sean public. 27Una implementacin explcita de miembro de interfaz se escribe utilizando el nombre completo de miembro de 28interfaz. Por ejemplo, la clase EditBox podra implementar los mtodos IControl.Paint e IDataBound.Bind 29utilizando implementaciones explcitas de miembro de interfaz del siguiente modo. 30 31 32 33public class EditBox: IControl, IDataBound { void IDataBound.Bind(Binder b) {...}

34 } 35Slo se puede tener acceso a los miembros de interfaz explcitos mediante el tipo de interfaz. Por ejemplo, la 36implementacin de IControl.Paint proporcionada por la clase EditBox anterior slo se puede invocar 37convirtiendo primero la referencia EditBox en el tipo de interfaz IControl. 38 39 40 41EditBox editBox = new EditBox(); editBox.Paint(); IControl control = editBox; // Error, no such method

8932

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

90

Captulo 18 Cdigo no seguro

11.10 Enumeraciones 2Un tipo enum (enumeracin) es un tipo de valor distinto con un conjunto de constantes con nombre. El ejemplo 3siguiente declara y utiliza un tipo de enumeracin denominado Co lo rcon tres valores constantes: Red , Green y 4Blue. 5 6 7 8 9 12 10 13 11 14 16 17 18 19 20 21 22 30 23 31 24 32 25using System; enum Color { Red, class Test { static void PrintColor(Color color) { switch (color) { case Color.Red: Console.WriteLine("Red"); break; case Color.Green: Console.WriteLine("Green"); break; case Color.Blue: static void Main() { Color c = Color.Red; PrintColor(c); Green,

15

33 26Cada tipo enum PrintColor(Color.Blue); 36 tiene un tipo integral correspondiente denominado tipo subyacente del tipo de enumeracin. Un 34tipo de enumeracin que no declara explcitamente un tipo subyacente tiene int como tipo subyacente. El 37 27 38formato de almacenamiento y el rango de posibles valores de un tipo de enumeracin vienen determinados por 35 28 39su tipo subyacente. El conjunto de valores que puede tomar un tipo enum no est limitado por sus miembros de 40enumeracin. En concreto, cualquier valor del tipo subyacente de una enumeracin puede convertirse en el tipo 29 41enum, y es un valor aceptado y distintivo de dicho tipo enum. 42El ejemplo siguiente declara un tipo de enumeracin denominado Alignment con un tipo subyacente de sbyte. 43 44 45 46 47 4891Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

enum Alignment: sbyte { Left = -1, Center = 0,

33

92Especificacin del lenguaje C#

1Como se muestra en el ejemplo anterior, una declaracin de miembro de enumeracin puede incluir una 2expresin constante que especifica el valor del miembro. El valor constante de cada miembro de enumeracin 3debe estar comprendido en el intervalo del tipo subyacente de la enumeracin. Cuando una declaracin de 4miembro de enumeracin no especifica explcitamente un valor, se da al miembro el valor cero (si es el primer 5miembro del tipo enum) o el valor del miembro de la enumeracin precedente ms uno. 6Los valores de enumeracin se pueden convertir en valores de tipo integral y viceversa, utilizando las 7conversiones de tipo. Por ejemplo: 8int i = (int)Color.Blue; // int i = 2;

9 // Color el = Color.Blue; 10El valor Color c = (Color)2; tipo de enumeracin es c valor cero de tipo integral convertido en el tipo predeterminado de cualquier 11enum. En los casos en los que las variables se inicializan automticamente con un valor predeterminado, ste es 12el valor proporcionado para las variables de tipos enum. Para que el valor predeterminado de un tipo enum est 13fcilmente disponible, el literal 0 se convierte implcitamente en cualquier tipo enum. De este modo, se permite 14lo siguiente. 15Color c = 0;

161.11 Delegados 17Un tipo delegado representa las referencias a los mtodos con una lista de parmetros determinada y un tipo de 18valor devuelto. Los delegados permiten tratar mtodos como entidades, que se pueden asignar a las variables y 19pasarse como parmetros. Los delegados son similares al concepto de punteros a funcin de otros lenguajes, 20pero al contrario de los punteros a funcin, los delegados estn orientados a objetos y proporcionan seguridad de 21tipos. 22El ejemplo siguiente declara y utiliza un tipo delegado denominado Func t i on . 23 24 25 26 27 28 29 30 31 32 33 35 34 36 37 38 40 39 41 42 43 449334Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

using System; delegate double Function(double x); class Multiplier { public Multiplier(double factor) { this.factor = factor; public double Multiply(double x) { return x * factor; } class Test { static double Square(double x) { static double[] Apply(double[] a, Function f) { double[] result = new double[a.Length]; for (int i = 0; i < a.Length; i++) result[i] = f(a[i]);

94

Captulo 18 Cdigo no seguro

1 2 3 4 5 6 7 8

static void Main() { double[] a = {0.0, 0.5, 1.0}; double[] squares = Apply(a, new Function(Square)); double[] sines = Apply(a, new Function(Math.Sin)); Multiplier m = new Multiplier(2.0); double[] doubles = } Apply(a, new Function(m.Multiply));

95Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

35

96Especificacin del lenguaje C#

1Una instancia del tipo delegado Func t i onpuede hacer referencia a cualquier mtodo que tome un argumento 2doub le y que devuelva un valor double. El mtodo Apply aplica un tipo Function determinado a los 3elementos de un tipo double[] y devuelve un tipo double[] con los resultados. En el mtodo Main, se utiliza 4Apply para aplicar tres funciones diferentes a un double[]. 5Un delegado puede hacer referencia a un mtodo esttico (como Square o Math.Sin en el ejemplo anterior) o a 6un mtodo de instancia (como m.Multiply en el ejemplo anterior). Un delegado que hace referencia a un 7mtodo de instancia tambin hace referencia a un objeto determinado y, cuando se invoca el mtodo de instancia 8a travs del delegado, dicho objeto pasa a ser this en la invocacin. 9Una propiedad interesante y til de un delegado es que no conoce ni necesita conocer la clase del mtodo a la 10que hace referencia; lo nico que importa es que el mtodo al que se hace referencia tenga los mismos 11parmetros y el mismo tipo de valor devuelto que el delegado. 121.12 Atributos 13Los tipos, miembros y otras entidades de un programa de C# admiten modificadores que controlan ciertos 14aspectos de su comportamiento. Por ejemplo, la accesibilidad de un mtodo se controla utilizando los 15modificadores public, protected, internal y private. C# generaliza esta funcin de tal forma que los tipos 16definidos por el usuario de informacin declarativa puedan agregarse a las entidades del programa y ser 17recuperados en tiempo de ejecucin. Los programas especifican esta informacin declarativa adicional 18definiendo y utilizando atributos. 19El ejemplo siguiente declara un atributo HelpAttribute que se puede colocar en entidades de programa para 20proporcionar vnculos a la documentacin asociada. 21 22 23 24 26 25 27 28 29 30 31 32 33using System; public class HelpAttribute: Attribute { string url; public HelpAttribute(string url) { this.url = url; public string Url { get { return url; } public string Topic { get { return topic; }

34 set { topic = value; } 37 35Todas las clases de atributo derivan de la clase base System.Attribute proporcionada por .NET Framework. Si 38el nombre de un atributo termina en Attribute, se puede omitir dicha parte del nombre al hacer referencia al 36atributo. Por ejemplo, el atributo HelpAttribute se puede utilizar del siguiente modo. 39 40 41 42 43 44 459736Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

[Help("http://msdn.microsoft.com/.../MyClass.htm")] public class Widget { [Help("http://msdn.microsoft.com/.../MyClass.htm", Topic = "Display")]

98

Captulo 18 Cdigo no seguro

1Este ejemplo asocia un He lpAt t r i bu tela clase Widget y otro HelpAttribute al mtodo Display de la clase. a 2Los constructores pblicos de una clase de atributo controlan la informacin que debe proporcionarse al asociar 3el atributo a una entidad de programa. Puede proporcionarse informacin adicional haciendo referencia a las 4propiedades pblicas de lectura y escritura de la clase de atributo (como la referencia previa a la propiedad 5Topic). 6El ejemplo siguiente muestra cmo utilizar la reflexin para recuperar en tiempo de ejecucin la informacin de 7atributos para una entidad determinada del programa. 8 9 10 11 12 13 14 15 16 17 23 18} static void Main() { using System; using System.Reflection; class Test { static void ShowHelp(MemberInfo member) { HelpAttribute a = Attribute.GetCustomAttribute(member, typeof(HelpAttribute)) as HelpAttribute; if (a == null) { Console.WriteLine("No help for {0}", member);

24 ShowHelp(typeof(Widget)); 19 25 ShowHelp(typeof(Widget).GetMethod("Display")); 20 28 26Cuando se solicita un atributo determinado a travs de la reflexin, se invoca al constructor para la clase de 21 29atributo con la informacin proporcionada en el cdigo fuente del programa y se devuelve la instancia de 27 30 22atributo resultante. Si la informacin adicional se proporciona a travs de propiedades, dichas propiedades se 31establecen en los valores dados antes de que se devuelva la instancia de atributo.

99Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

37

100Especificacin del lenguaje C#

1

2.Estructura lxica

22.1 Programas 3Un programa de C# consta de uno o varios archivos de cdigo fuente, formalmente conocidos como unidades 4de compilacin (9.1). Un archivo de cdigo fuente es una secuencia ordenada de caracteres Unicode. Los 5archivos de cdigo fuente normalmente tienen una correspondencia de uno a uno con los archivos de un sistema 6de archivos, pero esta correspondencia no es necesaria. Para maximizar la portabilidad, se recomienda utilizar la 7codificacin UTF-8 para los archivos de un sistema de archivos. 8En trminos conceptuales, un programa se compila en tres fases: 91. Transformacin, que convierte un archivo, a partir de un repertorio de caracteres y un esquema de 10 codificacin concretos, en una secuencia de caracteres Unicode. 112. Anlisis lxico, que convierte una secuencia de caracteres de entrada Unicode en una secuencia de smbolos 12 (token). 133. Anlisis sintctico, que convierte la secuencia de smbolos en cdigo ejecutable. 142.2 Gramticas 15Esta especificacin presenta la sintaxis del lenguaje de programacin C# mediante el uso de dos gramticas. La 16gramtica lxica (2.2.2) define cmo se combinan los caracteres Unicode para formar terminadores de lnea, 17espacios en blanco, comentarios, smbolos (tokens) y directivas de preprocesamiento. La gramtica sintctica 18(2.2.3) define cmo se combinan los smbolos resultantes de la gramtica lxica para formar programas de C#. 192.2.1 Notacin gramatical 20Las gramticas lxica y sintctica se presentan mediante producciones gramaticales. Cada produccin 21gramatical define un smbolo no terminal y las posibles expansiones de dicho smbolo en secuencias de 22smbolos no terminales o terminales. En las producciones gramaticales, los smbolos no terminales se muestran 23en cursiva, y los smbolos te rm ina lse muestran en una fuente de ancho fijo. 24La primera lnea de una produccin gramatical es el nombre del smbolo no terminal que se define, seguido de 25un carcter de dos puntos. Cada lnea con sangra sucesiva contiene una expansin posible del smbolo no 26terminal dado como una secuencia de smbolos no terminales o terminales. Por ejemplo, la produccin: 27 28while-statement: whi l e ( boolean-expression ) embedded-statement

29define una instruccin while (while-statement) formada por el smbolo (token) whi l e seguida del smbolo (, , 30de una expresin booleana (boolean-expression), del smbolo ) y de una instruccin incrustada (embedded31statement). 32Cuando hay ms de una expansin posible de un smbolo no terminal, las alternativas se muestran en lneas 33individuales. Por ejemplo, la produccin: 34 35 36statement-list: statement statement-list statement

10138

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

102

Captulo 18 Cdigo no seguro

1define una lista de instrucciones (statement-list) que consta de una instruccin (statement) o de una lista de 2instrucciones (statement-list) seguida de una instruccin (statement). Es decir, la definicin es recursiva y 3especifica que una lista de instrucciones consta de una o varias instrucciones. 4Se utiliza un sufijo en subndice opt para indicar un smbolo opcional. La produccin: 5 block: 6 { statement-listopt } 7es una forma abreviada de: 8 9 10block:{ } { statement-list }

11y define un bloque (block) compuesto por una lista de instrucciones (statement-list) opcional entre los smbolos 12{ y }. 13Las alternativas normalmente se enumeran en lneas distintas, aunque en los casos en los que hay varias 14alternativas, el texto una de las siguientes puede preceder a una lista de expansiones proporcionadas en la 15misma lnea. Esto es sencillamente una forma abreviada de mostrar todas las alternativas en lneas distintas. Por 16ejemplo, la produccin: 17 18 20 21 22 23 24 25 26real-type-suffix: uno de los siguientesF f D d M m

19es una forma abreviada de:real-type-suffix:F f D d M m

272.2.2 Gramtica lxica 28La gramtica lxica de C# se presenta en 2.3, 2.3.3 y 2.5. Los smbolos terminales de la gramtica lxica son 29los caracteres del juego de caracteres Unicode, y la gramtica lxica especifica cmo se combinan los caracteres 30para formar tokens (2.4), espacios en blanco (2.3.3), comentarios (2.3.2) y directivas de preprocesamiento 31(2.5). 32Todos los archivos de cdigo fuente de un programa de C# deben ajustarse a la produccin entrada (input) de la 33gramtica lxica (2.3). 342.2.3 Gramtica sintctica 35La gramtica sintctica de C# se presenta en los captulos y apndices que siguen a este captulo. Los smbolos 36terminales de la gramtica sintctica son los tokens definidos por la gramtica lxica, mientras la gramtica 37sintctica es la que especifica cmo se combinan los smbolos para formar programas de C#. 38Todos los archivos de cdigo fuente de un programa de C# deben cumplir la produccin unidad de compilacin 39(compilation-unit) de la gramtica sintctica (9.1).

103Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

39

104Especificacin del lenguaje C#

12.3 Anlisis lxico 2La produccin entrada (input) define la estructura lxica de un archivo de cdigo fuente de C#. Un archivo de 3cdigo fuente de un programa de C# debe ajustarse a esta produccin de la gramtica lxica. 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18input: input-sectionopt input-section: input-section-part input-section input-section-part input-section-part: input-elementsopt new-line pp-directive input-elements: input-element input-elements input-element input-element: whitespace comment token

19Cinco elementos bsicos constituyen la estructura lxica de un archivo de cdigo fuente de C#: los terminadores 20de lnea (2.3.1), el espacio en blanco (2.3.3), los comentarios (2.3.2), los smbolos (token) (2.4) y las 21directivas de preprocesamiento (2.5). De estos elementos bsicos, solamente los tokens son significativos en la 22gramtica sintctica de un programa de C# (2.2.3). 23El procesamiento lxico de un archivo de cdigo fuente de C# consiste en reducir el archivo a una secuencia de 24smbolos para formar la entrada del anlisis sintctico. Los terminadores de lnea, el espacio en blanco y los 25comentarios pueden corresponder a smbolos diferentes, y las directivas de preprocesamiento pueden hacer que 26se omitan secciones del archivo de cdigo fuente, pero por lo dems estos elementos lxicos no tienen 27repercusiones en la estructura sintctica de un programa de C#. 28Cuando varias producciones de la gramtica lxica coinciden con una secuencia de caracteres de un archivo de 29cdigo fuente, el procesamiento lxico siempre forma el elemento lxico ms largo posible. Por ejemplo, la 30secuencia de caracteres / /se procesa como el principio de un comentario en una sola lnea, porque este elemento 31lxico es ms largo que un smbolo de una sola /. 322.3.1 Terminadores de lnea 33Los terminadores de lnea dividen los caracteres de un archivo de cdigo fuente de C# en lneas. 34 new-line: 35 Carcter de retorno de carro (U+000D ) 36 Carcter de salto de lnea (U+000A ) 37 Carcter de retorno de carro (U+000D) seguido de un carcter de salto de lnea (U+000A) 38 Carcter de lnea siguiente (U+0085) 39 Carcter separador de lnea (U+2028) 40 Carcter separador de prrafo (U+2029) 41Por compatibilidad con las herramientas de edicin de cdigo fuente que agregan marcadores de fin de archivo, 42y para permitir que un archivo de cdigo fuente pueda verse como una secuencia de lneas terminadas 43correctamente, se aplican las siguientes transformaciones, por orden, a todos los archivos de cdigo fuente de un 44programa de C#:

10540

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

106

Captulo 18 Cdigo no seguro

1 2 3 4 5

Si el ltimo carcter del archivo de cdigo fuente es un carcter Control-Z (U+001A ), el carcter se elimina. Al final del archivo de cdigo de fuente se agrega un carcter de retorno de carro (U+000D ) si este archivo no est vaco y si su ltimo carcter no es un retorno de carro (U+000D ), un salto de lnea (U+000A), un separador de lnea (U+2028) o un separador de prrafo (U+2029D).

62.3.2 Comentarios 7Se aceptan dos formas de comentarios: comentarios en una lnea y comentarios delimitados. Los comentarios 8de una sola lnea empiezan con los caracteres // y se extienden hasta el final de la lnea de cdigo fuente. Los 9comentarios delimitados empiezan con los caracteres /* y terminan con los caracteres */. Estos comentarios 10pueden estar en varias lneas. 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41comment: single-line-comment delimited-comment single-line-comment: / / input-charactersopt input-characters: input-character input-characters input-character input-character: Cualquier carcter Unicode salvo un carcter de nueva lnea (new-line-character) new-line-character: Carcter de retorno de carro (U+000D ) Carcter de salto de lnea (U+000A ) Carcter de lnea siguiente (U+0085) Carcter separador de lnea (U+2028) Carcter separador de prrafo (U+2029) delimited-comment:: /* delimited-comment-textopt asterisks / delimited-comment-text:: delimited-comment-section delimited-comment-text delimited-comment-section delimited-comment-section:: not-asterisk asterisks not-slash asterisks::*

asterisks * not-asterisk: Cualquier carcter Unicode excepto * not-slash: Cualquier carcter Unicode excepto /

42Los comentarios no pueden anidarse. Las secuencias de caracteres /* y */ no tienen ningn significado especial 43dentro de un comentario //, y las secuencias de caracteres// y /* no tienen ningn significado especial dentro de 44un comentario delimitado.107Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

41

108Especificacin del lenguaje C#

1Los comentarios no se procesan dentro de literales de carcter y de cadena. 2En el ejemplo 3 4 5 6 7*/ class Hello { /* Hello, world program This program writes hello, world to the console

8 static delimitado. 12incluye un comentariovoid Main() { 9 13En el ejemplo 10 14 11 15 16 17 18// Hello, world program // This program writes hello, world to the console // class Hello // any name will do for this class {

19 static void Main() { 23muestra varios comentarios en una lnea. // this method must be named "Main" 20 242.3.3 Espacio en blanco 21 25Espacio en blanco se define como cualquier carcter con la clase Unicode Zs (que incluye el carcter de espacio) 26 22as como el carcter de tabulacin horizontal, el carcter de tabulacin vertical y el carcter de avance de pgina. 27 whitespace: 28 Cualquier carcter con clase Unicode Zs 29 Carcter de tabulacin horizontal (U+0009 ) 30 Carcter de tabulacin vertical (U+000B ) 31 Carcter de avance de pgina (U+000C) 322.4 Smbolos 33Existen varias clases de smbolos (token): identificadores, palabras clave, literales, operadores y signos de 34puntuacin. Los espacios en blanco y los comentarios no son smbolos (token), si bien actan como separadores 35entre ellos. 36 37 38 39 40 41 42 43token: identifier keyword integer-literal real-literal character-literal string-literal operator-or-punctuator

10942

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

110

Captulo 18 Cdigo no seguro

12.4.1 Secuencias de escape de caracteres Unicode 2Una secuencia de escape de caracteres Unicode representa un carcter Unicode. Las secuencias de escape de 3carcter Unicode se procesan en identificadores (2.4.2), literales de carcter (2.4.4.4) y literales de cadena 4normales (2.4.4.5). Un carcter de escape Unicode no se procesa en ninguna otra ubicacin (por ejemplo, para 5formar un operador, un signo de puntuacin o una palabra clave). 6 7 8unicode-escape-sequence: \ u hex-digit hex-digit hex-digit hex-digit \U hex-digit hex-digit hex-digit hex-digit hex-digit hex-digit hex-digit hex-digit

9Una secuencia de escape Unicode representa el carcter Unicode nico formado por el nmero hexadecimal que 10sigue a los caracteres \ u o \U. Dado que C# usa una codificacin de 16 bits de los puntos de cdigo Unicode 11en caracteres y valores de cadena, un carcter Unicode en el intervalo de U+10000 a U+10FFFF no est 12permitido en un literal de caracteres y se representa mediante un par Unicode suplente en un literal de cadena. 13Los caracteres Unicode con puntos de cdigo por encima de 0x10FFFF no se aceptan. 14No se llevan a cabo conversiones mltiples. Por ejemplo, el literal de la cadena \ u005Cu005C equivale a 15\ u005C y no a \. El valor Unicode \u005C es el carcter \. 16En el ejemplo 17 18 19 20class Class1 { static void Test(bool \u0066) { char c = '\u0066';

21 if (\u0066) 25muestra varios usos de \u0066, que es la secuencia de escape de la letra f. El programa equivale a 22 26 class Class1 23 27 24 28 29 30{ static void Test(bool f) { char c = 'f'; if (f)

31 342.4.2 Identifiers 35Las reglas de los identificadores explicadas en esta seccin se corresponden exactamente con las recomendadas 32 36por la norma Unicode Anexo 15, a excepcin del carcter de subrayado, que est permitido como carcter inicial 33(como era tradicional en el lenguaje de programacin C). Las secuencias de escape Unicode estn permitidas en 37 38los identificadores y el carcter @ est permitido como prefijo para habilitar el uso de palabras clave como 39identificadores. 40 41 42 43 44identifier: available-identifier @ identifier-or-keyword available-identifier: Un elemento identifier-or-keyword que no sea keyword

111Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

43

112Especificacin del lenguaje C#

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34

identifier-or-keyword: identifier-start-character identifier-part-charactersopt identifier-start-character: letter-character _ (carcter de subrayado U+005F ) identifier-part-characters: identifier-part-character identifier-part-characters identifier-part-character identifier-part-character: letter-character decimal-digit-character connecting-character combining-character formatting-character letter-character: Un carcter Unicode de clases Lu, Ll, Lt, Lm, Lo, o Nl Una secuencia de escape Unicode (unicode-escape-sequence) que representa un carcter de clases Lu, Ll, Lt, Lm, Lo o Nl combining-character: Un carcter Unicode de clases Mn o Mc Una secuencia de escape Unicode (unicode-escape-sequence) que representa un carcter de clases Mn o Mc decimal-digit-character: Un carcter Unicode de la clase Nd Una secuencia de escape Unicode (unicode-escape-sequence) que representa un carcter de la clase Nd connecting-character: Un carcter Unicode de la clase Pc Una secuencia de escape Unicode (unicode-escape-sequence) que representa un carcter de la clase Pc formatting-character: Un carcter Unicode de la clase Cf Una secuencia de escape Unicode (unicode-escape-sequence) que representa un carcter de la clase Cf

35Para obtener ms informacin sobre las anteriores clases de caracteres, consulte la seccin 4.5 de la versin 3.0 36de la norma Unicode (Unicode Standard, Version 3.0). 37Entre los ejemplos de identificadores vlidos se incluyen i den t i f i e, _ iden t i f i e r2 @if. r1 , y 38Los identificadores incluidos en programas segn la norma debern seguir el formato cannico definido en el 39documento Unicode Normalization Form C (anexo 15 de la norma Unicode). El comportamiento ante 40identificadores que no se ajusten a dicho formato depender de la implementacin; no obstante, no sern 41necesarios diagnsticos. 42El prefijo @ habilita el uso de palabras clave como identificadores, lo cual resulta til cuando se interacta 43con otros lenguajes de programacin. El carcter @ en realidad no forma parte del identificador, por lo que el 44identificador podra considerarse en otros lenguajes como un identificador normal, sin el prefijo. Los 45identificadores con prefijo @ se conocen como identificadores textuales. El uso del prefijo @ para los 46identificadores que no son palabras clave est permitido, pero no se recomienda por cuestin de estilo.11344Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

114

Captulo 18 Cdigo no seguro

1En el ejemplo: 2 3 4 5 6class @class { public static void @static(bool @bool) { if (@bool) System.Console.WriteLine("true");

20Dos identificadores se consideran el mismo si son idnticos despus de aplicarse las siguientes 21transformaciones, por orden: 22 23 24 25El prefijo @, si aparece, ser eliminado.

7 else 11 class Class1 8 12 { 9 13 static void M() { 10 14 cl\u0061ss.st\u0061tic(true); 17define una clase denominada c lass con un mtodo esttico llamado s ta t i que toma un parmetro c 15denominado bool. Tenga en cuenta que, dado que los escapes de Unicode no estn permitidos en las palabras 18 19clave, el smbolo cl\u0061ss es un identificador idntico a @class. 16

Cada secuencia de escape Unicode (unicode-escape-sequence) se transformar en su carcter Unicode correspondiente. Todos los caracteres de formato (formatting-characters) sern eliminados.

26Los identificadores que contienen dos caracteres de subrayado (U+005F) consecutivos se reservan para uso de 27la implementacin. Por ejemplo, una implementacin podra proporcionar palabras clave extendidas que 28empiecen por dos caracteres de subrayado. 292.4.3 Palabras clave 30Una palabra clave es una secuencia de caracteres similar a un identificador que est reservada y no puede 31utilizarse como identificador excepto cuando tiene como prefijo el carcter @.

115Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

45

116Especificacin del lenguaje C#

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17

keyword: una de las siguientesabs t rac t as base boo l break byte case ca tch char checked c lass cons t cont inue dec ima l de fau l t de legate do doub le e l se enu m event exp l i c i t exte rn f a l se f i na l l y f i xed f l oa t fo r f o reach goto if imp l i c i t in int i n te r face i n te rna l is l ock l ong namespace new nu l l ob jec t opera to r out ove r r i de params pr i va te pro tec tedpub l i c readon ly re f re tu rn sby te sea led shor t s i zeo f s tacka l l oc ta t i c s s t r i ng s t ruc t sw i t ch th i s th row t rue t ry t ypeo f u in t u long unchecked unsa fe ushor t us ing v i r tua l vo id vo la t i l e whi l e

18En algunos lugares de la gramtica, hay identificadores especficos con significados especiales, pero no son 19palabras clave. Por ejemplo, en una declaracin de propiedad, los identificadores get y se t tienen un 20significado especial (10.6.2). En estas ubicaciones no se permite usar identificadores distintos de get o set, 21por lo que este uso no presenta conflictos si se utilizan estas palabras como identificadores. 222.4.4 Literales 23Un literal es una representacin en cdigo fuente de un valor. 24 25 26 27 28 29 30literal: boolean-literal integer-literal real-literal character-literal string-literal null-literal

312.4.4.1 Literales booleanos 32Existen dos valores literales booleanos: true y false. 33 34 35boolean-literal:t rue f a l se

36El tipo de un literal booleano (boolean-literal) es boo l. 372.4.4.2 Literales enteros 38Los literales enteros permiten escribir valores de los tipos int, uint, long, y ulong. Los literales enteros tienen 39dos formatos posibles: decimal y hexadecimal. 40 41 42 43 4411746

integer-literal: decimal-integer-literal hexadecimal-integer-literal decimal-integer-literal: decimal-digits integer-type-suffixopt

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

118

Captulo 18 Cdigo no seguro

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 17 18 19 20 21 22 23

decimal-digits: decimal-digit decimal-digits decimal-digit decimal-digit: uno de los siguientes0 U 1 u 2 L 3 l 4 UL 5 Ul 6 7 uL 8 ul 9 LU Lu lU lu

integer-type-suffix: uno de los siguientes hexadecimal-integer-literal: 0x hex-digits integer-type-suffixopt 0X hex-digits integer-type-suffixopt hex-digits: hex-digit hex-digits hex-digit hex-digit: uno de los siguientes0 1 2 3 4 5 6 7 8 9 A B C D E F a b c d e f

16El tipo de un literal entero se determina como sigue:Si el literal no tiene sufijo, su tipo es el primero de los tipos en los cuales se puede representar su valor: i n t , u in t long, ulong. , Si el literal tiene el sufijo U o u, su tipo es el primero de los tipos en los cuales se puede representar su valor: uint, ulong. Si el literal tiene el sufijo L o l, su tipo es el primero de los tipos en los cuales se puede representar su valor: long, ulong. Si el literal tiene el sufijo UL, Ul, uL, ul, LU, Lu, lU, o lu, es de tipo ulong.

24Si el valor representado por un literal entero est fuera del intervalo de valores del tipo ulong, se produce un 25error en tiempo de compilacin. 26Por cuestiones de estilo, a la hora de escribir literales de tipo long se recomienda el uso de L en lugar de l 27para evitar la fcil confusin de la letra l con el dgito 1. 28Para que el nmero de valores int y long escritos como literales enteros decimales sea el mnimo posible, 29existen las dos reglas siguientes: 30 31 32 33 34 35 36 37 38 39Cuando aparece un literal entero decimal (decimal-integer-literal) con el valor 2147483648 (231) y sin sufijo de tipo entero (integer-type-suffix) como el smbolo (token) inmediatamente posterior a un smbolo de operador unario menos (7.6.2), el resultado es una constante de tipo int con el valor 2147483648 (231). En todas las dems situaciones, un literal entero decimal (decimal-integer-literal) de estas caractersticas es de tipo uint. Cuando aparece un literal entero decimal (decimal-integer-literal) con el valor 9223372036854775808 (263) y sin sufijo de tipo entero (integer-type-suffix) o con el sufijo de tipo entero L o l como smbolo inmediatamente posterior de un smbolo de operador unario menos (7.6.2), el resultado es una constante de tipo long con el valor 9223372036854775808 (263). En todas las dems situaciones, un literal entero decimal (decimal-integer-literal) de estas caractersticas es de tipo ulong.

402.4.4.3 Literales reales 41Los literales reales permiten escribir valores de los tipos float, double y decimal.

119Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

47

120Especificacin del lenguaje C#

1 2 3 4 5 6 7 8 9 10 11 12

real-literal: decimal-digits . decimal-digits exponent-partopt real-type-suffixopt . decimal-digits exponent-partopt real-type-suffixopt decimal-digits exponent-part real-type-suffixopt decimal-digits real-type-suffix exponent-part: e signopt decimal-digits E signopt decimal-digits sign: uno de los siguientes+ -

real-type-suffix: uno de los siguientesF f D d M m

13Si no se especifica el sufijo de tipo real (real-type-suffix ), el tipo del literal real es doub le. De lo contrario, el 14sufijo de tipo real determina el tipo del literal real, como sigue: 15 16 17 18 19 20 21 22 23 24Un literal real con el sufijo F o f es de tipo float. Por ejemplo, los literales 1f, 1.5f, 1e10f y 123.456F son de tipo float. Un literal real con el sufijo D o d es de tipo double. Por ejemplo, los literales 1d, 1.5d, 1e10d y 123.456D son de tipo double. Un literal real con el sufijo M o m es de tipo decimal. Por ejemplo, los literales 1m, 1.5m, 1e10m y 123.456M son de tipo decimal. Este literal se convierte en un valor decimal tomando el valor exacto y, si es necesario, redondeando al valor ms cercano que se pueda representar mediante el redondeo de banca (4.1.7). Se conserva cualquier escala que se detecte en el literal, salvo que el valor est redondeado o sea cero (en este caso, el signo y la escala son 0). Por lo tanto, el anlisis del literal 2.900m se interpreta para formar un decimal con signo 0, coeficiente 2900 y escala 3.

25Si el literal especificado no puede representarse en el tipo indicado, se produce un error en tiempo de 26compilacin. 27El valor de un literal real de tipo f l oa t doub le se determina mediante el uso del modo redondeo al ms o 28cercano de IEEE. 29Tenga en cuenta que, en un literal real, siempre son necesarios dgitos decimales tras el punto decimal. Por 30ejemplo, 1 .3F es un literal real pero 1 .F no lo es. 312.4.4.4 Literales de carcter 32Un literal de carcter representa un carcter nico y normalmente est compuesto por un carcter entre comillas, 33como por ejemplo ' a .' 34 35 36 37 38 39 40 41 42 4312148

character-literal: ' character ' character: single-character simple-escape-sequence hexadecimal-escape-sequence unicode-escape-sequence single-character: Cualquier carcter excepto ' (U+0027 ), \ (U+005C), y carcter de nueva lnea (new-linecharacter)

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

122

Captulo 18 Cdigo no seguro

1 2 3 4

simple-escape-sequence: una de las siguientes\' \" \\ \0 \a \b \f \n \r \t \v

hexadecimal-escape-sequence: \ x hex-digit hex-digitopt hex-digitopt hex-digitopt

5Todo carcter que siga a un carcter de barra diagonal (\) en un carcter (character) debe ser uno de los 6siguientes: ', ", \, 0, a, b, f, n, r, t, u, U, x, v. En caso contrario, se producir un error en tiempo de compilacin. 7Una secuencia de escape hexadecimal representa un solo carcter Unicode cuyo valor est formado por el 8nmero hexadecimal que siga a \x. 9Si el valor representado por un literal de carcter es mayor que U+FFFF, se produce un error en tiempo de 10compilacin. 11Una secuencia de escape de caracteres Unicode (2.4.1) en un literal de caracteres debe estar comprendido en el 12intervalo de U+0000 a U+FFFF. 13Una secuencia de escape sencilla representa una codificacin de caracteres Unicode, como se describe en la 14tabla inferior.15

Secuencia de escape\' \" \\ \0 \a \b \f \n \r \t \v

Nombre del carcter Comilla simple Comilla doble Barra invertida Nulo Alerta Retroceso Avance de pgina Nueva lnea Retorno de carro Tabulacin horizontal Tabulacin vertical

Codificacin Unicode0x0027 0x0022 0x005C 0x0000 0x0007 0x0008 0x000C 0x000A 0x000D 0x0009 0x000B

16 17El tipo de un literal de caracteres (character-literal) es char. 182.4.4.5 Literales de cadena 19C# admite dos formatos de literales de cadena: literales de cadena regulares y literales de cadena textuales. 20Un literal de cadena regular consta de cero o ms caracteres entre comillas dobles (como en "hello") y puede 21incluir secuencias de escape sencillas (como \t para el carcter de tabulacin) y secuencias de escape 22hexadecimales y Unicode. 23Un literal de cadena textual consta de un carcter @ seguido de un carcter de comillas dobles, cero o ms 24caracteres y un carcter de comillas dobles de cierre. Un ejemplo sencillo puede ser @"he l l o " En un literal de .123Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

49

124Especificacin del lenguaje C#

1cadena textual, los caracteres comprendidos entre los delimitadores se interpretan de manera literal, siendo la 2nica excepcin una secuencia de escape comillas (quote-escape-sequence). En concreto, las secuencias de 3escape sencillas, las secuencias de escape hexadecimales y Unicode no se procesan en los literales de cadena 4textuales. Un literal de cadena textual puede estar en varias lneas. 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32string-literal: regular-string-literal verbatim-string-literal regular-string-literal: " regular-string-literal-charactersopt " regular-string-literal-characters: regular-string-literal-character regular-string-literal-characters regular-string-literal-character regular-string-literal-character: single-regular-string-literal-character simple-escape-sequence hexadecimal-escape-sequence unicode-escape-sequence single-regular-string-literal-character: Cualquier carcter excepto " (U+0022 ), \ (U+005C), y un carcter de nueva lnea (new-linecharacter) verbatim-string-literal: @" verbatim -string-literal-charactersopt " verbatim-string-literal-characters: verbatim-string-literal-character verbatim-string-literal-characters verbatim-string-literal-character verbatim-string-literal-character: single-verbatim-string-literal-character quote-escape-sequence single-verbatim-string-literal-character: Cualquier carcter excepto " quote-escape-sequence:""

33Todo carcter que siga a un carcter de barra diagonal (\) en un carcter literal de cadena regular (regular-string34literal-character) debe ser uno de los siguientes: ', ", \, 0, a, b, f, n, r, t, u, U, x, v. En caso contrario, se 35producir un error en tiempo de compilacin. 36En el ejemplo 37 38 39 40 41 42 43 4412550

s t r i ng a = "he l l o , wor ld" ; s t r i ng b = @"he l l o , wor ld" ; s t r i ng c = "he l l o \ t wor ld" ; s t r i ng d = @"he l l o \ t wor ld" ; s t r i ng e = " J oe sa id \ "He l l o \ " to me" ;

/ / he l l o , wor ld / / he l l o , wor ld / / he l l o wor ld / / he l l o \ t wor ld / / J oe sa id "He l l o " to me

s t r i ng f = @"Joe sa id " "He l l o " " to me" ; / / J oe sa id "He l l o " to me s t r i ng g = " \ \ \ \ se rve r \ \ sha re \ \ f i l e . t x t " ; / / \ \ se rve r \ sha re \ f i l e . t x t s t r i ng h = @"\ \ se rve r \ sha re \ f i l e . t x t " ; / / \ \ se rve r \ sha re \ f i l e . t x t

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

126

Captulo 18 Cdigo no seguro

1 2

string i = "one\r\ntwo\r\nthree"; string j = @"one

3 two 5muestra varios literales de cadena. El ltimo literal de cadena, j, es un literal de cadena textual que ocupa varias 6 4lneas. Los caracteres encerrados entre comillas, incluidos los espacios en blanco (por ejemplo, caracteres de 7nueva lnea), se conservan literalmente. 8Puesto que una secuencia de escape hexadecimal puede tener un nmero variable de dgitos hexadecimales, el 9literal de cadena " \ x123"contiene un solo carcter con un valor hexadecimal de 123. Para crear una cadena que 10contenga el carcter con el valor hexadecimal 12 seguido del carcter 3, se podra escribir " \ x00123"o "\x12" 11+ "3" en su lugar. 12El tipo de un literal de cadena (string-literal) es string. 13Cada literal de cadena no genera necesariamente una nueva instancia de cadena. Cuando aparecen dos o ms 14literales de cadena equivalentes segn el operador de igualdad de cadenas (7.9.7) en el mismo programa, estos 15literales se refieren a la misma instancia de cadena. Por ejemplo, el resultado del programa 16 17 18 19class Test { static void Main() { object a = "hello";

20 object b = "hello"; 24es True porque los dos literales hacen referencia a la misma instancia de cadena. 21 25 222.4.4.6 El literal null 26 null-literal: 23 27 nu l l 28El tipo de un literal nulo (null-literal) es el tipo null. 292.4.5 Operadores y signos de puntuacin 30Existen varias clases de operadores y signos de puntuacin. Los operadores se utilizan en las expresiones para 31describir operaciones que implican uno o ms operandos. Por ejemplo, la expresin a + b usa el operador + 32para sumar los dos operandos, a y b. Los signos de puntuacin permiten agrupar y separar. 33 34 35 36 37 38operator-or-punctuator: uno de los siguientes{ + = == |= } < != ^= [ * > = ( % ++ += -> ) & --= . | && *= , ^ || /= : ! > &=

392.5 Directivas de preprocesamiento 40Las directivas de preprocesamiento ofrecen la capacidad de omitir condicionalmente secciones de los archivos 41de cdigo fuente, con el fin de notificar errores y advertencias, as como de delimitar regiones caractersticas del 42cdigo fuente. El trmino directivas de preprocesamiento se utiliza por motivos de coherencia con los 43lenguajes de programacin C y C++. En C#, no existe un paso de preprocesamiento individual; las directivas de 44preprocesamiento se procesan como parte de la fase de anlisis lxico.127Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

51

128Especificacin del lenguaje C#

1 2 3 4 5 6 8 9 10 11 12 13 14

pp-directive: pp-declaration pp-conditional pp-line pp-diagnostic pp-region#def ine y #unde f , que permiten definir y anular, respectivamente, smbolos de compilacin condicional

7A continuacin se indican las directivas de preprocesamiento disponibles:(2.5.3).#i f, #el i , #else, y #endif, para omitir de forma condicional secciones de archivos de cdigo fuente f

(2.5.4).#line, que permite controlar nmeros de lnea de errores y advertencias (2.5.7). #error y #warning, que permiten emitir errores y advertencias, respectivamente (2.5.5). #region y #endregion, para marcar de forma explcita secciones del cdigo fuente (2.5.6).

15Una directiva de preprocesamiento siempre ocupa una lnea independiente del cdigo fuente y siempre empieza 16por un carcter # y un nombre de directiva de preprocesamiento. Puede haber un espacio en blanco antes del 17carcter # y entre ste y el nombre de la directiva. 18Una lnea del cdigo fuente que contiene una directiva #define, #undef, #if, #elif, #else, #endif o #line 19puede terminar con un comentario de una sola lnea. Los comentarios delimitados (el estilo de comentarios /* 20*/ ) no estn permitidos en las lneas de cdigo fuente que contienen directivas de preprocesamiento. 21Las directivas de preprocesamiento no son smbolos (tokens) y no forman parte de la gramtica sintctica de C#. 22No obstante, las directivas de preprocesamiento pueden utilizarse para incluir o excluir secuencias de smbolos 23y, de esta forma, pueden afectar al significado de un programa de C#. Por ejemplo, una vez compilado, el 24programa: 25 26 27 28 29 30 31 34 32 35 33 36#define A #undef B class C { #if A void F() {} #else #if B void H() {} #else

37 void I() {} 40produce como resultado exactamente la misma secuencia de smbolos que el programa: 38 41 class C 39 42 { 43 44 45 12952Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

void F() {}

130

Captulo 18 Cdigo no seguro

1Por lo tanto, aunque los dos programas sean muy diferentes lxicamente, sintcticamente son idnticos. 22.5.1 Smbolos de compilacin condicional 3La compilacin condicional que suministran funcionalmente las directivas #i f, #e l i ,f #else, y #endif se 4controla mediante expresiones de preprocesamiento (2.5.2) y smbolos de compilacin condicional. 5 6conditional-symbol: Cualquier elemento identifier-or-keyword excepto t rueo f a l se

7Un smbolo de compilacin condicional tiene dos estados posibles: definido o no definido. Al principio del 8procesamiento lxico de un archivo de cdigo fuente, un smbolo de compilacin condicional tiene el estado no 9definido, a menos que haya sido definido de forma explcita por un mecanismo externo (como una opcin del 10compilador de la lnea de comandos). Cuando se procesa una directiva #define, el smbolo de compilacin 11condicional nombrado en la directiva queda definido en el archivo de cdigo fuente. El smbolo permanece 12definido hasta que se procesa una directiva #undef del mismo smbolo o hasta que se llega al final del archivo 13de cdigo fuente. Una de las implicaciones es que las directivas #define y #undef de un archivo de cdigo 14fuente no surten efecto en otros archivos de cdigo fuente del mismo programa. 15Cuando se hace referencia a un smbolo de compilacin condicional definido en una expresin de 16preprocesamiento, ste adquiere el valor booleano true, y un smbolo de compilacin condicional no definido 17tiene el valor booleano false. No es necesario que los smbolos de compilacin condicional se declaren 18explcitamente antes de que se haga referencia a ellos en expresiones de preprocesamiento. En lugar de ello, los 19smbolos no declarados simplemente no se definen y, por lo tanto, tienen el valor false. 20El espacio de nombres de los smbolos de compilacin condicional es nico y exclusivo de todas las dems 21entidades con nombre de un programa de C#. Slo puede hacerse referencia a los smbolos de compilacin 22condicional en directivas #define y #undef y en expresiones de preprocesamiento. 232.5.2 Expresiones de preprocesamiento 24Las expresiones de preprocesamiento pueden encontrarse en las directivas #if y #elif. En las expresiones de 25preprocesamiento se permiten los operadores !, ==, !=, && y ||, adems de los parntesis, empleados para 26agrupar. 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41pp-expression: whitespaceopt pp-or-expression whitespaceopt pp-or-expression: pp-and-expression pp-or-expression whitespaceopt | | whitespaceopt pp-and-expression pp-and-expression: pp-equality-expression pp-and-expression whitespaceopt && whitespaceopt pp-equality-expression pp-equality-expression: pp-unary-expression pp-equality-expression whitespaceopt = = whitespaceopt pp-unary-expression pp-equality-expression whitespaceopt != whitespaceopt pp-unary-expression pp-unary-expression: pp-primary-expression ! whitespaceopt pp-unary-expression

131Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

53

132Especificacin del lenguaje C#

1 2 3 4 5

pp-primary-expression:t rue f a l se

conditional-symbol ( whitespaceopt pp-expression whitespaceopt )

6Cuando se hace referencia a un smbolo de compilacin condicional definido en una expresin de 7preprocesamiento, ste adquiere el valor booleano t rue y un smbolo de compilacin condicional no definido , 8tiene el valor booleano f a l se . 9La evaluacin de una expresin de preprocesamiento siempre produce un valor booleano. Las reglas de 10evaluacin de una expresin de preprocesamiento son las mismas que las de una expresin constante (7.15), 11excepto en que las nicas entidades definidas por el usuario a las que puede hacerse referencia son smbolos de 12compilacin condicional. 132.5.3 Directivas de declaracin 14Las directivas de declaracin permiten definir o anular la definicin de smbolos de compilacin condicional. 15 16 17 18 19pp-declaration: whitespaceopt # whitespaceopt define whitespace conditional-symbol pp-new-line whitespaceopt # whitespaceopt undef whitespace conditional-symbol pp-new-line pp-new-line: whitespaceopt single-line-commentopt new-line

20El procesamiento de una directiva #def ine causa la definicin del smbolo de compilacin condicional dado, 21empezando en la lnea del cdigo fuente que sigue a la directiva. De igual manera, el procesamiento de una 22directiva #unde f causa la eliminacin de la definicin del smbolo de compilacin condicional dado, 23empezando en la lnea del cdigo fuente que sigue a la directiva. 24Todas las directivas #def ine y #unde f de un archivo de cdigo fuente deben aparecer antes del primer smbolo 25(token) (2.4) en el archivo de cdigo fuente; de lo contrario, se producir un error en tiempo de compilacin. 26En trminos intuitivos, las directivas #define y #undef deben preceder a cualquier cdigo real en el archivo 27de cdigo fuente. 28En el ejemplo: 29 #def ine Ente rp r i se 30 #i f Pro fess i ona l | | Ente rp r i se 31 #def ine Advanced 32 #end i f 33 namespace Megacorp .Data 34 { 35 #i f Advanced 36 c lass P ivo t Tab le { . . . } 37 #end i f 39es vlido porque las directivas #define preceden al primer smbolo (token) (la palabra clave namespace) en 38 40el archivo de cdigo fuente. 41El siguiente ejemplo dara como resultado un error en tiempo de compilacin porque en l hay una directiva 42#define despus del cdigo real:

13354

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

134

Captulo 18 Cdigo no seguro

1 2 3 4

#define A namespace N { #define B

5 #if B 9Puede utilizarse #def ine para definir un smbolo de compilacin condicional que ya est definido, sin 6 10necesidad de que intervenga ningn smbolo #unde f para ello. El ejemplo siguiente define un smbolo de 11compilacin condicional A y despus lo define otra vez. 7 8 12#define A

13#undef#define A la definicin de un smbolo de compilacin condicional que no est definido. En el 14 puede anular 15siguiente ejemplo se define un smbolo de compilacin condicional A para despus eliminar dicha definicin dos 16veces; el segundo #undef , pese a no surtir ningn efecto, sigue siendo vlido. 17 18 19#define A #undef A

135Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

55

136Especificacin del lenguaje C#

12.5.4 Directivas de compilacin condicional 2Las directivas de compilacin condicional permiten incluir o excluir de forma condicional partes de un archivo 3de cdigo fuente. 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31pp-conditional: pp-if-section pp-elif-sectionsopt pp-else-sectionopt pp-endif pp-if-section: whitespaceopt # whitespaceopt i f whitespace pp-expression pp-new-line conditionalsectionopt pp-elif-sections: pp-elif-section pp-elif-sections pp-elif-section pp-elif-section: whitespaceopt # whitespaceopt e l i f whitespace pp-expression pp-new-line conditionalsectionopt pp-else-section: whitespaceopt # whitespaceopt e l se pp-new-line conditional-sectionopt pp-endif: whitespaceopt # whitespaceopt end i f pp-new-line conditional-section: input-section skipped-section skipped-section: skipped-section-part skipped-section skipped-section-part skipped-section-part: skipped-charactersopt new-line pp-directive skipped-characters: whitespaceopt not-number-sign input-charactersopt not-number-sign: Cualquier carcter de entrada (input-character) excepto #

32Como indica la sintaxis, las directivas de compilacin condicional deben escribirse como conjuntos formados 33por (en este orden): una directiva #i f , cero o ms directivas #el i f, cero o ms directivas #else y una directiva 34#endif. Entre las directivas se encuentran secciones condicionales de cdigo fuente. Cada seccin est 35controlada por la directiva inmediatamente precedente. Una seccin condicional puede contener directivas de 36compilacin condicional anidadas a condicin de que dichas directivas formen conjuntos completos. 37Una condicional pp (pp-conditional) selecciona como mucho una de las secciones condicionales (conditional38section) contenidas para el procesamiento lxico normal: 39 40 41 42 4313756

Las expresiones pp (pp-expression) de las directivas #if y #elif se evalan por orden hasta que una produce un resultado true. Si una expresin produce true, se selecciona la seccin condicional (conditional-section) de la directiva correspondiente. Si el resultado de todas las expresiones pp (pp-expression) es false, y si hay presente una directiva #else, se selecciona la seccin condicional (conditional-section) de la directiva #else.

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

138

Captulo 18 Cdigo no seguro

1

En caso contrario, no se selecciona la seccin condicional (conditional-section).

2La seccin condicional seleccionada, si existe, se procesa como una seccin entrada (input-section) normal: el 3cdigo fuente de la seccin debe cumplir la gramtica lxica, se generan smbolos a partir de dicho cdigo y las 4directivas de preprocesamiento de la seccin tienen los efectos prescritos. 5Las secciones condicionales restantes (conditional-sections), si existen, se procesan como secciones omitidas 6(skipped-sections): excepto en lo que respeta a las directivas de preprocesamiento, el cdigo fuente de la seccin 7no tiene por qu cumplir la gramtica lxica; no se generan tokens a partir del cdigo fuente de la seccin; y las 8directivas de preprocesamiento de la seccin deben ser lxicamente correctas, pero en caso contrario no se 9procesan. Dentro de una seccin condicional (conditional-section) que se ha procesado como seccin 10omitida(skipped-section), cualquier seccin condicional (conditional-section) anidada (contenida en 11construcciones #i f...#end i f y #region...#endregion anidadas) tambin se procesa como seccin omitida 12(skipped-section). 13En el ejemplo siguiente se ilustra cmo pueden anidarse directivas de compilacin condicional: 14 15 16 17 18 19 20 21 22#define Debug // Debugging on #undef Trace // Tracing off class PurchaseTransaction { void Commit() { #if Debug CheckConsistency(); #if Trace WriteToLog(this.ToString());

28 23Excepto por las directivas de preprocesamiento, el cdigo fuente omitido no se somete al anlisis lxico. Por 29ejemplo, el cdigo siguiente es vlido, a pesar del comentario sin terminacin de la seccin #else: 24 30 #define Debug // Debugging on 25 31 class PurchaseTransaction 26 32 { 27 33 void Commit() { 34 35#if Debug CheckConsistency();

36 #else 41 37No obstante, debe tenerse en cuenta que las directivas de preprocesamiento deben ser lxicamente correctas 42aunque se encuentren en secciones omitidas del cdigo fuente. 38 43Las directivas de preprocesamiento no se procesan cuando aparecen en elementos de entrada que ocupan varias 44lneas. Por ejemplo, el programa: 39 40

139Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

57

140Especificacin del lenguaje C#

1 2 3 4 5 6 7 9 14 10 15

class Hello { static void Main() { System.Console.WriteLine(@"hello, #if Debug world #else

13da como resultado: 8hello, #if Debug

11 16 world 12 17 #else 20En casos concretos, el conjunto de directivas de preprocesamiento que se procesa puede depender de la 18 21evaluacin de la expresin pp (pp-expression). En el ejemplo: 19 22 23#if X /*

24 #else 27 25muestra siempre la misma secuencia de smbolos (c lassQ { }), independientemente de que X est definido o 28no. Si X est definido, las nicas directivas que se procesan son #if y #endif, a causa del comentario en varias 26lneas. Si X no est definido, las tres directivas (#if, #else, #endif) forman parte del conjunto de directivas. 29 302.5.5 Directivas de diagnstico 31Las directivas de diagnstico permiten generar de forma explcita mensajes de error y advertencias que se 32notifican de la misma manera que otros errores y advertencias en tiempo de compilacin. 33 34 35 36 37 38pp-diagnostic: whitespaceopt # whitespaceopt er ro r pp-message whitespaceopt # whitespaceopt warning pp-message pp-message: new-line whitespace input-charactersopt new-line

39En el ejemplo: 40 # warn ing Code rev iew needed be fo re check - i n 41 #i f Debug && Reta i l 42 #er ro r A bu i l d can ' t be both debug and re ta i l 43 #end i f 44 c lass Tes t { . . . } 45muestra siempre la advertencia (Code review needed before check-in). Adems, si estn definidos los 46smbolos condicionales Debug y Retail , muestra el error en tiempo de compilacin A build can't be both14158

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

142

Captulo 18 Cdigo no seguro

1debug and retail. Observe que en un mensaje pp (pp-message) puede especificarse cualquier texto: no es 2necesario incluir smbolos formados correctamente, como indica el apstrofo (comilla simple) de la palabra 3can t . 42.5.6 Directivas de regin 5Las directivas de regin marcan de forma explcita regiones del cdigo fuente. 6 7 8 9 10 11pp-region: pp-start-region conditional-sectionopt pp-end-region pp-start-region: whitespaceopt # whitespaceopt reg ion pp-message pp-end-region: whitespaceopt # whitespaceopt endreg ion pp-message

12No se asocia ningn significado semntico a las regiones; los programadores y las herramientas automticas las 13utilizan para marcar secciones del cdigo fuente. El mensaje especificado en una directiva #reg ion o 14#endreg ion tampoco tiene un significado semntico; sencillamente se usa para identificar la regin. Las 15directivas #region y #endregion correspondientes pueden tener mensajes pp (pp-message) diferentes. 16El procesamiento lxico de una regin: 17 #reg ion 18 ... 19 #endreg ion 20se corresponde exactamente con el procesamiento lxico de una directiva de compilacin condicional de la 21forma: 22 #i f t rue 23 ... 24 #end i f 252.5.7 Directivas de lnea 26Las directivas de lnea permiten cambiar los nmeros de lnea y los nombres de archivo de cdigo fuente que 27comunica el compilador en resultados del tipo de advertencias y errores. 28Las directivas de lnea suelen utilizarse en herramientas de metaprogramacin que generan cdigo fuente C# a 29partir de otras entradas de texto. 30 31 32 33 34 35 36 37 38 39 40 41pp-line: whitespaceopt # whitespaceopt l i ne whitespace line-indicator pp-new-line line-indicator: decimal-digits whitespace file-name decimal-digitsde fau l t h idden

file-name: " file-name-characters " file-name-characters: file-name-character file-name-characters file-name-character

143Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

59

144Especificacin del lenguaje C#

1 2

file-name-character: Cualquier carcter de entrada (input-character) excepto "

3Cuando no aparecen directivas #l ine el compilador muestra en su resultado los nmeros de lnea y nombres de , 4archivo de cdigo fuente reales. La directiva #l inesuele utilizarse en herramientas de metaprogramacin que 5generan cdigo fuente C# a partir de otras entradas de texto. Cuando se procesa una directiva #line que incluye 6un indicador de lnea (line-indicator) que no es default, el compilador trata la lnea siguiente a la directiva 7como si tuviera el nmero de lnea dado (y el nombre de archivo, si se especifica). 8Una directiva #line default invierte el efecto de todas las directivas #line anteriores. El compilador comunica 9la informacin de lnea real para las lneas posteriores, exactamente igual que si no se hubieran procesado 10directivas #line. 11Una directiva #line hidden no produce ningn efecto sobre el archivo ni sobre los nmeros de lnea de los que 12se informa en los mensajes de error, pero s afecta a la depuracin en el nivel de cdigo fuente. Durante la 13depuracin, las lneas entre una directiva #line hidden y la siguiente directiva #line (no #line hidden) 14carecern de informacin de nmero de lnea. Cuando se recorre el cdigo en el depurador, estas lneas se 15omiten por completo. 16Observe que los nombres de archivo (file-name) se diferencian de los literales de cadena ordinarios en que los 17caracteres de escape no se procesan; en los nombres de archivo, el carcter \ slo designa un carcter 18convencional de barra diagonal inversa.

14560

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

146

Captulo 18 Cdigo no seguro

1

3.Conceptos bsicos

23.1 Inicio de la aplicacin 3Una aplicacin es un ensamblado que contiene un punto de entrada. Cuando se ejecuta una aplicacin, se crea 4un nuevo dominio de aplicacin. Pueden existir varias creaciones de instancias diferentes de una aplicacin 5simultneamente en el mismo equipo, cada una con su propio dominio de aplicacin. 6Un dominio de aplicacin habilita el aislamiento de aplicaciones, al actuar como contenedor del estado de una 7aplicacin. Un dominio de aplicacin se comporta como contenedor y lmite de los tipos definidos en la 8aplicacin y en las bibliotecas de clases que utiliza. Los tipos cargados en un dominio de aplicacin son distintos 9de los mismos tipos cargados en otro, y las instancias de los objetos no se comparten directamente entre 10dominios de aplicacin. Por ejemplo, cada dominio de aplicacin mantiene su propia copia de variables estticas 11para estos tipos, y un constructor esttico de un tipo se ejecuta como mximo una vez por dominio de 12aplicacin. Las implementaciones tienen libertad para proporcionar mecanismos o directivas especficas de la 13implementacin para la creacin y destruccin de los dominios de aplicacin. 14Un inicio de programa se produce cuando el entorno de ejecucin llama a un mtodo designado, que se conoce 15como punto de entrada de la aplicacin. Este mtodo de punto de entrada siempre se denomina Main y puede 16tener una de las firmas siguientes: 17 static void Main() {...} 18 static void Main(string[] args) {...} 19 static int Main() {...} 20 static int Main(string[] args) {...} 21Como se muestra, el punto de entrada de manera opcional puede devolver un valor i n t El valor devuelto se . 22utiliza en la finalizacin de la aplicacin (3.2). 23El punto de entrada puede tener, opcionalmente, un parmetro formal. El parmetro puede tener cualquier 24nombre, pero el tipo del parmetro debe ser s t r i ng .[ Si el parmetro formal est presente, el entorno de ] 25ejecucin crea y pasa un argumento s t r i ng [que contiene los argumentos de lnea de comandos especificados al ] 26iniciar la aplicacin. El argumento string[] nunca es null, pero puede tener longitud cero si no se encuentra 27especificado ningn argumento de lnea de comandos. 28Dado que C# acepta la sobrecarga de mtodos, una clase o una estructura puede contener varias definiciones del 29mismo mtodo, a condicin de que todas tengan una firma diferente. No obstante, ninguna clase o estructura de 30un mismo programa podr contener ms de un mtodo denominado Main cuya definicin lo califique para ser 31utilizado como punto de entrada de aplicacin. Sin embargo, s se permiten otras versiones sobrecargadas de 32Main, a condicin de que tengan ms de un parmetro o de que su nico parmetro no sea de tipo string[]. 33Una aplicacin puede estar compuesta por varias clases o estructuras, dos o ms de las cuales pueden contener 34un mtodo denominado Main cuya definicin le califica para utilizarlo como punto de entrada de la aplicacin. 35En tales casos, debe utilizarse un mecanismo externo (por ejemplo, una opcin de compilador de lnea de 36comandos) para seleccionar uno de estos mtodos Main como punto de entrada. 37En C#, todos los mtodos deben estar definidos como miembros de una clase o una estructura. Normalmente, la 38accesibilidad declarada (3.5.1) de un mtodo est determinada por los modificadores de acceso (10.2.3) 39especificados en su declaracin y, de forma similar, la accesibilidad declarada de un tipo est determinada por

147Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

61

148Especificacin del lenguaje C#

1los modificadores de acceso especificados en su declaracin. Para que sea posible llamar a un mtodo dado de 2un tipo concreto, tanto el tipo como el miembro deben ser accesibles. No obstante, el punto de entrada de la 3aplicacin es un caso especial. En concreto, el entorno de ejecucin puede tener acceso al punto de entrada de la 4aplicacin con independencia de su accesibilidad declarada y de la accesibilidad declarada de sus declaraciones 5de tipo envolvente. 6A todos los dems respectos, los mtodos de punto de entrada se comportan como los de punto de no entrada. 73.2 Finalizacin de la aplicacin 8La finalizacin de la aplicacin devuelve el control al entorno de ejecucin. 9Si el tipo del valor devuelto por el mtodo de punto de entrada de la aplicacin es i n t el valor devuelto , 10cumple la funcin de cdigo de estado de finalizacin de la misma. El propsito de este cdigo es permitir la 11comunicacin del xito o el error al entorno de ejecucin. 12Si el tipo del valor devuelto del mtodo de punto de entrada es vo id, cuando se alcanza la llave de cierre (}), 13que finaliza el mtodo, o cuando se ejecuta una instruccin return que no contiene una expresin, se produce un 14cdigo de estado de finalizacin igual a 0. 15Antes de la finalizacin de una aplicacin, se llama a destructores para todos los objetos que an no hayan sido 16sometidos a la recoleccin de elementos no utilizados (salvo que se haya suprimido este tipo de limpieza 17mediante, por ejemplo, una llamada al mtodo de biblioteca GC.SuppressFinalize). 183.3 Declaraciones 19Las declaraciones de un programa de C# definen los elementos constituyentes del programa. Los programas de 20C# se organizan mediante el uso de espacios de nombres (9), que pueden contener declaraciones de tipo y 21declaraciones de espacio de nombres anidadas. Las declaraciones de tipo (9.5) se utilizan para definir clases 22(10), estructuras (11), interfaces (13), enumeraciones (14) y delegados (15). Las categoras de los 23miembros permitidos en una declaracin de tipo dependen de la forma de la declaracin. Por ejemplo, las 24declaraciones de clase pueden contener declaraciones para las constantes (10.3), campos (10.4), mtodos 25(10.5), propiedades (10.6), eventos (10.7), indizadores (10.8), operadores (10.9), constructores de 26instancia (10.10), constructores estticos (10.11), destructores (10.12) y tipos anidados. 27Una declaracin define un nombre en el espacio de declaracin (declaration space ) al que pertenece la 28declaracin. Con la excepcin de los miembros sobrecargados (3.6), es un error en tiempo de compilacin 29contar con dos o ms declaraciones que introducen miembros con el mismo nombre en un espacio de 30declaracin. No est permitido que un espacio de declaracin contenga categoras de miembros diferentes con el 31mismo nombre. Por ejemplo, un espacio de declaracin no puede contener un campo y un mtodo con el mismo 32nombre. 33Existen varios tipos diferentes de espacios de declaracin, como se explica a continuacin. 34 35 36 37 38 39 40 41 42 4314962

Dentro de todos los archivos de cdigo fuente de un programa, las declaraciones de miembro de espacio de nombres (namespace-member-declarations ) sin una declaracin de espacio de nombres envolvente son miembros de un solo espacio de declaracin combinado, denominado espacio de declaracin global (global declaration space). Dentro de todos los archivos de cdigo fuente de un programa, las declaraciones de miembro de espacio de nombres (namespace-member-declarations) de las declaraciones de espacio de nombres (namespacedeclarations) que tienen el mismo nombre completo del espacio de nombres son miembros de un solo espacio de declaracin combinado. Cada declaracin de clase, estructura o interfaz crea un nuevo espacio de declaracin. Los nombres se introducen en este espacio de declaracin mediante declaraciones de miembros de clase (class-member-

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

150

Captulo 18 Cdigo no seguro

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34

declarations), declaraciones de miembros de estructura (struct-member-declarations) o declaraciones de miembros de interfaz (interface-member-declarations). Excepto en las declaraciones de constructores de instancia y declaraciones de constructor esttico sobrecargadas, una declaracin de miembro de clase o estructura no puede introducir un miembro del mismo nombre como la clase o la estructura. Una clase, estructura o interfaz permite la declaracin de mtodos e indizadores sobrecargados. Asimismo, las clases y estructuras admiten la declaracin de operadores y constructores de instancia sobrecargados. Por ejemplo, una clase, una estructura o una interfaz pueden contener varias declaraciones de mtodo con el mismo nombre, a condicin de que dichas declaraciones difieran en su firma (3.6). Debe tenerse en cuenta que las clases base no contribuyen al espacio de declaracin de una clase, y que las interfaces base no contribuyen al espacio de declaracin de una interfaz. Por lo tanto, una clase o interfaz derivada tiene permitido declarar un miembro con el mismo nombre que un miembro heredado. Se dice que un miembro como ste oculta al miembro heredado. Una declaracin de enumeracin crea un espacio de declaracin nuevo. Los nombres se introducen en este espacio de declaracin mediante declaraciones de miembros de enumeracin (enum-member-declarations). Cada bloque (block) o bloque switch (switch-block) , , as como una instruccin for, foreach y using crea un espacio de declaracin para variables y constantes locales denominado espacio de declaracin de la variable local. Los nombres se introducen en este espacio de declaracin mediante declaraciones de variable local (local-variable-declarations) y declaraciones de constante local (local-constant-declarations). Si un bloque es el cuerpo de un constructor de instancia, de un mtodo o una declaracin de operador o de un descriptor de acceso get o set para una declaracin de indizador, los parmetros declarados en dicha declaracin sern miembros del espacio de declaracin de la variable local del bloque. Que dos miembros de un espacio de declaracin de la variable local tengan el mismo nombre supone un error. Que el espacio de declaracin de la variable local de un bloque y el espacio de declaracin de la variable local anidado contengan elementos con el mismo nombre supone un error. Por lo tanto, dentro de un espacio de declaracin anidado no es posible declarar una variable o constante local con el mismo nombre que una variable o constante local contenida en un espacio de declaracin. Es posible que dos espacios de declaracin contengan elementos con el mismo nombre siempre y cuando ninguno de los espacios de declaracin contenga al otro. Cada bloque (block) o bloque switch (switch-block) crea un espacio de declaracin independiente para las etiquetas. Los nombres se introducen en este espacio de declaracin mediante instrucciones con etiquetas (labeled-statements), y se hace referencia a ellos mediante instrucciones goto (goto-statements). El espacio de declaracin de etiquetas de un bloque incluye bloques anidados. Por lo tanto, dentro de un bloque anidado no es posible declarar una etiqueta del mismo nombre que una etiqueta contenida en un bloque contenedor.

35El orden textual de declaracin de los nombres generalmente carece de importancia. As, el orden textual no 36resulta significativo para la declaracin o el uso de espacios de nombres, constantes, mtodos, propiedades, 37eventos, indizadores, operadores, constructores de instancia, destructores, constructores estticos o tipos. El 38orden de declaracin es significativo de las siguientes formas: 39 40 41 42 43El orden de declaracin de las declaraciones de campos y de variables locales determina el orden en que se ejecutan sus inicializadores (si existen). Las variables locales no se pueden utilizar antes de su definicin (3.7). El orden de declaracin para las declaraciones de miembros de enumeracin (14.3) es importante cuando se omiten los valores de expresin constante (constant-expression).

151Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

63

152Especificacin del lenguaje C#

1El espacio de declaracin de un espacio de nombres es de extremo abierto, es decir, dos declaraciones de 2espacio de nombres con un mismo nombre completo contribuirn al mismo espacio de declaracin. Por ejemplo: 3 4 5 6 7 10 8 11 9 12 13namespace Megacorp.Data { class Customer { ... namespace Megacorp.Data { class Order {

14Las dos declaraciones de espacios de nombres anteriores contribuyen al mismo espacio de declaracin, en este ... 17 18caso declarando dos clases con los nombres completos Megacorp .Data .Cus tomery Megacorp .Data .O rde.r 15 19Como las dos declaraciones contribuyen al mismo espacio de declaracin, si cada una contiene una declaracin 20de clase con el mismo nombre se producir un error en tiempo de compilacin. 16 21Como se especific anteriormente, el espacio de declaracin de un bloque incluye cualquier bloque anidado. De 22este modo, en el siguiente ejemplo, los mtodos F y G producen errores en tiempo de compilacin porque el 23nombre i se declara en el bloque exterior y no se puede volver a declarar en el bloque interior. Sin embargo, los 24mtodos H e I son vlidos porque los dos caracteres i se declaran en bloques independientes no anidados. 25 26 27 28 29 33 30 34 31 35 32 36 39 37 40 38 41 42 43 44 45 4615364Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

class A { void F() { int i = 0; if (true) { void G() { if (true) { int i = 0; void H() { if (true) { int i = 0; } if (true) { }

154

Captulo 18 Cdigo no seguro

1 2 3 4

void I() { for (int i = 0; i < 10; i++) H(); for (int i = 0; i < 10; i++)

5 H(); 83.4 Miembros 6 9Los espacios de nombres y los tipos tienen miembros. Los miembros de una entidad estn generalmente 10disponibles mediante el uso de un nombre completo compuesto por una referencia a la entidad seguida de un 7 11smbolo . y el nombre del miembro. 12Los miembros de un tipo se declaran en el tipo o se heredan de la clase base del tipo. Si un tipo se deriva de una 13clase base, todos los miembros de dicha clase, excepto los constructores de instancia, destructores y 14constructores estticos, pasan a ser miembros del tipo derivado. La accesibilidad declarada de un miembro de 15clase base no controla si el miembro se hereda: la herencia se ampla a cualquier miembro que no sea un 16constructores de instancia, un constructor esttico o un destructor. No obstante, un miembro heredado puede no 17estar accesible en un tipo derivado, ya sea a causa de su accesibilidad declarada (3.5.1) o porque est oculto por 18una declaracin del propio tipo (3.7.1.2). 193.4.1 Miembros de espacio de nombres 20Los espacios de nombres y los tipos que no tienen un espacio de nombres envolvente son miembros del espacio 21de nombres global. Esto corresponde directamente a los nombres declarados en el espacio de declaracin 22global. 23Los espacios de nombres y los tipos declarados en de un espacio de nombres son miembros de dicho espacio. 24Esto corresponde directamente a los nombres declarados en el espacio de declaracin del espacio de nombres. 25Los espacios de nombres no presentan restricciones de acceso. No es posible declarar espacios de nombres 26privados, protegidos o internos, y los nombres de los espacios de nombres siempre son accesibles pblicamente. 273.4.2 Miembros de estructura 28Los miembros de una estructura son los miembros declarados en la estructura y los miembros heredados de la 29clase base directa de la estructura Sys tem.Va lueType la clase base indirecta ob jec t y . 30Los miembros de un tipo simple se corresponden directamente con los del tipo de la estructura con alias por el 31tipo simple: 32 33 34 35 36 37 38 39 40Los miembros de sby te son los miembros de la estructura Sys tem.SByte. Los miembros de byte son los miembros de la estructura Sys tem.By te . Los miembros de shor tson los miembros de la estructura Sys tem. In t16 . Los miembros de ushor t son los miembros de la estructura Sys tem.U In t16 . Los miembros de i n tson los miembros de la estructura Sys tem. In t32 . Los miembros de u in tson los miembros de la estructura Sys tem.U In t32 . Los miembros de l ong son los miembros de la estructura Sys tem. In t64 . Los miembros de u long son los miembros de la estructura Sys tem.U In t64 . Los miembros de char son los miembros de la estructura Sys tem.Char.65

155Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

156Especificacin del lenguaje C#

1 2 3 4

Los miembros de f l oa t los miembros de la estructura Sys tem.S ing le son . Los miembros de doub le son los miembros de la estructura Sys tem.Doub le. Los miembros de dec ima l son los miembros de la estructura Sys tem.Dec ima l. Los miembros de boo l son los miembros de la estructura Sys tem.Boo lean .

53.4.3 Miembros de enumeraciones 6Los miembros de una enumeracin son las constantes declaradas en la enumeracin, los miembros heredados de 7la clase base directa de la enumeracin Sys tem.Enum y las clases base indirectas Sys tem.Va lueTypey 8object. 93.4.4 Miembros de clase 10Los miembros de una clase son aquellos que se declaran en la clase y los que se heredan de la clase base (a 11excepcin de la clase object, que no tiene clase base). Entre los miembros heredados de la clase base se 12incluyen las constantes, los campos, los mtodos, las propiedades, los eventos, los indizadores, los operadores y 13los tipos de la clase base, pero no los constructores de instancia, los destructores ni los constructores estticos de 14la clase base. Los miembros de la base clase se heredan con independencia de su accesibilidad. 15La declaracin de una clase puede contener declaraciones de constantes, campos, mtodos, propiedades, 16eventos, indizadores, operadores, constructores de instancia, destructores, constructores estticos y tipos. 17Los miembros de object y string se corresponden directamente con los miembros de los tipos de clases de los 18que son alias: 19 20Los miembros de ob jec tson los miembros de la clase Sys tem.Ob jec t . Los miembros de s t r i ng los miembros de la clase Sys tem.S t r i ng son .

213.4.5 Miembros de interfaz 22Los miembros de una interfaz son los miembros declarados en la interfaz y en todas las interfaces base de la 23misma. Los miembros de la clase object no son, estrictamente hablando, miembros de ninguna interfaz (13.2). 24Sin embargo, los miembros de la clase object estn disponibles a travs de la bsqueda de miembros en 25cualquier tipo de interfaz (7.3). 263.4.6 Miembros de matriz 27Los miembros de una matriz son los miembros heredados de la clase System.Array. 283.4.7 Miembros de delegados 29Los miembros de un delegado son los miembros heredados de la clase System.Delegate. 303.5 Acceso a miembros 31Las declaraciones a miembros aportan control sobre el acceso a los miembros. La accesibilidad de un miembro 32se establece mediante la accesibilidad declarada (3.5.1) del miembro combinada con la accesibilidad del tipo 33contenedor inmediato, si existe. 34Cuando se permite el acceso a un miembro concreto, se dice que ste es accesible. Por otro lado, cuando no se 35permite el acceso a un miembro concreto, se dice que ste es inaccesible. El acceso a un miembro est permitido 36cuando la ubicacin textual en la que tiene lugar el acceso est incluida en el dominio de accesibilidad (3.5.2) 37del miembro.

15766

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

158

Captulo 18 Cdigo no seguro

13.5.1 Accesibilidad declarada 2La accesibilidad declarada de un miembro puede ser cualquiera de las siguientes: 3 4 5 6 7 8 9 10 11 12 13 14Public, que se selecciona mediante la inclusin de un modificador pub l i cen la declaracin del miembro. El significado intuitivo de pub l i ces acceso sin restricciones. Protected, que se selecciona mediante la inclusin de un modificador pro tec ted la declaracin del en miembro. El significado intuitivo de pro tec ted acceso restringido para la clase contenedora o los tipos es derivados de ella. Internal, que se selecciona mediante la inclusin de un modificador i n te rnaen la declaracin del miembro. l El significado intuitivo de i n te rnaes acceso restringido al programa. l Protected internal (es decir, protegida o interna), que se selecciona mediante la inclusin de los modificadores pro tec ted i n te rnaen la declaracin del miembro. El significado intuitivo de protected e l internal es acceso restringido al programa actual o a los tipos derivados de la clase contenedora. Private, que se selecciona mediante la inclusin de un modificador private en la declaracin del miembro. El significado intuitivo de private es acceso restringido al tipo contenedor.

15Segn el contexto en el que se produce la declaracin de un miembro, slo se permite declarar ciertos tipos de 16accesibilidad. Adems, si una declaracin del miembro no incluye modificadores de acceso, el contexto en que 17tiene lugar la declaracin determina la accesibilidad declarada predeterminada. 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37Los espacios de nombres tienen implcitamente la accesibilidad declarada public. Los modificadores de acceso no se pueden utilizar en las declaraciones de espacios de nombres. Los tipos declarados en las unidades de compilacin o los espacios de nombres pueden tener la accesibilidad declarada public o internal y su valor predeterminado puede ser internal. Los miembros de clase pueden tener cualquiera de las cinco clases de accesibilidad declarada y el valor predeterminado de la accesibilidad declarada private. (Debe tenerse en cuenta que un tipo declarado como miembro de una clase slo puede tener una de las cinco clases de accesibilidad declarada, mientras que un tipo declarado como miembro de un espacio de nombres slo puede tener la accesibilidad declarada public o internal.) Los miembros de estructura pueden tener la accesibilidad declarada public, internal o private, siendo el valor predeterminado private, puesto que las estructuras son implcitamente de tipo sealed. Los miembros de estructura introducidos en una estructura (es decir, no heredados por ella) no pueden tener una accesibilidad declarada protected o protected internal. Tenga en cuenta que un tipo declarado como miembro de una estructura slo puede tener una de las clases de accesibilidad declarada public, internal o private , mientras que un tipo declarado como miembro de un espacio de nombres slo puede tener la accesibilidad declarada public o internal. Los miembros de interfaz tienen implcitamente la accesibilidad declarada public. Los modificadores de acceso no se pueden utilizar en las declaraciones de miembros de interfaz. Los miembros de enumeracin tienen implcitamente la accesibilidad declarada public. Los modificadores de acceso no pueden utilizarse en las declaraciones de miembros de enumeracin.

383.5.2 Dominios de accesibilidad 39El dominio de accesibilidad de un miembro est formado por las secciones (posiblemente separadas) de texto 40del programa en las que est permitido el acceso al miembro. Para fines de definicin del dominio de 41accesibilidad de un miembro, se dice que un miembro es de nivel superior si no est declarado dentro de un tipo, 42y se dice que est anidado si se declara dentro de otro tipo. Asimismo, el texto de programa de un programa se159Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

67

160Especificacin del lenguaje C#

1define como todo el texto de programa contenido en todos los archivos de cdigo fuente. El texto de programa 2de un tipo se define como todo el texto del programa contenido entre los smbolos de apertura y cierre { y } 3del cuerpo de clase (class-body), del cuerpo de estructura (struct-body), del cuerpo de interfaz (interface-body) o 4del cuerpo de enumeracin (enum-body) del tipo (incluidos, posiblemente, los tipos anidados dentro del tipo). 5El dominio de accesibilidad de un tipo predefinido (como ob jec t i n to double) es ilimitado. , 6El dominio de accesibilidad de un tipo de nivel superior T declarado en un programa P se define como sigue: 7 8 9 10La accesibilidad declarada de T es public, el dominio de accesibilidad de T es el texto del programa de P y cualquier programa que haga referencia a P. Si la accesibilidad declarada de T es i n te rna l dominio de accesibilidad de T es el texto del programa de , el P.

11A partir de estas definiciones, se deduce que el dominio de accesibilidad de un tipo de nivel superior es, al 12menos, el texto del programa en el que se declara ese tipo. 13El dominio de accesibilidad de un miembro anidado M declarado en un tipo T dentro de un programa P se define 14como sigue (teniendo en cuenta que M probablemente sea un tipo): 15 16 17 18 19 20 21 22 23 24 25Si la accesibilidad declarada de M es public, el dominio de accesibilidad de M es el dominio de T. Si la accesibilidad declarada de M es protected internal, D ser la unin del texto de programa de P y del texto de programa de cualquier tipo derivado de T que se declare fuera de P. El dominio de accesibilidad de M es la interseccin del dominio de accesibilidad de T con D. Si la accesibilidad declarada de M es protected, D ser la unin del texto de programa de T y del texto de programa de cualquier tipo derivado de T. El dominio de accesibilidad de M es la interseccin del dominio de accesibilidad de T con D. Si la accesibilidad declarada de M es internal, el dominio de accesibilidad de M es la interseccin del dominio de accesibilidad de T con el texto de programa de P. Si la accesibilidad declarada de M es private, el dominio de accesibilidad de M es el texto del programa de T.

26De estas definiciones se deduce que el dominio de accesibilidad de un tipo anidado es siempre, al menos, el 27texto de programa del tipo donde el miembro aparece declarado. Asimismo, se concluye que el dominio de 28accesibilidad de un miembro nunca es ms inclusivo que el dominio de accesibilidad del tipo en el que se 29declara el miembro. 30En trminos intuitivos, cuando se obtiene acceso a un tipo o un miembro M, se evalan los pasos siguientes para 31garantizar que est permitido el acceso: 32 33 34 35 36 37 38 39 40 4116168

En primer lugar, si M se declara dentro de un tipo (por oposicin a una unidad de compilacin o un espacio de nombres), se produce un error en tiempo de compilacin si el tipo no est accesible. Despus, si M es public, el acceso est permitido. O bien, si M es protected internal, el acceso est permitido si se produce dentro del programa en el que est declarado M o si se produce dentro de una clase derivada de la clase en la que est declarado M y tiene lugar por medio del tipo de la clase derivada (3.5.3). O bien, si M es protected, el acceso est permitido si se produce dentro de la clase en la que est declarado M o si se produce dentro de una clase derivada de la clase en la que est declarado M y tiene lugar por medio del tipo de la clase derivada (3.5.3). O bien, si M es internal, el acceso est permitido si ocurre dentro del programa en el que est declarado M.

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

162

Captulo 18 Cdigo no seguro

1 2

O bien, si M es pr i va teel acceso est permitido si ocurre dentro del programa en el que est declarado M. , De lo contrario, el tipo o el miembro es inaccesible y se produce un error en tiempo de compilacin.

163Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

69

164Especificacin del lenguaje C#

1En el siguiente ejemplo: 2 3 4 5 8 6public class A { public static int X; internal class B { public static int X; public class C { public static int X; private class D { public static int X; internal static int Y; internal static int Y; internal static int Y;

9 7 10 11 13 12 14 15 16 19 17

20 18 21 22 24 27 25 28 29 30 31 32 33 34 35

23las clases y los miembros tienen los siguientes dominios de accesibilidad: private static int Z; 26El dominio de accesibilidad de A y A.X es ilimitado. El dominio de accesibilidad de A.Y, B, B.X, B.Y, B.C, B.C.X, y B.C.Y es el texto del programa contenedor. El dominio de accesibilidad de A.Z es el texto del programa de A. El dominio de accesibilidad de B .Z y B .D es el texto de programa de B, incluido el texto de programa de B.C y de B.D. El dominio de accesibilidad de B.C.Z es el texto del programa de B.C. El dominio de accesibilidad de B.D.X y B.D.Y es el texto de programa de B, incluido el texto de programa de B.C y de B.D. El dominio de accesibilidad de B.D.Z es el texto del programa de B.D.

36Como muestra el ejemplo, el dominio de accesibilidad de un miembro nunca es mayor que el de un tipo 37contenedor. Por ejemplo, aunque todos los miembros X tengan una accesibilidad declarada como public, todos 38excepto A.X tienen dominios de accesibilidad que estn restringidos por un tipo contenedor. 39Como se explica en la 3.4, todos los miembros de una clase base, a excepcin de los constructores de instancia, 40destructores y constructores estticos, son heredados por tipos derivados. Esto incluye incluso a los miembros 41privados de una clase base. No obstante, el dominio de accesibilidad de un miembro privado slo incluye el 42texto del programa del tipo donde el miembro aparece declarado. En el siguiente ejemplo: 43 44 4516570

c lass A { int x;Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

166

Captulo 18 Cdigo no seguro

1 2 3 5 4 6 7

static void F(B b) { b.x = 1; } class B: A { static void F(B b) { // Ok

8 b.x = 1; // Error, x not accessible 11la clase B hereda el miembro privado x de la clase A. Dado que el miembro es privado, slo est accesible 9 12dentro del cuerpo de clase (class-body) de A. Por lo tanto, el acceso a b.x es correcto en el mtodo A.F, pero no 13en el mtodo B.F. 10 143.5.3 Acceso protegido para miembros de instancia 15Cuando se obtiene acceso a un miembro de instancia protected fuera del texto del programa de la clase en la 16que est declarado, y cuando se obtiene acceso a un miembro de instancia protected internal fuera del texto 17del programa en el que est declarado, el acceso debe tener lugar a travs de una instancia del tipo de la clase 18derivada en la que se produce el acceso. Supongamos que B es una clase base que declara un miembro de 19instancia M protegido, y que D es una clase que se deriva de B. Dentro del cuerpo de clase (class-body) de D, el 20acceso a M puede tener uno de los siguientes formatos: 21 22 23 24Un nombre de tipo (type-name) o expresin primaria (primary-expression) sin calificar de la forma M. Una expresin primaria (primary-expression) de la forma E.M, a condicin de que el tipo de E sea D o una clase derivada de D. Una expresin primaria (primary-expression) de la forma base.M.

25Adems de estas formas de acceso, una clase derivada puede tener acceso a un constructores de instancia 26protegido de una clase base en un inicializador de constructor (constructor-initializer) (10.10.1). 27En el siguiente ejemplo: 28 pub l i c c lass A 29 { 30 pro tec ted i n t x ; 31 s ta t i c vo id F (A a , B b) { 32 a .x = 1 ; / / Ok 33 b .x = 1 ; / / Ok 34 } 35 36 pub l i c c lass B: A 37 { 38 s ta t i c vo id F (A a , B b) { 39 a .x = 1 ; / / Er ro r , m ust access th rough i n s tance o f B 40 b .x = 1 ; / / Ok 41 } 43dentro de A, es posible obtener acceso a x mediante instancias de A y de B, puesto que en cualquiera de los dos 42 44casos el acceso tiene lugar mediante una instancia de A o una clase derivada de A. No obstante, dentro de B, no 45es posible el acceso a x por medio de una instancia de A, puesto que A no se deriva de B.

167Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

71

168Especificacin del lenguaje C#

13.5.4 Restricciones de accesibilidad 2Algunas construcciones del lenguaje C# requieren que un tipo sea al menos tan accesible como un miembro u 3otro tipo. Se dice que un tipo T es por lo menos tan accesible como un miembro o un tipo M si el dominio de 4accesibilidad de T es un supraconjunto del dominio de accesibilidad de M. Es decir, T es por lo menos tan 5accesible como M si T es accesible en todos los contextos donde M es accesible. 6Existen las siguientes restricciones de la accesibilidad: 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23La clase base directa de un tipo de clase debe ser al menos tan accesible como el propio tipo de clase. Las interfaces base explcitas de un tipo de interfaz deben ser al menos tan accesibles como el propio tipo de interfaz. El tipo de valor devuelto y los tipos de los parmetros 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 parmetros de un mtodo deben ser al menos tan accesibles como el propio mtodo. 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. El tipo y los tipos de parmetros de un indizador deben ser al menos tan accesibles como el propio indizador. El tipo de valor devuelto y los tipos de parmetros de un operador deben ser al menos tan accesibles como el propio operador. Los tipos de parmetros de un constructores de instancia deben ser al menos tan accesibles como el propio constructores de instancia.

24En el siguiente ejemplo: 25 c lass A { . . . } 26 pub l i c c lass B: A { . . . } 27la clase B produce un error en tiempo de compilacin porque A no tiene una capacidad de acceso mnima como 28B. 29Anlogamente, en el ejemplo: 30 c lass A { . . . } 31 pub l i c c lass B 32 { 33 A F( ) {. . .} 34 i n te rna l A G( ) { . . . } 35 pub l i c A H( ) { . . . } 36 } 37el mtodo H de B produce un error en tiempo de compilacin porque el tipo de valor devuelto A no es por lo 38menos tan accesible como el mtodo.

16972

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

170

Captulo 18 Cdigo no seguro

13.6 Firmas y sobrecargas 2Los mtodos, constructores de instancia, indizadores y operadores estn caracterizados por sus firmas: 3 4 5 6 7 8 9 10 11 12 13 14 15 16La firma de un mtodo se compone del nombre del mtodo y del tipo y la categora (valor, referencia o resultado) de sus parmetros formales, considerados de izquierda a derecha. La firma de un mtodo no incluye especficamente el tipo de valor devuelto ni el modificador params que puede especificarse para el parmetro situado ms a la derecha. La firma de un constructor de instancias se compone del tipo y la categora (valor, referencia o resultado) de sus parmetros formales, considerados de izquierda a derecha. La firma de un constructor de instancias no incluye especficamente el modificador params , que puede especificarse para el parmetro situado ms a la derecha. La firma de un indizador est formada por el tipo de sus parmetros formales, considerados de izquierda a derecha. La firma de un indizador no incluye especficamente el tipo de elemento ni el modificador params que puede estar especificado para el parmetro situado ms a la derecha. La firma de un operador se compone del nombre del operador y del tipo de sus parmetros formales, considerados de izquierda a derecha. La firma de un operador no incluye especficamente el tipo del resultado.

17Las firmas constituyen el mecanismo de habilitacin que permite sobrecargar los miembros de clases, 18estructuras e interfaces: 19 20 21 22 23 24 25 26La sobrecarga de los mtodos permite que una clase, estructura o interfaz declare varios mtodos con el mismo nombre, siempre que sus firmas sean nicas dentro de esa clase, estructura o interfaz. La sobrecarga de los constructores de instancia permite que una clase o una estructura declare varios constructores de instancia, a condicin de que sus firmas sean nicas dentro de esa clase o estructura. La sobrecarga de los indizadores permite que una clase, estructura o interfaz declare varios indizadores, siempre que sus firmas sean nicas dentro de esa clase, estructura o interfaz. La sobrecarga de los operadores permite que una clase o una estructura declare varios operadores con el mismo nombre, siempre que sus firmas sean nicas dentro de esa clase o estructura.

27Aunque los modificadores de parmetros out y re fse consideran como parte de una firma, los miembros 28declarados en un tipo nico no pueden diferir en la firma nicamente por ref y out. Si dos miembros se declaran 29en el mismo tipo con firmas que seran iguales si todos los parmetros de ambos mtodos con modificadores out 30se cambiaran a modificadores ref, se produce un error de compilacin. Para otros propsitos de coincidencia de 31firma (por ejemplo, para ocultar o reemplazar), ref y out se consideran como parte de la firma y no coinciden 32entre s. (Esta restriccin se utiliza para permitir traducir con facilidad los programas de C# para que se ejecuten 33en Common Language Infrastructure (CLI), que no proporciona una manera de definir mtodos que solamente 34se diferencian en ref y out.) 35El siguiente ejemplo muestra un conjunto de declaraciones de mtodos sobrecargados con sus firmas. 36 37 38 39 40 41 42interface ITest { void F(int x); void F(ref int x); void F(out int x); void F(int x, int y); // F(int) // F(ref int) // F(out int) // F(int, int) 73 error

171Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

172Especificacin del lenguaje C#

1 2 3 4

int F(string s); int F(int x); void F(string[] a); void F(params string[] a);

// F(string) // F(int) // F(string[]) // F(string[]) error error

5Se debe } 6 tener en cuenta que los modificadores de parmetros re fy out (10.5.1) forman parte de una firma. Por 7lo tanto, F(int) y F(ref int) son firmas nicas. Sin embargo, F(refint) y F(outint) no se pueden declarar dentro 8de la misma interfaz porque sus firmas se diferencian nicamente en ref y out. Asimismo, el tipo de valor 9devuelto y el modificador params no forman parte de una firma, por lo que no es posible sobrecargar 10basndose exclusivamente en el tipo de valor devuelto o en la inclusin o exclusin del modificador params. 11Como tales, las declaraciones de los mtodos F(int) y F(params string[]) anteriormente identificadas producen 12un error en tiempo de compilacin. 133.7 mbitos 14El mbito de un nombre es la regin del texto del programa en la cual es posible referirse a la entidad declarada 15por el nombre sin la calificacin de ste. Los mbitos se pueden anidar y un mbito interno puede volver a 16declarar el significado de un nombre de un mbito exterior (sin embargo, de esta forma no se quita la restriccin 17impuesta por 3.3 de que, dentro de un bloque anidado, no se puede declarar una variable local con el mismo 18nombre de una variable local de un bloque contenedor). En este caso, se dice que el nombre del mbito externo 19est oculto en la regin del texto del programa cubierta por el mbito interno, y el acceso al nombre externo slo 20es posible si se califica el nombre. 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43El mbito de un miembro de espacio de nombres declarado por una declaracin de miembro de espacio de nombres (namespace-member-declaration) (9.4) sin declaracin de espacio de nombres (namespacedeclaration) envolvente es todo el texto del programa. El mbito de un miembro de espacio de nombres declarado mediante una declaracin de miembro de espacio de nombres (namespace-member-declaration), dentro de una declaracin de espacio de nombres (namespace-declaration) cuyo nombre completo sea N, ser el cuerpo de espacio de nombres (namespacebody) de todas las declaraciones de espacio de nombres (namespace-declaration) cuyo nombre completo sea N o empiece por N, seguido por un punto. El mbito de un nombre definido o importado por una directiva using (using-directive) (9.3) se ampla a las declaraciones de miembro de espacio de nombres (namespace-member-declarations) de la unidad de compilacin (compilation-unit) o del cuerpo de espacio de nombres (namespace-body) en que tiene lugar la directiva using (using-directive). Una directiva using (using-directive) puede ofrecer cero o ms espacios de nombres o nombres de tipos disponibles dentro de una unidad de compilacin (compilation-unit) o cuerpo de espacio de nombres (namespace-body) en particular, pero no aporta ningn miembro nuevo al espacio de declaracin subyacente. Es decir, una directiva using (using-directive) no es transitiva, sino que afecta nicamente a la unidad de compilacin (compilation-unit) o al cuerpo de espacio de nombres (namespacebody) en que tiene lugar. El mbito de un miembro declarado por una declaracin de miembro de clase (class-member-declaration) (10.2) es el cuerpo de clase (class-body) en que se produce la declaracin. Asimismo, el mbito de un miembro de clase se ampla al cuerpo de clase (class-body) de las clases derivadas que estn incluidas en el dominio de accesibilidad (3.5.2) del miembro. El mbito de un miembro declarado por una declaracin de miembro de estructura (struct-memberdeclaration) (11.2) es el cuerpo de estructura (struct-body) en que se produce la declaracin.

17374

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

174

Captulo 18 Cdigo no seguro

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25

El mbito de un miembro declarado por una declaracin de miembro de enumeracin (enum-memberdeclaration) (14.3) es el cuerpo de enumeracin (enum-body) en el que se produce la declaracin. El mbito de un parmetro declarado en una declaracin de mtodo (method-declaration) (10.5) es el cuerpo del mtodo (method-body) de dicha declaracin de mtodo (method-declaration). El mbito de un parmetro declarado en una declaracin de indizador (indexer-declaration) (10.8) es la declaracin de descriptor de acceso (accessor-declaration) de dicha declaracin de indizador (indexerdeclaration). El mbito de un parmetro declarado en una declaracin de operador (operator-declaration) (10.9) es el bloque (block) de dicha declaracin de operador (operator-declaration). El mbito de un parmetro declarado en una declaracin de constructor (constructor-declaration) (10.10) es el inicializador de constructor (constructor-initializer) y el bloque (block) de dicha declaracin de constructor (constructor-declaration). El mbito de una etiqueta declarada en una instruccin con etiqueta (labeled-statement) (8.4) es el bloque (block) en que se produce la declaracin. El mbito de una variable local declarada en una declaracin de variable local (local-variable-declaration) (8.5.1) es el bloque donde se produce la declaracin. El mbito de una variable local declarada en un bloque switch (switch-block) de una instruccin sw i t ch (8.7.2) es el bloque switch (switch-block). El mbito de una variable local declarada en un inicializador for (for-initializer) de una instruccin f o r (8.8.3) es el inicializador for (for-initializer), la condicin for (for-condition), el iterador for (for-iterator) y la instruccin (statement) contenida de la instruccin f o r . El mbito de una constante local declarada en una declaracin de constante local (local-constantdeclaration) (8.5.2) es el bloque donde se produce la declaracin. Es un error en tiempo de compilacin hacer referencia a una constante local en una posicin textual que precede a su declarador de constante (constant-declarator).

26Dentro del mbito de un miembro de espacio de nombres, clase, estructura o enumeracin es posible hacer 27referencia al miembro en una posicin textual que precede a la declaracin del miembro. Por ejemplo: 28 c lass A 29 { 30 vo id F ( ) { 31 i = 1; 32 33 i n t i = 0; 34 } 35Por lo tanto, es vlido que F haga referencia a i antes de su declaracin. 36En el mbito de una variable local, es un error en tiempo de compilacin hacer referencia a la variable local en 37una posicin textual que preceda al declarador de la variable local (local-variable-declarator). Por ejemplo: 38 39 40c lass A { i n t i = 0;

175Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

75

176Especificacin del lenguaje C#

1 2 3 4 6 5 7 8 9 10

void F() { i = 1; int i; void G() { int j = (j = 1); void H() { int a = 1, b = ++a; // Valid // Valid // Error, use precedes declaration

11 } 13En el mtodo F anterior, la primera asignacin de i no hace ninguna referencia concreta al campo declarado en el 14 12mbito externo. En lugar de ello, hace referencia a la variable local, con lo que se produce un error durante la 15compilacin, porque precede textualmente a la declaracin de la variable. En el mtodo G, el uso de j en el 16inicializador de la declaracin de j es vlido porque no precede al declarador de variable local (local-variable17declarator). En el mtodo H, un declarador de variable local (local-variable-declarator) posterior hace 18referencia correctamente a una variable local declarada en un declarador de variable local (local-variable19declarator) anterior con la misma declaracin de variable local (local-variable-declarator). 20Las reglas que rigen el mbito de las variables locales pretenden garantizar que el significado de un nombre 21utilizado en el contexto de una expresin no vare dentro de un bloque. Si el mbito de una variable local slo se 22extiende desde su declaracin hasta el final del bloque, entonces, en el ejemplo anterior, la primera asignacin 23asignar a la variable de instancia y la segunda a la variable local, lo que posiblemente producir errores en 24tiempo de compilacin si ms adelante fuera necesario reorganizar las instrucciones del bloque. 25El significado de un nombre contenido en un bloque puede diferir segn el contexto en que se utilice el nombre. 26En el siguiente ejemplo: 27 us ing Sys tem; 28 c lass A {} 29 c lass Tes t 30 { 31 s ta t i c vo id Main ( ) { 32 s t r i ng A = "he l l o , wor ld" ; 33 34 Type t = t ypeo f (A ) ; / / t ype contex t 35 Conso le .Wr i teL ine (s ) ; / / wr i tes "he l l o , wor ld" 36 Conso le .Wr i teL ine ( t ) ; / / wr i tes "A" 37 } 38el nombre A se utiliza en el contexto de una expresin para hacer referencia a la variable local A y en un } 39 40contexto de tipo para hacer referencia a la clase A. 413.7.1 Ocultar nombres 42El mbito de una entidad habitualmente abarca ms texto del programa que el espacio de declaracin de la 43entidad. En concreto, el mbito de una entidad puede incluir declaraciones que introducen nuevos espacios de 44declaracin que contienen entidades con el mismo nombre. Las declaraciones de este tipo hacen que la entidad 45original quede oculta (hidden). A la inversa, se dice que una entidad es visible cuando no est oculta.

17776

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

178

Captulo 18 Cdigo no seguro

1La ocultacin de nombres se produce cuando los mbitos se superponen a causa del anidamiento y cuando se 2superponen por herencia. Las caractersticas de los dos tipos de ocultacin se explican en las prximas 3secciones. 43.7.1.1 Ocultar mediante anidacin 5La ocultacin de nombres por medio del anidamiento puede ser el resultado del anidamiento de espacios de 6nombres o tipos contenidos en espacios de nombres, la consecuencia del anidamiento de tipos dentro de clases o 7estructuras y el resultado de las declaraciones de parmetros y variables locales.

179Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

77

180Especificacin del lenguaje C#

1En el siguiente ejemplo: 2 3 4 5 6 7 8 9class A { void F() { int i = 1; void G() { i = 1;

10 } 12dentro del mtodo F, la variable de instancia i queda oculta por la variable local i, pero dentro del mtodo G, i se 13sigue refiriendo a la variable de instancia. 11 14Cuando un nombre en un mbito interno oculte otro nombre en el mbito externo, ocultar tambin todas sus 15apariciones sobrecargadas. En el siguiente ejemplo: 16 17 18 19 20 21 22 23 26 24class Outer { static void F(string s) {} class Inner { void G() { static void F(long l) {} F(1); // Invokes Outer.Inner.F

27 } 25 29la llamada F(1) invoca la F declarada en Inner porque la declaracin interna oculta todas las apariciones 28 30externas de F. Por el mismo motivo, la llamada F("Hello") produce un error en tiempo de compilacin. 313.7.1.2 Ocultar mediante herencia 32La ocultacin de nombres por medio de la herencia ocurre cuando clases o estructuras vuelven a declarar 33nombres que se han heredado de clases base. Este tipo de ocultacin de nombres toma una de las siguientes 34formas: 35 36 37 38 39 40 41Una constante, campo, propiedad, evento o tipo introducido en una clase o estructura que oculta todos los miembros de la clase base con el mismo nombre. Un mtodo introducido en una clase o estructura que oculta todos los miembros de clase base no de mtodo con el mismo nombre, y todos los mtodos de clase base con la misma firma (nombre de mtodo y nmero de parmetros, modificadores y tipos). Indizador introducido en una clase o estructura que oculta todos los indizadores de la clase base con la misma firma (nmero de parmetros y tipos).

42Las reglas que gobiernan las declaraciones de operador (10.9) imposibilitan la declaracin por una clase 43derivada de un operador con la misma firma que un operador de una clase base. Por lo tanto, los operadores 44nunca se ocultan mutuamente.

18178

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

182

Captulo 18 Cdigo no seguro

1Al contrario que cuando se oculta un nombre de un mbito externo, cuando se oculta un nombre accesible desde 2un mbito heredado se genera una advertencia. En el siguiente ejemplo: 3 4 5 7 6 8class Base { public void F() {} class Derived: Base {

9 public void F() {} // Warning, hiding an inherited name 11la declaracin de F en Der i vedgenera una advertencia. Ocultar un nombre heredado no es especficamente un 12error, puesto que esto impedira la evolucin independiente de las clases base. Por ejemplo, la situacin anterior 10 13podra haberse producido porque una versin posterior de Base introdujo un mtodo F que no estaba presente 14en una versin anterior de la clase. Si la situacin anterior hubiera sido un error, cualquier cambio realizado a 15una clase base en una versin independiente de la biblioteca de clases podra haber invalidado las clases 16derivadas. 17La advertencia causada por la ocultacin de un nombre heredado puede eliminarse mediante uso del 18modificador new: 19 20 21 23 22 24class Base { public void F() {} class Derived: Base {

25 new public void F() {} 27El modificador new indica que F de Derived es nuevo, y que su propsito real es ocultar el miembro 28 26heredado. 29Una declaracin de un miembro nuevo oculta un miembro heredado slo dentro del mbito del nuevo miembro. 30 31 32 34 33 35 36 38 37 39class Base { public static void F() {} class Derived: Base { new private static void F() {} class MoreDerived: Derived { // Hides Base.F in Derived only

40 static void G() { F(); } // Invokes Base.F 42En el ejemplo anterior, la declaracin de mtodo F en la clase Derived oculta el mtodo F que se hered de 43Base pero, como el nuevo mtodo F de Derived tiene acceso de tipo privado, su mbito no se extiende a 41 44MoreDerived. De este modo, la llamada F() de MoreDerived.G es vlida e invocar a Base.F.

183Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

79

184Especificacin del lenguaje C#

13.8 Espacios de nombres y nombres de tipos 2Algunos contextos de un programa de C# requieren que se especifique un nombre de espacio de nombres 3(namespace-name) o un nombre de tipo (type-name). Cualquiera de los dos formatos de nombre se escribe como 4uno o ms identificadores separados por smbolos (token) ".". 5 6 7 8 9 10 11namespace-name: namespace-or-type-name type-name: namespace-or-type-name namespace-or-type-name: identifier namespace-or-type-name . identifier

12Un nombre de tipo (type-name) es un nombre de espacio de nombres o de tipo (namespace-or-type-name) que 13hace referencia a un tipo. Conforme a la resolucin explicada ms adelante, el nombre de espacio de nombres o 14de tipo (namespace-or-type-name) de un nombre de tipo (type-name) debe hacer referencia a un tipo o, de lo 15contrario, se producir un error en tiempo de compilacin. 16Un nombre de espacio de nombres (namespace-name) es un nombre de espacio de nombres o de tipo 17(namespace-or-type-name) que hace referencia a un espacio de nombres. Conforme a la resolucin explicada 18ms adelante, el nombre de espacio de nombres o de tipo (namespace-or-type-name) de un nombre de espacio 19de nombres (namespace-name) debe hacer referencia a un espacio de nombres o, de lo contrario, se producir un 20error en tiempo de compilacin. 21El significado de un nombre de espacio de nombres o de tipo (namespace-or-type-name) se determina como 22sigue: 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43Si el nombre de espacio de nombres o de tipo (namespace-or-type-name) consta de un solo identificador: o Si el nombre de espacio de nombres o de tipo (namespace-or-type-name) aparece dentro del cuerpo de la declaracin de una clase o estructura, entonces, empezando con esa declaracin de clase o estructura y siguiendo con la declaracin de cada clase o estructura envolvente (si la hay), si existe un miembro con el nombre dado, es accesible y denota un tipo, el nombre de espacio de nombres o de tipo (namespace-or-type-name) hace referencia a dicho miembro. Tngase en cuenta que los miembros que no son de tipo (constantes, campos, mtodos, propiedades, indizadores, operadores, constructores de instancia, destructores y constructores estticos) se omiten a la hora de determinar el significado de un nombre de espacio de nombres o de tipo (namespace-or-type-name). O bien, empezando por el espacio de nombres en el que se produce el nombre de espacio de nombres o de tipo (namespace-or-type-name), continuando por cada uno de los espacios de nombres envolventes (si los hubiera) y terminando por el espacio de nombres global, se irn evaluando los siguientes pasos hasta que se localice una entidad: Si el espacio de nombres contiene un miembro de espacio de nombres con el nombre dado, entonces el nombre de espacio de nombres o de tipo (namespace-or-type-name) hace referencia a dicho miembro y, dependiendo del miembro, se clasifica como un espacio de nombres o como un tipo. O bien, si el espacio de nombres tiene una declaracin de espacio de nombres correspondiente que abarca la ubicacin donde se produce el nombre de espacio de nombres o de tipo (namespace-ortype-name), entonces: o Si la declaracin de espacio de nombres contiene una directiva alias using (using-aliasdirective) que asocia el nombre dado a un espacio de nombres o tipo importado, entonces el

o

18580

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

186

Captulo 18 Cdigo no seguro

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25o o

nombre de espacio de nombres o de tipo (namespace-or-type-name) hace referencia a dicho espacio de nombres o tipo. O bien, si los espacios de nombres importados por las directivas using de espacio de nombres (using-namespace-directives) de la declaracin del espacio de nombres contienen exactamente un nico tipo con el nombre dado, entonces el nombre de espacio de nombres o de tipo (namespace-or-type-name) hace referencia a dicho tipo. O bien, si los espacios de nombres importados por las directivas using de espacio de nombres (using-namespace-directives) de la declaracin del espacio de nombres contienen ms de un tipo con el mismo nombre dado, entonces el nombre de espacio de nombres o de tipo (namespace-or-type-name) ser ambiguo y se producir un error.

o

De lo contrario, el nombre de espacio de nombres o de tipo (namespace-or-type-name) no est definido y se produce un error en tiempo de compilacin.

O bien, el nombre de espacio de nombres o de tipo (namespace-or-type-name) tiene el formato N. I donde N , es un nombre de espacio de nombres o de tipo (namespace-or-type-name) compuesto por todos los identificadores excepto el situado ms a la derecha, e I es el identificador situado ms a la derecha. N se resuelve en primer lugar como nombre de espacio de nombres o de tipo (namespace-or-type-name). Si la resolucin de N no es correcta, se produce un error en tiempo de compilacin. De lo contrario, N.I se resuelve como sigue: o Si N es un espacio de nombres e I es el nombre de un miembro accesible de dicho espacio de nombres, entonces N.I hace referencia a dicho miembro y, dependiendo del miembro, se clasifica como un espacio de nombres o un tipo. Si N es un tipo de clase o estructura e I es el nombre de un tipo accesible contenido en N, entonces N.I hace referencia a dicho tipo. De lo contrario, N.I es un nombre de espacio de nombres o de tipo no vlido (invalid namespace-ortype-name) y se produce un error en tiempo de compilacin.

o o

263.8.1 Nombres completos 27Todos los espacios de nombres y todos los tipos tienen un nombre completo, que los identifica de forma 28exclusiva. El nombre completo de un espacio de nombres o un tipo N se determina como sigue: 29 30 31Si N es un miembro del espacio de nombres global, su nombre completo es N. De 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.

32Esto es, el nombre completo de N es la ruta de acceso jerrquica completa de los identificadores que conducen a 33N, empezando desde el espacio de nombres global. Dado que todos los miembros de un espacio de nombres o un 34tipo deben tener un nombre nico, se deduce que el nombre completo de un espacio de nombres o tipo siempre 35es nico. 36En el ejemplo siguiente se muestran varias declaraciones de espacio de nombres y tipo con sus nombres 37completos asociados. 38c lass A {} // A

187Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

81

188Especificacin del lenguaje C#

1 2 3 4 7 5 8 6 9 10 12 11 13

namespace X { class B { { class D {} namespace X.Y { namespace Y

// X // X.B // X.Y // X.Y.D // X.Y

14 class E {} // X.Y.E 16 153.9 Administracin automtica de la memoria 17C# usa la administracin automtica de memoria, que exime a los programadores de la asignacin manual y la 18liberacin de la memoria ocupada por objetos. Las directivas de administracin automtica de la memoria se 19implementan mediante un recolector de elementos no utilizados. El ciclo de vida de la administracin de la 20memoria de un objeto es: 211. Cuando se crea el objeto, se le asigna memoria, se ejecuta el constructor y el objeto se considera activo. 222. 23 24 25 26 27 28 29En caso de que no se pueda obtener acceso al objeto o alguna de sus partes por medio de las posibles continuaciones de la ejecucin, en lugar de iniciar los destructores, el objeto dejar de considerarse en uso y quedar expuesto al proceso de destruccin. El compilador de C# y el recolector de elementos no utilizados pueden optar por analizar el cdigo para determinar qu referencias a un objeto podrn utilizarse en el futuro. Por ejemplo, si una variable local que se encuentra dentro del mbito es la nica referencia existente a un objeto, pero no se hace ninguna referencia a tal variable local en ninguna continuacin posible de la ejecucin desde el punto actual de ejecucin dentro del procedimiento, el recolector de elementos no utilizados puede tratar los objetos (aunque no necesariamente) como si ya no estuvieran en uso.

303. Cuando el objeto ya es candidato a la destruccin, el destructor del objeto (si existe) se ejecuta en un 31 momento posterior no especificado (10.12). Salvo que se realicen llamadas explcitas, el destructor del 32 objeto slo se ejecuta una vez. 334. Si, una vez ejecutado el destructor de un objeto, las posibles continuaciones de la ejecucin (incluida la 34 ejecucin de los destructores) no pudieran obtener acceso al objeto o a alguna de sus partes, se considerar 35 que ya no se encuentra accesible y quedar expuesto al proceso de recoleccin. 365. Por ltimo, cuando el objeto ya es candidato para la recoleccin, en un momento posterior, el recolector de 37 elementos no utilizados libera la memoria asociada al objeto. 38El recolector de elementos no utilizados mantiene informacin acerca de la utilizacin de objetos y la utiliza 39para tomar decisiones sobre la administracin de memoria. Por ejemplo, contiene datos como en qu parte de la 40memoria se ubica un objeto recin creado, cundo se reubica un objeto y cundo un objeto ya no se utiliza o est 41inaccesible. 42Igual que otros lenguajes que dan por supuesta la existencia de un recolector de elementos no utilizados, C# se 43ha diseado para que el recolector de elementos no utilizados pueda implementar una amplia gama de directivas 44de administracin de la memoria. Por ejemplo, C# no exige que se lleve a cabo la ejecucin de destructores ni la 45recoleccin de objetos en el momento en que pasen a ser candidatos a ella, ni que los destructores se ejecuten en 46un orden concreto o en un subproceso concreto.

18982

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

190

Captulo 18 Cdigo no seguro

1El comportamiento del recolector de elementos no utilizados puede controlarse, en cierta medida, mediante 2mtodos estticos de la clase Sys tem.GC , una clase que puede utilizarse para solicitar la ejecucin de la 3recoleccin o de los destructores (o su no ejecucin), etc. 4Dado que el recolector de elementos no utilizados tiene una amplia libertad para decidir cundo debe recolectar 5objetos y ejecutar destructores, una implementacin compatible puede producir resultados diferentes de los 6mostrados en el cdigo siguiente. El programa 7 8 9 10 11 14 12 15 13 16 17 18 19 20 21 22 24 23 25 26 27 28using System; class A { ~A() { class B { public B(object o) { Ref = o; ~B() { Console.WriteLine("Destruct instance of B"); } class Test { static void Main() { B b = new B(new A()); b = null; Console.WriteLine("Destruct instance of A");

29crea una instancia de la clase A y otra de la clase B. Estos objetos se convierten en candidatos a la recoleccin de GC.Collect(); 33 34 30elementos no utilizados cuando se asigna a la variable b el valor null, puesto que, despus de ello, no se puede 35obtener acceso a ellos mediante ningn cdigo escrito por el usuario. El resultado podra ser 31 36 Destruct instance of A 32 37 38o bien Destruct instance of B 39Destruct instance of B

40puesto que el lenguaje no impone restricciones al orden en que se lleva a cabo la recoleccin de elementos de los Destruct instance of A 41 42objetos no utilizados. 43En casos concretos, la distincin entre candidato a la destruccin y candidato a la recoleccin puede ser 44importante. Por ejemplo, 45using System;

191Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

83

192Especificacin del lenguaje C#

1 2 3 4 6 5 7 8 9 11 10 12 13 14 15 16 17 19 18 20 21 23 22 24 25 26 29 27 30 28 31 32 33

class A { ~A() { public void F() { Console.WriteLine("A.F"); Test.RefA = this; class B { ~B() { Console.WriteLine("Destruct instance of B"); Ref.F(); class Test { public static A RefA; static void Main() { RefB = new B(); RefA = new A(); RefB.Ref = RefA; GC.Collect(); // B now eligible for collection, but A is not if (RefA != null) // A and B now eligible for destruction

34 Console.WriteLine("RefA is not null"); 37 35En el programa anterior, si el recolector de elementos no utilizados decide ejecutar el destructor de A antes que 38el de B, el resultado de este programa puede ser: 36 39 Destruct instance of A 40Destruct instance of B

41 A.F 43Debe tenerse en cuenta que, aunque la instancia de A no estaba en uso cuando se ejecut el destructor de A, 44todava es posible llamar a los mtodos de A (en este caso, F) desde otro destructor. Asimismo, no debe 42 45olvidarse que la ejecucin de un destructor puede hacer que un objeto vuelva a ser utilizable desde el programa 46principal. En este caso, la ejecucin del destructor de B hace que una instancia de A que no estaba anteriormente 47en uso est ahora accesible desde la referencia activa Test.RefA. Tras la llamada a WaitForPendingFinalizers, 48la instancia de B pasa a quedar expuesta a la recoleccin, pero no as la instancia de A, debido a la referencia 49Test.RefA.

19384

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

194

Captulo 18 Cdigo no seguro

1Para evitar confusiones y comportamientos inesperados, generalmente es recomendable que los destructores 2solamente realicen la limpieza de los datos almacenados en los campos propios de sus objetos, y que no realicen 3acciones en los objetos a los que se hace referencia o en campos estticos. 43.10 Orden de ejecucin 5La ejecucin de los programas de C# se realiza de tal modo que los efectos secundarios de cada subproceso en 6ejecucin se van conservando en puntos crticos de ejecucin. Un efecto secundario se define como la lectura o 7escritura de un campo voltil, la escritura en una variable no voltil, la escritura en un recurso externo o el inicio 8de una excepcin. Los puntos de ejecucin crticos en los que deben conservarse tales efectos secundarios son 9las referencias a campos voltiles (10.4.3), las instrucciones de bloqueo l ock(8.12) y la creacin y 10terminacin de subprocesos. El entorno de ejecucin puede cambiar el orden de ejecucin de un programa de 11C#, con las siguientes restricciones: 12 13 14 15 16 17 18 19 20 21Se conservar la dependencia de datos dentro de un subproceso de ejecucin. Es decir, el valor de cada variable se calcular como si todas las instrucciones del subproceso se ejecutaran en el orden del programa original. Se conservan las reglas de orden de inicializacin (10.4.4 y 10.4.5). Se conserva el orden de los efectos secundarios respecto a las lecturas y escrituras voltiles (10.4.3). Adems, el entorno de ejecucin no necesitar evaluar parte de una expresin si puede deducir que el valor de esa expresin no se utiliza y que no se producen efectos secundarios necesarios (incluidos los causados por la llamada a un mtodo o el acceso a un campo voltil). Cuando un evento asincrnico (tal como una excepcin iniciada por otro subproceso) interrumpe la ejecucin de un programa, no habr garantas de que los efectos secundarios observables resulten visibles en el orden del programa original.

195Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

85

196Especificacin del lenguaje C#

1

4.Tipos

2Los tipos del lenguaje C# se dividen en dos categoras principales: tipos de valor y tipos de referencia. 3 4 5type: value-type reference-type

6Una tercera categora de tipos, los punteros, slo est disponible en el cdigo no seguro. Esta categora se 7explica con ms detalle en la seccin 18.2. 8Los tipos de valor se diferencian de los tipos de referencia en que sus variables contienen directamente sus 9datos, mientras que las variables de los tipos de referencia contienen referencias a sus datos, que se conocen 10como objetos. En el caso de los tipos de referencia, es posible que dos variables hagan referencia al mismo 11objeto y, por tanto, que las operaciones en una variable afecten al objeto al que hace referencia la otra variable. 12En el caso de los tipos de valor, cada variable tiene su propia copia de los datos, de manera que no es posible 13que las operaciones de una afecten a la otra. 14El sistema de tipos de C# est unificado, de manera que un valor de cualquier tipo puede tratarse como un 15objeto. Todos los tipos de C# se derivan directa o indirectamente del tipo de clase ob jec t que es la clase base , 16definitiva de todos los tipos. Los valores de los tipos de referencia se tratan como objetos considerndolos 17sencillamente como del tipo ob jec t Los valores de los tipos de valor se tratan como objetos mediante la . 18realizacin de operaciones de conversin boxing y unboxing (4.3). 194.1 Tipos de valor 20Un tipo de valor es un tipo struct o un tipo enum. C# proporciona un conjunto de tipos struct predefinidos 21denominados tipos simples. Los tipos simples se identifican mediante palabras reservadas. 22 23 24 25 26 27 28 29 30 31 32 33 34value-type: struct-type enum-type struct-type: type-name simple-type simple-type: numeric-typeboo l

numeric-type: integral-type floating-point-typedec ima l

19786

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

198

Captulo 18 Cdigo no seguro

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15

integral-type:sby te byte shor t ushor t int u in t l ong u long char

floating-point-type:f l oa t doub le

enum-type: type-name

16Una variable de un tipo de valor siempre contiene un valor de dicho tipo. A diferencia de los tipos de referencia, 17el valor de un tipo de valor no puede ser nu l lni puede hacer referencia a un objeto de un tipo ms derivado. 18La asignacin a una variable de un tipo de valor crea una copia del valor que se asigna, lo cual difiere de la 19asignacin a una variable de un tipo de referencia, que copia la referencia, pero no el objeto identificado por 20ella. 214.1.1 Tipo System.ValueType 22Todos los tipos de valor se heredan implcitamente de la clase Sys tem.Va lueTypeque, a su vez, se hereda de , 23la clase ob jec t No es posible que cualquier tipo se derive de un tipo de valor y, por lo tanto, los tipos de valor . 24son implcitamente tipos sealed (10.1.1.2). 25Observe que Sys tem.Va lueTypeno es en s ningn tipo de valor (value-type). Ms bien, es un tipo de clase 26(class-type) del que se derivan automticamente todos los tipos de valores (value-types). 274.1.2 Constructores predeterminados 28Todos los tipos de valor declaran implcitamente un constructor de instancia pblico sin parmetros denominado 29constructor predeterminado. El constructor predeterminado devuelve una instancia inicializada en cero 30conocida como el valor predeterminado del tipo de valor: 31 32 33 34 35 36 37 38 39 40 41Para todos los tipos simples (simple-types), el valor predeterminado es el generado por un modelo de bits de todo ceros: o o o o o o Para sby te, byte, short, ushort, int, uint, long y ulong, el valor predeterminado es 0. Para char, el valor predeterminado es ' \ x0000. ' Para f l oa,tel valor predeterminado es 0 .0 f . Para doub le, el valor predeterminado es 0 .0d. Para dec ima l, el valor predeterminado es 0 .0m. Para boo l, el valor predeterminado es f a l se .

Para un tipo enum (enum-type) E, el valor predeterminado es 0. Para un tipo de estructura (struct-type), el valor predeterminado es el que se genera al configurar todos los campos de tipo de valor en su valor predeterminado y todos los tipos de referencia en nu l .l87

199Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

200Especificacin del lenguaje C#

1Igual que con cualquier otro constructores de instancia, se llama al constructor predeterminado de un tipo de 2valor mediante el operador new . Por razones de eficacia, el objetivo de este requisito no es lograr que la 3implementacin genere una llamada de constructor. En el ejemplo siguiente, las dos variables i y j se inicializan 4en cero. 5 6 7 8class A { void F() { int i = 0;

9 int j de valor implcitamente tienen un constructor de instancias pblico sin parmetros, un 12Dado que todos los tipos= new int(); 13tipo struct no puede contener una declaracin explcita de un constructor sin parmetros. No obstante, en un tipo 10 14struct se pueden declarar constructores de instancia con parmetros (11.3.8). 11 154.1.3 Tipos de estructura 16Un tipo struct es un tipo de valor que puede declarar constantes, campos, mtodos, propiedades, indizadores, 17operadores, constructores de instancia, constructores estticos y tipos anidados. Los tipos de estructura se 18describen en 11. 194.1.4 Tipos simples 20C# proporciona un conjunto de tipos struct predefinidos denominados tipos simples. Los tipos simples se 21identifican mediante palabras reservadas, pero stas son sencillamente alias de tipos struct predefinidos del 22espacio de nombres System, como se explica en la tabla siguiente.23

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

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

24 25Como un tipo simple equivale a un tipo struct, todos los tipos simples tienen miembros. Por ejemplo, int tiene 26los miembros declarados en System.Int32 y los miembros heredados de System.Object, y se permiten las 27siguientes instrucciones:

20188

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

202

Captulo 18 Cdigo no seguro

1

int i = int.MaxValue;

// System.Int32.MaxValue constant

2 string s = i.ToString(); // System.Int32.ToString() instance method 4Los tipos simples se diferencian de otros tipos struct en que permiten determinadas operaciones adicionales: 3 5 6 7 8 9 10 11 12 13 14 15 16 17La mayora de los tipos simples permiten la creacin de valores mediante la escritura de literales (2.4.4). Por ejemplo, 123 es un literal del tipo i n ty 'a' es un literal del tipo char. C# no proporciona literales de tipos struct en general, y los valores no predeterminados de otros tipos struct se crean siempre en ltimo trmino mediante constructores de instancia de dichos tipos struct. Cuando todos los operandos de una expresin son constantes de tipo simple, es posible que el compilador evale la expresin en tiempo de compilacin. Dicha expresin se conoce por el nombre de expresin constante (constant-expression) (7.15). Las expresiones que incluyen operadores definidos por otros tipos struct no se consideran expresiones constantes. Mediante las declaraciones const es posible declarar constantes de los tipos simples (10.3). No es posible tener constantes de otros tipos struct, pero se consigue un efecto similar mediante campos static readonly. Las conversiones que involucran tipos simples pueden participar en la evaluacin de los operadores de conversin definidos por otros tipos struct, pero un operador de conversin definido por el usuario no puede participar en la evaluacin de otros operadores definidos por el usuario (6.4.2).

184.1.5 Tipos integrales 19C# admite nueve tipos integrales: sbyte, byte, short, ushort, int, uint, long, ulong y char. Los tipos 20integrales tienen los siguientes tamaos e intervalos de valores: 21 22 23 24 25 26 27 28 29 30 31 32 33 34El tipo sbyte, que representa enteros de 8 bits con signo con valores comprendidos entre -128 y 127. El tipo byte, que representa enteros de 8 bits sin signo con valores comprendidos entre 0 y 255. El tipo short, que representa enteros de 16 bits con signo con valores comprendidos entre 32768 y 32767. El tipo ushor t que representa enteros de 16 bits sin signo con valores comprendidos entre 0 y 65535. , El tipo int, que representa enteros de 32 bits con signo con valores comprendidos entre 2147483648 y 2147483647. El tipo u in t que representa enteros de 32 bits sin signo con valores comprendidos entre 0 y 4294967295. , El tipo long, que representa enteros de 64 bits con signo con valores comprendidos entre 9223372036854775808 y 9223372036854775807. El tipo u long, que representa enteros de 64 bits sin signo con valores comprendidos entre 0 y 18446744073709551615. El tipo char representa enteros sin signo de 16 bits con valores entre 0 y 65535. El conjunto de valores posibles para el tipo char corresponde al conjunto de caracteres Unicode. Aunque char tiene la misma representacin que ushort, no todas las operaciones permitidas en un tipo estn permitidas en el otro.

35Los operadores unarios y binarios de tipos integrales siempre trabajan con precisin de 32 bits con signo, 36precisin de 32 bits sin signo, precisin de 64 bits con signo o precisin de 64 bits sin signo: 37 38 39Para los operadores unarios + y ~, el operando se convierte al tipo T, donde T es el primero de int, uint, long y ulong que puede representar completamente todos los valores posibles del operando. Despus se ejecuta la operacin con la precisin del tipo T, y el tipo del resultado es T.

203Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

89

204Especificacin del lenguaje C#

1 2 3 4 5 6 7 8 9 10 11 12 14 15 16 17 18 19

Para el operador unario , el operando se convierte al tipo T, donde T es el primero de int y long que puede representar completamente todos los valores posibles del operando. Despus se ejecuta la operacin con la precisin del tipo T, y el tipo del resultado es T. El operador unario - no se puede aplicar a operandos del tipo ulong. Para los operadores binarios +, , *, /, %, &, ^, |, ==, !=, >, = y , el operando izquierdo se convierte al tipo T, donde T es el primero de int, uint, long y ulong que puede representar completamente todos los valores posibles del operando. Despus se ejecuta la operacin con la precisin del tipo T, y el tipo del resultado es T. No existen conversiones implcitas desde otros tipos al tipo char. En concreto, aunque los tipos sbyte, byte y ushort tienen intervalos de valores que son totalmente representables mediante el tipo char, las conversiones implcitas de sbyte, byte o ushort a char no existen. La constantes de tipo char deben escribirse como literales de caracteres (character-literals) o como literales de enteros (integer-literals) en combinacin con una conversin al tipo char. Por ejemplo, (char)10 es lo mismo que '\x000A'.

13El tipo char se clasifica como un tipo integral, pero difiere de otros tipos integrales en dos aspectos:

20Los operadores e instrucciones checked y unchecked se utilizan para controlar la comprobacin del 21desbordamiento para las operaciones y conversiones aritmticas de tipos integrales (7.5.12). En un contexto 22checked, un desbordamiento produce un error de tiempo de compilacin o causa una excepcin 23System.OverflowException. En un contexto unchecked, los desbordamientos no se tienen en cuenta y los 24bits de orden superior que no son aceptables para el tipo de destino se descartan. 254.1.6 Tipos de punto flotante 26C# admite dos tipos de punto flotante: float y double. Los tipos float y double se representan mediante los 27formatos IEEE 754 de 32 bits de precisin simple y de 64 bits de precisin doble, que proporcionan los 28siguientes conjuntos de valores: 29 30 31 32 33 34 35 36 37 38 39 40Cero positivo y cero negativo. En la mayora de las situaciones, cero positivo y cero negativo tienen un comportamiento idntico al del valor simple cero, pero algunas operaciones distinguen entre los dos (7.7.2). Infinito positivo e infinito negativo. Los infinitos son generados por operaciones como dividir por cero un nmero distinto de cero. Por ejemplo, el resultado de 1.0 / 0.0 es infinito positivo, y el de 1.0 / 0.0 es infinito negativo. El valor no numrico (Not-a-Number), abreviado normalmente como NaN. Los valores NaN se generan por operaciones de punto flotante no vlidas, como dividir cero por cero. El conjunto finito de valores distintos de cero con el formato s m 2e, donde s es 1 o 1, y m y e estn determinados por el tipo de punto flotante concreto: para float, 0 < m < 224 y 149 e 104, y para double, 0 < m < 253 y 1075 e 970. Los nmeros de punto flotante sin normalizar se consideran valores vlidos distintos de cero.

41El tipo float puede representar valores comprendidos entre aproximadamente 1.5 1045 y 3.4 1038 con una 42precisin de 7 dgitos.

20590

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

206

Captulo 18 Cdigo no seguro

1El tipo doub le puede representar valores comprendidos entre aproximadamente 5.0 10324 y 1.7 10308 con 2una precisin de 15-16 dgitos. 3Si uno de los operandos de un operador binario es un tipo de punto flotante, el otro debe ser un tipo integral o un 4tipo de punto flotante, y la operacin se evala como sigue: 5 6 7 8 9 10Si uno de los operandos es un tipo integral, se convierte al tipo de punto flotante del otro operando. Despus, si uno de los operandos es de tipo doub le, el otro se convierte a doub le, la operacin se ejecuta utilizando por lo menos el intervalo y la precisin double, y el tipo del resultado es double (o bool para los operadores relacionales). O bien, la operacin se ejecuta utilizando por lo menos el intervalo y la precisin float y el tipo del resultado es float (o bool para los operadores relacionales).

11Los operadores de punto flotante, incluidos los operadores de asignacin, nunca producen excepciones. En lugar 12de ello, en situaciones excepcionales, las operaciones de punto flotante producen cero, infinito o NaN, como se 13explica a continuacin: 14 15 16 17 18 19Si el resultado de una operacin de punto flotante es demasiado pequeo para el formato de destino, el resultado de la operacin es cero positivo o cero negativo. Si el resultado de una operacin de punto flotante es demasiado grande para el formato de destino, el resultado de la operacin es infinito positivo o infinito negativo. Si una operacin de punto flotante no es vlida, el resultado de la operacin es NaN. Si uno o los dos operandos de una operacin de punto flotante es NaN, el resultado de la operacin es NaN.

20Las operaciones de punto flotante pueden realizarse con mayor precisin que el tipo de resultado de la 21operacin. Por ejemplo, algunas arquitecturas de hardware admiten el tipo de punto flotante extended o long 22double con un intervalo y precisin mayores que el tipo double, e implcitamente realizan todas las 23operaciones de punto flotante utilizando este tipo de mayor precisin. Se puede conseguir que las arquitecturas 24de hardware de esta clase realicen operaciones de punto flotante con menor precisin slo a cambio de un costo 25excesivo en el rendimiento; en vez de requerir una implementacin que penalice tanto el rendimiento como la 26precisin, C# permite utilizar un tipo de mayor precisin para todas las operaciones de punto flotante. Aparte de 27proporcionar resultados ms precisos, esto rara vez tiene efectos medibles. No obstante, en expresiones con la 28forma x * y / z, donde la multiplicacin genera un resultado que sale del intervalo de double, pero la siguiente 29divisin devuelve el resultado temporal al intervalo de double, el hecho de que la expresin se evale en un 30formato de intervalo mayor puede producir un resultado finito en lugar de infinito. 314.1.7 Tipo decimal 32El tipo decimal es un tipo de datos de 128 bits apto para clculos financieros y monetarios. El tipo decimal 33puede representar valores comprendidos entre aproximadamente 1.0 1028 y 7.9 1028 con 28-29 dgitos 34significativos. 35El conjunto finito de valores de tipo decimal tiene la forma (1)s c 10-e, donde el signo s es 0 o 1, el 36coeficiente c viene dado por 0 c < 296 y la escala e es 0 e 28. El tipo decimal no admite ceros con signo, 37valores infinitos ni valores NaN. Un decimal se representa como un entero de 96 bits elevado a diez. Para 38valores decimal con un valor absoluto menor que 1.0m, el valor es exacto slo hasta la posicin decimal 28. 39Para valores decimal con un valor absoluto mayor o igual que 1.0m, el valor es exacto hasta el dgito 28 o 29. 40Al contrario que los tipos de datos float y double, los nmeros fraccionarios decimales como 0,1 pueden 41representarse exactamente en la representacin decimal. En las representaciones float y double, estos nmeros 42con frecuencia son fracciones infinitas, lo que las hace ms susceptibles de errores de redondeo.

207Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

91

208Especificacin del lenguaje C#

1Si uno de los operandos de un operador binario es de tipo dec ima l, el otro debe ser un tipo integral o un tipo 2dec ima l. Si est presente un operando de tipo integral, se convertir a decimal antes de realizar la operacin. 3El resultado de una operacin con valores de tipo decimal es el que resultara de calcular un resultado exacto 4(conservando la escala, segn lo definido por cada operador) y, a continuacin, redondearlo para ajustarse a la 5representacin. El resultado se redondea hasta el valor representable ms prximo y, en caso de que un resultado 6tenga la misma proximidad con dos valores representables, se redondea al valor que tenga un nmero par en la 7posicin del dgito menos significativo (esto se conoce como redondeo de banca). Un resultado cero siempre 8tiene un signo 0 y una escala 0. 9Si una operacin aritmtica decimal genera un valor menor o igual que 5 x 10-29 en valor absoluto, el resultado 10de la operacin es cero. Si una operacin aritmtica decimal genera un resultado demasiado grande para el 11formato decimal, se origina una excepcin System.OverflowException. 12El tipo decimal tiene una precisin mayor, pero un intervalo menor, que los tipos de punto flotante. Por lo 13tanto, las conversiones de los tipos de punto flotante a decimal pueden producir excepciones de 14desbordamiento, y las conversiones de decimal a los tipos de punto flotante pueden causar una prdida de 15precisin. Por estos motivos, no existen conversiones implcitas entre los tipos de punto flotante y decimal, y 16sin conversiones explcitas, no es posible combinar operandos de punto flotante y decimal en la misma 17expresin. 184.1.8 Tipo bool 19El tipo bool representa cantidades lgicas booleanas. Los valores posibles del tipo bool son true y false. 20No existen conversiones estndar entre bool y otros tipos. En concreto, el tipo bool es nico y exclusivo de los 21tipos integrales, y un valor bool no puede sustituir a un valor integral, ni viceversa. 22En los lenguajes C y C++, un valor integral o de punto flotante cero, o un puntero de valor null, pueden 23convertirse al valor booleano false, y un valor integral o de punto flotante distinto de cero o un puntero con un 24valor distinto de null pueden convertirse al valor booleano true. En C#, las conversiones de esta categora se 25llevan a cabo mediante la comparacin explcita de un valor integral o de punto flotante con cero, o mediante la 26comparacin explcita de una referencia de objeto con null. 274.1.9 Tipos de enumeracin 28Un tipo de enumeracin es un tipo exclusivo con constantes con nombre. Todos los tipos de enumeracin tienen 29un tipo subyacente, que debe ser byte, sbyte, short, ushort, int, uint, long o ulong. El conjunto de valores 30del tipo de enumeracin es el mismo que el del conjunto de valores del tipo subyacente. Los valores del tipo de 31la enumeracin no se restringen a los valores de las constantes nombradas. Los tipos de enumeracin se definen 32mediante declaraciones de enumeracin (14.1). 334.2 Tipos de referencia 34Un tipo de referencia es un tipo de clase, un tipo de interfaz, un tipo de matriz o un tipo delegado. 35 36 37 38 39 40 41 42 43reference-type: class-type interface-type array-type delegate-type class-type: type-nameob jec t s t r i ng

20992

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

210

Captulo 18 Cdigo no seguro

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16

interface-type: type-name array-type: non-array-type rank-specifiers non-array-type: type rank-specifiers: rank-specifier rank-specifiers rank-specifier rank-specifier: [ dim-separatorsopt ] dim-separators:,

dim-separators , delegate-type: type-name

17Un valor de tipo de referencia es una referencia a una instancia del tipo, que se conoce como objeto. El valor 18especial nu l les compatible con todos los tipos de referencia e indica la ausencia de una instancia. 194.2.1 Tipos de clase 20Un tipo de clase define una estructura de datos que contiene miembros de datos (constantes y campos), 21miembros de funcin (mtodos, propiedades, eventos, indizadores, operadores, constructores de instancia, 22destructores y constructores estticos) y tipos anidados. Los tipos de clase admiten la herencia, un mecanismo 23mediante el cual una clase derivada puede extender y especializar a las clases base. Las instancias de los tipos de 24clase se crean mediante expresiones de creacin de objetos (object-creation-expressions) (7.5.10.1). 25Los tipos de clase se describen en 10. 26Ciertos tipos de clases predefinidos tienen un significado especial en el lenguaje C#, tal como se describe en la 27siguiente tabla.28

Tipo de claseSystem.Object System.String System.ValueType System.Enum System.Array System.Delegate System.Exception

Descripcin Clase base definitiva de todos los dems tipos. Vea 4.2.2. El tipo de cadena del lenguaje de C#. Vea 4.2.3. La clase base de todos los tipos de valor. Vea 4.1.1. La clase base de todos los tipos enum. Vea 14. La clase base de todos los tipos de matriz. Vea 12. La clase base de todos los tipos de delegado. Vea 15. La clase base de todos los tipos de excepcin. Vea 16.

29

304.2.2 Tipo object 31El tipo de clase ob jec tes la clase base definitiva de todos los dems tipos. Todos los tipos de C# se derivan 32directa o indirectamente del tipo de clase ob jec t .

211Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

93

212Especificacin del lenguaje C#

1La palabra clave ob jec tno es ms que un alias de la clase predefinida Sys tem.Ob jec t . 24.2.3 Tipo string 3El tipo s t r i ng un tipo de clase sealed que hereda directamente de ob jec t Las instancias de la clase string es . 4representan cadenas de caracteres Unicode. 5Los valores del tipo string pueden escribirse como literales de cadena (2.4.4). 6La palabra clave s t r i ng es ms que un alias de la clase predefinida Sys tem.S t r i ng no . 74.2.4 Tipos de interfaz 8Una interfaz define un contrato. Una clase o estructura que implementa una interfaz debe adherirse a su 9contrato. Una interfaz puede derivarse de varias interfaces base, y una clase o estructura puede implementar 10varias interfaces. 11Los tipos de interfaz se describen en 13. 124.2.5 Tipos de matriz 13Una matriz es una estructura de datos que contiene cero o ms variables, a las que se obtiene acceso a travs de 14ndices calculados. Las variables contenidas en una matriz, tambin conocidas como elementos de la matriz, son 15todas del mismo tipo, denominado tipo de elemento de la matriz. 16Los tipos de matriz se describen en 12. 174.2.6 Tipos de delegados 18Un delegado es una estructura de datos que se refiere a uno o ms mtodos y, por mtodos de instancia, se 19refiere tambin a sus correspondientes instancias de objeto. 20El equivalente ms cercano de un delegado en C o C++ es un puntero a una funcin pero, mientras que ste slo 21puede hacer referencia a funciones estticas, un delegado puede hacer referencia tanto a mtodos estticos como 22a mtodos de instancia. En este caso, el delegado no slo almacena una referencia al punto de entrada del 23mtodo, sino que tambin almacena una referencia a la instancia de objeto para el que se invoca el mtodo. 24Los tipos de delegado se describen en 15. 254.3 Boxing y Unboxing 26El concepto de boxing y unboxing desempea un papel central en el sistema de tipos de C#. Sirven como enlace 27entre los tipos de valor (value-types) y los tipos de referencia (reference-types), al permitir la conversin de 28cualquier valor de un tipo de valor (value-type) al tipo ob jec ty viceversa. Las conversiones boxing y unboxing 29habilitan una visin unificada del sistema de tipos en la que un valor de cualquier tipo puede tratarse 30bsicamente como un objeto. 314.3.1 Conversiones boxing 32Una conversin boxing permite que un tipo de valor (value-type) se convierta implcitamente en un tipo de 33referencia (reference-type). Existen los siguientes tipos de conversiones boxing: 34 35 36 37De cualquier tipo de valor (value-type), incluidos los tipos enum (enum-type), al tipo ob jec t . De cualquier tipo de valor (value-type), incluidos los tipos enum (enum-type), al tipo Sys tem.Va lueType . De cualquier tipo de valor (value-type) a cualquier tipo de interfaz (interface-type) implementada por el tipo de valor (value-type).

21394

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

214

Captulo 18 Cdigo no seguro

1

De cualquier tipo enum (enum-type) al tipo Sys tem.Enum .

2La conversin boxing de un valor a un tipo de valor (value-type) consiste en asignar una instancia del objeto y 3despus copiar en ella el valor del tipo de valor (value-type). 4El proceso real de conversin boxing del valor de un tipo de valor (value-type) se entiende mejor si uno se 5imagina la existencia de una clase boxing para ese tipo. Para cualquier tipo de valor (value-type) T, la clase 6boxing se comporta como si se declarara de la manera siguiente: 7 sea led c lass T_Box : Sys tem.Va lueType 8 { 9 T va lue ; 10 pub l i c T_Box(T t ) { 11 va lue = t ; 12 } 13La conversin boxing de un valor v de tipo T consiste ahora en ejecutar la expresin new T_Box(v) y devolver } 14 15la instancia resultante como un valor de tipo object. Por lo tanto, las instrucciones 16 i n t i = 123 ; 17 ob jec t box = i ; 18conceptualmente se corresponden con 19 i n t i = 123 ; 20 ob jec t box = new i n t _Box ( i ) ; 21La conversin boxing de clases como T_Box e int_Box mencionadas anteriormente no existe en realidad y el 22tipo dinmico de un valor al que se ha aplicado la conversin boxing no es realmente un tipo de clase. En lugar 23de ello, un valor convertido mediante boxing de tipo T tiene el tipo dinmico T, y una comprobacin tipo 24dinmica que usa el operador is sencillamente puede hacer referencia al tipo T. Por ejemplo, 25 i n t i = 123 ; 26 ob jec t box = i ; 27 i f (box i s i n t ) { 28 Conso le .Wr i te ( "Box conta ins an i n t " ) ; 29devolver la cadena Box contains an int en la consola. 30 31Una conversin boxing implica la creacin de una copia del valor al que se aplica la conversin. Esto es distinto 32de la conversin de un tipo de referencia (reference-type) a un tipo ob jec t en la cual el valor sigue haciendo , 33referencia a la misma instancia y sencillamente se considera como el tipo ob jec tmenos derivado. Por ejemplo, 34dada la declaracin 35 s t ruc t Po in t 36 { 37 pub l i c i n t x , y ; 38 pub l i c Po in t ( i n t x , i n t y ) { 39 th i s . x = x ; 40 th i s . y = y ; 41 } 42las siguientes instrucciones 43

215Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

95

216Especificacin del lenguaje C#

1 2

Point p = new Point(10, 10); object box = p;

3 p.x = 20; 5muestran en la consola el valor 10, porque la operacin boxing implcita que ocurre en la asignacin de p a box 6 4causa la copia del valor de p. En cambio, si se hubiera declarado Point como class, el resultado sera 20, puesto 7que p y box haran referencia a la misma instancia. 84.3.2 Conversiones Unboxing 9Una conversin unboxing permite que un tipo de referencia (reference-type) se convierta explcitamente en un 10tipo de valor (value-type). Existen los siguientes tipos de conversiones unboxing: 11 12 13 14 15Del tipo ob jec ta cualquier tipo de valor (value-type), incluidos los tipos enum (enum-type). Del tipo Sys tem.Va lueType cualquier tipo de valor (value-type), incluidos los tipos enum (enum-type). a De cualquier tipo de interfaz (interface-type) a cualquier tipo de valor (value-type) que implemente el tipo de interfaz (interface-type). Del tipo Sys tem.Enum a cualquier tipo enum (enum-type).

16Una operacin unboxing consiste en comprobar primero que la instancia del objeto es un valor al que se ha 17aplicado la conversin boxing del tipo de valor (value-type) dado, y copiar despus el valor fuera de la instancia. 18En cuanto a la clase boxing imaginaria descrita en la seccin anterior, una conversin unboxing de un objeto 19box a un tipo de valor T consiste en ejecutar la expresin ((T_Box)box).value. Por lo tanto, las instrucciones 20 ob jec t box = 123 ; 21 i n t i = ( i n t )box ; 22conceptualmente se corresponden con 23 ob jec t box = new i n t _Box (123 ) ; 24 i n t i = ( ( i n t _Box )box ) . va lue ; 25Para que una conversin unboxing a un tipo de valor (value-type) dado se ejecute correctamente en tiempo de 26ejecucin, el valor del operando de origen debe ser una referencia a un objeto que se cre anteriormente 27mediante una conversin boxing de un valor de ese tipo de valor (value-type). Si el operando de origen tiene 28valor null, se producir una excepcin System.NullReferenceException. Si el operando de origen es una 29referencia a un objeto incompatible, se producir una excepcin System.InvalidCastException.

21796

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

218

Captulo 18 Cdigo no seguro

1

5.Variables

2Las variables representan ubicaciones de almacenamiento. Toda variable tiene un tipo, que determina los valores 3que pueden almacenarse en ella. C# es un lenguaje con seguridad de tipos, y el compilador de C# garantiza que 4los valores almacenados en variables siempre son del tipo apropiado. El valor de una variable puede modificarse 5mediante una asignacin o con el uso de los operadores ++ y --. 6Una variable debe estar definitivamente asignada (5.3) para que pueda obtenerse su valor. 7Como se explica en las secciones siguientes, las variables pueden ser asignadas inicialmente o no asignadas 8inicialmente. Una variable asignada inicialmente tiene un valor inicial bien definido y siempre se considera 9asignada definitivamente. Una variable no asignada inicialmente no tiene un valor inicial. Para que una variable 10no asignada inicialmente se considere asignada definitivamente en una ubicacin determinada, debe ocurrir una 11asignacin de la variable en todas las rutas de ejecucin posibles que conduzcan a dicha ubicacin. 125.1 Categoras de variables 13C# define siete categoras de variables: variables estticas, variables de instancia, elementos de matriz, 14parmetros de valores, parmetros de referencia, parmetros de salida y variables locales. En las prximas 15secciones se describen estas categoras. 16En el siguiente ejemplo: 17 18 19 21 20 22class A { public static int x; void F(int[] v, int a, ref int b, out int c) { int i = 1;

23 c = a + b++; 26x es una variable esttica, y es una variable de instancia, v[0] es un elemento de matriz, a es un parmetro de 24 27valores, b es un parmetro de referencias, c es un parmetro de salida e i es una variable local. 25 285.1.1 Variables estticas 29Un campo declarado con el modificador static se denomina variable esttica. Una variable esttica se genera 30antes de la ejecucin del constructor esttico (10.11) de su tipo contenedor, y deja de existir a la vez que el 31dominio de aplicacin asociado. 32El valor inicial de una variable esttica es el valor predeterminado (5.2) del tipo de la variable. 33Para los fines de comprobacin de asignacin definitiva, una variable esttica se considera asignada 34inicialmente. 355.1.2 Variables de instancia 36Un campo declarado sin el modificador static se denomina variable de instancia.

219Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

97

220Especificacin del lenguaje C#

15.1.2.1 Variables de instancia en clases 2Una variable de instancia de una clase se genera cuando se crea una nueva instancia de esa clase, y deja de 3existir cuando no hay referencias a esa instancia y se ha ejecutado el destructor de la instancia (si existe). 4El valor inicial de una variable de instancia de una clase es el valor predeterminado (5.2) del tipo de la variable. 5Para los fines de comprobacin de asignacin definitiva, una variable de instancia de una clase se considera 6asignada inicialmente. 75.1.2.2 Variables de instancia en estructuras 8Una variable de instancia de una estructura tiene exactamente el mismo perodo de duracin que la variable de 9estructura a la que pertenece. Es decir, cuando se genera o deja de existir una variable de tipo de estructura, le 10ocurre lo mismo a las variables de instancia de la estructura. 11El estado de asignacin inicial de una variable de instancia de una estructura es el mismo que el de la variable 12que contiene la estructura. Es decir, si una variable de estructura se considera asignada inicialmente, lo mismo le 13ocurre a sus variables de instancia, y si una variable de estructura se considera no asignada inicialmente, sus 14variables de instancia tampoco lo estn. 155.1.3 Elementos matriciales 16Los elementos de una matriz comienzan a existir cuando se crea una instancia de la matriz y cesa su existencia 17cuando dejan de existir referencias a dicha instancia. 18El valor inicial de los elementos de una matriz es el valor predeterminado (5.2) del tipo de los elementos de la 19matriz. 20Para los fines de comprobacin de asignacin definitiva, un elemento de matriz se considera asignado 21inicialmente. 225.1.4 Parmetros de valor 23Un parmetro de valor es un parmetro que se declara sin re fu out. 24Un parmetro de valor se genera al invocar el miembro de funcin (mtodo, constructores de instancia, 25descriptor de acceso u operador) al que pertenece el parmetro, y se inicializa con el valor del argumento 26especificado en la invocacin. Un parmetro de valores deja de existir al regresar el miembro de funcin. 27Para los fines de comprobacin de asignacin definitiva, un parmetro de valores se considera asignado 28inicialmente. 295.1.5 Parmetros de referencia 30Un parmetro de referencia es un parmetro que se declara con un modificador re f . 31Un parmetro de referencia no crea una nueva ubicacin de almacenamiento. En lugar de ello, un parmetro de 32referencia representa la misma ubicacin de almacenamiento que la variable especificada como argumento en la 33invocacin del miembro de funcin. Por lo tanto, el valor de un parmetro de referencia siempre es el mismo 34que el de la variable subyacente. 35Se aplican las siguientes reglas de asignacin definitiva a los parmetros de referencia. Deben tenerse en cuenta 36las distintas reglas de los parmetros de resultados explicadas en 5.1.6. 37 38 39Una variable debe estar asignada definitivamente (5.3) para que pueda pasarse como parmetro de referencia en la invocacin de un miembro de funcin. Dentro de un miembro de funcin, un parmetro de referencia se considera asignado inicialmente.

22198

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

222

Captulo 18 Cdigo no seguro

1Dentro de un mtodo de instancia o un descriptor de acceso de instancia de tipo struct, la palabra clave th i s 2tiene exactamente el mismo comportamiento que un parmetro de referencia de tipo struct (7.5.7). 35.1.6 Parmetros de salida 4Un parmetro de salida es un parmetro que se declara con un modificador out. 5Un parmetro de salida no crea una nueva ubicacin de almacenamiento. En lugar de ello, un parmetro de 6salida representa la misma ubicacin de almacenamiento que la variable especificada como argumento en la 7invocacin del miembro de funcin. Por lo tanto, el valor de un parmetro de salida siempre es el mismo que el 8de la variable subyacente. 9Se aplican las siguientes reglas de asignacin definitiva a los parmetros de salida. Deben tenerse en cuenta las 10distintas reglas de los parmetros de referencia explicadas en 5.1.5. 11 12 13 14 15 16 17Una variable no tiene por qu estar asignada definitivamente para poder pasarla como parmetro de salida en una invocacin de miembro de funcin. Tras la finalizacin normal de la invocacin de un miembro de funcin, cada variable que se pase como parmetro de salida se considera asignada en esa ruta de ejecucin. Dentro de un miembro de funcin, un parmetro de salida se considera no asignado inicialmente. Todos los parmetros de resultado de un miembro de funcin deben estar asignados definitivamente (5.3) antes de que se devuelva normalmente el miembro de funcin.

18Dentro de un constructores de instancia del tipo struct, la palabra clave th i stiene exactamente el mismo 19comportamiento que un parmetro de salida de tipo struct (7.5.7). 205.1.7 Variables locales 21Una variable local se declara mediante una declaracin de variable local (local-variable-declaration), lo cual 22puede ocurrir en un bloque (block), una instruccin for (for-statement), una instruccin switch (switch23statement)o una instruccin using (using-statement). 24El perodo de duracin de una variable local representa la parte de la ejecucin del programa durante la cual se 25garantiza que hay un espacio de almacenamiento reservado para ella. Este perodo se prolonga desde la entrada 26en el bloque (block), instruccin for (for-statement), instruccin switch (switch-statement) o instruccin using 27(using-statement) a los que est asociada, hasta que la ejecucin de dichos bloque, instruccin for, instruccin 28switch o instruccin using finaliza de cualquier modo. (La entrada en un bloque contenedor o la llamada a un 29mtodo suspende, aunque no finaliza, la ejecucin del bloque, la instruccin for, la instruccin switch o la 30instruccin using actuales.) Si se entra de manera recursiva en el bloque primario, en la instruccin for, en la 31instruccin switch o en la instruccin using, se crear una instancia nueva de la variable local cada vez, y su 32inicializador de variable local (local-variable-initializer), si existe, se evaluar en cada ocasin. 33Una variable local no se inicializa automticamente y, por lo tanto, no tiene un valor predeterminado. Para los 34fines de comprobacin de asignacin definitiva, una variable local se considera no asignada inicialmente. Una 35declaracin de variable local (local-variable-declaration) puede incluir un inicializador de variable local (local36variable-initializer), en cuyo caso la variable se considera asignada definitivamente en todo su mbito, a 37excepcin de la expresin suministrada en el inicializador de la variable local. 38Dentro del mbito de una variable local, hacer referencia a la variable local en una posicin textual anterior a su 39declarador de variable local (local-variable-declarator) produce un error en tiempo de compilacin. 40La duracin real de una variable local depende de la implementacin. Por ejemplo, un compilador puede 41determinar estticamente que una variable local de un bloque slo se utiliza para una pequea parte del bloque,

223Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

99

224Especificacin del lenguaje C#

1y usar este anlisis para que el compilador genere un cdigo que d como resultado que el almacenamiento de la 2variable tenga una duracin ms corta que la de su bloque contenedor. 3El almacenamiento a que se refiere una variable de referencia local se reclama independientemente de la 4duracin de esa variable de referencia local (3.9). 5Una variable local tambin se declara mediante una instruccin foreach (foreach-statement) y mediante una 6clusula catch especfica (specific-catch-clause) en una instruccin try (try-statement). Para una instruccin 7foreach (foreach-statement), la variable local es una variable de iteracin (8.8.4). Para una clusula catch 8especfica (a specific-catch-clause), la variable local es una variable de excepcin (8.10). Una variable local 9declarada por una instruccin foreach (foreach-statement) o una clusula catch especfica (specific-catch-clause) 10se considera asignada de forma definitiva en todo su mbito. 115.2 Valores predeterminados 12Las categoras de variables siguientes se inicializan de forma automtica a sus valores predeterminados: 13 14 15 17 18 19Variables estticas. Variables de instancia de instancias de clase. Elementos matriciales. Para una variable de un tipo de valor (value-type), el valor predeterminado es el mismo que el valor calculado por el constructor predeterminado del tipo de valor (value-type) (4.1.1). Para una variable de tipo de referencia (reference-type), el valor predeterminado es nu l .l

16El valor predeterminado de una variable depende de su tipo y se determina como sigue:

20La inicializacin a valores predeterminados, la suelen llevar a cabo el administrador de la memoria o el 21recolector de elementos no utilizados, que inicializan la memoria a todos los bits cero antes de asignarla para su 22uso. Por este motivo, es conveniente utilizar todos los bits cero para representar la referencia nula. 235.3 Estado de asignacin definitiva 24En una ubicacin dada del cdigo ejecutable de un miembro de funcin, se dice que una variable est asignada 25definitivamente si el compilador puede probar, mediante un anlisis de flujo esttico concreto (5.3.3), que la 26variable se ha inicializado automticamente o ha sido el destino de por lo menos una asignacin. Dicho de una 27manera informal, las reglas de la asignacin definitiva son: 28 29 30 31 32 33 34 35Una variable asignada inicialmente (5.3.1) siempre se considera asignada definitivamente. Una variable no asignada inicialmente (5.3.2) se considera asignada definitivamente en una ubicacin dada si todas las rutas de ejecucin posibles que llevan a ella contienen por lo menos uno de los siguientes elementos: o o o Una asignacin simple (7.13.1) en la cual la variable es el operando izquierdo. Una expresin de llamada (7.5.5) o una expresin de creacin de objeto (7.5.10.1) que pasa la variable como parmetro de salida. Para una variable local, una declaracin de variable local (8.5) que incluye un inicializador de variable.

36La especificacin formal subyacente a las reglas informales anteriores se describe en los apartados 5.3.1, 375.3.2 y 5.3.3.

225100

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

226

Captulo 18 Cdigo no seguro

1El estado de asignacin definitiva de las variables de instancia de una variable de tipo struct (struct-type) puede 2tener un seguimiento individual y tambin colectivo. Adems de las reglas anteriores, se aplican las reglas 3siguientes a las variables de tipo struct (struct-type) y a sus variables de instancia: 4 5 6 7 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26Una variable de instancia se considera asignada definitivamente si la variable de tipo struct (struct-type) que la contiene se considera asignada definitivamente. Una variable de tipo struct (struct-type) se considera asignada definitivamente si todas sus variables de instancia se consideran asignadas definitivamente. Una variable debe estar asignada definitivamente en cada ubicacin donde se obtenga su valor. Esto asegura que nunca puedan ocurrir valores no definidos. Se considera que la ocurrencia de una variable en una expresin obtiene el valor de la variable, excepto cuando: o o o la variable es el operando izquierdo de una asignacin simple, la variable se pasa como un parmetro de salida, o la variable es de tipo struct (struct-type) y se produce como el operando izquierdo de un acceso a miembros.

8La asignacin definitiva es un requisito obligatorio en los contextos siguientes:

Una variable debe estar asignada definitivamente en cada ubicacin donde se pase como un parmetro de referencia. Esto asegura que el miembro de funcin que se invoca puede considerar al parmetro de referencias como asignado inicialmente. Todos los parmetros de resultado de un miembro de funcin deben estar asignados definitivamente en cada ubicacin donde regrese el miembro de funcin (mediante una instruccin re tu rno cuando la ejecucin llega al final del cuerpo del miembro de funcin). Esto asegura que los miembros de funcin no devuelven valores no definidos en los parmetros de salida, lo que permite al compilador considerar la invocacin de un miembro de funcin que llame a una variable como un parmetro de salida equivalente a una asignacin de la variable. La variable th i sde un constructores de instancia de un tipo struct (struct-type) debe estar asignada definitivamente en cada ubicacin a la que regrese el constructor de instancia.

275.3.1 Variables asignadas inicialmente 28Las siguientes categoras de variables se clasifican como asignadas inicialmente: 29 30 31 32 33 34 35Variables estticas. Variables de instancia de instancias de clase. Variables de instancia de variables de estructura asignadas inicialmente. Elementos matriciales. Parmetros de valor. Parmetros de referencia. Variables declaradas en una clusula ca tch o en una instruccin f o reach .

365.3.2 Variables no asignadas inicialmente 37Las siguientes categoras de variables se clasifican como no asignadas inicialmente:

227Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

101

228Especificacin del lenguaje C#

1 2 3

Variables de instancia de variables de estructura no asignadas inicialmente. Parmetros de salida, incluida la variable th i sde constructores de instancia de estructuras. Variables locales, excepto aquellas declaradas en una clusula ca tch o en una instruccin f o reach .

45.3.3 Reglas precisas para determinar asignaciones definitivas 5Para determinar que cada variable utilizada est asignada definitivamente, el compilador debe utilizar un 6proceso equivalente al descrito en esta seccin. 7El compilador procesa el cuerpo de cada miembro de funcin que tenga una o ms variables no asignadas 8inicialmente. El compilador determina un estado de asignacin definitiva para cada variable v no asignada 9inicialmente, en cada uno de los siguientes puntos del miembro de funcin: 10 11 12 13 14 16 17 18 19 20 21 22 23 24 25 26Al principio de cada instruccin En el punto final (8.1) de cada instruccin En cada arco que transfiere el control a otra instruccin o al punto final de una instruccin Al principio de cada expresin Al final de cada expresin Asignada definitivamente. Indica que en todos los posibles flujos de control para este punto, a v se le ha asignado un valor. No asignada definitivamente. Para el estado de una variable al final de una expresin de tipo boo l, el estado de una variable que no se ha asignado definitivamente puede caer (aunque no necesariamente) en uno de los siguientes subestados: o Asignada definitivamente despus de una expresin true. Este estado indica que si la expresin booleana se evala como true, v estar asignada definitivamente, pero si la expresin booleana se evala como false, no tiene por qu estar asignada. Asignada definitivamente despus de una expresin false. Este estado indica que si la expresin booleana se evala como false, v estar asignada definitivamente, pero si la expresin booleana se evala como true, no tiene por qu estar asignada.

15El estado de asignacin definitiva de v puede ser:

o

27Las reglas siguientes rigen la forma en la que se determina el estado de una variable v en cada posicin. 285.3.3.1 Reglas generales para instrucciones 29 v no se asigna definitivamente al principio del cuerpo de un miembro de funcin. 30 31 32 33 34 35 36 37 38229102

v se asigna definitivamente al principio de cualquier instruccin inalcanzable. El estado de asignacin definitiva de v al principio de cualquier otra instruccin se determina mediante la comprobacin del estado de asignacin definitiva de v en todas las transferencias de flujo de control que apunten al principio de esa instruccin. Si (y slo en este caso) v se asigna definitivamente en todas estas transferencias de flujo de control, se asigna tambin definitivamente al principio de la instruccin. El conjunto de posibles transferencias de flujo de control se determina del mismo modo que en la comprobacin del alcance de la instruccin (8.1). El estado de asignacin definitiva de v en el punto final de una instruccin de bloque, checked, unchecked, if, while, do, for, foreach, lock, using o switch se determina mediante la comprobacin del

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

230

Captulo 18 Cdigo no seguro

1 2 3 4 5

estado de asignacin definitiva de v en todas las transferencias de flujo de control que apunten al punto final de esa instruccin. Si v se asigna definitivamente en todas estas transferencias de flujo de control, entonces v se asigna definitivamente en el punto final de la instruccin. De lo contrario, v no se asigna definitivamente en el punto final de la instruccin. El conjunto de posibles transferencias de flujo de control se determina del mismo modo que en la comprobacin del alcance de la instruccin (8.1).

65.3.3.2 Instrucciones de bloques e instrucciones checked y unchecked 7El estado de asignacin definitiva de v, en la transferencia de control a la primera instruccin de la lista de 8instrucciones del bloque (o al punto final del bloque, si la lista de instrucciones est vaca), es el mismo que el 9de la instruccin de asignacin definitiva de v antes de la instruccin de bloque checked o unchecked. 105.3.3.3 Instrucciones de expresiones 11Para una instruccin de expresin stmt que consta de la expresin expr: 12 13 14v tiene el mismo estado de asignacin definitiva al principio de expr que al principio de stmt. Si v se asigna definitivamente al final de expr, tambin lo har en el punto final de stmt; de lo contrario, este punto no recibir tal asignacin.

155.3.3.4 Instrucciones de declaracin 16 Si stmt es una instruccin de declaracin sin inicializadores, entonces v tiene el mismo estado de asignacin 17 definitiva en el punto final de stmt que al principio de stmt. 18 19 20Si stmt es una instruccin de declaracin con inicializadores, el estado de asignacin definitiva de v se determina como si stmt fuera una lista de instrucciones, con una instruccin de asignacin para cada declaracin con un inicializador (en el orden de la declaracin).

215.3.3.5 Instrucciones If 22Para una instruccin i fstmt con la estructura: 23 24 25 26 27 28 29 30 31 32 33 34 35i f ( expr ) then-stmt else else-stmt

v tiene el mismo estado de asignacin definitiva al principio de expr que al principio de stmt. Si v est definitivamente asignada al final de expr, tambin lo estar en la transferencia de flujo de control a then-stmt y a else-stmt, o bien al punto final de stmt si no hay clusula else. Si v est definitivamente asignada despus de una expresin true al final de expr, entonces tambin lo estar en la transferencia de flujo de control a then-stmt; si no hay clusula else, no estar definitivamente asignada en la transferencia de flujo de control a else-stmt o al punto final de stmt. Si v tiene el estado definitivamente asignada despus de expresin false al final de expr, entonces est definitivamente asignada en la transferencia de flujo de control a else-stmt y no lo est a then-stmt en la transferencia de flujo de control. Est definitivamente asignada al punto final de stmt solamente si est tambin definitivamente asignada al punto final de then-stmt. De lo contrario, v se considera no asignada definitivamente a then-stmt o a else-stmt en la transferencia de flujo de control o, si no hay clusula else, al punto final de stmt.

365.3.3.6 Instrucciones Switch 37En una instruccin switch stmt con una expresin de control expr:

231Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

103

232Especificacin del lenguaje C#

1 2 3 4

El estado de asignacin definitiva de v al principio de expr es el mismo que el estado de v al principio de stmt. El estado de asignacin definitiva de v en la transferencia de flujo de control a una lista de instrucciones de bloque switch localizable es el mismo que al final de expr.

233104

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

234

Captulo 18 Cdigo no seguro

15.3.3.7 Instrucciones While 2Para una instruccin whi l estmt con la siguiente estructura: 3 4 5 6 7 8 9 10 11 12whi l e ( expr ) while-body

v tiene el mismo estado de asignacin definitiva al principio de expr que al principio de stmt. Si v est asignada definitivamente al final de expr, entonces est definitivamente asignada en la transferencia de flujo de control a while-body y al punto final de stmt. Si el estado de v al final de expr es definitivamente asignada despus de una expresin true, est definitivamente asignada en la transferencia de flujo de control a while-body, pero no en el punto final de stmt. Si el estado de v al final de expr es definitivamente asignada despus de una expresin false, est definitivamente asignada en la transferencia de flujo de control al punto final de stmt, pero no a while-body en la transferencia de flujo de control.

135.3.3.8 Instrucciones Do 14Para una instruccin do stmt con la siguiente estructura: 15 16 17 18 19 20 21 22do do-body while ( expr ) ;

v tiene el mismo estado de asignacin definitiva en la transferencia de flujo de control, desde el principio de stmt a do-body, que al principio de stmt. v tiene el mismo estado de asignacin definitiva al principio de expr que en el punto final de do-body. Si v est asignada definitivamente al final de expr, tambin lo est en la transferencia de flujo de control al punto final de stmt. Si el estado de v al final de expr es asignada definitivamente despus de una expresin false, entonces est definitivamente asignada en la transferencia de flujo de control al punto final de stmt.

235.3.3.9 Instrucciones For 24La comprobacin de asignacin definitiva de una instruccin f o rcon la estructura 25 f o r ( for-initializer ; for-condition ; for-iterator ) embedded-statement 26se realiza como si la instruccin estuviera escrita de la siguiente forma: 27 28 29 30 3132 33

{

for-initializer ; while ( for-condition ) { embedded-statement ; for-iterator ;} }

34Si se omite la condicin for (for-condition) en la instruccin for, la evaluacin o la asignacin definitiva 35continuar como si se sustituyera la condicin for por true en la expansin anterior. 365.3.3.10 Instrucciones Break, Continue y Goto 37El estado de asignacin definitiva de v en la transferencia de flujo de control causada por una instruccin break, 38continue o goto es el mismo que el de v al principio de la instruccin.235Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

105

236Especificacin del lenguaje C#

15.3.3.11 Instrucciones Throw 2Para una instruccin stmt con la estructura: 3 throw expr ; 4El estado de asignacin definitiva de v al principio de expr es el mismo que el de v al principio de stmt. 55.3.3.12 Instrucciones Return 6Para una instruccin stmt con la estructura: 7 8 9 10 11 13 14 15 16El estado de asignacin definitiva de v al principio de expr es el mismo que el de v al principio de stmt. Si v es un parmetro de salida, debe asignarse definitivamente: o o despus de expr o bien al final del bloque f i na l lde t r y - f i na lol try-catch-finally que incluya la instruccin return. y yreturn expr ;

12Para una instruccin stmt con la estructura:Si v es un parmetro de salida, debe asignarse definitivamente: o o antes de stmt o bien al final del bloque finally de try-finally o try-catch-finally que incluya la instruccin return.return ;

175.3.3.13 Instrucciones Try-catch 18Para una instruccin stmt con la estructura: 19 20 22 23 24 25 26 27 2821

El estado de asignacin definitiva de v al principio de try-block es igual al de v al principio de stmt. El estado de asignacin definitiva de v al principio de catch-block-i (para cualquier i) es el mismo que el de v al principio de stmt. El estado de asignacin definitiva de v en el punto final de stmt est asignado definitivamente si (y slo si) v est definitivamente asignada en el punto final de try-block y de todos los catch-block-i (para cada i de 1 a n).

try try-block catch(...) catch-block-1 ... catch(...) catch-block-n

295.3.3.14 Instrucciones Try-finally 30Para una instruccin try stmt con la siguiente estructura: 31 32 33 34 35try try-block finally finally-block El estado de asignacin definitiva de v al principio de try-block es igual al de v al principio de stmt.

El estado de asignacin definitiva de v al principio de finally-block es igual al de v al principio de stmt. v estar definitivamente asignada en el punto final de stmt si (y slo si) al menos una de las siguientes afirmaciones es verdadera:

237106

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

238

Captulo 18 Cdigo no seguro

1 2

o o

v est asignada definitivamente en el punto final de try-block v est asignada definitivamente en el punto final de finally-block

3Si se realiza una transferencia de flujo de control (por ejemplo, una instruccin goto) que se inicia dentro de un 4bloque try (try-block) y termina fuera del bloque try, entonces v tambin se considerar asignada definitivamente 5en esa transferencia de flujo de control si tambin lo est en el punto final del bloque finally (finally-block). 6(Esta condicin no es exclusiva: si v est asignada definitivamente por otra razn en esta transferencia de flujo 7de control, se considerar asignada definitivamente). 85.3.3.15 Instrucciones Try-finally-catch 9El anlisis de asignacin definitiva de una instruccin try-catch-finally con la estructura: 10 1112

13 14 15se realiza como si la instruccin fuera una instruccin t r y - f i na lque incluyera una instruccin t r y - ca tch ly : 16 17 18 2021 19

t r y try-block catch(...) catch-block-1 ... catch(...) catch-block-n finally finally-block t ry {

t r y try-block catch(...) catch-block-1 ... catch(...) catch-block-n }

22 finally finally-block 23El ejemplo siguiente demuestra cmo afectan los diferentes bloques de una instruccin t ry(8.10) a la 24asignacin definitiva. 25 26 27 28 29 30 31 32 35 33 36 34 37 38 39c lass A { s ta t i c vo id F ( ) { int i , j ; t ry { goto LABEL ; / / ne i the r i nor j de f i n i te l y ass igned i = 1; ca tch { / / ne i the r i nor j de f i n i te l y ass igned i = 3; / / i de f i n i te l y ass igned

239Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

107

240Especificacin del lenguaje C#

1 2 3 4 5 6

finally { // neither i nor j definitely assigned j = 5; // j definitely assigned } // i and j definitely assigned

7 LABEL:; 125.3.3.16 Instrucciones Foreach 8 13Para una instruccin f o reachstmt con la siguiente estructura: 9 14 f o reach ( type identifier in expr ) embedded-statement 10 15 El estado de asignacin definitiva de v al principio de expr es el mismo que el estado de v al principio de 11 16 stmt. 17 18El estado de asignacin definitiva de v en la transferencia de flujo de control a una instruccin incrustada (embedded-statement) o al punto final de stmt es el mismo que el estado de v al final de expr.

195.3.3.17 Instrucciones Using 20Para una instruccin using stmt con la siguiente estructura: 21 22 23 24 25us ing ( resource-acquisition ) embedded-statement

El estado de asignacin definitiva de v al principio de adquisicin de recurso (resource-acquisition) es igual al estado de v al principio de stmt. El estado de asignacin definitiva de v en la transferencia de flujo de control a una instruccin incrustada (embedded-statement) es igual al de v al final de la adquisicin de recurso (resource-acquisition).

265.3.3.18 Instrucciones Lock 27Para una instruccin lock stmt con la siguiente estructura: 28 29 30 31 32l ock ( expr ) embedded-statement

El estado de asignacin definitiva de v al principio de expr es el mismo que el estado de v al principio de stmt. El estado de asignacin definitiva de v en la transferencia de flujo de control a una instruccin incrustada (embedded-statement) es igual que el estado de v al final de la expresin (expr).

335.3.3.19 Reglas generales para expresiones simples 34La siguiente regla se aplica a estos tipos de expresiones: literales (7.5.1), nombres simples (7.5.2), 35expresiones de acceso a miembros (7.5.4), expresiones de acceso a bases no indizadas (7.5.8) y expresiones 36typeof (7.5.11). 37 38El estado de asignacin definitiva de v al final de una expresin de este tipo es igual que el de v al principio de la expresin.

241108

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

242

Captulo 18 Cdigo no seguro

15.3.3.20 Reglas generales para expresiones con expresiones incrustadas 2Las reglas siguientes se aplican a estos tipos de expresiones: expresiones entre parntesis (7.5.3), expresiones 3de acceso a elementos (7.5.6), expresiones de acceso a bases con indizacin (7.5.8), expresiones de 4incremento y decremento (7.5.9, 7.6.5), expresiones de conversin de tipos (7.6.6), expresiones unarias +, -, 5~, *, expresiones binarias +, -, *, /, %, , =, ==, !=, is, as, &, |, ^ (7.7, 7.8, 7.9, 67.10), expresiones de asignacin compuestas (7.13.2), expresiones checked y unchecked (7.5.12), y 7expresiones de creacin de matrices y de delegados (7.5.10). 8Cada una de estas expresiones tiene una o ms subexpresiones que se evalan incondicionalmente en un orden 9fijo. Por ejemplo, el operador binario % evala el lado izquierdo del operador y, a continuacin, el lado derecho. 10Una operacin de indizacin evala la expresin indizada y, a continuacin, cada una de las expresiones de 11ndice por orden, de izquierda a derecha. Para una expresin expr que tiene las subexpresiones expr1, expr2, ..., 12exprn, evaluadas en ese orden: 13 14 15 16 17El estado de asignacin definitiva de v al principio de expr1 es igual que el estado de asignacin definitiva al principio de expr. El estado de asignacin definitiva de v al principio de expri (siendo i mayor que uno) es igual que el estado al final de expri-1. El estado de asignacin definitiva de v al principio de expr es igual que el estado al final de exprn.

185.3.3.21 Expresiones de invocacin y expresiones de creacin de objetos 19Para una expresin de invocacin expr con la estructura: 20 22 23 24 25 26 27 28 29 30 31 32 33 34 35primary-expression ( arg1 , arg2 , , argn )

21o una expresin de creacin de objeto con la estructura:new type ( arg1 , arg2 , , argn ) Para una expresin de invocacin, el estado de asignacin definitiva de v antes de la expresin primaria (primary-expression) es igual que el estado de v antes de expr.

Para una expresin de invocacin, el estado de asignacin definitiva de v antes de arg1 es igual que el estado de v despus de la expresin primaria (primary-expression). Para una expresin de creacin de objeto, el estado de asignacin definitiva de v antes de arg1 es igual que el estado de v antes de expr. Para cada argumento argi, el estado de asignacin definitiva de v despus de argi est determinado por las reglas de expresin normales omitiendo los modificadores ref u out. Para cada argumento argi, siendo i mayor que uno, el estado de asignacin definitiva de v antes de argi es el mismo que el de v despus de argi-1. Si se pasa la variable v como un argumento out (es decir, un argumento de forma "out v") en cualquiera de los argumentos, el estado de v despus de expr se asigna definitivamente. De lo contrario, el estado de v despus de expr es el mismo que el estado de v despus de argn.

365.3.3.22 Expresiones de asignacin simples 37Para una expresin expr con la estructura w = expr-rhs: 38El estado de asignacin definitiva de v antes de expr-rhs es igual que el de v antes de expr.

243Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

109

244Especificacin del lenguaje C#

1 2 3

Si w es la misma variable que v, el estado de asignacin definitiva de v despus de expr se asigna definitivamente. De lo contrario, el estado de asignacin definitiva de v despus de expr ser igual que el de v despus de expr-rhs.

45.3.3.23 Expresiones && 5Para una expresin expr con la estructura expr-first && expr-second: 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25El estado de asignacin definitiva de v antes de expr-first es igual que el de v antes de expr. El estado de asignacin definitiva de v antes de la segunda expresin (expr-second) se asigna definitivamente, si el estado de v despus de la primera expresin (expr-first) se asigna definitivamente o es asignado definitivamente despus de una expresin true. En cualquier otro caso, no se asigna definitivamente. El estado de asignacin definitiva de v despus de expr se determina de la siguiente forma: o o Si el estado de v despus de expr-first se asigna definitivamente, tambin lo har el estado de v despus de expr. De lo contrario, si el estado de v despus de la segunda expresin (expr-second) se asigna definitivamente y el estado de v despus de la primera expresin (expr-first) es asignado definitivamente despus de una expresin false, entonces el estado de v despus de la expresin (expr) se asigna definitivamente. De lo contrario, si el estado de v despus de la segunda expresin (expr-second) se asigna definitivamente o es asignado definitivamente despus de expresin true, entonces el estado de v despus de la expresin (expr) es asignado definitivamente despus de una expresin true. De lo contrario, si el estado de v despus de la primera expresin (expr-first) es asignado definitivamente despus de una expresin false y el estado de v despus de segunda expresin (exprsecond) es asignado definitivamente despus de una expresin false, entonces el estado de v despus de la expresin (expr) es asignado definitivamente despus de una expresin false. De lo contrario, el estado de v despus de expr no se asignar definitivamente.

o

o

o

26En el siguiente ejemplo: 27 c lass A 28 { 29 s ta t i c vo id F ( i n t x , i n t y ) { 30 int i ; 31 i f ( x > 0 && ( i = y ) > 0) { = = 32 / / i de f i n i te l y ass igned 33 } 34 e l se { 35 / / i not de f i n i te l y ass igned 36 } 37la variable i se considera asignada definitivamente en una de las instrucciones incrustadas de una instruccin i f 40 41 38pero no en la otra. En la instruccin if del mtodo F, la variable i est asignada definitivamente en la primera 42instruccin incrustada porque la ejecucin de la expresin (i = y) siempre precede a la ejecucin de esta 39 43instruccin incrustada. Por contra, la variable i no est asignada definitivamente en la segunda instruccin 44incrustada, puesto que x >= 0 podra dar como resultado false y causar que la variable i no se asigne.

245110

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

246

Captulo 18 Cdigo no seguro

15.3.3.24 Expresiones || 2Para una expresin expr con la estructura expr-first | |expr-second: 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22El estado de asignacin definitiva de v antes de expr-first es igual que el de v antes de expr. El estado de asignacin definitiva de v antes de la segunda expresin (expr-second) se asigna definitivamente si el estado de v despus de la primera expresin (expr-first) se asigna definitivamente o es asignado definitivamente despus de una expresin false. En cualquier otro caso, no se asigna definitivamente. El estado de asignacin definitiva de v despus de expr se determina de la siguiente forma: o o Si el estado de v despus de expr-first se asigna definitivamente, tambin lo har el estado de v despus de expr. De lo contrario, si el estado de v despus de la segunda expresin (expr-second) se asigna definitivamente y el estado de v despus de la primera expresin (expr-first) es asignado definitivamente despus de una expresin true, entonces el estado de v despus de expr se asignar definitivamente. De lo contrario, si el estado de v despus de la segunda expresin (expr-second) se asigna definitivamente o es asignado definitivamente despus de una expresin false, entonces el estado de v despus de la expresin (expr) es asignado definitivamente despus de una expresin false. De lo contrario, si el estado de v despus de la primera expresin (expr-first) es asignado definitivamente despus de una expresin true y el estado de v despus de la segunda expresin (exprsecond) es asignado definitivamente despus de una expresin true, entonces el estado de v despus de expr es asignado definitivamente despus de una expresin true. De lo contrario, el estado de v despus de expr no se asignar definitivamente.

o

o

o

23En el siguiente ejemplo: 24 c lass A 25 { 26 s ta t i c vo id G( in t x , i n t y ) { 27 int i ; 28 i f ( x > 0 | | ( i = y ) > 0) { = = 29 / / i not de f i n i te l y ass igned 30 } 31 e l se { 32 / / i de f i n i te l y ass igned 33 } 34la variable i se considera asignada definitivamente en una de las instrucciones incrustadas de una instruccin i f 37 38pero no en la otra. En la instruccin if del mtodo G, la variable i est asignada definitivamente en la segunda 35 39instruccin incrustada porque la ejecucin de la expresin (i = y) siempre precede a la ejecucin de esta 36 40instruccin incrustada. Por contra, la variable i no est asignada definitivamente en la primera instruccin 41incrustada, puesto que x >= 0 podra dar como resultado true y causar que la variable i no se asigne. 425.3.3.25 ! Expresiones ! 43Para una expresin expr con la estructura ! expr-operand:

247Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

111

248Especificacin del lenguaje C#

1 2 3 4 5 6 7 8 9 10 11 12 13

El estado de asignacin definitiva de v antes de expr-operand es igual que el estado de asignacin definitiva de v antes de expr. El estado de asignacin definitiva de v despus de expr se determina de la siguiente forma: o o o Si el estado de v despus de expr-operand se asigna definitivamente, el estado de v despus de expr se asigna definitivamente. Si el estado de v despus de expr-operand no se asigna definitivamente, el estado de v despus de expr no se asigna definitivamente. Si el estado de v despus del operando de la expresin (expr-operand) es asignado definitivamente despus de una expresin false, entonces el estado de v despus de la expresin (expr) es asignado definitivamente despus de una expresin true. Si el estado de v despus del operando de la expresin (expr-operand) es asignado definitivamente despus de una expresin true, entonces el estado de v despus de la expresin (expr) es asignado definitivamente despus de una expresin false.

o

145.3.3.26 Expresiones ?: 15Para una expresin expr con la estructura expr-cond ? expr-true : expr-false: 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32El estado de asignacin definitiva de v antes de expr-cond es igual al estado de v antes de expr. El estado de asignacin definitiva de v antes de la expresin para true (expr-true) se asigna definitivamente solamente en el caso de que el estado de v despus de la expresin condicional (expr-cond) se asigne definitivamente o sea asignado definitivamente despus de una expresin true. El estado de asignacin definitiva de v antes de la expresin para false (expr-false) se asigna definitivamente solamente en el caso de que el estado de v despus de la expresin condicional (expr-cond) se asigne definitivamente o sea asignado definitivamente despus de una expresin false. El estado de asignacin definitiva de v despus de expr se determina de la siguiente forma: o Si la expresin condicional (expr-cond) es una expresin constante (7.15) con valor t rue entonces el , estado de v despus de la expresin (expr) es el mismo que el estado de v despus de la expresin para true (expr-true). De lo contrario, si la expresin condicional (expr-cond) es una expresin constante (7.15) con valor f a l seentonces el estado de v despus de la expresin (expr) es el mismo que el estado de v despus de , la expresin para false (expr-false). De lo contrario, si el estado de v despus de expr-true y el estado de v despus de expr-false se asignan definitivamente, entonces el estado de v despus de expr tambin se asignar definitivamente. De lo contrario, el estado de v despus de expr no se asignar definitivamente.

o

o o

335.4 Referencias de variables 34Una referencia de variable (variable-reference) es una expresin que se clasifica como una variable. Una 35referencia de variable (variable-reference) es una ubicacin de almacenamiento a la que se puede obtener 36acceso, tanto para obtener el valor actual, como para almacenar un valor nuevo. 37 38variable-reference: expression

39En C y C++, una referencia de variable (variable-reference) se conoce como lvalue.

249112

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

250

Captulo 18 Cdigo no seguro

15.5 Atomicidad de las referencias de variable 2Las lecturas y escrituras de los siguientes tipos de datos son atmicas: boo l, char, byte, sbyte, short, ushort, 3uint, int, float y tipos de referencia. Adems, las lecturas y escrituras de tipos enum cuyo tipo subyacente est 4en la lista anterior son tambin atmicas. No se garantiza que las lecturas y escrituras de otros tipos (como long, 5ulong, double o decimal, as como los tipos definidos por el usuario) sean atmicas. Aparte de las funciones 6de biblioteca diseadas para este propsito, no hay garanta de lectura, modificacin ni escritura atmicas, como 7en el caso de incrementos o decrementos.

251Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

113

252Especificacin del lenguaje C#

1

6.Conversiones

2Una conversin permite que una expresin de un tipo sea tratada como de otro tipo. Las conversiones pueden 3ser implcitas o explcitas, y esto determina si se requiere una conversin de tipo explcita. Por ejemplo, la 4conversin del tipo i n tal tipo l ong es implcita, por lo que las expresiones de tipo int pueden tratarse 5implcitamente como del tipo long. La conversin opuesta, del tipo long a int, es explcita y, por ello, se 6requiere una conversin explcita. 7int a = 123;

8 long b = a; // implicit conversion from int to long 10Algunas conversiones estn definidas por el lenguaje. Los programas tambin pueden definir sus propias 9 11conversiones (6.4). 126.1 Conversiones implcitas 13Las siguientes conversiones se clasifican como conversiones implcitas: 14 15 16 17 18 19 20Conversiones de identidad Conversiones numricas implcitas Conversiones de enumeracin implcitas Conversiones de referencia implcitas Conversiones boxing Conversiones implcitas de expresin constante Conversiones definidas por el usuario implcitas

21Las conversiones implcitas pueden ocurrir en distintas situaciones, incluyendo las invocaciones de miembros de 22funcin (7.4.3), las expresiones de conversin (7.6.6) y las asignaciones (7.13). 23Las conversiones implcitas predefinidas siempre tienen xito y nunca causan excepciones. Las conversiones 24implcitas definidas por el usuario correctamente diseadas tambin deben exhibir estas caractersticas. 256.1.1 Conversiones de identidad 26Una conversin de identidad convierte de cualquier tipo al mismo tipo. Esta conversin existe solamente para 27que una entidad que ya sea de un tipo requerido pueda considerarse convertible a dicho tipo. 286.1.2 Conversiones numricas implcitas 29Las conversiones implcitas numricas son: 30 31 32 33253114

De sby te a shor t int, long, float, double o decimal. , De byte a short, ushort, int, uint, long, ulong, float, double o decimal. De short a int, long, float, double o decimal. De ushort a int, uint, long, ulong, float, double o decimal.Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

254

Captulo 18 Cdigo no seguro

1 2 3 4 5 6

De i n ta l ong float, double o decimal. , De uint a long, ulong, float, double o decimal. De long a float, double o decimal. De ulong a float, double o decimal. De char a ushort, int, uint, long, ulong, float, double o decimal. De f l oa t doub le. a

, 7Las conversiones de i n t u in t long o ulong a ulong o float y de long o ulong a double pueden producir una , 8prdida de precisin, pero no una prdida de magnitud. En las dems conversiones implcitas numricas nunca 9se pierde informacin.

10No hay conversiones implcitas al tipo char, por tanto los valores de otros tipos integrales no se convierten 11automticamente al tipo char. 126.1.3 Conversiones de enumeracin implcitas 13Una conversin implcita de enumeracin permite convertir el literal entero decimal (decimal-integer-literal) 0 14al tipo enum (enum-type). 156.1.4 Conversiones de referencia implcitas 16Las conversiones implcitas de referencia son: 17 18 19 20 21 22 23 24 25 26 27 28 29 30De cualquier tipo de referencia (reference-type) a object. De cualquier tipo de clase (class-type) S a cualquier tipo de clase T, a condicin de que S se derive de T. De cualquier tipo de clase (class-type) S a cualquier tipo de interfaz (interface-type) T, a condicin de que S implemente a T. De cualquier tipo de interfaz (interface-type) S a cualquier tipo de interfaz (interface-type) T, a condicin de que S se derive de T. De un tipo matricial (array-type) S con un tipo de elemento SE a un tipo matricial T con un tipo de elemento TE, siempre que todo lo siguiente sea verdadero: o o oS y T difieren solamente en el tipo de elemento. Esto es, S y T tienen el mismo nmero de dimensiones.

Tanto SE como TE son tipos de referencia (reference-types). Existe una conversin implcita de referencia de SE a TE.

De cualquier tipo matricial (array-type) a System.Array. De cualquier tipo delegado (delegate-type) a System.Delegate. Del tipo nulo a cualquier tipo de referencia (reference-type).

31Las conversiones implcitas de referencia son aquellas entre tipos de referencia (reference-types) que se puede 32demostrar que siempre se realizan con xito y, por lo tanto, no requieren comprobaciones en tiempo de 33ejecucin. 34Las conversiones de referencia, tanto implcitas como explcitas, nunca cambian la identidad referencial del 35objeto que se convierte. Es decir, si bien una conversin de referencia puede cambiar el tipo de la referencia, 36nunca cambia el tipo o el valor del objeto al que se refiere.

255Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

115

256Especificacin del lenguaje C#

16.1.5 Conversiones boxing 2Una conversin boxing permite convertir implcitamente cualquier tipo de valor (value-type) al tipo ob jec to 3Sys tem.Va lueTypeo a cualquier tipo de interfaz (interface-type) implementado por el tipo de valor (value, 4type). La conversin boxing de un valor a un tipo de valor (value-type) consiste en asignar una instancia del 5objeto y despus copiar en ella el valor del tipo de valor (value-type). Se puede aplicar a una estructura la 6conversin boxing al tipo System.ValueType, puesto que sa es una clase base para todas las 7estructuras (11.3.2). 8Las conversiones boxing se describen ms detalladamente en 4.3.1. 96.1.6 Conversiones implcitas de expresin constante 10Una conversin implcita de expresin constante permite las siguientes conversiones: 11 12 13 14 15Una expresin constante (constant-expression) (7.15) de tipo i n tse puede convertir al tipo sby te, byte, short, ushort, uint o ulong, siempre que el valor de la expresin constante (constant-expression) quede dentro del intervalo del tipo de destino. Una expresin constante (constant-expression) de tipo long puede convertirse al tipo ulong, a condicin de que el valor de la expresin constante no sea negativo.

166.1.7 Conversiones definidas por el usuario implcitas 17Una conversin implcita definida por el usuario consta de una conversin implcita opcional estndar, seguida 18por la ejecucin de un operador de conversin implcita definido por el usuario, seguido por otra conversin 19implcita opcional estndar. Las reglas exactas para la evaluacin de conversiones definidas por el usuario se 20describen en 6.4.3. 216.2 Conversiones explcitas 22Las siguientes conversiones se clasifican como conversiones explcitas: 23 24 25 26 27 28 29Todas las conversiones implcitas. Conversiones explcitas numricas. Conversiones explcitas de enumeracin. Conversiones explcitas de referencia. Conversiones explcitas de interfaz. Conversiones Unboxing. Conversiones explcitas definidas por el usuario.

30Las conversiones explcitas pueden producirse en las expresiones de conversin de tipos (7.6.6). 31El conjunto de conversiones explcitas incluye todas las conversiones implcitas. Esto quiere decir que estn 32permitidas las expresiones de conversin de tipos redundantes. 33Las conversiones explcitas son conversiones que no se puede demostrar que siempre se realizan correctamente, 34conversiones en las que se sabe que se puede producir prdida de informacin y conversiones en dominios de 35tipos que, por sus diferencias, merecen una mencin explcita.

257116

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

258

Captulo 18 Cdigo no seguro

16.2.1 Conversiones explcitas numricas 2Las conversiones numricas explcitas son las conversiones de un tipo numrico (numeric-type) a otro tipo 3numrico para el que no existe ya una conversin de tipo numrico implcita (6.1.2): 4 5 6 7 8 9 10 11 12 13 14 15De sby te a byte, ushort, uint, ulong o char. De byte a sby te y char. De short a sbyte, byte, ushort, uint, ulong o char. De ushort a sbyte, byte, short o char. De int a sbyte, byte, short, ushort, uint, ulong o char. De uint a sbyte, byte, short, ushort, int o char. De long a sbyte, byte, short, ushort, int, uint, ulong o char. De ulong a sbyte, byte, short, ushort, int, uint, long o char. De char a sbyte, byte o short. De float a sbyte, byte, short, ushort, int, uint, long, ulong, char o decimal. De double a sbyte, byte, short, ushort, int, uint, long, ulong, char, float o decimal. De decimal a sbyte, byte, short, ushort, int, uint, long, ulong, char, float o double.

16Dado que las conversiones explcitas incluyen todas las conversiones numricas implcitas y explcitas, siempre 17es posible convertir de cualquier tipo numrico (numeric-type) a cualquier otro tipo numrico (numeric-type) 18mediante una expresin de conversin de tipos (7.6.6). 19Las conversiones explcitas numricas pueden producir prdida de informacin o incluso provocar excepciones. 20Una conversin explcita numrica se procesa como se explica a continuacin: 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38Para una conversin de un tipo integral a otro tipo integral, el procesamiento depende del contexto de comprobacin de desbordamiento (7.5.12) en el que tiene lugar la conversin: o En un contexto checked, la conversin termina correctamente si el valor del operando de origen queda dentro del intervalo del tipo de destino, pero inicia una excepcin System.OverflowException si queda fuera de dicho intervalo. En un contexto unchecked, la conversin siempre termina correctamente y procede como sigue. Si el tipo de origen es ms grande que el de destino, el valor de origen se trunca descartando sus bits extra ms significativos. Despus el resultado se trata como un valor del tipo de destino. Si el tipo de origen es menor que el tipo de destino, el valor de origen se ampla con un signo o con ceros, de forma que tenga el mismo tamao que el tipo de destino. La ampliacin con signo se utiliza si el tipo de origen tiene signo; se utiliza la ampliacin con ceros si el tipo de origen no lleva signo. Despus el resultado se trata como un valor del tipo de destino. Si el tipo del origen tiene el mismo tamao que el tipo de destino, el valor de origen se trata como un valor del tipo de destino.

o

Cuando se convierte un valor de tipo decimal a un tipo integral, el valor de origen se redondea hacia cero hasta el valor entero ms prximo, y ste pasa a ser el resultado de la conversin. Si el valor integral resultante queda fuera del intervalo del tipo de destino, se produce una excepcin System.OverflowException.

259Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

117

260Especificacin del lenguaje C#

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26

Para la conversin de un tipo f l oa t doub le a otro tipo integral, el procesamiento depende del contexto de o comprobacin de desbordamiento (7.5.12) en el que tiene lugar la conversin: o En un contexto checked, la conversin sigue este procedimiento: Si el valor del operando es NaN o infinito, se inicia una excepcin Sys tem.Over f l owExcept i on . De lo contrario, el operando de origen se redondea hacia cero, hasta el valor integral ms cercano. Si dicho valor se encuentra dentro del intervalo del tipo de destino, pasar a ser el resultado de la conversin. De lo contrario, se inicia una excepcin Sys tem.Over f l owExcept i on .

o

En un contexto unchecked, la conversin siempre termina correctamente y procede como sigue. Si el valor del operando es NaN o infinito, el resultado de la conversin es un valor no especificado del tipo de destino. De lo contrario, el operando de origen se redondea hacia cero, hasta el valor integral ms cercano. Si dicho valor se encuentra dentro del intervalo del tipo de destino, pasar a ser el resultado de la conversin. De no ser as, el resultado de la conversin ser un valor no especificado del tipo de destino.

Para una conversin de doub le a f l oa,tel valor double se redondea al valor float ms prximo. Si el valor double es demasiado pequeo para representarlo como float, el resultado se convierte en cero positivo o cero negativo. Si el valor double es demasiado grande para representarlo como float, el resultado se convierte en infinito positivo o infinito negativo. Si el valor double es NaN, el resultado tambin es NaN. Para una conversin de float o double a decimal, el valor de origen se convierte a la representacin decimal y se redondea hasta al nmero ms prximo despus de la posicin decimal 28 si es necesario (4.1.7). Si el valor de origen es demasiado pequeo para representarlo como decimal, el resultado es cero. Si el valor de origen es NaN, infinito o demasiado grande para representarlo como decimal, se inicia una excepcin System.OverflowException. Para una conversin de decimal a float o double, el valor decimal se redondea al valor float o double ms prximo. Aunque esta conversin puede perder precisin, nunca produce una excepcin.

276.2.2 Conversiones de enumeracin explcitas 28Las conversiones explcitas de enumeracin son: 29 30 31 32 33De sby te, byte, short, ushort, int, uint, long, ulong, char, float, double o decimal a cualquier tipo enum (type-enum). De cualquier tipo enum (type-enum) a sbyte, byte, short, ushort, int, uint, long, ulong, char, float, double o decimal. De cualquier tipo enum (enum-type) a cualquier otro tipo enum (enum-type).

34Una conversin explcita de enumeracin entre dos tipos se procesa tratando a uno de los tipos enum (enum35type) como tipo subyacente del otro, y realizando, a continuacin, una conversin numrica implcita o explcita 36entre los tipos resultantes. Por ejemplo, dado un tipo enum (enum-type) E con un tipo subyacente de int, una 37conversin de E a byte se trata como una conversin explcita numrica (6.2.1) de int a byte, y una 38conversin de byte a E se procesa como una conversin implcita numrica (6.1.2) de byte a int.

261118

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

262

Captulo 18 Cdigo no seguro

16.2.3 Conversiones explcitas de referencia 2Las conversiones explcitas de referencia son: 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18De ob jec ta cualquier otro tipo de referencia (reference-type). De cualquier tipo de clase (class-type) S a cualquier tipo de clase (class-type) T, siempre que S sea una clase base de T. De cualquier tipo de clase (class-type) S a cualquier tipo de interfaz (interface-type) T, siempre que S no sea sealed y que S no implemente a T. De cualquier tipo de interfaz (interface-type) S a cualquier tipo de clase (class-type) T, siempre que T no sea sealed ni implemente a S. De cualquier tipo de interfaz (interface-type) S a cualquier tipo de interfaz (interface-type) T, a condicin de que S no se derive de T. De un tipo matricial (array-type) S con un tipo de elemento SE a un tipo matricial T con un tipo de elemento TE, siempre que todo lo siguiente sea verdadero: o o oS y T difieren solamente en el tipo de elemento. Esto es, S y T tienen el mismo nmero de dimensiones.

Tanto SE como TE son tipos de referencia (reference-types). Existe una conversin explcita de referencia de SE a TE.

De System.Array y las interfaces que implementa, a cualquier tipo matricial (array-type). De System.Delegate y las interfaces que implementa a cualquier tipo delegado (delegate-type).

19Las conversiones explcitas de referencia son aquellas conversiones entre tipos de referencias que requieren 20comprobaciones en tiempo de ejecucin para asegurar que son correctas. 21Para que una conversin explcita de referencia se realice correctamente en tiempo de ejecucin, el valor del 22operando de origen debe ser una referencia null, o el tipo real del objeto al que hace referencia el operando de 23origen debe ser un tipo convertible al tipo de destino mediante una conversin implcita de referencia (6.1.4). 24Si una conversin explcita de referencia produce un error, se inicia una excepcin 25System.InvalidCastException. 26Las conversiones de referencia, tanto implcitas como explcitas, nunca cambian la identidad referencial del 27objeto que se convierte. Es decir, si bien una conversin de referencia puede cambiar el tipo de la referencia, 28nunca cambia el tipo o el valor del objeto al que se refiere. 296.2.4 Conversiones Unboxing 30Una conversin unboxing permite una conversin explcita del tipo object o System.ValueType a cualquier 31tipo de valor (value-type), o desde cualquier tipo de interfaz (interface-type) a cualquier tipo de valor (value32type) que implementa el tipo de interfaz. Una operacin unboxing consiste en comprobar primero que la 33instancia del objeto es un valor al que se ha aplicado la conversin boxing del tipo de valor (value-type) dado, y 34copiar despus el valor fuera de la instancia. Se puede aplicar a una estructura la conversin unboxing desde el 35tipo System.ValueType, porque sa es una clase base para todas las estructuras (11.3.2). 36Las conversiones unboxing se explican ms detalladamente en in 4.3.2. 376.2.5 Conversiones explcitas definidas por el usuario 38Una conversin explcita definida por el usuario consta de una conversin explcita opcional estndar, seguida 39por la ejecucin de un operador de conversin implcita o explcita definida por el usuario, seguido por otra

263Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

119

264Especificacin del lenguaje C#

1conversin explcita opcional estndar. Las reglas exactas para la evaluacin de conversiones definidas por el 2usuario se describen en 6.4.4. 36.3 Conversiones estndar 4Las conversiones estndar son conversiones predefinidas que pueden ocurrir como parte de una conversin 5definida por el usuario. 66.3.1 Conversiones implcitas estndar 7Las siguientes conversiones implcitas se clasifican como conversiones implcitas estndar: 8 9 10 11 12Conversiones de identidad (6.1.1) Conversiones numricas implcitas (6.1.2) Conversiones implcitas de referencia (6.1.4) Conversiones boxing (6.1.5) Conversiones implcitas de expresin constante (6.1.6)

13Las conversiones implcitas estndar excluyen de forma especfica las conversiones implcitas definidas por el 14usuario. 156.3.2 Conversiones explcitas estndar 16Las conversiones explcitas estndar son todas las conversiones implcitas estndar ms el subconjunto de las 17conversiones explcitas para las cuales existe una conversin implcita estndar opuesta. Es decir, si existe una 18conversin implcita estndar de un tipo A a un tipo B, entonces existe una conversin explcita estndar del tipo 19A al tipo B y del tipo B al tipo A. 206.4 Conversiones definidas por el usuario 21C# permite la ampliacin de las conversiones explcitas e implcitas predefinidas mediante conversiones 22definidas por el usuario. Las conversiones definidas por el usuario se introducen mediante la declaracin de 23operadores de conversin (10.9.3) en tipos de clase y struct. 246.4.1 Conversiones permitidas definidas por el usuario 25C# slo permite la declaracin de algunas conversiones definidas por el usuario. En concreto, no es posible 26redefinir una conversin explcita o implcita ya existente. Una clase o estructura tiene permitido declarar una 27conversin de un tipo de origen S a un tipo de destino T solamente si son verdaderos todos los siguientes: 28 29 30 31S y T son tipos diferentes S o T es el tipo de clase o estructura en el que tiene lugar la declaracin del operador.

Ni S ni T son de tipo object ni un tipo de interfaz (interface-type).T no es una clase base de S, y S tampoco lo es de T.

32Las restricciones aplicables a las conversiones definidas por el usuario se explican en 10.9.3. 336.4.2 Evaluacin de conversiones definidas por el usuario 34Una conversin definida por el usuario convierte un valor de su tipo, denominado tipo de origen, a otro tipo, 35denominado tipo de destino. La evaluacin de una conversin definida por el usuario se centra en descubrir el

265120

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

266

Captulo 18 Cdigo no seguro

1operador de conversin definido por el usuario ms especfico para los tipos de origen y de destino concretos. 2Esta determinacin se divide en varios pasos: 3 4 5 6 7 8 9 10 11 12 13 14 15Buscar el conjunto de clases y estructuras a partir del cual se consideran los operadores de conversin definida por el usuario. Este conjunto consta del tipo de origen y sus clases base y el tipo de destino y sus clases base (con los supuestos implcitos de que slo las clases y estructuras pueden declarar operadores definidos por el usuario y de que los tipos no de clase no tienen clases base). A partir del conjunto de tipos, determinar qu operadores de conversin definida por el usuario son aplicables. Para que un operador de conversin sea aplicable, debe ser posible realizar una conversin estndar (6.3) del tipo de origen al tipo de operando del operador, y debe ser posible realizar una conversin estndar del tipo del resultado del operador al tipo de destino. A partir del conjunto de operadores definidos por el usuario que puedan aplicarse, determinar qu operador es el ms especfico sin ninguna ambigedad. En trminos generales, el operador ms especfico es aqul cuyo tipo de operando es el ms prximo al tipo de origen y cuyo tipo de resultado es el ms prximo al tipo de destino. En las prximas secciones se definen las reglas exactas para establecer el operador de conversin definido por el usuario ms especfico.

16Una vez identificado un operador de conversin definido por el usuario ms especfico, la ejecucin de la 17conversin definida por el usuario implica hasta tres pasos: 18 19 20 21 22Primero, si se requiere, una conversin estndar del tipo de origen al tipo de operando del operador de conversin definido por el usuario. Despus, invocar al operador de conversin definido por el usuario para que realice la conversin. Por ltimo, si se requiere, realizar una conversin estndar del tipo del resultado del operador de conversin definido por el usuario al tipo de destino.

23La evaluacin de una conversin definida por el usuario nunca necesita ms de un operador de conversin 24definido por el usuario. Esto es, una conversin del tipo S al tipo T nunca ejecuta en primer lugar una 25conversin definida por el usuario de S a X y despus una conversin definida por el usuario de X a T. 26En las prximas secciones se ofrecen las definiciones exactas de la evaluacin de conversiones implcitas o 27explcitas definidas por el usuario. En las definiciones se usan los siguientes trminos: 28 29 30 31 32 33 34 35 36 37Si existe una conversin implcita estndar (6.3.1) de un tipo A a un tipo B, y si ni A ni B are son tipos de interfaz (interface-types), entonces se dice que A est abarcado por B, y que B abarca A. El tipo que ms abarca de un conjunto de tipos es aqul que abarca todos los dems tipos del conjunto. Si ninguno de los tipos abarca a todos los dems, entonces el conjunto no tiene tipo que ms abarca. En trminos ms intuitivos, el tipo que ms abarca es el ms grande del conjunto, el tipo al que pueden convertirse implcitamente todos los dems tipos. El tipo ms abarcado de un conjunto de tipos es aqul al que abarcan todos los dems tipos del conjunto. Si ninguno de los tipos es abarcado por todos los dems, entonces el conjunto no tiene un tipo ms abarcado. En trminos ms intuitivos, el tipo ms abarcado es el ms pequeo del conjunto, aqul que puede convertirse implcitamente a todos los dems tipos.

386.4.3 Conversiones explcitas definidas por el usuario 39Una conversin implcita definida por el usuario del tipo S al tipo T se procesa como sigue: 40 41 42Se busca un conjunto de tipos, D, a partir del cual se consideran los operadores de conversin definida por el usuario. Este conjunto est formado por S (si S es una clase o una estructura), las clases base de S (si S es una clase) y T (si T es una clase o una estructura).

267Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

121

268Especificacin del lenguaje C#

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21

Se busca el conjunto de operadores de conversin definida por el usuario aplicables, U. Este conjunto consta de los operadores de conversin implcita definida por el usuario declarados por las clases o estructuras de D que convierten de un tipo incluyente S a un tipo abarcado por T. Si U est vaca, la conversin no estar definida y se producir un error en tiempo de ejecucin. Se busca el tipo de origen ms especfico, SX, de los operadores de U: o o Si uno de los operadores de U se convierte desde S, entonces SX es S. De lo contrario, SX es el tipo ms abarcado del conjunto combinado de tipos de origen de los operadores de U. Si no se encuentra un tipo ms abarcado, la conversin ser ambigua y se producir un error en tiempo de compilacin. Si uno de los operadores de U se convierte a T, entonces TX es T. De lo contrario, TX es el tipo ms que ms abarca del conjunto combinado de tipos de destino de los operadores de U. Si no se encuentra un tipo ms incluyente, la conversin ser ambigua y se producir un error en tiempo de compilacin.

Se busca el tipo de destino ms especfico, TX, de los operadores de U: o o

Si U contiene exactamente un operador de conversin definido por el usuario que convierte de SX a TX, ste es el operador de conversin ms especfico. Si no existe tal operador o si existen varios, la conversin ser ambigua y se producir un error en tiempo de compilacin. De lo contrario, se aplica la conversin definida por el usuario: o o o Si S no es SX, se realiza una conversin implcita estndar de S a SX. Se llama al operador de conversin ms especfico definido por el usuario para convertir de SX a TX. Si TX no es T, se realiza una conversin implcita estndar de TX a T.

226.4.4 Conversiones explcitas definidas por el usuario 23Una conversin explcita definida por el usuario del tipo S al tipo T se procesa como sigue: 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39Se busca un conjunto de tipos, D, a partir del cual se consideran los operadores de conversin definida por el usuario. Este conjunto consta de S (si S es una clase o estructura), las clases base de S (si S es una clase), T (si T es una clase o estructura) y las clases base de T (si T es una clase). Se busca el conjunto de operadores de conversin definida por el usuario aplicables, U. Este conjunto consta de los operadores de conversin implcita o explcita definidos por el usuario, declarados por las clases o estructuras de D que convierten de un tipo que abarca o abarcado por S a un tipo que abarca o es abarcado por T. Si U est vaca, la conversin no estar definida y se producir un error en tiempo de ejecucin. Se busca el tipo de origen ms especfico, SX, de los operadores de U: o o Si uno de los operadores de U se convierte desde S, entonces SX es S. De lo contrario, si uno de los operadores de U convierte de los tipos que abarca S, entonces SX es el tipo ms abarcado del conjunto combinado de tipos de origen de estos operadores. Si no se encuentra un tipo ms abarcado, la conversin ser ambigua y se producir un error en tiempo de compilacin. De lo contrario, SX es el tipo que ms abarca del conjunto combinado de tipos de origen de los operadores de U. Si no se encuentra un tipo ms incluyente, la conversin ser ambigua y se producir un error en tiempo de compilacin.

o

Se busca el tipo de destino ms especfico, TX, de los operadores de U:

269122

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

270

Captulo 18 Cdigo no seguro

1 2 3 4 5 6 7 8 9 10 11 12 13 14

o o

Si uno de los operadores de U se convierte a T, entonces TX es T. De lo contrario, si uno de los operadores de U convierte a los tipos abarcados por T, entonces TX es el tipo ms incluyente del conjunto combinado de tipos de origen de estos operadores. Si no se encuentra un tipo ms incluyente, la conversin ser ambigua y se producir un error en tiempo de compilacin. De lo contrario, TX es el tipo ms abarcado del conjunto combinado de tipos de destino de los operadores de U. Si no se encuentra un tipo ms abarcado, la conversin ser ambigua y se producir un error en tiempo de compilacin.

o

Si U contiene exactamente un operador de conversin definido por el usuario que convierte de SX a TX, ste es el operador de conversin ms especfico. Si no existe tal operador o si existen varios, la conversin ser ambigua y se producir un error en tiempo de compilacin. De lo contrario, se aplica la conversin definida por el usuario: o o o Si S no es SX, se realiza una conversin explcita estndar de S a SX. Se llama al operador de conversin ms especfico definido por el usuario para convertir de SX a TX. Si TX no es T, se realiza una conversin explcita estndar de TX a T.

271Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

123

272Especificacin del lenguaje C#

1

7.Expresiones

2Una expresin es una secuencia de operadores y operandos. En este captulo se definen la sintaxis, el orden de 3evaluacin de los operandos y los operadores, as como el significado de las expresiones. 47.1 Clasificaciones de expresin 5Una expresin se puede clasificar como: 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37Un valor. Todos los valores tienen asociado un tipo. Una variable. Todas variables tienen un tipo asociado, esto es, el tipo declarado de la variable. Un espacio de nombres. Una expresin con su clasificacin slo puede aparecer como el miembro izquierdo de un acceso a miembro (member-access) (7.5.4). En cualquier otro contexto, una expresin que se clasifica como un espacio de nombres produce un error en tiempo de compilacin. Tipo. Una expresin con esta clasificacin slo puede aparecer como el lado izquierdo de un acceso a miembro (member-access) (7.5.4), o como un operando para el operador as (7.9.10), el operador i s (7.9.9) o el operador typeof (7.5.11). En cualquier otro contexto, una expresin que se clasifica como un tipo produce un error en tiempo de compilacin. Un grupo de mtodos, que es un conjunto de mtodos sobrecargados producidos por una bsqueda de miembros (7.3) Un grupo de mtodos puede tener asociada una expresin de instancia. Cuando se invoca un mtodo de instancia, el resultado de la evaluacin de la expresin de instancia se convierte en la instancia representada por this (7.5.7). Un grupo de mtodos slo est permitido en una expresin de invocacin (invocation-expression) (7.5.5) o una expresin de creacin de delegado (delegate-creation-expression) (7.5.10.3). En cualquier otro contexto, una expresin que se clasifica como un grupo de mtodos produce un error en tiempo de compilacin. Un acceso de propiedad. Todos los accesos de propiedades tienen un tipo asociado, esto es, el tipo declarado de la propiedad. Adems, un acceso a propiedad puede tener asociada una expresin de instancia. Si se llama a un descriptor de acceso (el bloque get o set) de un acceso a propiedad de una instancia, el resultado de la evaluacin de la expresin de instancia se convierte en la instancia representada por this (7.5.7). Un acceso a evento. Todos los accesos de evento tienen un tipo asociado, el tipo declarado del evento. Adems, un acceso de evento puede tener asociada una expresin de instancia. Un acceso a evento puede aparecer como el operando izquierdo de los operadores += y -= (7.13.3). En cualquier otro contexto, una expresin que se clasifica como un acceso a evento produce un error en tiempo de compilacin. Un acceso a indizador. Todos los accesos a indizadores tienen un tipo asociado, el tipo declarado del indizador. Adems, un acceso a indizador tiene asociadas una expresin de instancia y una lista de argumentos. Si se llama a un descriptor de acceso (el bloque get o set) de un indizador, el resultado de la evaluacin de la expresin de instancia pasa a ser la instancia representada por this (7.5.7), y el resultado de la evaluacin de la lista de argumentos se convierte en la lista de parmetros de la invocacin. Nada. Esto ocurre cuando la expresin es una invocacin de un mtodo con el tipo de valor devuelto void. Una expresin clasificada como nada slo es vlida en el contexto de una expresin de instruccin (statement-expression) (8.6).

273124

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

274

Captulo 18 Cdigo no seguro

1El resultado final de una expresin nunca es un espacio de nombres, un tipo, un grupo de mtodos o un acceso 2de evento. En lugar de ello, como se ha mencionado antes, estas categoras de expresiones son construcciones 3intermedias que slo estn permitidas en determinados contextos. 4Un acceso a propiedad o un acceso a indizador siempre se reclasifican como un valor mediante una llamada del 5descriptor de acceso get (get-accessor) o del descriptor de acceso set (set-accessor). El descriptor de acceso 6concreto viene determinado por el contexto del acceso a propiedad o del acceso a indizador: si el acceso es el 7destino de una asignacin, se llama al descriptor de acceso set (set-accessor) para asignar un nuevo valor 8(7.13.1). En otro caso, se invoca el descriptor de acceso get (get-accessor) para obtener el valor actual (7.1.1). 97.1.1 Valores de expresiones 10La mayora de las construcciones que involucran una expresin requieren en definitiva que la expresin denote 11un valor. En estos casos, si la expresin real denota un espacio de nombres, un tipo, un grupo de mtodos o 12nada, se produce un error en tiempo de compilacin. No obstante, si la expresin denota un acceso a propiedad, 13un acceso a indizador o una variable, el valor de la propiedad, el indizador o la variable se sustituyen de forma 14implcita: 15 16 17 18 19 20 21 22 23 24 25 26El valor de una variable es sencillamente el valor almacenado en la ubicacin de almacenamiento que ella misma identifica. Una variable debe considerarse asignada definitivamente (5.3) para poder obtener su valor o, de lo contrario, se produce un error de tiempo de compilacin. El valor de una expresin de acceso a propiedad se obtiene mediante una llamada al descriptor de acceso get (get-accessor) de la propiedad. Si la propiedad no tiene un descriptor de acceso get (get-accessor), se produce un error durante la compilacin. En caso contrario, se realiza una llamada a un miembro de funcin (7.4.3) y el resultado de la llamada pasa a ser el valor de la expresin de acceso a propiedad. El valor de una expresin de acceso a indizador se obtiene mediante una llamada al descriptor de acceso get (get-accessor) del indizador. Si el indizador no tiene un descriptor de acceso get (get-accessor), se produce un error durante la compilacin. En caso contrario, se realiza una llamada a un miembro de funcin (7.4.3) con la lista de argumentos asociada a la expresin de acceso al indizador, y el resultado de la llamada se convierte en el valor de la expresin de acceso al indizador.

277.2 Operadores 28Las expresiones se construyen a partir de operandos y operadores. Los operadores de una expresin indican qu 29operaciones se aplican a los operandos. Entre los ejemplos de operadores se incluyen +, -, *, / y new. Son 30ejemplos de operandos los literales, campos, variables locales y expresiones. 31Existen tres tipos de operadores: 32 33 34 35 36 37Operadores unarios. Los operadores unarios tienen un operando y utilizan la notacin de prefijo (como x) o de postfijo (como x++). Operadores binarios. Los operadores binarios tienen dos operandos y utilizan una notacin infija (por ejemplo, x + y). Operador ternario. Slo existe un operador ternario, ?:, tiene tres operandos y utiliza notacin infija (c? x: y).

38El orden de evaluacin de los operadores de una expresin est determinado por la prioridad y asociatividad de 39los operadores (7.2.1). 40Los operandos de una expresin se evalan de izquierda a derecha. Por ejemplo, en F(i) + G(i++) * H(i), se 41llama al mtodo F con el valor antiguo de i, despus se llama al mtodo G con el valor antiguo de i y, por ltimo,

275Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

125

276Especificacin del lenguaje C#

1se llama al mtodo H con el valor nuevo de i. Esto es aparte y no est relacionado con la prioridad de los 2operadores. 3Algunos operadores no se pueden sobrecargar. La sobrecarga de operadores permite utilizar implementaciones 4de operadores definidas por el usuario en operaciones en las que al menos uno de los operandos es de un tipo 5estructura o clase definido por el usuario (7.2.2). 67.2.1 Prioridad y asociatividad de los operadores 7Cuando una expresin contiene varios operadores, la prioridad de los operadores controla el orden de 8evaluacin de los operadores individuales. Por ejemplo, la expresin x + y * z se evala como x + (y * z) 9porque el operador * tiene prioridad sobre el operador binario +. La prioridad de un operador est determinada 10por la definicin de su produccin gramatical asociada. Por ejemplo, una expresin aditiva (additive-expression) 11consta de una secuencia de expresiones multiplicativas (multiplicative-expressions) separadas por los operadores 12+ o -, lo que da a estos operadores una menor prioridad que a *, / y %. 13En la tabla siguiente se resumen todos los operadores, en orden de prioridad de mayor a menor:14

Seccin 7.5 7.6 7.7 7.7 7.8 7.9

Categora Principal Unario Multiplicativo Sumatorio Desplazamiento Comprobacin de tipos y relacionales Igualdad AND lgico XOR lgico OR lgico AND condicional OR condicional Condicional Asignacin

Operadoresx.y f(x) a[x] x++ x-- new typeof checked unchecked + - ! ~ ++x --x (T)x * / % + > < > = is as

7.9 7.10 7.10 7.10 7.11 7.11 7.12 7.13

== != & ^ | && || ?: = *= /= %= += -= = &= ^= |=

15 16Cuando un operando se encuentra entre dos operadores con igual grado de prioridad, la asociatividad de los 17operadores controla el orden en que se ejecutan las operaciones. 18 19 20A excepcin de los operadores de asignacin, todos los operadores binarios son asociativos por la izquierda, lo que significa que las operaciones se realizan de izquierda a derecha. Por ejemplo, x + y + z se evala como (x + y) + z.

277126

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

278

Captulo 18 Cdigo no seguro

1 2

Los operadores de asignacin y el operador condicional (? :) son asociativos por la derecha, lo que significa que las operaciones se ejecutan de derecha a izquierda. Por ejemplo, x = y = z se evala como x = (y + z).

3La precedencia y asociatividad pueden controlarse mediante el uso de parntesis. Por ejemplo, x + y * z primero 4multiplica y por z y despus suma el resultado a x, pero (x + y) * z primero suma x e y, y despus multiplica el 5resultado por z. 67.2.2 Sobrecarga de operadores 7Todos los operadores unarios y binarios tienen implementaciones predefinidas que estn disponibles 8automticamente en cualquier expresin. Adems de las implementaciones predefinidas, pueden introducirse 9implementaciones definidas por el usuario si se incluyen declaraciones operator en las clases y estructuras 10(10.9). Las implementaciones de operador definidas por el usuario siempre tienen precedencia sobre las 11implementaciones de operador predefinidas: slo se consideran las implementaciones de operador predefinidas 12cuando no existen implementaciones de operador definidas por el usuario que puedan aplicarse, como se explica 13en 7.2.3 y 7.2.4. 14Los operadores unarios sobrecargables son: 15 + ! ~ ++ -true false 16Aunque true y false no se utilizan explcitamente en las expresiones (por lo que no se incluyen en la tabla de 17prioridades de 7.2.1), se consideran operadores porque se los llama en varios contextos de expresin: 18expresiones booleanas (7.16) y expresiones que implican el condicional (7.12) y los operadores lgicos 19condicionales (7.11). 20Los operadores binarios sobrecargables son: 21 + * / % & | ^ > == != > < >= , = y M2 + M1 // M1 + M2 + M2 + M1 // => M1 + M1 // M1 + M2 + M2 + M1 // => M1 + M2 // M1 + M2 + M2 + M1 // => M1 + M2 + M2 + M1

22 } 247.8 Operadores de desplazamiento 23 25Los operadores > permiten realizar operaciones de desplazamiento de bits. 26 27 28 29shift-expression: additive-expression shift-expression < < additive-expression shift-expression > > additive-expression

30Para una operacin de la forma x > count, se aplica la resolucin de sobrecargas de 31operadores binarios (7.2.4) para seleccionar una implementacin de operador concreta. Los operandos se 32convierten a los tipos de parmetro del operador seleccionado, y el tipo del resultado es el tipo de valor devuelto 33por el operador. 34Cuando se declara un operador de desplazamiento sobrecargado, el tipo del primer operando siempre debe ser la 35clase o estructura que contiene su declaracin, mientras que el tipo del segundo operando siempre debe ser int. 36A continuacin se enumeran los operadores de desplazamiento predefinidos. 37 38 39 40 41 42 43 44 45Desplazamiento a la izquierda:i n t opera to r < in t x , i n t count ) ; (long x, int count);

El operador > desplaza x a la derecha el nmero de bits calculados como se explica a continuacin. > Si x es de tipo i n to long, los bits de orden inferior de x no se tienen en cuenta, los bits restantes se desplazan a la derecha y las posiciones vacas de los bits de orden superior se establecen en cero si x no es negativo, y en uno si x es negativo. Si x es de tipo uint o ulong, los bits de orden inferior de x no se tienen en cuenta, los bits restantes se desplazan a la derecha y las posiciones vacas de los bits de orden superior se establecen en cero.

12Para los operadores predefinidos, el nmero de bits del desplazamiento se calcula como se explica a 13continuacin: 14 15 16 17Si el tipo de x es i n to uint, el valor del desplazamiento viene dado por los cinco bits de orden inferior de count. Es decir, el recuento del desplazamiento se calcula a partir de count & 0x1F. Si el tipo de x es long o ulong, el valor del desplazamiento viene dado por los seis bits de orden inferior de count. Es decir, el recuento del desplazamiento se calcula a partir de count & 0x3F.

18Si el valor del desplazamiento resultante es cero, los operadores de desplazamiento sencillamente devuelven el 19valor de x. 20Las operaciones de desplazamiento nunca causan desbordamientos y producen el mismo resultado en los 21contextos checked y unchecked. 22Si el operando izquierdo del operador >> es de un tipo integral con signo, el operador realiza un 23desplazamiento aritmtico a la derecha, en el cual el valor del bit ms significativo (el bit de signo) del operando 24se propaga a las posiciones vacas de los bits de orden superior. Si el operando izquierdo del operador >> es de 25un tipo integral sin signo, el operador realiza un desplazamiento lgico a la derecha, en el cual las posiciones 26vacas de los bits de orden superior siempre se establecen en cero. Para realizar la operacin opuesta de la 27inferida a partir del tipo del operando, pueden utilizarse conversiones explcitas. Por ejemplo, si x es una 28variable de tipo int, la operacin unchecked((int)((uint)x >> y)) realiza un desplazamiento lgico a la 29derecha de x. 307.9 Operadores de comprobacin de tipos y relacionales 31Los operadores ==, !=, , =, is y as se denominan operadores relacionales y de comprobacin de 32tipos. 33 34 35 36 37 38 39 40 41 42 43 44373174

relational-expression: shift-expression relational-expression relational-expression relational-expression relational-expression relational-expression relational-expression

< shift-expression > shift-expression = shift-expression is type as type

equality-expression: relational-expression equality-expression == relational-expression equality-expression != relational-expression

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

374

Captulo 18 Cdigo no seguro

1El operador i s se describe en 7.9.9, y el operador as en 7.9.10. 2Los operadores == , !=, , = son operadores de comparacin. Para una operacin de la forma x op 3y, donde op es un operador de comparacin, se aplica la resolucin de sobrecargas de operadores binarios 4(7.2.4) para seleccionar una implementacin de operador concreta. Los operandos se convierten a los tipos de 5parmetro del operador seleccionado, y el tipo del resultado es el tipo de valor devuelto por el operador. 6Los operadores de comparacin predefinidos se describen en las siguientes secciones. Todos los operadores de 7comparacin predefinidos devuelven un resultado de tipo boo l, como se muestra en la tabla siguiente.8

Operacinx == y x != y xy x = y

Resultadot ruesi x es igual a y, false en los dems casos true si x no es igual a y, false en los dems casos true si x es menor que y, false en los dems casos true si x es mayor que y, false en los dems casos true si x es menor o igual que y, false en los dems casos true si x es mayor o igual que y, false en los dems casos

9

107.9.1 Operadores de comparacin de enteros 11Los operadores de comparacin de enteros predefinidos son: 1213 14 15 17 18 19

boo l opera to r ==(int x, int y); bool operator ==(uint x, uint y); bool operator ==(long x, long y); bool operator ==(ulong x, ulong y); boo l opera to r !=(int x, int y); bool operator !=(uint x, uint y); bool operator !=(long x, long y); bool operator !=(ulong x, ulong y); boo l opera to r (ulong x, ulong y); boo l opera to r =(ulong x, ulong y);

16

2021 22 23 25 26 27

24

2829 30 31 33 34 35

32

36Todos estos operadores comparan los valores numricos de los dos operandos enteros y devuelven un valor bool 37que indica si la relacin concreta es true o false.375Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

175

376Especificacin del lenguaje C#

17.9.2 Operadores de comparacin de punto flotante 2Los operadores de comparacin de punto flotante predefinidos son: 34 6 8

bool operator ==(float x, float y); bool operator ==(double x, double y); bool operator !=(float x, float y); bool operator !=(double x, double y); bool operator (double x, double y); bool operator =(double x, double y);

5 710 12 14

9

11 13 16 17 18 19 20 21 2223

15Los operadores comparan los operandos segn las reglas del estndar IEEE 754:Si uno de los operandos es NaN, el resultado es f a l se para todos los operadores excepto !=, cuyo resultado es true. Para dos operandos cualesquiera, x != y siempre produce el mismo resultado que !(x == y). No obstante, si uno o los dos operandos son NaN, los operadores , = no producen el mismo resultado que la negacin lgica del operador opuesto. Por ejemplo, si x o y es NaN, entonces x < y es false, pero !(x >= y) es true. Si ninguno de los operandos es NaN, los operadores comparan los valores de los dos operandos de punto flotante con respecto al orden < max < ... < min < 0.0 == +0.0 < +min < ... < +max < +

24 25 26 27 28 29 30

donde min y max son los valores finitos positivos mximo y mnimo que pueden representarse en el formato de punto flotante. Son efectos notables de este orden: o o o El cero negativo y el positivo se consideran iguales. Un infinito negativo se considera menor que todos los dems valores, pero igual que otro infinito negativo. Un infinito positivo se considera mayor que todos los dems valores, pero igual que otro infinito positivo.

317.9.3 Operadores de comparacin decimales 32Los operadores de comparacin de decimales predefinidos son: 33 34 35 36 37 38bool operator ==(decimal x, decimal y); bool operator !=(decimal x, decimal y); bool operator (decimal x, decimal y); bool operator =(decimal x, decimal y);

377176

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

378

Captulo 18 Cdigo no seguro

1Todos estos operadores comparan los valores numricos de los dos operandos decimales y devuelven un valor 2boo l que indica si la relacin concreta es t rueo false. Cada comparacin de decimales equivale al uso del 3operador relacional o de igualdad correspondiente de tipo System.Decimal. 47.9.4 Operadores de igualdad booleanos 5Los operadores de igualdad booleanos predefinidos son: 6 bool operator ==(bool x, bool y); 7 bool operator !=(bool x, bool y); 8El resultado de == es true si tanto x como y son true, o si tanto x como y son false. De lo contrario, el 9resultado es false. 10El resultado de != es false si tanto x como y son true, o si tanto x como y son false. De lo contrario, el 11resultado es true. Si los operandos son de tipo bool, el operador != produce el mismo resultado que ^. 127.9.5 Operadores de comparacin de tipo de enumeracin 13Todos los tipos de enumeracin proporcionan implcitamente los siguientes operadores de comparacin 14predefinidos: 15 bool operator ==(E x, E y); 16 bool operator !=(E x, E y); 17 bool operator (E x, E y); 19 bool operator =(E x, E y); 21El resultado de evaluar x op y, donde x e y son expresiones de un tipo de enumeracin E con un tipo subyacente 22U, y op es uno de los operadores de comparacin, es exactamente el mismo que el de evaluar ((U)x) op ((U)y). 23Esto es lo mismo que decir que los operadores de comparacin de tipo de enumeracin sencillamente comparan 24los valores subyacentes integrales de los dos operandos. 257.9.6 Operadores de igualdad de tipos de referencia 26Los operadores de igualdad de tipos de referencia predefinidos son: 27 bool operator ==(object x, object y); 28 bool operator !=(object x, object y); 29Los operadores devuelven el resultado de comparar la igualdad o desigualdad de las dos referencias. 30Dado que los operadores de igualdad de tipos de referencia predefinidos aceptan operandos de tipo object, se 31aplican a todos los tipos que no declaran miembros aplicables operator == y operator !=. A la inversa, 32cualquier operador de igualdad aplicable definido por el usuario oculta los operadores de igualdad predefinidos 33de tipos de referencia. 34Los operadores de igualdad de tipo de referencia predefinidos requieren que los operandos sean valores de tipo 35de referencia (reference-type) o el valor null; adems, requieren que exista una conversin implcita estndar 36(6.3.1) del tipo de uno de los operandos al tipo del otro operando. A menos que estas dos condiciones sean 37verdaderas, se producir un error de compilacin. Son implicaciones notables de estas reglas: 38 39Produce un error durante la compilacin utilizar los operadores de igualdad de tipos de referencia predefinidos para comparar dos referencias de las que se sabe que son diferentes en tiempo de compilacin.

379Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

177

380Especificacin del lenguaje C#

1 2 3 4 5 6 7 8 9 10

Por ejemplo, si los tipos de los operandos en tiempo de compilacin fueran dos tipos de clases A y B, y si ni A ni B se derivaran del otro, no sera posible que los operandos hicieran referencia al mismo objeto. Por lo tanto, la operacin se considera un error de compilacin. Los operadores de igualdad de tipos de referencia predefinidos no permiten la comparacin de operandos de tipo de valor. Por lo tanto, salvo que un tipo struct declare sus propios operadores de igualdad, no es posible comparar valores de ese tipo struct. Los operadores de igualdad de tipos de referencia predefinidos nunca causan operaciones boxing para sus operandos. No tendra sentido realizar este tipo de operaciones boxing, puesto que las referencias a las instancias convertidas mediante boxing recin asignadas diferiran necesariamente de todas las dems referencias.

11Para una operacin de la forma x == y o x != y, si existe un operator == u operator != aplicable, las reglas 12de resolucin de sobrecargas de operador (7.2.4) seleccionan este operador en lugar del operador de igualdad 13de tipos de referencia predefinido. No obstante, siempre es posible seleccionar el operador de igualdad de tipos 14de referencia predefinido mediante la conversin explcita de uno o los dos operandos al tipo object. En el 15ejemplo 16 17 18 19 20 21 22using System; class Test { static void Main() { string s = "Test"; string t = string.Copy(s); Console.WriteLine(s == t);

23 Console.WriteLine((object)s == t); 28produce el resultado 24 29 True 25 30 False 26 31 False 33Las variables s y t hacen referencia a las dos instancias nicas de string que contienen los mismos caracteres. 27 34 32La primera comparacin produce True a causa de la seleccin del operador de igualdad de cadenas predefinido 35(7.9.7) cuando los dos operandos son de tipo string. Todas las comparaciones restantes producen False a causa 36de la seleccin del operador de igualdad de tipos de referencia predefinido cuando uno o los dos operandos son 37de tipo object. 38Tngase en cuenta que la tcnica anterior no tiene sentido para los tipos de valor. En el ejemplo 39 40 41 42 43 44 45381178 46Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

class Test { static void Main() { int i = 123; int j = 123;

382

Captulo 18 Cdigo no seguro

1produce Fa l seporque las conversiones de tipos crean referencias a dos instancias distintas de valores i n t 2convertidos mediante boxing. 37.9.7 Operadores de igualdad de cadenas 4Los operadores de igualdad de cadenas predefinidos son: 5 bool operator ==(string x, string y); 6 bool operator !=(string x, string y); 7Dos valores s t r i ng consideran iguales cuando una de las siguientes condiciones es verdadera: se 8 9 10Los dos valores son nu l .l Los dos valores son referencias no nulas a instancias de cadenas que tienen una longitud idntica y caracteres idnticos en cada posicin de carcter.

11Los operadores de igualdad de cadenas comparan valores de cadenas y no referencias a cadenas. Cuando dos 12instancias de cadena distintas contienen exactamente la misma secuencia de caracteres, los valores de las 13cadenas son iguales, pero las referencias son diferentes. Como se explica en la 7.9.6, los operadores de 14igualdad de tipos de referencia sirve para comparar referencias de cadenas en lugar de valores de cadenas.

383Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

179

384Especificacin del lenguaje C#

17.9.8 Operadores de igualdad de delegados 2Todos los tipos delegados proporcionan implcitamente los siguientes operadores de comparacin predefinidos: 3 bool operator ==(System.Delegate x, System.Delegate y); 4 bool operator !=(System.Delegate x, System.Delegate y); 5Dos instancias de delegados se consideran iguales en los siguientes casos: 6 7 8 9 10 11 12 13 14 15Si una de las instancias de delegado es nu l ,l son iguales si y solamente si las dos son nu l .l Si una de las instancias de delegado contiene una lista de invocaciones (15.1) que contiene una sola entrada, son iguales si y solamente si la otra tambin tiene una lista de invocaciones que slo contiene una entrada, y: las dos hacen referencia al mismo mtodo esttico, o bien ambas hacen referencia al mismo mtodo no esttico del mismo objeto de destino.

Si una de las instancias de delegado tiene una lista de invocaciones que contiene dos o ms entradas, dichas 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, por orden, de la lista de invocaciones de la otra.

16Debe tenerse en cuenta que los delegados de tipos diferentes pueden considerarse iguales por la definicin 17anterior, siempre y cuando el tipo del valor devuelto y los tipos de parmetros sean los mismos. 187.9.9 Operador Is 19El operador i s se utiliza para comprobar dinmicamente si el tipo en tiempo de ejecucin de un objeto es 20compatible con un tipo dado. El resultado de la operacin e is T, donde e es una expresin y T es un tipo, es un 21valor booleano que indica si e puede convertirse de forma satisfactoria al tipo T mediante una conversin de 22referencias, una conversin boxing o una conversin unboxing. La operacin se evala como sigue: 23 24 25 26 27 28 29 30 31 32 33 34 35Si el tipo de e en tiempo de compilacin es el mismo que el de T, o si existe una conversin de referencia implcita (6.1.4) o una conversin boxing (6.1.5) desde el tipo de tiempo de compilacin de e a T: o o Si e es un tipo de referencia, el resultado de la operacin equivale a evaluar e != null. Si e es un tipo de valor, el resultado de la operacin es true.

O bien, si existe una conversin explcita de referencia (6.2.3) o una conversin unboxing (6.2.4) desde el tipo de tiempo de compilacin de e a T, se ejecuta una comprobacin de tipo dinmico: o o Si el valor de e es null, el resultado es false. O bien, supongamos que R es el tipo en tiempo de ejecucin de la instancia a la que hace referencia e. Si R y T son del mismo tipo, si R es un tipo de referencia y existe una conversin implcita de referencia de R a T o si R es un tipo de valor y T es un tipo de interfaz que implementa R, el resultado es true. De lo contrario, el resultado es false.

o

O bien, no es posible una conversin de referencia o boxing de e al tipo T, y el resultado de la operacin es false.

36Tenga en cuenta que el operador is solamente tiene en cuenta las conversiones de referencia, las conversiones 37boxing y las conversiones unboxing. El operador is no tiene en cuenta otras conversiones, como las 38conversiones definidas por el usuario.

385180

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

386

Captulo 18 Cdigo no seguro

17.9.10 Operador As 2El operador as permite convertir explcitamente un valor a un tipo de referencia dado mediante una conversin 3de referencia o una conversin boxing. A diferencia de una expresin de conversin de tipos (7.6.6), el 4operador as nunca inicia una excepcin. En lugar de ello, si la conversin indicada no es posible, el valor 5resultante es null. 6En una operacin de la forma e as T, e debe ser una expresin y T debe ser un tipo de referencia. El tipo del 7resultado es T, y el resultado siempre se clasifica como un valor. La operacin se evala como sigue: 8 9 10 11 12 13 14 15 16 17 18 19 20Si el tipo de e en tiempo de compilacin es el mismo que el de T, el resultado es sencillamente el valor de e. O bien, si existe una conversin implcita de referencia (6.1.4) o una conversin boxing (6.1.5) desde el tipo de tiempo de compilacin de e a T, se ejecuta esta conversin, que pasa a ser el resultado de la operacin. O bien, si existe una conversin explcita de referencia (6.2.3) desde el tipo de tiempo de compilacin de e a T, se realiza una comprobacin de tipo dinmico: o o Si el valor de e es null, el resultado es el valor null con el tipo de tiempo de compilacin T. O bien, supongamos que R es el tipo en tiempo de ejecucin de la instancia a la que hace referencia e. Si R y T son del mismo tipo, si R es un tipo de referencia y existe una conversin implcita de referencia de R a T o si R es un tipo de valor y T es un tipo de interfaz que implementa R, el resultado es la referencia dada por e con el tipo de tiempo de compilacin T. En caso contrario, el resultado es el valor null con el tipo de tiempo de compilacin T.

o

O bien, la conversin indicada no es posible y se produce un error en tiempo de compilacin.

21Debe tenerse en cuenta que el operador as solamente ejecuta conversiones de referencia y conversiones boxing. 22Otras conversiones, como las definidas por el usuario, no son posibles con el operador as y deben realizarse 23mediante expresiones de conversin de tipos (cast). 247.10 Operadores lgicos 25Los operadores &, ^ y | se denominan operadores lgicos. 26 27 28 29 30 31 32 33 34and-expression: equality-expression and-expression & equality-expression exclusive-or-expression: and-expression exclusive-or-expression ^ and-expression inclusive-or-expression: exclusive-or-expression inclusive-or-expression | exclusive-or-expression

35Para una operacin de la forma x op y, donde op es uno de los operadores lgicos, se aplica la resolucin de 36sobrecargas de operadores binarios (7.2.4) para seleccionar una implementacin de operador concreta. Los 37operandos se convierten a los tipos de parmetro del operador seleccionado, y el tipo del resultado es el tipo de 38valor devuelto por el operador. 39Los operadores lgicos predefinidos se describen en las siguientes secciones.

387Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

181

388Especificacin del lenguaje C#

17.10.1 Operadores lgicos enteros 2Los operadores lgicos enteros predefinidos son: 34 5 6

int operator &(int x, int y); uint operator &(uint x, uint y); long operator &(long x, long y); ulong operator &(ulong x, ulong y); int operator |(int x, int y); uint operator |(uint x, uint y); long operator |(long x, long y); ulong operator |(ulong x, ulong y);

8 9 10

7

int operator ^(int x, int y); 12 uint operator ^(uint x, uint y); 13 long operator ^(long x, long y); 14 ulong operator ^(ulong x, ulong y); 15El operador & calcula la operacin lgica AND bit a bit de los dos operandos, el operador | calcula la operacin 16lgica OR bit a bit de los dos operandos y el operador ^ calcula la operacin lgica OR exclusivo bit a bit de los

11

17dos operandos. Los desbordamientos no son posibles en estas operaciones.

187.10.2 Operadores lgicos de enumeracin 19Todo tipo de enumeracin E proporciona implcitamente los siguientes operadores lgicos predefinidos: 20E operator &(E x, E y); 21 E operator |(E x, E y); 22 E operator ^(E x, E y); 23El resultado de evaluar x op y, donde x e y son expresiones de un tipo de enumeracin E con un tipo subyacente 24U, y op es uno de los operadores lgicos, es exactamente el mismo que el de evaluar (E)((U)x op (U)y). Esto es

25lo mismo que decir que los operadores lgicos de tipo de enumeracin sencillamente ejecutan la operacin 26lgica en el tipo subyacente de los dos operandos. 277.10.3 Operadores lgicos booleanos 28Los operadores lgicos booleanos predefinidos son: 29 bool operator &(bool x, bool y); 30 bool operator |(bool x, bool y); 31 bool operator ^(bool x, bool y); 32El resultado de x & y es true si tanto x como y son true. De lo contrario, el resultado es false. 33El resultado de x | y es true si x o y es true. De lo contrario, el resultado es false.

34El resultado de x ^ y es true si x es true e y es false, o si x es false e y es true. De lo contrario, el resultado 35es false. Si los operandos son de tipo bool, el operador ^ calcula el mismo resultado que el operador !=. 367.11 Operadores lgicos condicionales 37Los operadores && y || se denominan operadores lgicos condicionales. Tambin se conocen como operadores 38lgicos de evaluacin cortocircuitada. 39 40 41389182

conditional-and-expression: inclusive-or-expression conditional-and-expression && inclusive-or-expression

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

390

Captulo 18 Cdigo no seguro

1 2 3 5 6

conditional-or-expression: conditional-and-expression conditional-or-expression | | conditional-and-expression La operacin x && y corresponde a la operacin x & y, excepto que y se evala solamente si x es true. La operacin x || y corresponde a la operacin x | y, excepto que y se evala solamente si x es false.

4Los operadores && y | |son versiones condicionales de los operadores & y |:

7Una operacin de la forma x && y o x || y se procesa mediante la aplicacin de la resolucin de sobrecargas 8(7.2.4) como si la operacin estuviera escrita como x & y o x | y. Entonces: 9 10 11 12 13 14Si la resolucin de sobrecargas no encuentra un solo operador mejor o selecciona uno de los operadores lgicos enteros predefinidos, se produce un error durante la compilacin. O bien, si el operador seleccionado es uno de los operadores lgicos booleanos predefinidos (7.10.3), la operacin se procesa como se explica en 7.11.1. O bien, el operador seleccionado es un operador definido por el usuario y la operacin se procesa como se explica en 7.11.2.

15No es posible sobrecargar directamente los operadores lgicos condicionales. No obstante, dado que los 16operadores lgicos condicionales se evalan en trminos de los operadores lgicos regulares, las sobrecargas de 17stos, con algunas restricciones, tambin se consideran sobrecargas de los operadores lgicos condicionales. 18Esta categora se explica con ms detalle en la seccin 7.11.2. 197.11.1 Operadores lgicos condicionales booleanos 20Si los operandos de && o || son de tipo bool, o si los operandos son de tipos que no definen un operator & o 21un operator | aplicable, pero s definen conversiones implcitas a bool, la operacin se procesa como sigue: 22 23 24 25 26 27La operacin x && y se evala como x ? y : false. En otras palabras, primero se evala x y se convierte al tipo bool. Despus, si x es true, y se evala y se convierte al tipo bool, y se convierte en el resultado de la operacin. De lo contrario, el resultado de la operacin es false. La operacin x || y se evala como x ? true : y. En otras palabras, primero se evala x y se convierte al tipo bool. Despus, si el valor de x es true, el resultado de la operacin es true. O bien, y se evala y se convierte al tipo bool, y pasa a ser el resultado de la operacin.

287.11.2 Operadores lgicos condicionales definidos por el usuario 29Si los operandos de && o de || son de tipos que declaran un operador operator & o un operador operator | 30aplicable definidos por el usuario, las dos siguientes declaraciones deben ser verdaderas, donde T es el tipo en 31que se declara el operador seleccionado: 32 33 34 35El tipo del valor devuelto y el tipo de todos los parmetros del operador seleccionado debe ser T. Es decir, el operador debe calcular el AND lgico o el OR lgico de los dos operandos de tipo T, y debe devolver un resultado de tipo T.T debe contener declaraciones de operator true y operator false.

36Si alguno de estos requisitos no se satisface, se produce un error de compilacin. O bien, la operacin && o || se 37evala mediante la combinacin de operadores operator true u operator false definidos por el usuario con el 38operador seleccionado definido por el usuario: 39 40La operacin x && y se evala como T.false(x) ? x : T.&(x, y), donde T.false(x) es una invocacin del elemento operator false declarado en T, y T.&(x, y) es una invocacin del elemento operator &

391Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

183

392Especificacin del lenguaje C#

1 2 3 4 5 6 7 8 9 10 11 12

seleccionado. En otras palabras, x es el primero en evaluarse y se invoca opera to r f a l se el resultado en para averiguar si x es definitivamente false. Despus, si x es definitivamente false, el resultado de la operacin es el valor previamente calculado para x. De lo contrario, se evala y y se invoca el operador operator & seleccionado en el valor previamente calculado para x y el valor calculado para y, a fin de producir el resultado de la operacin. La operacin x || y se evala como T.true(x) ? x : T.|(x, y), donde T.true(x) es una invocacin del elemento operator true declarado en T, y T.|(x, y) es una invocacin del elemento operator | seleccionado. En otras palabras, x es el primero en evaluarse y se invoca operator true en el resultado para averiguar si x es definitivamente true. Despus, si x es definitivamente true, el resultado de la operacin es el valor previamente calculado para x. De lo contrario, se evala y y se invoca el operador operator | seleccionado en el valor previamente calculado para x y el valor calculado para y, a fin de producir el resultado de la operacin.

13En cualquiera de estas operaciones, la expresin dada por x se evala una sola vez, y la expresin dada por y no 14se evala o bien se evala exactamente una vez. 15Para obtener un ejemplo de un tipo que implementa operator true y operator false, vea 11.4.2. 167.12 Operador condicional 17El operador ?: se denomina operador condicional. A veces tambin se le denomina operador ternario. 18 19 20conditional-expression: conditional-or-expression conditional-or-expression ? expression : expression

21Una expresin condicional con la estructura b ? x : y evala en primer lugar la condicin b. Despus, si el valor 22de b es true, se evala x y pasa a ser el resultado de la operacin. De lo contrario, se evala y, que se convierte 23en el resultado de la operacin. Una expresin condicional nunca evala x e y. 24El operador condicional es asociativo por la derecha, lo que significa que las operaciones se agrupan de derecha 25a izquierda. Por ejemplo, una expresin con la estructura a ? b : c ? d : e se evala como a ? b : (c ? d : e). 26El primer operando del operador ?: debe ser una expresin de un tipo que pueda convertirse implcitamente a 27bool o una expresin de un tipo que implemente operator true. Si no se cumple ninguna de estas dos 28condiciones, se producir un error de compilacin. 29El segundo y tercer operandos del operador ?: controlan el tipo de la expresin condicional. Supongamos que X 30e Y sean los tipos del segundo y tercer operandos. Entonces: 31 32 33 34 35 36Si X e Y son del mismo tipo, entonces ste es el tipo de la expresin condicional. O bien, si existe una conversin implcita (6.1) de X a Y, pero no de Y a X, entonces Y es el tipo de la expresin condicional. O bien, si existe una conversin implcita (6.1) de Y a X, pero no de X a Y, entonces X es el tipo de la expresin condicional. En caso contrario, no puede determinarse una expresin y se produce un error de compilacin.

37El procesamiento en tiempo de ejecucin de una expresin condicional con la estructura b ? x : y consta de los 38siguientes pasos: 39 40 41En primer lugar, se evala b y se determina el valor bool de b: o Si existe una conversin implcita del tipo de b a bool, se ejecuta dicha conversin para generar un valor bool.

393184

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

394

Captulo 18 Cdigo no seguro

1 2 3 4 5

o

De lo contrario, se invoca el opera to r t rue definido por el tipo de b para generar un valor bool.

Si el valor bool producido por el paso anterior es true, entonces se evala x y se convierte al tipo de la expresin condicional, que pasa a ser el resultado de la expresin condicional. O bien, y se evala y se convierte al tipo de la expresin condicional, y pasa a ser el resultado de dicha de expresin.

67.13 Operadores de asignacin 7Los operadores de asignacin se utilizan para asignar un valor nuevo a una variable, propiedad, evento o 8elemento de indizador. 9 10 11 12assignment: unary-expression assignment-operator expression assignment-operator: uno de= + = -= *= /= % = & = |= ^ = = >

13El operando izquierdo de una asignacin debe ser una expresin clasificada como una variable, un acceso a 14propiedad, un acceso a indizador o un acceso a evento. 15El operador = se denomina operador de asignacin simple. Asigna el valor del operando derecho a la variable, 16propiedad o elemento de indizador dado por el operando izquierdo. El operando de la izquierda del operador de 17asignacin simple puede no ser un acceso a evento (excepto en las condiciones descritas en 10.7.1). El 18operador de asignacin simple se explica en 7.13.1. 19Los operadores de asignacin distintos del operador = se denominan operadores de asignacin compuestos. 20Dichos operadores ejecutan la operacin indicada en los dos operandos y despus asignan el valor resultante a la 21variable, propiedad o elemento de indizador dado por el operando izquierdo. Los operadores de asignacin 22compuesta se explican en 7.13.2. 23Los operadores += y -= con una expresin de acceso a eventos como operando izquierdo se denominan 24operadores de asignacin de eventos. Ningn otro operador de asignacin es vlido si incluye un acceso a 25eventos como operando izquierdo. Los operadores de asignacin de eventos se explican en 7.13.3. 26Los operadores de asignacin son asociativos por la derecha, lo que significa que las operaciones se agrupan de 27derecha a izquierda. Por ejemplo, una expresin de la forma a = b = c se evala como a = (b = c). 287.13.1 Asignacin simple 29El operador = se denomina operador de asignacin simple. En una asignacin simple, el operando derecho 30debe ser una expresin de un tipo que pueda convertirse implcitamente al tipo del operando izquierdo. La 31operacin asigna el valor del operando derecho a la variable, propiedad o elemento de indizador dado por el 32operando izquierdo. 33El resultado de una expresin de asignacin simple es el valor asignado al operando izquierdo. El resultado tiene 34el mismo tipo que el operando izquierdo y siempre se clasifica como un valor. 35Si el operando izquierdo es una propiedad o un acceso a indizador, debe tener un descriptor de acceso set. Si no 36es ste el caso, se produce un error en tiempo de compilacin. 37El procesamiento en tiempo de ejecucin de una asignacin simple de la forma x = y consta de los siguientes 38pasos: 39 40Si x est clasificada como una variable: o Se evala x para producir la variable.

395Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

185

396Especificacin del lenguaje C#

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15

o o

Se evala y y, si es necesario, se convierte al tipo de x mediante una conversin implcita (6.1). Si la variable dada por x es un elemento de matriz de un tipo de referencia (reference-type), se lleva a cabo una comprobacin en tiempo de ejecucin para garantizar que el valor calculado de y es compatible con la instancia de matriz a la cual pertenece x. La comprobacin es satisfactoria si y es null o si existe una conversin de referencia implcita (6.1.4) del tipo real de la instancia a que hace referencia y al tipo del elemento real de la instancia de matriz que contiene a x. De lo contrario, se inicia una excepcin System.ArrayTypeMismatchException. El valor resultante de la evaluacin y conversin de y se almacena en la ubicacin dada por la evaluacin de x. Se evalan la expresin de instancia (si x no es s ta t i)cy la lista de argumentos (si x es un acceso a indizador) asociadas con x, y el resultado se utiliza en la posterior invocacin de descriptor de acceso set. Se evala y y, si es necesario, se convierte al tipo de x mediante una conversin implcita (6.1). Se invoca el descriptor de acceso set de x con el valor calculado para y como su argumento value.

o

Si x se clasifica como una propiedad o un acceso a indizador: o

o o

16Las reglas de covarianza matricial (12.5) permiten que un valor de un tipo de matriz A[] se trate como una 17referencia a una instancia de un tipo matricial B[], siempre que exista una conversin implcita de referencias de 18B a A. Debido a estas reglas, la asignacin de un tipo de referencia (reference-type) a un elemento de matriz 19requiere una comprobacin en tiempo de ejecucin para garantizar que el valor asignado es compatible con la 20instancia de matriz. En el siguiente ejemplo: 21 s t r i ng [ ] sa = new s t r i ng [10 ] ; 22 ob jec t [ ] oa = sa ; 23 oa[0 ] = nu l l ; / / Ok 24 oa[1 ] = "He l l o " ; / / Ok 25 oa[2 ] = new ArrayL i s t ( ) ; / / ArrayTypeMismatchExcept i on 26la ltima asignacin produce el inicio de la excepcin System.ArrayTypeMismatchException, debido a que 27la instancia de ArrayList no se puede almacenar en un elemento de una cadena string[]. 28Cuando una propiedad o un indizador declarado en un tipo struct (struct-type) es el destino de una asignacin, la 29expresin de instancia asociada al acceso a propiedad o a indizador debe estar clasificada como una variable. Si 30la expresin de instancia est clasificada como un valor, se produce un error de compilacin. Conforme a la 317.5.4, la misma regla tambin es aplicable a los campos. 32Dadas las declaraciones: 33 34 35 36 37 38 39 40 41 42 43s t ruc t Po in t { int x, y; pub l i c Po in t ( i n t x , i n t y ) { th i s . x = x ; th i s . y = y ; } pub l i c i n t X { get { re tu rn x ; } se t { x = va lue ; } }

397186

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

398

Captulo 18 Cdigo no seguro

1 2 3 4 6 5 7 8 9 10 11 13 12 14 15 17 16 18{

public int Y { get { return y; } set { y = value; } struct Rectangle

public Rectangle(Point a, Point b) { this.a = a; this.b = b; public Point A { get { return a; } set { a = value; } public Point B { get { return b; } set { b = value; }

19 22del ejemplo: 20 21 23 24 25

Point p = new Point(); p.X = 100; p.Y = 100;

26 Rectangle r = new Rectangle(); 29las asignaciones a p .X, p .Y, r.A y r.B estn permitidas porque p y r son variables. No obstante, en el ejemplo: 27 30 Rectangle r = new Rectangle(); 28 31 r.A.X = 10; 32 r.A.Y = 10; 35 33las asignaciones no son vlidas, puesto que r.A y r.B no son variables. 34 367.13.2 Asignacin compuesta 37Una operacin de la forma x op= y se procesa mediante la aplicacin de la resolucin de sobrecargas de 38operadores binarios (7.2.4) como si la operacin se hubiera escrito x op y. Entonces: 39 40 41 42 43 44 45Si el tipo de valor devuelto del operador seleccionado es convertible implcitamente al tipo de x, la operacin se evala como x = x op y, excepto en que x se evala una sola vez. O bien, si el operador seleccionado es un operador predefinido, si el tipo del valor devuelto del operador seleccionado es convertible explcitamente al tipo de x, y si y es convertible implcitamente al tipo de x, entonces la operacin se evala como x = (T)(x op y), donde T es el tipo x, excepto en que x se evala una sola vez. O bien, la asignacin compuesta no es vlida y se produce un error en tiempo de compilacin.

399Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

187

400Especificacin del lenguaje C#

1La expresin se evala una sola vez implica que, en la evaluacin de x op y, el resultado de cualquier 2expresin que forme parte de x se guarda temporalmente y se reutiliza cuando se realiza la asignacin a x. Por 3ejemplo, en la asignacin A()[B()] += C(), donde A es un mtodo que devuelve int[], y B y C son mtodos que 4devuelven int, los mtodos se invocan solamente una vez, en el orden A, B, C. 5Si el operando izquierdo de una asignacin compuesta es un acceso a propiedad o un acceso a indizador, la 6propiedad o el indizador debe tener un descriptor de acceso get y un descriptor de acceso se t. Si no es ste el 7caso, se produce un error en tiempo de compilacin. 8La segunda regla mencionada permite que x op= y se evale como x = (T)(x op y) en ciertos contextos. La 9regla existe para permitir utilizar los operadores predefinidos como operadores compuestos cuando el operando 10izquierdo es de tipo sbyte, byte, short, ushort o char. Aunque los dos argumentos sean de uno de estos tipos, 11los operadores predefinidos producen un resultado de tipo int, como se explica en 7.2.6.2. Por lo tanto, sin una 12conversin, no sera posible asignar el resultado al operando izquierdo. 13El efecto intuitivo de la regla de los operadores predefinidos es, sencillamente, que x op= y est permitido si 14estn permitidos x op y, y x = y. En el siguiente ejemplo: 15 byte b = 0 ; 16 char ch = ' \ 0 ' ; 17 i n t i = 0; 18 b + 1; = / / Ok 19 b + 1000 ; = / / Er ro r , b = 1000 not permi t ted 20 b + i; = / / Er ro r , b = i not permi t ted 21 b + (by te ) i ; = / / Ok 22 ch + 1 ; = / / Er ro r , ch = 1 not permi t ted 23 ch + ( cha r )1 ; = / / Ok 24el motivo intuitivo de cada error es que una asignacin simple correspondiente tambin habra sido un error. 257.13.3 Asignacin de eventos 26Si el operando izquierdo de un operador += o - = se clasifica como acceso a evento, la expresin se evala de la 27siguiente forma: 28 29 30 31 32 33Si existe una expresin de instancia del acceso a evento, se evala. Se evala el operando de la derecha del operador + o - =y, si fuera necesario, se convierte al tipo del = operando de la izquierda mediante una conversin implcita (6.1). Despus de la evaluacin y, si es necesario, tambin despus de la conversin, se invoca un descriptor de acceso del evento, con la lista de argumentos formada por el operando derecho. Si el operador fuera + , se = invoca el descriptor de acceso add ; si el operador fuera -=, se invoca el descriptor de acceso remove.

34Una expresin de asignacin de evento no produce ningn valor. Por tanto, una expresin de asignacin de 35eventos slo ser vlida en el contexto de una expresin de instruccin (statement-expression) (8.6). 367.14 Expresin 37Una expresin (expression) es una expresin condicional (conditional-expression) o una asignacin 38(assignment). 39 40 41expression: conditional-expression assignment

401188

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

402

Captulo 18 Cdigo no seguro

17.15 Expresiones constantes 2Una expresin constante (constant-expression) es una expresin que se puede evaluar totalmente en tiempo de 3compilacin. 4 5constant-expression: expression

6El tipo de una expresin constante puede ser uno de los siguientes: sby te, byte, short, ushort, int, uint, long, 7ulong, char, float, double, decimal, bool, string, cualquier tipo de enumeracin o el tipo null. Se permiten 8las siguientes construcciones en expresiones de constantes: 9 10 11 12 13 14 15 16 17 19 20 21 22 23 24Literales (incluido null). Referencias a miembros const y tipos de clase y estructura. Referencias a miembros de tipos de enumeracin. Subexpresiones entre parntesis, que son en s mismas expresiones constantes. Expresiones de conversin, siempre que el tipo de destino sea uno de los antes indicados. Los operadores unarios predefinidos +, , ! y ~. Los operadores binarios predefinidos +, , *, /, %, , &, |, ^, &&, ||, ==, !=, , =, siempre que todos los operandos sean de uno de los tipos indicados anteriormente. El operador condicional ?:. Conversiones de identidad Conversiones numricas Conversiones de enumeracin Conversiones de expresin constante Conversiones de referencia implcita y explcita, siempre y cuando el origen de las conversiones sea una expresin constante que se evale como null.

18Se permiten las siguientes conversiones en expresiones de constantes:

25Otras conversiones, incluidas las conversiones boxing y unboxing, y las conversiones de referencia implcita de 26valores distintos de null no se permiten en expresiones constantes. Por ejemplo: 27 28class C { const object i = 5; // error: boxing conversion not permitted

29 const object str = hello; // error: implicit reference conversion 31la inicializacin de ies un error porque es necesaria una conversin boxing. La inicializacin de s t res un error 32 30porque es necesaria una conversin de referencia implcita desde un valor distinto de null. 33Siempre que una expresin es de uno de los tipos mencionados y slo contiene las construcciones indicadas, la 34expresin se evala en tiempo de compilacin. Esto ocurre as aunque la expresin sea una sub-expresin de una 35expresin mayor que contiene construcciones no constantes. 36La evaluacin en tiempo de compilacin de expresiones constantes est regida por las mismas reglas que la 37evaluacin en tiempo de ejecucin de expresiones no constantes, excepto porque donde la evaluacin en tiempo 38de ejecucin iniciara una excepcin, la evaluacin en tiempo de compilacin causa un error de tiempo de 39compilacin.403Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

189

404Especificacin del lenguaje C#

1Salvo que una expresin constante se coloque explcitamente en un contexto unchecked, los desbordamientos 2que ocurran en las conversiones y operaciones aritmticas de tipo integral durante la evaluacin en tiempo de 3compilacin de la expresin siempre causarn errores de tiempo de compilacin (7.5.12). 4Las expresiones constantes ocurren en los contextos que se enumeran a continuacin. En estos contextos, se 5produce un error durante la compilacin si una expresin no puede evaluarse totalmente en tiempo de 6compilacin. 7 8 9 10 11 12Declaraciones de constantes (10.3). Declaraciones de miembros de enumeracin (14.3). Etiquetas case de una instruccin sw i t ch(8.7.2). Instrucciones goto case (8.9.3). Longitudes de dimensin en una expresin de creacin de matriz (7.5.10.2) que incluye un inicializador. Atributos (17).

13Una conversin implcita de expresin constante (6.1.6) permite la conversin de una expresin constante de 14tipo i n tal tipo sby te, byte, short, ushort, uint o ulong, siempre que el valor de la expresin constante quede 15dentro del intervalo del tipo de destino. 167.16 Expresiones booleanas 17Una expresin booleana (boolean-expression) es una expresin que da como resultado un valor boo l. 18 19boolean-expression: expression

20La expresin condicional que controla una instruccin if (if-statement) (8.7.1), instruccin while (while21statement) (8.8.1), instruccin do (do-statement) (8.8.2) o instruccin for (for-statement) (8.8.3) es una 22expresin booleana (boolean-expression). La expresin condicional de control del operador ? : (7.12) sigue las 23mismas reglas que una expresin booleana (boolean-expression) pero, por motivos de prioridad de operadores, 24se clasifica como una expresin or condicional (conditional-or-expression). 25Una expresin booleana (boolean-expression) debe ser de un tipo que pueda convertirse implcitamente a boo l o 26de un tipo que implemente opera to rtrue. Si no se satisface ninguno de los requisitos, se produce un error de 27compilacin. 28Si una expresin booleana es de un tipo que no puede convertirse implcitamente a bool pero que implementa 29operator true, despus de la evaluacin de la expresin, se llama a la implementacin de operator true 30suministrada por este tipo para generar un valor bool. 31El tipo struct DBBool de la 11.4.2 proporciona un ejemplo de un tipo que implementa operator true y 32operator false.

405190

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

406

Captulo 18 Cdigo no seguro

1

8.Instrucciones

2C# proporciona una gran variedad de instrucciones. La mayora de ellas son conocidas por los programadores de 3C y C++. 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19statement: labeled-statement declaration-statement embedded-statement embedded-statement: block empty-statement expression-statement selection-statement iteration-statement jump-statement try-statement checked-statement unchecked-statement lock-statement using-statement

20La instruccin incrustada (embedded-statement) sin terminacin se utiliza en instrucciones que aparecen dentro 21de otras instrucciones. El uso de una instruccin incrustada en lugar de una instruccin (statement) permite que 22no sea necesario utilizar instrucciones de declaracin y con etiqueta en dichos contextos. En el ejemplo 23 24void F(bool b) { if (b)

25 int i = 44; 27da como resultado un error en tiempo de compilacin, ya que una instruccin i frequiere una instruccin 28 26incrustada (embedded-statement) en lugar de una instruccin (instruction) para su rama if. Si se admitiera este 29cdigo, la variable i se declarara pero no se utilizara nunca. Observe, sin embargo, que si coloca la declaracin 30de i en un bloque, el ejemplo es vlido. 318.1 Puntos finales y alcance 32Toda instruccin tiene un punto final. De manera intuitiva, el punto final de una instruccin es la ubicacin que 33sigue a la instruccin. Las reglas para la ejecucin de instrucciones compuestas (instrucciones que contienen 34instrucciones incrustadas) especifican las acciones a tomar cuando el control llega al punto final de una 35instruccin incrustada. Por ejemplo, cuando el control llega al punto final de una instruccin dentro de un 36bloque, pasa a la siguiente instruccin del bloque. 37Si una instruccin tiene posibilidades de ejecutarse, se dice que la instruccin es alcanzable. De manera inversa, 38si una instruccin no tiene ninguna posibilidad de ejecutarse, se dice que es una instruccin inalcanzable.

407Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

191

408Especificacin del lenguaje C#

1En el siguiente ejemplo: 2 3 4 5void F() { Console.WriteLine("reachable"); goto Label; Console.WriteLine("unreachable");

6la segunda llamada a Conso le .Wr i teL ine inalcanzable porque no hay posibilidad de que se ejecute la Label: 9 es 10instruccin. 7 11Si el compilador determina que existe alguna instruccin inalcanzable, emite una advertencia. Que una 8 12instruccin sea inalcanzable no es un error propiamente dicho. 13Para determinar si una determinada instruccin o punto final es o no alcanzable, el compilador realiza un 14anlisis del flujo del programa de acuerdo a las reglas de alcance definidas para cada instruccin. El anlisis de 15flujo tiene en cuenta los valores de expresiones de constantes (7.15) que controlan el comportamiento de las 16instrucciones, pero no considera los posibles valores de expresiones de variables. En otras palabras, en el 17anlisis de flujo se considera que una expresin de variable de un determinado tipo puede tener cualquier valor 18posible de dicho tipo. 19En el siguiente ejemplo: 20 21void F() { const int i = 1;

22 if (i == 2) Console.WriteLine("unreachable"); 24la expresin booleana de la instruccin i fes una expresin constante porque los dos operandos del operador == 25son constantes. La expresin constante se evala en tiempo de compilacin y, como devuelve el valor false, la 23 26llamada a Console.WriteLine se considera inalcanzable. Sin embargo, si i se convierte en una variable local 27 28void F() { int i = 1;

29 if (i == 2) Console.WriteLine("reachable"); 31la llamada a Console.WriteLine se considera alcanzable, aunque en realidad no se ejecutar nunca. 30El bloque (block) de un miembro de funcin siempre se considera alcanzable. Evaluando sucesivamente las 32 33reglas de alcance de cada instruccin de un bloque, puede determinarse el alcance de una determinada 34instruccin. 35En el siguiente ejemplo: 36 37void F(int x) { Console.WriteLine("start");

38 if (x < 0) Console.WriteLine("negative"); 40el alcance de la segunda instruccin Console.WriteLine se determina de la forma siguiente: 39 La primera instruccin de la expresin Console.WriteLine es alcanzable, ya que el bloque del mtodo F 41 42tambin lo es. El punto final de la primera instruccin Console.WriteLine es alcanzable porque esta instruccin tambin lo es.

43 44

409192

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

410

Captulo 18 Cdigo no seguro

1 2 3 4

La instruccin i fes alcanzable porque el punto final de la primera instruccin Conso le .Wr i teL ine tambin lo es. Por ltimo, como la expresin booleana de la instruccin i fno tiene el valor constante f a l sela segunda , instruccin Console.WriteLine es alcanzable.

5Existen dos situaciones en las que supone un error en tiempo de compilacin que el punto final de una 6instruccin sea alcanzable: 7 8 9 10 11Como la instruccin switch no admite que de una seccin se pase a la siguiente seccin, supone un error en tiempo de compilacin que el punto final de la lista de instrucciones de una seccin de switch sea alcanzable. Este error suele producirse cuando falta una instruccin break. Es un error que sea alcanzable el punto final del bloque de un miembro de funcin que calcula un valor. Este error suele producirse cuando falta una instruccin return.

128.2 Bloques 13Un bloque (block) permite escribir varias instrucciones en contextos donde se admite una nica instruccin. 14 15block:{ statement-listopt }

16Un bloque (block) est formado por una lista de instrucciones (statement-list) opcional (8.2.1), encerrada entre 17llaves. Si se omite la lista de instrucciones, se dice que el bloque es un bloque vaco. 18Un bloque puede contener instrucciones de declaracin (8.5). El mbito de una variable o constante local 19declarada en un bloque es el propio bloque. 20Dentro de un bloque, el significado de un nombre utilizado en un contexto de expresin siempre debe ser el 21mismo (7.5.2.1). 22Un bloque se ejecuta de la siguiente forma: 23 24 25Si el bloque est vaco, el control se transfiere al punto final del bloque. Si no est vaco, el control se transfiere a la lista de instrucciones. Cuando el control alcanza el punto final de la lista de instrucciones, se transfiere al punto final del bloque.

26La lista de instrucciones de un bloque es alcanzable si el propio bloque es alcanzable. 27El punto final de un bloque es alcanzable si el bloque est vaco o si el punto final de la lista de instrucciones es 28alcanzable. 298.2.1 Listas de instrucciones 30Una lista de instrucciones est formada por una o varias instrucciones escritas secuencialmente. Las listas de 31instrucciones aparecen en bloques (blocks) (8.2) y en bloques de modificadores (switch-blocks) (8.7.2). 32 33 34statement-list: statement statement-list statement

35Cuando se ejecuta una lista de instrucciones, se transfiere el control a la primera instruccin. Cuando el control 36alcanza el punto final de una instruccin, se transfiere a la siguiente instruccin. Cuando el control alcanza el 37punto final de la ltima instruccin, se transfiere al punto final de la lista de instrucciones. 38Una instruccin que forma parte de una lista de instrucciones es alcanzable si se cumple al menos una de las 39siguientes condiciones:

411Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

193

412Especificacin del lenguaje C#

1 2 3 4

Es la primera instruccin y la propia lista de instrucciones es alcanzable. El punto final de la instruccin anterior es alcanzable. La instruccin es una instruccin con etiqueta y la etiqueta es referenciada por una instruccin goto alcanzable.

5El punto final de una lista de instrucciones es alcanzable si el punto final de la ltima instruccin de la lista es 6alcanzable. 78.3 Instruccin vaca 8Una instruccin vaca (empty-statement) no hace nada. 9 10empty-statement:;

11Una instruccin vaca se utiliza cuando no hay operaciones que realizar en un contexto donde se requiere una 12instruccin. 13Cuando se ejecuta una instruccin vaca, simplemente se transfiere el control al punto final de la instruccin. Por 14lo tanto, el punto final de una instruccin vaca es alcanzable si la instruccin vaca es alcanzable. 15Puede utilizar una instruccin vaca cuando escriba una instruccin whi l esin cuerpo:16 17 18 19 20 22 23 24 25 26 27

boo l ProcessMessage ( ) {...} vo id ProcessMessages ( ) { whi l e ( P rocessMessage ( ) ) ; } vo id F ( ) { ... i f (done ) goto ex i t ; ... } ex i t : ;

21Tambin puede utilizarla para declarar una etiqueta justo antes de la llave de cierre } de un bloque:

288.4 Instrucciones con etiqueta 29Una instruccin con etiqueta (labeled-statement) permite agregar una etiqueta por delante de una instruccin. 30Las instrucciones con etiqueta se pueden incluir en bloques, pero no estn permitidas como instrucciones 31incrustadas. 32 33labeled-statement: identifier : statement

34Una instruccin con etiqueta declara una etiqueta con el nombre especificado en el identificador (identifier). El 35mbito de una etiqueta es el bloque entero en el cual se declara, incluyendo los bloques anidados. Se produce un 36error en tiempo de compilacin cuando se definen dos etiquetas con el mismo nombre para que sus mbitos se 37solapen. 38Se puede hacer referencia a una etiqueta desde instrucciones goto (8.9.3) dentro del mbito de la etiqueta. Esto 39significa que las instrucciones goto pueden transferir el control dentro y fuera de los bloques, pero nunca en los 40bloques.

413194

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

414

Captulo 18 Cdigo no seguro

1Las etiquetas tienen su propio espacio de declaracin y no interfieren con otros identificadores. En el ejemplo 2 3int F(int x) { if (x >= 0) goto x;

8Una instruccin con etiqueta se ejecuta tal y como se ejecute la instruccin que sigue a la etiqueta. 6 9Adems de la capacidad de alcance que proporciona el flujo normal de control, una instruccin con etiqueta es 10alcanzable si una instruccin goto alcanzable hace referencia a la etiqueta. (Excepcin: si una instruccin goto 11se encuentra dentro de otra try que incluye un bloque finally, la instruccin con etiqueta est fuera de try y el 12extremo del bloque finally no es alcanzable, entonces la instruccin con etiqueta tampoco es alcanzable desde 13esta instruccin goto). 148.5 Instrucciones de declaracin 15Una instruccin de declaracin (declaration-statement) declara una variable o una constante local. Las 16instrucciones de declaracin se pueden incluir en bloques, pero no estn permitidas como instrucciones 17incrustadas. 18 19 20declaration-statement: local-variable-declaration ; local-constant-declaration ;

4 x = -x; 7 5es un ejemplo vlido que utiliza el nombre x como parmetro y como etiqueta.

218.5.1 Declaraciones de variables locales 22Una declaracin de variable local (local-variable-declaration) declara una o varias variables locales. 23 24 25 26 27 28 29 30 31 32 33local-variable-declaration: type local-variable-declarators local-variable-declarators: local-variable-declarator local-variable-declarators , local-variable-declarator local-variable-declarator: identifier identifier = local-variable-initializer local-variable-initializer: expression array-initializer

34El tipo (type) de una declaracin de variable local (local-variable-declaration) especifica el tipo de las variables 35que se incluyen en la declaracin. El tipo aparece seguido de una lista de declaradores de variable local (local36variable-declarators), cada una de las cuales incluye una nueva variable. Un declarador de variable local (local37variable-declarator) est formado por un identificador (identifier) que da nombre a la variable, que 38opcionalmente puede ir seguido del smbolo (token) = y de un inicializador de variable local (local-variable39initializer) que establece el valor inicial de la variable. 40Para obtener el valor de una variable local en una expresin se utiliza un nombre simple (simple-name) (7.5.2) 41y, para modificarlo, se realiza una asignacin (assignment) (7.13). Una variable local debe estar asignada 42definitivamente (5.3) en cada ubicacin donde se obtenga su valor.

415Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

195

416Especificacin del lenguaje C#

1El mbito de una variable local declarada en una declaracin de variable local (local-variable-declaration) es el 2bloque donde se produce la declaracin. Supone un error hacer referencia a una variable local en una posicin 3textual que precede al declarador de la variable local (local-variable-declarator). Dentro del mbito de una 4variable local, supone un error en tiempo de compilacin declarar otra variable o constante local con el mismo 5nombre. 6Una declaracin de variable local que declara varias variables equivale a varias declaraciones de una sola 7variable con el mismo tipo. Un inicializador de variable (variable-initializer) en una declaracin de variable 8local es en realidad una instruccin de asignacin que se inserta inmediatamente despus de la declaracin. 9En el ejemplo 10void F() {

11 int x = 1, y, z = x * 2; 13 12es idntico a 14 15 16void F() { int x; x = 1; int y;

17 198.5.2 Declaraciones de constantes locales 18 20Una declaracin de constante local (local-constant-declaration) declara una o varias constantes locales. 21 22 23 24 25 26 27local-constant-declaration: cons t type constant-declarators constant-declarators: constant-declarator constant-declarators , constant-declarator constant-declarator: identifier = constant-expression

28El tipo (type) de una declaracin de constante local (local-constant-declaration) especifica el tipo de las 29constantes que se incluyen en la declaracin. El tipo (type) viene seguido de una lista de declaradores de 30constante (constant-declarators), cada uno de los cuales incluye una nueva constante. Un declarador de 31constante (constant-declarator) consta de un identificador (identifier) que da nombre a la constante, seguido del 32smbolo (token) = y de una expresin constante (constant-expression) (7.15) que establece el valor de la 33constante. 34El tipo (type) y la expresin constante (constant-expression) de una declaracin de constante local deben seguir 35las reglas de declaracin de miembros de constantes (10.3). 36Para obtener el valor de una constante local en una expresin, se utiliza el nombre simple (simple-name) 37(7.5.2). 38El mbito de una constante local es el bloque donde se produce la declaracin. Es un error hacer referencia a una 39constante local en una posicin textual anterior a su declarador de constante (constant-declarator). Dentro del 40mbito de una constante local, supone un error en tiempo de compilacin declarar otra variable o constante local 41con el mismo nombre. 42Una declaracin de constante local que declara varias constantes equivale a varias declaraciones de una sola 43constante con el mismo tipo.

417196

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

418

Captulo 18 Cdigo no seguro

18.6 Instrucciones de expresiones 2Una instruccin de expresin (expression-statement) evala una expresin determinada. El valor calculado por 3la expresin, en el caso de haber alguno, se descarta. 4 5 6 7 8 9 10 11 12 13expression-statement: statement-expression ; statement-expression: invocation-expression object-creation-expression assignment post-increment-expression post-decrement-expression pre-increment-expression pre-decrement-expression

14No todas las expresiones pueden ser instrucciones. En concreto, expresiones como x + y y x == 1, que 15simplemente calculan un valor (el cual ser descartado), no se admiten como instrucciones. 16La ejecucin de una instruccin de expresin (expression-statement) evala la expresin que contiene y despus 17transfiere el control al punto final de la instruccin de expresin. Por lo tanto, el punto final de una instruccin 18de expresin es alcanzable si dicha instruccin tambin lo es. 198.7 Instrucciones de seleccin 20Las instrucciones de seleccin (selection-statement) seleccionan una de las instrucciones que se van a ejecutar 21en funcin del valor de alguna expresin. 22 23 24selection-statement: if-statement switch-statement

258.7.1 Instruccin If 26La instruccin if selecciona una instruccin que se va a ejecutar basndose en el valor de una expresin 27booleana. 28 29 30 31 32if-statement: i f ( boolean-expression ) embedded-statement if ( boolean-expression ) embedded-statement else embedded-statement boolean-expression: expression

33La seccin else se asocia a la instruccin if anterior ms cercana permitida por la sintaxis. Por lo tanto, una 34instruccin if de la forma 35 i f ( x ) i f ( y ) F ( ) ; e l se G( ) ; 36equivale a

419Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

197

420Especificacin del lenguaje C#

1 2 3 4

if (x) { if (y) { F(); }

5 else { 9Una instruccin i fse ejecuta de la siguiente forma: 6 10 Se evala la expresin booleana (boolean-expression) (7.16). 7 11 Si la expresin booleana devuelve t rue el control se transfiere a la primera instruccin incrustada. Cuando , 8 12 el control alcanza el punto final de dicha instruccin, se transfiere al punto final de la instruccin i f . 13 14 15 16 17Si la expresin booleana devuelve f a l se existe una seccin e l se el control se transfiere a la segunda y , instruccin incrustada. Cuando el control alcanza el punto final de dicha instruccin, se transfiere al punto final de la instruccin if. Si la expresin booleana devuelve false y no existe una seccin else, el control se transfiere al punto final de la instruccin if.

18La primera instruccin incrustada de una instruccin if es alcanzable si la instruccin if es alcanzable y la 19expresin booleana no tiene el valor constante false. 20La segunda instruccin incrustada de una instruccin if, si existe, es alcanzable si la instruccin if es alcanzable 21y la expresin booleana no tiene el valor constante true. 22El punto final de una instruccin if es alcanzable si el punto final de al menos una de sus instrucciones 23incrustadas es alcanzable. Adems, el punto final de una instruccin if que no tiene seccin else es alcanzable si 24la instruccin if es alcanzable y la expresin booleana no tiene el valor constante true. 258.7.2 Instruccin Switch 26La instruccin switch (switch-statement) selecciona una lista de instrucciones que se van a ejecutar que tengan 27asociada una etiqueta switch (switch-label) que se corresponda con el valor de la expresin switch. 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42switch-statement: sw i t ch ( expression ) switch-block switch-block: { switch-sectionsopt } switch-sections: switch-section switch-sections switch-section switch-section: switch-labels statement-list switch-labels: switch-label switch-labels switch-label switch-label: case constant-expression :default :

421198

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

422

Captulo 18 Cdigo no seguro

1Una instruccin switch (switch-statement) est formada por la palabra clave sw i t ch seguida de una expresin , 2entre parntesis (denominada expresin switch) y de un bloque switch (switch-block). El bloque switch consiste 3en varias o ninguna secciones de switch (switch-section), encerradas entre llaves. Cada seccin de switch 4(switch-section) est formada por una o varias etiquetas de switch (switch-label) seguidas de una lista de 5instrucciones (statement-list) (8.2.1). 6El tipo aplicable en una instruccin sw i t chest establecido por la expresin switch. Si el tipo de la expresin 7switch es sby te, byte, short, ushort, int, uint, long, ulong, char, string o un tipo enum (enum-type), se 8ser el tipo aplicable en la instruccin switch. En caso contrario, debe existir una conversin implcita definida 9por el usuario (6.4) del tipo de la expresin switch a uno de los posibles tipos aplicables: sbyte, byte, short, 10ushort, int, uint, long, ulong, char y string. Si no existe una conversin implcita o existe ms de una, se 11producir un error en tiempo de compilacin. 12La expresin constante de cada etiqueta case debe denotar un valor de tipo convertible implcitamente (6.1) al 13tipo aplicable en la instruccin sw i t ch Si dos o ms etiquetas case de la misma instruccin switch especifican . 14el mismo valor constante, se producir un error en tiempo de compilacin. 15Puede existir como mximo una etiqueta default en una instruccin switch. 16Una instruccin switch se ejecuta de la siguiente forma: 17 18 19 20 21 22 23 24 25 26Se evala la expresin switch y se convierte en el tipo aplicable. Si una de las constantes especificadas en una etiqueta case de una instruccin switch es igual al valor de la expresin switch, el control se transfiere a la lista de instrucciones que estn a continuacin de dicha etiqueta case. Si ninguna de las constantes especificadas en las etiquetas case de una instruccin switch es igual al valor de la expresin switch y existe una etiqueta default, el control se transfiere a la lista de instrucciones que aparece a continuacin de la etiqueta default. Si ninguna de las constantes especificadas en las etiquetas case de una instruccin switch es igual al valor de la expresin switch y no existe una etiqueta default, el control se transfiere al punto final de la instruccin switch.

27Si el punto final de la lista de instrucciones de una seccin de switch es alcanzable, se producir un error en 28tiempo de compilacin. Esto se conoce como regla sin paso explcito. En el ejemplo 29 sw i t ch ( i ) { 30 case 0 : 31 CaseZero ( ) ; 32 break ; 33 case 1 : 34 CaseOne( ) ; 35 break ; 36 de fau l t : 37 CaseOthe rs ( ) ; 40es vlido porque ninguna seccin de switch tiene un punto final alcanzable. A diferencia de C y C++, la 38ejecucin de una seccin switch no permite el paso explcito a la siguiente seccin de switch, y el ejemplo 41 39

423Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

199

424Especificacin del lenguaje C#

1 2 3 4

switch (i) { case 0: CaseZero(); case 1:

5 CaseZeroOrOne(); 9da como resultado un error en tiempo de compilacin. Para ejecutar una seccin de switch despus de la 6 10ejecucin de otra seccin de switch, debe utilizar una instruccin goto case goto de fau lexplcita: o t 7 11 switch (i) { 8 12 case 0: 13 14 15 16CaseZero(); goto case 1; case 1: CaseZeroOrOne();

17 goto default; 22Una seccin switch (switch-section) admite varias etiquetas. En el ejemplo 18 23 switch (i) { 19 24 case 0: 20 25 CaseZero(); 21 26 break; 27 28 29case 1: CaseOne(); break;

35 30es vlido. El ejemplo no viola la regla sin paso explcito porque las etiquetas case 2 : y default: forman 36parte de la misma seccin de switch (switch-section). 31 37La regla sin paso explcito evita una clase de errores comunes que se producen en C y C++ cuando se omiten 32involuntariamente instrucciones break. Adems, gracias a esta regla, las secciones de switch de una instruccin 38 39sw i t chse pueden reorganizar arbitrariamente sin afectar al comportamiento de la instruccin. Por ejemplo, las 33 40secciones de la instruccin switch anterior se pueden colocar en orden inverso sin modificar el comportamiento 34de la instruccin: 41

425200

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

426

Captulo 18 Cdigo no seguro

1 2 3 4 5 6

switch (i) { default: CaseAny(); break; case 1: CaseZeroOrOne();

7 goto default; 12La lista de instrucciones de una seccin de switch termina normalmente con una instruccin break, goto case 13o goto default, pero tambin se admite cualquier sintaxis que convierta el punto final de la lista de 8 14instrucciones en inalcanzable. Por ejemplo, una instruccin while controlada mediante la expresin booleana 9 15true nunca alcanzar su punto final. Igualmente, una instruccin throw o return siempre transfiere el control a 16 10otra parte y nunca alcanza su punto final. Por tanto, el siguiente ejemplo es correcto: 11 17 18 19 20switch (i) { case 0: while (true) F(); case 1:

21 throw new ArgumentException(); 25El tipo aplicable en una instruccin switch puede ser el tipo string. Por ejemplo: 22 26 void DoCommand(string command) { 23 27 24 28 29 30 31 32 33 34switch (command.ToLower()) { case "run": DoRun(); break; case "save": DoSave(); break; case "quit":

35De la misma forma que los operadores de igualdad (7.9.7), la instruccin switch distingue maysculas de DoQuit(); 42 43minsculas y ejecutar una determinada seccin slo si la cadena de expresin switch coincide exactamente con 36 44una constante de etiqueta case. 37 45Cuando el tipo aplicable en una instruccin switch es string, se admite el valor null como constante de etiqueta 38case. 46 47 39Las listas de instrucciones (statement-lists) de bloque switch (switch-block) puede contener instrucciones de 48declaracin (8.5). El mbito de una variable o constante local declarada en un bloque switch es el propio 40bloque. 49 41427Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

201

428Especificacin del lenguaje C#

1Dentro de un bloque switch, el significado de un nombre utilizado en un contexto de expresin siempre debe ser 2el mismo (7.5.2.1). 3La lista de instrucciones de una seccin de switch determinada es alcanzable si la instruccin sw i t ches 4alcanzable y se cumple al menos una de las condiciones siguientes: 5 6 7 8 9 11 12 13 14 15 16La expresin switch no es un valor constante. La expresin switch es un valor de constante que coincide con una etiqueta case de la seccin de switch. La expresin switch es un valor de constante que no coincide con ninguna etiqueta case y la seccin de switch contiene la etiqueta de fau l .t Una instruccin goto case o goto default alcanzable hace referencia a una etiqueta switch de la seccin. La instruccin sw i t chcontiene una instruccin break alcanzable que provoca la salida de la instruccin switch. La instruccin switch es alcanzable, la expresin switch no es un valor constante y no existe etiqueta default. La instruccin switch es alcanzable, la expresin switch es una constante que no coincide con ninguna etiqueta case y no existe etiqueta default.

10El punto final de una instruccin sw i t ches alcanzable si se cumple al menos una de las siguientes condiciones:

429202

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

430

Captulo 18 Cdigo no seguro

18.8 Instrucciones de iteracin 2Las instrucciones de iteracin (iteration-statement) ejecutan repetidas veces una instruccin incrustada. 3 4 5 6 7iteration-statement: while-statement do-statement for-statement foreach-statement

88.8.1 Instruccin While 9La instruccin whi l eejecuta una instruccin incrustada cero o varias veces dependiendo de una condicin. 10 11 13 14 15 16 17while-statement: whi l e ( boolean-expression ) embedded-statement Se evala la expresin booleana (boolean-expression) (7.16). Si la expresin booleana devuelve t rue el control se transfiere a la instruccin incrustada. Cuando el , control alcanza el punto final de la instruccin incrustada (posiblemente desde la ejecucin de una instruccin cont inue se transfiere al inicio de la instruccin while. ), Si la expresin booleana devuelve false, el control se transfiere al punto final de la instruccin while.

12Una instruccin while se ejecuta de la siguiente forma:

18Dentro de la instruccin incrustada de la instruccin while, puede utilizar una instruccin break (8.9.1) para 19transferir el control al punto final de la instruccin while (terminando as la iteracin de la instruccin 20incrustada), y una instruccin continue (8.9.2) para transferir el control al punto final de la instruccin 21incrustada (de esta forma se realizar otra iteracin de la instruccin while). 22La instruccin incrustada de una instruccin while es alcanzable si la instruccin while es alcanzable y la 23expresin booleana no tiene el valor constante false. 24El punto final de una instruccin while es alcanzable si se cumple al menos una de las siguientes condiciones: 25 26 27La instruccin while contiene una instruccin break alcanzable que provoca la salida de la instruccin while. La instruccin while es alcanzable y la expresin booleana no tiene el valor constante true.

288.8.2 Instruccin Do 29La instruccin do ejecuta una instruccin incrustada una o varias veces dependiendo de una condicin. 30 31 33 34 35 36 37do-statement: do embedded-statement while ( boolean-expression ) ; El control se transfiere a la instruccin incrustada. Cuando el control alcanza el punto final de la instruccin incrustada (posiblemente desde la ejecucin de una instruccin continue), se evala la expresin booleana (boolean-expression) (7.16). Si la expresin booleana devuelve true, el control se transfiere al inicio de la instruccin do. En caso contrario, el control se transfiere al punto final de la instruccin do.

32Una instruccin do se ejecuta de la siguiente forma:

431Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

203

432Especificacin del lenguaje C#

1Dentro de la instruccin incrustada de la instruccin do, puede utilizar una instruccin break (8.9.1) para 2transferir el control al punto final de la instruccin do (terminando as la iteracin de la instruccin incrustada), 3y una instruccin continue (8.9.2) para transferir el control al punto final de la instruccin incrustada. 4La instruccin incrustada de una instruccin do es alcanzable si la instruccin do es alcanzable. 5El punto final de una instruccin es alcanzable si se cumple al menos una de las siguientes condiciones: 6 7 8La instruccin do contiene una instruccin break alcanzable que provoca la salida de la instruccin do. El punto final de la instruccin incrustada es alcanzable y la expresin booleana no tiene el valor constante true.

98.8.3 Instruccin For 10La instruccin for evala primero una secuencia de expresiones de inicializacin y, mientras se cumpla una 11determinada condicin, ejecuta repetidas veces una instruccin incrustada y evala una secuencia de expresiones 12de iteracin. 13 14 15 16 17 18 19 20 21 22 23 24for-statement: for ( for-initializeropt ; for-conditionopt ; for-iteratoropt ) embedded-statement for-initializer: local-variable-declaration statement-expression-list for-condition: boolean-expression for-iterator: statement-expression-list statement-expression-list: statement-expression statement-expression-list , statement-expression

25El inicializador de for (for-initializer), si existe, es una declaracin de variable local (local-variable-declaration) 26(8.5.1) o una lista de expresiones de instruccin (statement-expressions) (8.6) separadas por comas. El mbito 27de una variable local declarada por un inicializador for (for-initializer) se inicia en el declarador de variable 28local (local-variable-declarator) y se extiende hasta el final de la instruccin incrustada. El mbito incluye la 29condicin de for (for-condition) y el iterador de for (for-iterator). 30La condicin de for (for-condition), si existe, debe ser una expresin booleana (boolean-expression) (7.16). 31El iterador de for (for-iterator), si existe, consiste en una lista de expresiones de instruccin (statement32expressions) (8.6) separadas por comas. 33Una instruccin for se ejecuta de la siguiente forma: 34 35 36 37 38 39 40 41Si existe un inicializador de for, se ejecutan los inicializadores de variable o las expresiones de instruccin en el orden en el que se hayan codificado. Este paso slo se realiza una vez. Si existe una condicin de for, se evala. Si no existe una condicin de for (for-condition), o existe y la evaluacin devuelve true, el control se transfiere a la instruccin incrustada. Cuando el control alcanza el punto final de la instruccin incrustada (posiblemente desde la ejecucin de una instruccin continue), las expresiones del iterador de for (foriterator), si existen, se evalan en secuencia y, a continuacin, se realiza una nueva iteracin empezando por la evaluacin de la condicin for (for-condition), como se describe en el paso anterior.

433204

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

434

Captulo 18 Cdigo no seguro

1 2

Si existe una condicin de for (for-condition) y devuelve f a l seel control se transfiere al punto final de la , instruccin f o r .

3Dentro de la instruccin incrustada de una instruccin f o r se puede utilizar una instruccin break (8.9.1) para , 4transferir el control al punto final de la instruccin for (terminando as la iteracin de la instruccin incrustada), 5y una instruccin continue (8.9.2) para transferir el control al punto final de la instruccin incrustada (de esta 6manera, se ejecuta el iterador de for (for-iterator) y se realiza otra iteracin de la instruccin for, empezando por 7la condicin de for (for-condition). 8La instruccin incrustada de una instruccin f o res alcanzable si se cumple alguna de las condiciones siguientes: 9 10 11 13 14 15La instruccin for es alcanzable y no hay ninguna condicin de for (for-condition). La instruccin for es alcanzable y hay una condicin de for (for-condition), pero sta ltima no tiene el valor constante false. La instruccin for contiene una instruccin break alcanzable que provoca la salida de la instruccin for. La instruccin for es alcanzable y hay una condicin de for (for-condition), pero sta ltima no tiene el valor constante true.

12El punto final de una instruccin for es alcanzable si se cumple al menos una de las siguientes condiciones:

168.8.4 Instruccin Foreach 17La instruccin f o reachenumera los elementos de una coleccin, ejecutando una instruccin incrustada para 18cada elemento de la coleccin. 19 20foreach-statement: foreach ( type identifier in expression ) embedded-statement

21El tipo (type) y el identificador (identifier) de una instruccin foreach declaran la variable de iteracin de la 22instruccin. La variable de iteracin es una variable local de slo lectura con un mbito que se extiende a lo 23largo de toda la instruccin incrustada. Durante la ejecucin de una instruccin foreach, la variable de iteracin 24representa el elemento de coleccin para el que se est realizando la iteracin en ese momento. Se producir un 25error en tiempo de compilacin si la instruccin incrustada intenta modificar la variable de iteracin (por medio 26de asignacin o utilizando los operadores ++ y --) o bien si la pasa como un parmetro ref o out. 27El tipo de la expresin (expression) de una instruccin foreach debe ser un tipo de coleccin (como se define 28ms adelante), y debe existir una conversin explcita (6.2) del tipo del elemento de la coleccin al tipo de la 29variable de iteracin. Si la expresin (expression) tiene el valor null, se inicia una excepcin 30System.NullReferenceException. 31Un tipo C es un tipo de coleccin si implementa la interfaz Sys tem.Co l l ec t i ons . I Enumerab le o implementa 32el diseo de coleccin cumpliendo todos los criterios siguientes: 33 34 35 36 37C contiene un mtodo de instancia public con la firma GetEnumerator() que devuelve un tipo struct (struct-type), tipo clase (class-type) o tipo interfaz (interface-type), que se denomina E en el texto siguiente. E contiene un mtodo de instancia pub l i ccon la firma MoveNext() y el tipo de valor devuelto bool. E contiene una propiedad de instancia public denominada Current que permite la lectura del valor actual.

Se dice que el tipo de esta propiedad es el tipo de elemento del tipo de coleccin.

38Un tipo que implementa IEnumerable tambin es un tipo de coleccin, aun cuando no satisface las condiciones 39anteriores. Esto es posible si implementa alguno de los miembros IEnumerable por medio de una 40implementacin de miembro de interfaz explcita, como se describe en 13.4.1.)

435Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

205

436Especificacin del lenguaje C#

1El tipo Sys tem.Ar ray(12.1.1) es un tipo de coleccin y, puesto que todos los tipos de matriz se derivan de 2Sys tem.Ar ray en una instruccin foreach se admite cualquier expresin de tipo de matriz. El orden en que , 3foreach recorre los elementos de una matriz es el siguiente: en matrices unidimensionales, los elementos se 4recorren en orden creciente, empezando por el ndice 0 y acabando por el ndice Length 1. Los elementos de 5matrices multidimensionales se recorren de manera que los ndices de la dimensin del extremo derecho se 6incrementan en primer lugar, a continuacin la dimensin situada inmediatamente a su izquierda y as 7sucesivamente hacia la izquierda. 8Una instruccin f o reachde la forma: 9 f o reach (E lement Type e lement i n co l l ec t i on ) s ta tement 10corresponde a una de dos posibles expansiones: 11 12 13 14 15 16 17 18 19 20 21 22 25 23 26 27 24 28 29 30 31 32Si la expresin co l l ec t i on de un tipo que implementa el diseo de coleccin (como se ha definido es anteriormente), la expansin de la instruccin f o reaches:E enu mera to r = ( co l l ec t i on ) .Ge tEnumera to r ( ) ; t ry { E lement Type e lement ; whi l e (enumera to r .MoveNext ( ) ) { e lement = (E lement Type )enumera to r .Cu r ren t ; s ta tement ; } } f i na l l y { ID i sposab le d i sposab anterior pueden conseguirse con bastante facilidad. Optimizaciones significativas de lo le = enumera to r as Sys tem. ID i sposab le ; Si el tipo E implementa Sys tem. ID i sposab le expresin (enumerator as System.IDisposable) siempre ser , la distinta de null y la implementacin puede sustituir de forma segura una sencilla conversin por una comprobacin de tipo posiblemente ms costosa. A la inversa, si el tipo E es sealed y no implementa System.IDisposable, la expresin (enumerator as System.IDisposable) siempre se evaluar como null. En este caso, la implementacin puede optimizar de forma segura toda la clusula finally.

En caso contrario, la expresin collection es de un tipo que implementa System.IEnumerable y la expansin de la instruccin foreach es:

33 I Enumera to r enu mera to r = 34 ( (Sys tem.Co l l ec t i ons . I Enumerab le ) ( co l l ec t i on ) ) .Ge tEnumera to r ( ) ; 35 t ry { 36 E lement Type e lement ; 37 whi l e (enumera to r .MoveNext ( ) ) { 38 e lement = (E lement Type )enumera to r .Cu r ren t ; 39 s ta tement ; 40 } 41 } 42 f i na l l y { 43En cualquiera de las expansiones, enumerator es una variable temporal a la que no puede obtenerse acceso (ni 46 47 44es visible) en la instruccin statement incrustada; adems, la variable element es de slo lectura en esta 48instruccin (statement) incrustada. 45437206Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

438

Captulo 18 Cdigo no seguro

1El cdigo del siguiente ejemplo muestra cada valor de una matriz bidimensional segn el orden de los 2elementos: 3 4 5 6 7 8 11 9 12 13 10using System; class Test { static void Main() { double[,] values = { {1.2, 2.3, 3.4, 4.5}, foreach (double elementValue in values) Console.Write("{0} ", elementValue); Console.WriteLine();

14 } 16El resultado producido es el siguiente: 15 171.2 2.3 3.4 4.5 5.6 6.7 7.8 8.9

188.9 Instrucciones Jump 19Las instrucciones de salto (jump-statement) transfieren el control de forma incondicional. 20 21 22 23 24 25jump-statement: break-statement continue-statement goto-statement return-statement throw-statement

26La posicin a la que transfiere el control una instruccin de salto se denomina destino de la instruccin de salto. 27Cuando se ejecuta una instruccin de salto dentro de un bloque y el destino se encuentra fuera del bloque, se 28dice que la instruccin de salto sale del bloque. Aunque una instruccin de salto puede transferir el control fuera 29de un bloque, no puede transferirlo dentro del bloque. 30La ejecucin de las instrucciones de salto se complica cuando intervienen instrucciones t r y Si no existen . 31instrucciones t r y la instruccin de salto transfiere incondicionalmente el control a su destino. Pero si existen , 32instrucciones try, la ejecucin es ms compleja. Si la instruccin de salto sale de uno o varios bloques try que 33llevan asociados bloques finally, el control se transfiere inicialmente al bloque finally de la instruccin try ms 34interna. Cuando el control alcanza el punto final de un bloque finally, el control se transfiere al bloque finally 35de la siguiente instruccin envolvente try. Este proceso se repite hasta que se ejecuten los bloques finally de 36todas las instrucciones try que intervienen.

439Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

207

440Especificacin del lenguaje C#

1En el siguiente ejemplo: 2 3 4 5 6 7 8 9 10 11 12 13} finally { Console.WriteLine("Innermost finally block"); using System; class Test { static void Main() { while (true) { try { try { Console.WriteLine("Before break"); break;

14 } 23los bloques f i na l lasociados a las dos instrucciones t ryse ejecutan antes de transferir el control al destino de la y 15 24instruccin de salto. 16 25El resultado producido es el siguiente: 17 26 Before break 18 27 Innermost finally block 19 28 Outermost finally block 208.9.1 Instruccin Break 30 29 31 , 21La instruccin break provoca la salida de la instruccin envolvente sw i t ch while, do, for o foreach ms 32prxima. 22 33 break-statement: 34 break ; 35El destino de una instruccin break es el punto final de la instruccin envolvente switch, while, do, for o 36foreach ms prxima. Si la instruccin break no se encuentra dentro de una instruccin switch, while, do, for 37o foreach, se produce un error en tiempo de compilacin. 38Cuando existen varias instrucciones switch, while, do, for o foreach anidadas, la instruccin break se aplica 39slo a la instruccin ms interna. Para transferir el control a travs de varios niveles de anidamiento, debe 40utilizar una instruccin goto (8.9.3). 41Una instruccin break no puede salir de un bloque f i na l l(8.10). Cuando se ejecuta una instruccin break y 42dentro de un bloque finally, el destino de la instruccin break debe encontrarse dentro del propio bloque 43finally; en caso contrario, se producir un error en tiempo de compilacin. 44Una instruccin break se ejecuta de la siguiente forma: 45 46441208

Si la instruccin break sale de uno o ms bloques try que llevan asociados bloques finally, el control se transfiere inicialmente al bloque finally de la instruccin try ms interna. Cuando el control alcanza el

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

442

Captulo 18 Cdigo no seguro

1 2 3 4

punto final de un bloque f i na l , y control se transfiere al bloque f i na l lde la siguiente instruccin l el y envolvente try. Este proceso se repite hasta que se ejecuten los bloques finally de todas las instrucciones try que intervienen. El control se transfiere al destino de la instruccin break.

5Como una instruccin break transfiere incondicionalmente el control a otra parte del cdigo, el punto final de 6una instruccin break nunca es alcanzable. 78.9.2 Instruccin Statement 8La instruccin continue inicia una nueva iteracin de la instruccin envolvente while, do, for o foreach ms 9prxima. 10 11continue-statement:cont inue ;

12El destino de una instruccin continue es el punto final de la instruccin incrustada de la instruccin 13envolvente while, do, for o foreach ms prxima. Si la instruccin continue no se encuentra dentro de una 14instruccin while, do, for o foreach, se produce un error en tiempo de compilacin. 15Cuando existen varias instrucciones while, do, for o foreach anidadas, la instruccin continue se aplica slo a 16la instruccin ms interna. Para transferir el control a travs de varios niveles de anidamiento, debe utilizar una 17instruccin goto (8.9.3). 18Una instruccin cont inueno puede salir de un bloque f i na l l(8.10). Cuando se ejecuta una instruccin y 19continue dentro de un bloque finally, el destino de la instruccin continue debe encontrarse dentro del propio 20bloque finally; en caso contrario, se producir un error en tiempo de compilacin. 21Una instruccin continue se ejecuta de la siguiente forma: 22 23 24 25 26 27Si la instruccin continue sale de uno o ms bloques try que llevan asociados bloques finally, el control se transfiere inicialmente al bloque finally de la instruccin try ms interna. Cuando el control alcanza el punto final de un bloque finally, el control se transfiere al bloque finally de la siguiente instruccin envolvente try. Este proceso se repite hasta que se ejecuten los bloques finally de todas las instrucciones try que intervienen. El control se transfiere al destino de la instruccin continue.

28Como una instruccin continue transfiere incondicionalmente el control a otra parte del cdigo, el punto final 29de una instruccin continue nunca es alcanzable. 308.9.3 Instruccin Goto 31La instruccin goto transfiere el control a una instruccin marcada con una etiqueta. 32 33 34 35goto-statement: goto identifier ; goto case constant-expression ;goto default ;

36El destino de una instruccin goto identificador (identifier) es la instruccin con etiqueta con el nombre de 37dicha etiqueta. Si no existe una etiqueta con dicho nombre en el miembro de funcin actual, o si la instruccin 38goto no se encuentra dentro del mbito de la etiqueta, se produce un error en tiempo de compilacin. Esta regla 39permite el uso de una instruccin goto para transferir el control fuera de un mbito anidado, pero no en un 40mbito anidado. En el siguiente ejemplo: 41us ing Sys tem;

443Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

209

444Especificacin del lenguaje C#

1 2 3 4 5 8 6 9 7 10 11 14 12 15 13 16 17

class Test { static void Main(string[] args) { string[,] table = { {"Red", "Blue", "Green"}, foreach (string str in args) { int row, colm; for (row = 0; row 5) + 1] ; > 20 th i s . l eng th = l eng th ; 21 22 pub l i c i n t Length { 23 get { re tu rn l eng th ; } 24 } 25 pub l i c boo l th i s [ i n t i ndex ] { 26 get { 27 i f ( i ndex < 0 | | i ndex > l eng th ) { = 28 th row new I ndexOutOfRangeExcept i on ( ) ; 29 } 30 re tu rn (b i t s [ i ndex > 5] & 1 < i ndex ) != 0 ; > < 31 } 32 se t { 33 i f ( i ndex < 0 | | i ndex > l eng th ) { = 34 th row new I ndexOutOfRangeExcept i on ( ) ; 35 } 36 i f ( va lue ) { 37 b i t s [ i ndex > 5] |= 1 < i ndex ; > < 38 } 39 e l se { 40Una instancia de la claseb i t s [ i ndex >> 5] &= ~(1 'Z') { throw new ArgumentException(); } if (col < 0 || col >= NumCols) { throw new IndexOutOfRangeException();

8 1310.8.1 Sobrecarga de indizadores 9 14Las reglas de resolucin de sobrecarga de indizadores se describen en 7.4.2. 10 1510.9 Operadores 11 16Un operador es un miembro que define el significado de un operador de expresin que puede aplicarse a 17 12instancias de la clase. Los operadores se declaran mediante declaraciones de operadores (operator18declarations): 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42operator-declaration: attributesopt operator-modifiers operator-declarator operator-body operator-modifiers: operator-modifier operator-modifiers operator-modifier operator-modifier:pub l i c s ta t i c exte rn

operator-declarator: unary-operator-declarator binary-operator-declarator conversion-operator-declarator unary-operator-declarator: type opera to r overloadable-unary-operator ( type identifier ) overloadable-unary-operator: uno de+ - ! ~ ++ -- true false

binary-operator-declarator: type operator overloadable-binary-operator ( type identifier , type identifier ) overloadable-binary-operator: uno de+ - * / % & | ^ > == != > < >= , = o y operator y operator 9) throw new ArgumentException(); this.value = value; public static implicit operator byte(Digit d) { return d.value; public static explicit operator Digit(byte b) { return new Digit(b);

10 } 12la conversin de Dig i ta byte es implcita porque nunca produce excepciones ni pierde informacin, pero la 13conversin de byte a Digit es explcita ya que Digit slo puede representar un subconjunto de los posibles 11 14valores de un byte. 1510.10Constructores de instancia 16Un constructor de instancia es un miembro que implementa las acciones que se requieren para inicializar una 17instancia de una clase. Los constructores de instancia se declaran mediante declaraciones de constructor 18(constructor declarations): 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37constructor-declaration: attributesopt constructor-modifiersopt constructor-declarator constructor-body constructor-modifiers: constructor-modifier constructor-modifiers constructor-modifier constructor-modifier:public protected internal private extern

constructor-declarator: identifier ( formal-parameter-listopt ) constructor-initializeropt constructor-initializer: : base ( argument-listopt ) : this ( argument-listopt ) constructor-body: block;

38Una declaracin de constructor (constructor-declaration) puede incluir un conjunto de atributos (17), una 39combinacin vlida de los cuatro modificadores de acceso (10.2.3) y un modificador extern (10.5.7). No se 40permite que una declaracin de constructor incluya un mismo modificador varias veces. 41El identificador (identifier) de un declarador de constructor (constructor-declarator) debe nombrar la clase en la 42que se declara el constructor de instancia. Si se especifica cualquier otro nombre, se produce un error en tiempo 43de compilacin. 44La lista de parmetros formales (formal-parameter-list) opcional de un constructor de instancia est sujeta a las 45mismas reglas que la lista de parmetros formales (formal-parameter-list) de un mtodo (10.5). La lista de607Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

291

608Especificacin del lenguaje C#

1parmetros formales define la firma (3.6) de un constructor de instancia y dirige el proceso por el que la 2resolucin de sobrecarga (7.4.2) selecciona un constructor de instancia en particular en una invocacin. 3Cada uno de los tipos a los que se hace referencia en la lista de parmetros formales (formal-parameter-list) de 4un constructor de instancia deben tener como mnimo el mismo nivel de accesibilidad que el propio constructor 5(3.5.4). 6El inicializador de constructor (constructor-initializer) opcional especifica otro constructor de instancia al que 7hay que invocar antes de ejecutar las instrucciones que aparecen en el cuerpo del constructor (constructor-body) 8del primer constructor de instancia. Esta categora se explica con ms detalle en la seccin 10.10.1. 9Cuando la declaracin de un constructor incluye un modificador ex te rn se dice que el constructor es un , 10constructor externo. Debido a que la declaracin de constructor externo no proporciona una implementacin 11real, su cuerpo del constructor (constructor-body) consiste en un punto y coma. Para el resto de constructores, el 12cuerpo del constructor (constructor-body) consiste en un bloque (block) que especifica las instrucciones para 13inicializar una nueva instancia de la clase. Esto corresponde exactamente al bloque (block) de un mtodo de 14instancia con un tipo de valor devuelto vo id (10.5.8). 15Los constructores de instancia no se heredan. Por lo tanto, una clase slo tiene los constructores de instancia que 16se declaran realmente en la clase. Si una clase no contiene ninguna declaracin de constructor de instancia, se 17proporciona automticamente un constructor de instancia predeterminado (10.10.4). 18Los constructores de instancia se invocan mediante expresiones de creacin de objetos (object-creation19expressions) (7.5.10.1) y a travs de inicializadores de constructor (constructor-initializers). 2010.10.1Inicializadores de constructor 21Todos los constructores de instancia (excepto aquellos para la clase ob jec t incluyen implcitamente una ) 22invocacin de otro constructor de instancia inmediatamente antes del cuerpo del constructor (constructor-body). 23El constructor que se invoca implcitamente est determinado por el inicializador de constructor (constructor24initializer): 25 26 27 28 29 30 31 32 33 34 35 36 37 38Un inicializador de constructor de instancia de la forma base (lista de argumentos opcional o argumentlistopt) causa la invocacin de un constructor de instancia desde la clase base directa. Este constructor se selecciona utilizando la lista de argumentos (argument-list) y las reglas de resolucin de sobrecargas de 7.4.2. El conjunto de constructores de instancia candidatos est compuesto de todos los constructores de instancia accesibles contenidos en la clase base directa, o del constructor predeterminado (10.10.4), si en la clase base directa no se declara ningn constructores de instancia. Si el conjunto est vaco o no es posible identificar el mejor constructor de instancia, se produce un error en tiempo de compilacin. Un inicializador de constructor de instancia de la forma th i sargument-listopt) causa la invocacin de un ( constructor de instancia desde la propia clase. El constructor se selecciona utilizando la lista de argumentos (argument-list) y las reglas de resolucin de sobrecargas de 7.4.2. El conjunto de constructores de instancia candidatos est formado por todos los constructores de instancia accesibles declarados en la clase. Si el conjunto est vaco o no es posible identificar el mejor constructor de instancia, se produce un error en tiempo de compilacin. Si la declaracin de un constructor de instancia incluye un inicializador de constructor que invoca al propio constructor, se produce un error en tiempo de compilacin.

39Si un constructor de instancia no tiene inicializador de constructor, se proporciona implcitamente uno de la 40forma base ( ) Por lo tanto, una declaracin de constructor de instancia de la forma . 41 C( . . . ) { . . . } 42equivale exactamente a 43C( . . . ) : base ( ) { . . . }

609292

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

610

Captulo 18 Cdigo no seguro

1El mbito de los parmetros dados en la lista de parmetros formales (formal-parameter-list) de una declaracin 2de constructor de instancia incluye el inicializador de constructor de dicha declaracin. Por lo tanto, un 3inicializador de constructor puede tener acceso a los parmetros del constructor. Por ejemplo: 4 5 6 8 7 9class A { public A(int x, int y) {} class B: A {

10 public B(int x, int y): base(x + y, x - y) {} 12Un inicializador de constructor de instancia no puede tener acceso a la instancia que est siendo creada. Por ello, 13se produce un error en tiempo de compilacin si se hace referencia a th i sen una expresin de argumento del 11 14inicializador del constructor, al igual que se produce un error en tiempo de compilacin si una expresin de 15argumento hace referencia a cualquier miembro de instancia a travs del nombre simple (simple-name). 1610.10.2Inicializadores de variables de instancia 17Cuando un constructor de instancia no tiene inicializador de constructor, o cuando tiene uno de la forma 18base ( . . ,. el constructor realiza implcitamente las inicializaciones especificadas por los inicializadores de ) 19variables (variable-initializers) de los campos de instancia declarados en su clase. Esto corresponde a una 20secuencia de asignaciones que se ejecutan inmediatamente al entrar en el constructor y antes de invocar 21implcitamente al constructor de la clase base directa. Los inicializadores de variable se ejecutan en el orden 22textual en que aparecen en la declaracin de clase. 2310.10.3Ejecucin de constructores 24Los inicializadores de variables se transforman en instrucciones de asignacin, que se ejecutan antes de la 25invocacin del constructor de instancia de la clase base. Tal ordenamiento garantiza que todos los campos de 26instancia son inicializados por sus inicializadores de variable antes de que se ejecute cualquier instruccin que 27tenga acceso a la instancia. 28Dado el ejemplo:29 30 31 32 33 34 35 36 37 38 39 40 41 42 43

us ing Sys tem; c lass A { pub l i c A( ) { Pr in t F i e lds ( ) ; } pub l i c v i r tua l vo id Pr in t F i e lds ( ) {} } c lass B: A { i n t x = 1; int y; pub l i c B( ) { y = - 1; }

611Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

293

612Especificacin del lenguaje C#

1 2

public override void PrintFields() { Console.WriteLine("x = {0}, y = {1}", x, y);

3 } 5cuando se utiliza new B( ) para crear una instancia de B, el resultado que se produce es: 4 6 x = 1, y = 0 7El valor de x es 1 porque el inicializador de variable se ejecuta antes de que se invoque el constructor de 8instancia de la clase base. Sin embargo, el valor de y es 0 (el valor predeterminado para un tipo int) porque la 9asignacin a y no se ejecuta hasta que el constructor de la clase base devuelve el control. 10Es til considerar los inicializadores de variables de instancia y los inicializadores de constructor como 11instrucciones que se insertan automticamente antes del cuerpo del constructor (constructor-body). En el 12ejemplo 13 14 15 16 17 18 19 20 21 22 23 25 24 26 27 28 30 29 31 32 33 34using System; using System.Collections; class A { public A() { count = 0; public A(int n) { count = n; } class B: A { double sqrt2 = Math.Sqrt(2.0); public B(): this(100) { items.Add("default"); public B(int n): base(n 1) { max = n;

35 } 37contiene varios inicializadores de variable e inicializadores de constructor de ambas formas (base y this). El 38 36cdigo del ejemplo se corresponde con el cdigo siguiente, donde cada comentario indica una instruccin que se 39inserta automticamente (la sintaxis utilizada para invocar el constructor insertado automticamente no es 40correcta, pero sirve para ilustrar el mecanismo). 41 42 43 44using System.Collections; class A {

613294

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

614

Captulo 18 Cdigo no seguro

1 2 3 4 7 5 8 6 9 10 11 14 12 15 13 16 17 19 18 20 21 23 22 24 25 26

public A() { x = 1; y = -1; public A(int n) { x = 1; y = -1; object(); count = n; class B: A { double sqrt2; public B(): this(100) { B(100); items.Add("default"); public B(int n): base(n 1) { sqrt2 = Math.Sqrt(2.0); items = new ArrayList(100); A(n 1); // Variable initializer // Variable initializer // Invoke A(int) constructor // Invoke B(int) constructor object(); // Variable initializer // Variable initializer // Invoke object() constructor // Variable initializer // Variable initializer // Invoke object() constructor

27 max = n; 3010.10.4Constructores predeterminados 28Si una clase no contiene ninguna declaracin de constructores de instancia, se proporciona automticamente un 31 32constructor de instancia predeterminado. El constructor predeterminado simplemente invoca el constructor sin 29 33parmetros de la clase base directa. Si la clase base directa no tiene un constructor de instancia sin parmetros 34accesible, se producir un error en tiempo de compilacin. Si la clase es abstracta, la accesibilidad declarada 35para el constructor predeterminado es protected. Si no, la accesibilidad declarada para el constructor 36predeterminado es public. Por lo tanto, el constructor predeterminado es siempre de la forma 37 protected C(): base() {} 38o bien 39 public C(): base() {} 40donde C es el nombre de la clase. 41En el siguiente ejemplo: 42 43 44 45 46615Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

class Message { object sender;

295

616Especificacin del lenguaje C#

1se proporciona un constructor predeterminado debido a que la clase no contiene ninguna declaracin de 2constructor de instancia. As, el ejemplo es exactamente equivalente a 3 4class Message {

5 object sender; 7 public Message(): base() {} 6 8 } 910.10.5Constructores Private 10Cuando una clase T slo declara constructores de instancia privados, las clases externas al texto del programa de 11T no pueden ni derivarse ni crear directamente instancias de T. Por lo tanto, si una clase contiene slo miembros 12estticos y no se desea crear una instancia con l, puede evitarse tal instancia agregando un constructor de 13instancia privado que est vaco. Por ejemplo: 14 15 16 17 18 19public class Trig { public const double PI = 3.14159265358979323846; public static double Sin(double x) {...} public static double Cos(double x) {...}

20 public static double Tan(double x) {...} 22La clase Trig agrupa mtodos y constantes relacionados, pero la intencin no es crear una instancia de la misma. 23Por ello declara un nico constructor de instancia privado vaco. Se debe declarar al menos un constructor de 21 24instancia para suprimir la generacin automtica de un constructor predeterminado. 2510.10.6Parmetros de constructor de instancia opcionales 26La forma this(...) de un inicializador de constructor se suele utilizar conjuntamente con sobrecarga para 27implementar parmetros de constructor de instancia opcionales. En el siguiente ejemplo: 28 29 30 31 32 33class Text { public Text(int x, int y): this(x, y, null) {} public Text(int x, int y, string s) { // Actual constructor implementation

34 } 36los dos primeros constructores de instancia slo proporcionan los valores predeterminados para los argumentos 37 35que faltan. Ambos usan un inicializador de constructor this(...) para invocar el tercer constructor de instancia, 38que es el que realmente inicializa la nueva instancia. El efecto son parmetros de constructor opcionales: 39 40 41Text t1 = new Text(); Text t2 = new Text(5, 10); // Same as Text(0, 0, null) // Same as Text(5, 10, null)

617296

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

618

Captulo 18 Cdigo no seguro

110.11Constructores static 2Un constructor esttico es un miembro que implementa las acciones que se requieren para inicializar una clase. 3Los constructores estticos se declaran mediante declaraciones de constructores estticos (static-constructor4declarations): 5 6 7 8 9 10 11 12static-constructor-declaration: attributesopt static-constructor-modifiers identifier ( ) static-constructor-body static-constructor-modifiers:exte rn s ta t i c opt static externopt

static-constructor-body: block;

13Una declaracin de constructor esttico (static-constructor-declaration) puede incluir un conjunto de atributos 14(attributes) (17) y un modificador ex te rn(10.5.7). 15El identificador (identifier) de una declaracin de constructor esttico (static-constructor-declaration) debe 16nombrar la clase en la que se declara el constructor esttico. Si se especifica cualquier otro nombre, se produce 17un error en tiempo de compilacin. 18Cuando la declaracin de un constructor incluye un modificador ex te rn se dice que el constructor es un , 19constructor esttico externo. Debido a que la declaracin de constructor esttico no proporciona una 20implementacin real, su cuerpo de constructor esttico (static-constructor-body) consiste en un punto y coma. 21Para todas las dems declaraciones de constructor esttico, el cuerpo del constructor esttico (static-constructor22body) se compone de un bloque (block) que especifica las instrucciones que deben ejecutarse para poder 23inicializar la clase. Esto corresponde exactamente al cuerpo del mtodo (method-body) esttico con un tipo de 24valor devuelto vo id (10.5.8). 25Los constructores estticos no se heredan y no pueden ser llamados directamente. 26El constructor esttico de una clase se ejecuta como mucho una vez en un dominio de aplicacin dado. La 27ejecucin de un constructor esttico la desencadena el primero de los siguientes eventos que se produzcan en un 28dominio de aplicacin. 29 30Se crea una instancia de la clase. Se hace referencia a cualquiera de los miembros estticos de la clase.

31Si una clase contiene el mtodo Main (3.1) en el que comienza la ejecucin, el constructor esttico de esta 32clase se ejecuta antes de que se llame al mtodo Main. Si una clase contiene cualquier campo esttico con 33inicializadores, stos se ejecutan en orden textual inmediatamente antes de ejecutar el constructor esttico. 34En el ejemplo 35 36 37 38 39 40 41 42us ing Sys tem; c lass Tes t { s ta t i c vo id Main ( ) { A.F ( ) ; B .F ( ) ; }

619Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

297

620Especificacin del lenguaje C#

1 2 3 4 5 6 10 7 11 8 12 9 13 14

class A { static A() { Console.WriteLine("Init A"); } public static void F() { class B { static B() { Console.WriteLine("Init B"); }

15el resultado debe ser: static void F() { public 19 16 20 Init A 17 21 A.F 18 22 Init B 24porque la ejecucin de los constructores estticos de A se desencadena al llamar a A.F, y la ejecucin de los 25 23constructores estticos de B se desencadena cuando se llama a B.F. 26Es posible construir dependencias circulares que permitan a los campos estticos con inicializadores de variables 27ser observados en su estado de valor predeterminado. 28En el ejemplo 29 30 31 32 33 34 35 37 36 38 39 40 41 42using System; class A { static A() { X = B.Y + 1; } class B { static B() {} static void Main() { Console.WriteLine("X = {0}, Y = {1}", A.X, B.Y);

43 } 45produce el resultado 44 46 X = 1, Y = 2

621298

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

622

Captulo 18 Cdigo no seguro

1Para ejecutar el mtodo Main, el sistema ejecuta en primer lugar el inicializador de B.Y, antes que el constructor 2esttico de la clase B. El inicializador de Y hace que se ejecute el constructor esttico de A, porque se hace 3referencia al valor de A.X. Por su parte, el constructor esttico de A contina para calcular el valor de X y, para 4hacerlo, obtiene el valor predeterminado de Y, que es cero. As, A.X se inicializa a 1. A continuacin finaliza el 5proceso de ejecutar los inicializadores de campos estticos de A y el constructor esttico, volviendo al clculo 6del valor inicial de Y, cuyo resultado es 2. 710.12Destructores 8Un destructor es un miembro que implementa las acciones necesarias para destruir una instancia de una clase. 9Un destructor se declara utilizando una declaracin de destructor (destructor-declaration): 10 11 12 13 14destructor-declaration: attributesopt externopt ~ identifier ( ) destructor-body destructor-body: block;

15Una declaracin de destructor (destructor-declaration) puede incluir un conjunto de atributos (attributes) (17). 16El identificador (identifier) de un declaracin de destructor (destructor-declaration) debe nombrar la clase en la 17que se declara el destructor. Si se especifica cualquier otro nombre, se produce un error en tiempo de 18compilacin. 19Cuando una declaracin de destructor incluye un modificador ex te rn se dice que es un destructor externo. , 20Debido a que la declaracin de destructor externo no proporciona una implementacin real, su cuerpo de 21destructor (destructor-body) consiste en un punto y coma. Para el resto de destructores, el cuerpo del destructor 22(destructor-body) consiste en un bloque (block) que especifica las instrucciones necesarias para destruir una 23instancia de la clase. Un cuerpo de destructor (destructor-body) corresponde exactamente al cuerpo del mtodo 24(method-body) de un mtodo de instancia con un tipo de valor devuelto vo id (10.5.8). 25Los destructores no se heredan. Por lo tanto, una clase slo tiene el destructor que se puede declarar en la propia 26clase. 27Como un destructor no puede tener parmetros, no puede ser sobrecargado; por lo tanto, una clase slo puede 28tener como mximo un destructor. 29Los destructores se invocan automticamente y no se pueden invocar explcitamente. Una instancia se convierte 30en candidata para destruccin cuando ya ninguna parte de cdigo puede utilizarla. La ejecucin del destructor de 31la instancia puede ocurrir en cualquier momento una vez que la instancia se convierta en candidata para 32destruccin. Cuando se destruye una instancia, se llama a los destructores de su cadena de herencia en orden, de 33la ms derivada a la menos derivada. Un destructor puede ejecutarse en cualquier subproceso. Para leer una 34explicacin ms detallada de las reglas que controlan cmo y cundo se ejecuta un destructor, vea la seccin 353.9. 36El resultado del ejemplo 37 38 39 40 41 42 43us ing Sys tem; c lass A { ~A( ) { Conso le .Wr i teL ine ( "A ' s des t ruc to r " ) ; }

623Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

299

624Especificacin del lenguaje C#

1 2 3 4 7 5 8 6 9 10 11

class B: A { ~B() { class Test { static void Main() { B b = new B(); b = null; Console.WriteLine("B's destructor");

12es GC.Collect(); 16 13 17 Bs destructor 14 18 As cadena de herencia los destructores se llaman en orden, de la ms derivada a la menos derivada. 19ya que en unadestructor 15 20Los destructores se implementan reemplazando el mtodo virtual F ina l i ze Sys tem.Ob jec t Los programas en . 21de C# no permiten reemplazar este mtodo o llamarlo directamente (o a reemplazos del mismo). Por ejemplo, el 22programa 23 24 25 26 27class A { public void F() { this.Finalize(); // error

28 } 30contiene dos errores. 29

625300

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

626

Captulo 18 Cdigo no seguro

1El compilador se comporta como si este mtodo, y sus reemplazos, no existieran. Por lo tanto, este programa: 2 3class A {

4 void Finalize() {} // permitted 6es vlido, y el mtodo mostrado oculta el mtodo F ina l i ze Sys tem.Ob jec t de . 5Para leer una explicacin del comportamiento producido cuando se inicia una excepcin desde un destructor, 7 8vea la seccin 16.3.

627Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

301

628Especificacin del lenguaje C#

1

11.Estructuras

2Las estructuras son similares a las clases en que pueden representar estructuras de datos que pueden contener 3miembros de datos y miembros de funcin. No obstante, a diferencia de las clases, las estructuras son tipos de 4valores y no requieren asignacin del montn. Una variable de un tipo de estructura contiene directamente los 5datos de la estructura, mientras que una variable de un tipo de clase contiene una referencia a los datos, que se 6conocer posteriormente como objeto. 7Las estructuras son particularmente tiles para estructuras de datos pequeas que tienen semnticas de valor. Los 8nmeros complejos, los puntos de un sistema de coordenadas o los pares de valores clave de un diccionario son 9buenos ejemplos de estructuras. La clave de estas estructuras de datos es que tienen pocos miembros de datos, 10que no necesitan utilizar herencia o identidad referencial y que pueden ser implementadas convenientemente 11utilizando semnticas de valor donde la asignacin copia el valor en lugar de la referencia. 12Como se describe en 4.1.4, los tipos simples que proporciona C#, como i n t doub le y bool, son en realidad , 13tipos de estructuras. Como estos tipos predefinidos son estructuras, es posible tambin utilizar estructuras y 14sobrecarga de operadores para implementar nuevos tipos primitivos en el lenguaje C#. Al final de este 15captulo (11.4) se proporcionan dos ejemplos de estos tipos. 1611.1 Declaraciones de estructuras 17Una declaracin de estructura (struct-declaration) es una declaracin de tipo (type-declaration) (9.5) que 18declara una nueva estructura. 19 20struct-declaration: attributesopt struct-modifiersopt struct identifier struct-interfacesopt struct-body ;opt

21Una declaracin de estructura (struct-declaration) consiste en un conjunto de atributos (attributes) (17) 22opcionales, seguidos de un conjunto de modificadores de estructura (struct-modifiers) (11.1.1), de la palabra 23clave struct y un identificador (identifier) que da nombre a la estructura, de una especificacin de interfaces de 24estructura (struct-interfaces) (11.1.2) opcional, de un cuerpo de estructura (struct-body) (11.1.3), y de un 25punto y coma opcional. 2611.1.1 Modificadores de estructuras 27Una declaracin de estructura (struct-declaration) puede incluir opcionalmente una secuencia de modificadores 28de estructura: 29 30 31 32 33 34 35 36 37struct-modifiers: struct-modifier struct-modifiers struct-modifier struct-modifier:new public protected internal private

38Cuando el mismo modificador aparece varias veces en una declaracin de estructura, se produce un error en 39tiempo de compilacin.629302

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

630

Captulo 18 Cdigo no seguro

1Los modificadores de una declaracin de estructura tienen el mismo significado que los de las declaraciones de 2clases (10.1.1). 311.1.2 Interfaces Struct 4Una declaracin de estructura puede incluir una especificacin de interfaces de estructura (struct-interfaces), en 5cuyo caso se dice que la estructura implementa los tipos de interfaz dados. 6 7struct-interfaces: : interface-type-list

8Las implementaciones de interfaces se explican ms detalladamente en 13.4. 911.1.3 Cuerpo de estructura 10El cuerpo de estructura (struct-body) de una estructura define los miembros de la estructura. 11 12struct-body: { struct-member-declarationsopt }

1311.2 Miembros de estructura 14Los miembros de una estructura se componen de los miembros que introducen las declaraciones de miembros de 15estructura (struct-member-declarations) y los miembros heredados del tipo Sys tem.Va lueType . 16 17 18 19 20 21 22 23 24 25 26 27 28 29struct-member-declarations: struct-member-declaration struct-member-declarations struct-member-declaration struct-member-declaration: constant-declaration field-declaration method-declaration property-declaration event-declaration indexer-declaration operator-declaration constructor-declaration static-constructor-declaration type-declaration

30Excepto por las diferencias indicadas en 11.3, las descripciones de miembros de clase proporcionadas en las 31secciones 10.2 a 10.11 tambin se aplican a los miembros de estructuras. 3211.3 Diferencias entre clase y estructura 33Las estructuras se diferencian de las clases de diferentes maneras: 34 35 36 37 38Las estructuras son tipos de valor (11.3.1). Todos los tipos de estructura se heredan implcitamente de la clase Sys tem.Va lueType (11.3.2). La asignacin a una variable de un tipo de estructura crea una copia (copy) del valor que se asigne (11.3.3). El valor predeterminado de una estructura es el valor producido al establecer todos los campos de tipos de valor en su valor predeterminado, y todos los campos de tipos de referencia en nu l l(11.3.4).

631Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

303

632Especificacin del lenguaje C#

1 2 3 4 5 6 7

Las operaciones boxing y unboxing se utilizan para realizar la conversin entre un tipo struct y un tipo ob jec t(11.3.5). El significado de th i ses diferente para las estructuras (11.3.6). Las declaraciones de campos de instancia para una estructura no pueden incluir inicializadores de variables (11.3.7). Una estructura no puede declarar un constructor de instancia sin parmetros (11.3.8). No est permitido que una estructura declare un destructor (11.3.9).

811.3.1 Semnticas de valor 9Las estructuras son tipos de valor (4.1) y se dice que tienen semnticas de valor. Las clases, por el contrario, 10son tipos de referencia (4.2) y se dice que tienen semnticas de referencia. 11Una variable de un tipo de estructura contiene directamente los datos de la estructura, mientras que una variable 12de un tipo de clase contiene una referencia a los datos, que se conocer posteriormente como objeto. Cuando una 13estructura B contiene un campo de instancia A y A es un tipo de estructura, supone un error en tiempo de 14compilacin que A dependa de B. Una estructura X tiene una dependencia directa con una estructura Y si X 15contiene un campo de instancia del tipo Y. Dada esta definicin, el conjunto completo de estructuras de las 16cuales depende una estructura es el cierre transitivo de la relacin de dependencia directa. Por ejemplo: 17 s t ruc t Node 18 { 19 i n t data ; 20 Node nex t ; / / e r ro r , Node d i rec t l y depends on i t se l f 21 } 22es un error porque Node contiene un campo de instancia de su propio tipo. Otro ejemplo 23 s t ruc t A { B b ; } 24 s t ruc t B { C c ; } 25 s t ruc t C { A a ; } 26es un error porque cada uno de los tipos A, B y C dependen entre s. 27En el caso de las clases, es posible que dos variables hagan referencia al mismo objeto y, por tanto, que las 28operaciones en una variable afecten al objeto al que hace referencia la otra variable. En el caso de las 29estructuras, cada variable tiene su propia copia de los datos (exceptuando las variables de los parmetros ref y 30out), de manera que no posible que las operaciones de una afecten a la otra. Dado que las estructuras no son 31tipos de referencia, no es posible que los valores de un tipo de estructura sean null. 32Dada la declaracin 33 s t ruc t Po in t 34 { 35 pub l i c i n t x , y ; 36 pub l i c Po in t ( i n t x , i n t y ) { 37 th i s . x = x ; 38 th i s . y = y ; 39 } 40el fragmento de cdigo 41

633304

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

634

Captulo 18 Cdigo no seguro

1 2

Point a = new Point(10, 10); Point b = a;

3 a.x = 100; 5devuelve como resultado el valor 10. La asignacin de a a b crea una copia del valor y por tanto b no se ve 6 4afectada por la asignacin a a.x. En cambio, si se hubiera declarado Point como clase, el resultado sera 100 7puesto que a y b haran referencia al mismo objeto. 811.3.2 Herencia 9Todos los tipos de estructura heredan implcitamente de la clase System.ValueType, la cual, a su vez, hereda 10de la clase object. Una declaracin de estructura puede especificar una lista de interfaces implementadas, pero 11no es posible que especifique una clase base. 12Los tipos de estructura nunca son abstractos y son siempre sellados implcitamente. Por lo tanto, los 13modificadores abstract y sealed no estn permitidos en una declaracin de estructura. 14Debido a que las estructuras no permiten la herencia, la accesibilidad declarada de un miembro de estructura no 15puede ser protected o protected internal. 16Los miembros de funcin de una estructura no pueden ser abstract ni virtual, y slo se permite el modificador 17override para reemplazar mtodos heredados de System.ValueType. 1811.3.3 Asignacin 19La asignacin a una variable de un tipo de estructura crea una copia (copy) del valor que se asigne. Esto difiere 20de la asignacin a una variable de un tipo de clase, que copia la referencia pero no el objeto identificado por la 21referencia. 22De forma similar a una asignacin, cuando se pasa una estructura como parmetro de valor o se devuelve como 23resultado de un miembro de funcin, se crea una copia de la estructura. Una estructura se puede pasar por 24referencia a un miembro de funcin utilizando un parmetro ref u out. 25Cuando una propiedad o un indizador de una estructura es el destino de una asignacin, la expresin de instancia 26asociada con el acceso a la propiedad o indizador debe estar clasificada como una variable. Si la expresin de 27instancia est clasificada como un valor, se produce un error de compilacin. Esta categora se explica con ms 28detalle en la seccin 7.13.1. 2911.3.4 Valores predeterminados 30Como se describe en la seccin 5.2, cuando se crean algunos tipos de variables se inicializan automticamente 31a sus valores predeterminados. Para variables de tipos de clase y otros tipos de referencia, el valor 32predeterminado es null. Sin embargo, como las estructuras son tipos de valor que no pueden ser null, el valor 33predeterminado de una estructura es el valor producido al establecer todos los campos de tipo de valor a sus 34valores predeterminados y todos los campos de tipo de referencia a null. 35Haciendo referencia a la estructura Point declarada anteriormente, en el ejemplo 36 Point[] a = new Point[100]; 37se inicializa cada Point de la matriz al valor producido por establecer los campos x e y a cero. 38El valor predeterminado de una estructura corresponde al valor devuelto por el constructor predeterminado de la 39estructura (4.1.1). A diferencia de una clase, una estructura no permite declarar un constructor de instancia sin 40parmetros. En su lugar, cada estructura tiene implcitamente un constructor de instancia sin parmetros que 41siempre devuelve el valor que resulta de establecer todos los campos de tipo de valor a sus valores 42predeterminados y todos los campos de tipo de referencia a null.

635Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

305

636Especificacin del lenguaje C#

1Las estructuras deben disearse considerando que el estado de inicializacin predeterminado sea un estado 2vlido. En el siguiente ejemplo: 3 4 5 6 8 7 9 10using System; struct KeyValuePair { string key; public KeyValuePair(string key, string value) { if (key == null || value == null) throw new ArgumentException(); this.key = key;

11 this.value = value; 14el constructor de instancia definido por el usuario evita los valores nulos slo donde es llamado explcitamente. 12En los casos en los que una variable KeyVa luePa i r sujeta a una inicializacin de valor predeterminado, los 15 est 16campos key y value sern nulos y la estructura debe estar preparada para controlar este estado. 13 1711.3.5 Boxing y Unboxing 18Un valor de un tipo de clase se puede convertir a un tipo object o a un tipo de interfaz que es implementada por 19la clase simplemente tratando la referencia como otro tipo en tiempo de compilacin. Igualmente, un valor del 20tipo object o un valor de un tipo de interfaz se puede convertir de nuevo a un tipo de clase sin cambiar la 21referencia (pero en este caso es necesaria una comprobacin de tipo en tiempo de ejecucin). 22Dado que las estructuras no son tipos de referencia, estas operaciones se implementan de forma diferente para 23los tipos de estructura. Cuando se convierte un valor de un tipo de estructura a un tipo object o a un tipo de 24interfaz que es implementada por la estructura, tiene lugar una operacin boxing. De la misma forma, cuando un 25valor de tipo object o un valor de tipo de interfaz se vuelve a convertir a un tipo de estructura, tiene lugar una 26operacin unboxing. Una diferencia fundamental con las mismas operaciones en los tipos de clase es que las 27conversiones boxing y unboxing copian el valor de estructura en o fuera de la instancia a la que se ha aplicado la 28conversin boxing. Por lo tanto, despus de una operacin boxing o unboxing, los cambios realizados en la 29estructura a la que se ha aplicado la conversin unboxing no se reflejan en la estructura donde se ha aplicado la 30conversin boxing. 31Para obtener informacin detallada sobre boxing y unboxing, vea 4.3. 3211.3.6 Significado de This 33Dentro de un constructor de instancia o de un miembro de funcin de una clase, this est clasificado como un 34valor. Por lo tanto, mientras que this se puede utilizar para hacer referencia a la instancia para la que fue 35invocado el miembro de funcin, no es posible asignar a this en un miembro de funcin de una clase. 36Dentro de un constructor de instancia de una estructura, this corresponde a un parmetro out del tipo de 37estructura, y dentro de un miembro de funcin de instancia de una estructura, this corresponde a un parmetro 38ref del tipo de estructura. En ambos casos, this est clasificado como una variable, y es posible modificar toda 39la estructura para la que fue invocado el miembro de funcin mediante la asignacin a this o pasndola como 40parmetros ref u out. 4111.3.7 Inicializadores de campo 42Como se describe en la seccin 11.3.4, el valor predeterminado de una estructura es el valor que resulta de 43establecer todos los campos de tipo de valor a sus valores predeterminados y todos los campos de tipo de 44referencia a null. Por esta razn, una estructura no permite declaraciones de campos de instancia para incluir637306

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

638

Captulo 18 Cdigo no seguro

1inicializadores de variables. Esta restriccin slo se aplica a los campos de instancia. Los campos estticos de 2una estructura pueden incluir inicializadores de variable.

639Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

307

640Especificacin del lenguaje C#

1En el ejemplo 2 3struct Point {

4 public int x = 1; // Error, initializer not permitted 7 5hay un error porque la declaracin del campo de instancia incluye inicializadores de variables. 611.3.8 Constructores 8 9A diferencia de una clase, una estructura no permite declarar un constructor de instancia sin parmetros. En su 10lugar, cada estructura tiene implcitamente un constructor de instancia sin parmetros que siempre devuelve el 11valor que resulta de establecer todos los campos de tipo de valor a sus valores predeterminados y todos los 12campos de tipo de referencia a null (4.1.2). Una estructura puede declarar constructores de instancia con 13parmetros. Por ejemplo: 14 15 16 17 18struct Point { public Point(int x, int y) { this.x = x;

19 this.y = y; 22Dada la declaracin anterior, las instrucciones 20 21 23 Point p1 = new Point(); 24 Point p2 = new Point(0, 0); 25crean un Po in tcon x e y inicializados a cero. 26Un constructor de instancia de estructura no puede incluir un inicializador de constructor de la forma base(...). 27Si el constructor de instancia de la estructura no especifica un inicializador de constructor, la variable this 28corresponde a un parmetro out del tipo de estructura, y de forma similar a un parmetro out, this debe ser 29asignado de manera definitiva (5.3) a cada ubicacin a la que vuelva el constructor. Si el constructor de 30instancia de la estructura especifica un inicializador de constructor, la variable this corresponde a un parmetro 31ref del tipo de estructura, y de forma similar a un parmetro ref, this se considera definitivamente asignado en 32la entrada al cuerpo del constructor. Observe la implementacin del constructor de instancia siguiente: 33 34 35 36 37 38 39 40 41struct Point { public int X { set { x = value; } public int Y { set { y = value; }

641308

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

642

Captulo 18 Cdigo no seguro

1 2

public Point(int x, int y) { X = x; // error, this is not yet definitely assigned

3 Y = y; // error, this is not yet definitely assigned 6 4No puede llamarse a ninguna funcin de miembro de instancia (incluyendo los descriptores de acceso 7establecidos para las propiedades X e Y) hasta que todos los campos de la estructura que est construyndose se 5hayan asignado definitivamente. Observe, no obstante, que si Point fuera una clase en lugar de una estructura, 8 9estara permitida la implementacin del constructor de instancia. 1011.3.9 Destructores 11No est permitido que una estructura declare un destructor. 1211.3.10Constructores Static 13Los constructores estticos (static) para estructuras siguen la mayora de las mismas reglas que las clases. La 14ejecucin de un constructor esttico para una estructura la desencadena el primero de los siguientes eventos que 15se produzcan en un dominio de aplicacin: 16 17 18Se hace referencia a un miembro de instancia de la estructura. Se hace referencia a un miembro esttico de la estructura. Se llama a un constructor explcitamente declarado de la estructura.

19La creacin de valores predeterminados (11.3.4) de tipos de estructura no desencadena el constructor esttico. 20(Un ejemplo de esto es el valor inicial de los elementos de una matriz.) 2111.4 Ejemplos de estructuras 22A continuacin se muestran dos ejemplos significativos de la utilizacin de tipos struct para crear tipos que 23puedan utilizarse de manera similar a los tipos integrados del lenguaje, pero con semnticas modificadas. 2411.4.1 Tipo entero de base de datos 25La estructura DBInt siguiente implementa un tipo entero que puede representar el conjunto completo de valores 26del tipo int, adems de un estado adicional que indica un valor desconocido. Un tipo de estas caractersticas se 27utiliza normalmente en bases de datos. 28 29 30 31 32 33 34 35 36 37 38using System; public struct DBInt { public static readonly DBInt Null = new DBInt(); // When the defined field is true, this DBInt represents a known value // which is stored in the value field. When the defined field is false, int value; bool defined; // Private instance constructor. Creates a DBInt with a known value.

643Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

309

644Especificacin del lenguaje C#

1 2 3 5 4 6 7 8 9 10 11 12 13 14 15 16 17 18 20 19 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46645310

DBInt(int value) { this.value = value; this.defined = true; // The IsNull property is true if this DBInt represents an unknown value. public bool IsNull { get { return !defined; } } // The Value property is the known value of this DBInt, or 0 if this // DBInt represents an unknown value. public int Value { get { return value; } } // Implicit conversion from int to DBInt. public static implicit operator DBInt(int x) { return new DBInt(x); // Explicit conversion from DBInt to int. Throws an exception if the // given DBInt represents an unknown value. public static explicit operator int(DBInt x) { if (!x.defined) throw new InvalidOperationException(); return x.value; public static DBInt operator +(DBInt x) { return x; public static DBInt operator -(DBInt x) { return x.defined ? -x.value : Null; public static DBInt operator +(DBInt x, DBInt y) { return x.defined && y.defined? x.value + y.value: Null; public static DBInt operator -(DBInt x, DBInt y) { return x.defined && y.defined? x.value - y.value: Null; public static DBInt operator *(DBInt x, DBInt y) { return x.defined && y.defined? x.value * y.value: Null; public static DBInt operator /(DBInt x, DBInt y) { return x.defined && y.defined? x.value / y.value: Null; public static DBInt operator %(DBInt x, DBInt y) { return x.defined && y.defined? x.value % y.value: Null; public static DBBool operator ==(DBInt x, DBInt y) { return x.defined && y.defined? x.value == y.value: DBBool.Null; public static DBBool operator !=(DBInt x, DBInt y) { return x.defined && y.defined? x.value != y.value: DBBool.Null;

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

646

Captulo 18 Cdigo no seguro

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 18 17 19 20 21 22

public static DBBool operator >(DBInt x, DBInt y) { return x.defined && y.defined? x.value > y.value: DBBool.Null; public static DBBool operator =(DBInt x, DBInt y) { return x.defined && y.defined? x.value >= y.value: DBBool.Null; public static DBBool operator 0; // Equality operator. Returns Null if either operand is Null, otherwise // returns True or False. public static DBBool operator ==(DBBool x, DBBool y) { if (x.value == 0 || y.value == 0) return Null; return x.value == y.value? True: False; // Inequality operator. Returns Null if either operand is Null, otherwise // returns True or False. public static DBBool operator !=(DBBool x, DBBool y) { if (x.value == 0 || y.value == 0) return Null; return x.value != y.value? True: False; // Logical negation operator. Returns True if the operand is False, Null // if the operand is Null, or False if the operand is True. public static DBBool operator !(DBBool x) { return new DBBool(-x.value); // Logical AND operator. Returns False if either operand is False, // otherwise Null if either operand is Null, otherwise True. public static DBBool operator &(DBBool x, DBBool y) { return new DBBool(x.value < y.value? x.value: y.value); // Logical OR operator. Returns True if either operand is True, otherwise // Null if either operand is Null, otherwise False. public static DBBool operator |(DBBool x, DBBool y) { return new DBBool(x.value > y.value? x.value: y.value); // Definitely true operator. Returns true if the operand is True, false // otherwise. public static bool operator true(DBBool x) { return x.value > 0; // Definitely false operator. Returns true if the operand is False, false // otherwise.Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

650

Captulo 18 Cdigo no seguro

1 2 3 4 5 6 8 7 9 10 11 12 13 14 15 16

public static bool operator false(DBBool x) { return x.value < 0; public override bool Equals(object obj) { if (!(obj is DBBool)) return false; return value == ((DBBool)obj).value; public override int GetHashCode() { return value; public override string ToString() { if (value > 0) return "DBBool.True"; if (value < 0) return "DBBool.False"; return "DBBool.Null";

651Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

313

652Especificacin del lenguaje C#

1

12.Matrices

2Una matriz es una estructura de datos que contiene una serie de variables a las que se obtiene acceso a travs de 3ndices calculados. Las variables contenidas en una matriz, tambin conocidas como elementos de la matriz, son 4todas del mismo tipo, denominado tipo de elemento de la matriz. 5Una matriz tiene un rango que determina el nmero de ndices asociados a cada elemento de la matriz. El rango 6de una matriz tambin se conoce como nmero de dimensiones de la matriz. Una matriz con un rango de uno se 7denomina matriz unidimensional. Una matriz con un rango mayor que uno se denomina matriz 8multidimensional. Las matrices multidimensionales de un determinado tamao se suelen denominar matrices 9bidimensionales, tridimensionales, etc. 10Cada dimensin de una matriz tiene una longitud asociada, que es un nmero entero mayor o igual a cero. Las 11longitudes de dimensin no forman parte del tipo de matriz, sino que se establecen cuando se crea una instancia 12del tipo de matriz en tiempo de ejecucin. La longitud de una dimensin determina el intervalo vlido de ndices 13para esa dimensin: para una dimensin de longitud N, los ndices pueden tomar valores de cero a N 1 14inclusive. El nmero total de elementos en una matriz es el producto de las longitudes de cada dimensin de la 15matriz. Si alguna de las dimensiones de una matriz tiene una longitud cero, se dice que la matriz est vaca. 16Los elementos de una matriz pueden ser de cualquier tipo, incluido un tipo de matriz. 1712.1 Tipos de matriz 18Un tipo de matriz se escribe como non-array-type seguido de uno o ms especificadores de rango (rank19specifers): 20 21 22 23 24 25 26 27 28 29 30 31array-type: non-array-type rank-specifiers non-array-type: type rank-specifiers: rank-specifier rank-specifiers rank-specifier rank-specifier: [ dim-separatorsopt ] dim-separators:,

dim-separators ,

32Un tipo no de matriz (non-array-type) es cualquier tipo que no es en s mismo un tipo de matriz (array-type). 33El rango de un tipo de matriz viene dado por el especificador de rango (rank-specifier) situado en el extremo 34izquierdo del tipo de matriz (array-type): as, un especificador de rango indica que la matriz posee un rango de 35uno ms el nmero de smbolos "," del especificador de rango. 36El tipo de elemento de un tipo de matriz es el tipo resultante de eliminar el especificador de rango (rank37specifier) del extremo izquierdo: 38653314

Un tipo de matriz de la forma T[R] es una matriz de rango R y un tipo de elemento T que no sea de matriz.

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

654

Captulo 18 Cdigo no seguro

1 2

Un tipo de matriz de la forma T[R] [R]...[RN] es una matriz de rango R y un tipo de elemento T[R1]...[RN] 1 que no sea de matriz.

3Lo que sucede es que los especificadores de rango (rank-specifiers) se leen de izquierda a derecha, antes del tipo 4de elemento final que no es de matriz. El tipo int[][,,][,] es una matriz unidimensional que contiene matrices 5tridimensionales de matrices bidimensionales de tipo int. 6En tiempo de ejecucin, el valor de un tipo de matriz puede ser null o una referencia a una instancia de dicho 7tipo. 812.1.1 Tipo System.Array 9El tipo Sys tem.Ar rayes el tipo base abstracto de todos los tipos de matrices. Se produce una conversin de 10referencia implcita (6.1.4) entre cualquier tipo de matriz y un tipo Sys tem.Ar ray as como una conversin de , 11referencia explcita (6.2.3) de System.Array a cualquier tipo de matriz. Observe que System.Array no es en 12s mismo un tipo de matriz (array-type). Al contrario, es un tipo de clase (class-type) del que se derivan todos 13los tipos de matriz (array-types). 14En tiempo de ejecucin, un valor de tipo System.Array puede ser null o una referencia a una instancia de 15cualquier tipo de matriz. 1612.2 Creacin de matrices 17Las instancias de matriz se crean mediante expresiones de creacin de matriz (array-creation-expressions) 18(7.5.10.2) o mediante declaraciones de campo o variable local que incluyen un inicializador de matriz (array19initializer) (12.6). 20Cuando se crea una instancia de matriz, se establecen el rango y longitud de cada dimensin y a continuacin 21permanecen constante por toda la duracin de la instancia. Es decir, no es posible cambiar el rango de una 22instancia de matriz existente ni cambiar el tamao de sus dimensiones. 23Una instancia de matriz es siempre de tipo de matriz. El tipo System.Array es un tipo abstracto del que no se 24pueden crear instancias. 25Los elementos de matrices creadas mediante expresiones de creacin de matrices (array-creation-expressions) 26se inicializan siempre con sus valores predeterminados (5.2). 2712.3 Acceso a los elementos de matriz 28El acceso a los elementos de una matriz se obtiene mediante expresiones de acceso a elementos (element-access) 29(7.5.6.1) de la forma A[I1, I2, ..., IN], donde A es una expresin de un tipo de matriz y cada IX es una expresin 30de tipo int, uint, long, ulong, o de un tipo que puede convertirse de manera implcita a uno o varios de estos 31tipos. El resultado de un acceso a elemento de matriz es una variable, en concreto el elemento de matriz 32seleccionado por los ndices. 33Los elementos de una matriz se pueden enumerar mediante una instruccin foreach (8.8.4). 3412.4 Miembros de matriz 35Cada tipo de matriz hereda los miembros declarados por el tipo System.Array. 3612.5 Covarianza de matrices 37Por cada dos tipos de referencia (reference-types) A y B, si existe una conversin de referencia implcita (6.1.4) 38o explcita (6.2.3) entre A y B, tambin tiene lugar la misma conversin de referencia entre el tipo de matriz 39A[R] y el tipo de matriz B[R], donde R es cualquier especificador de rango (rank-specifier), si bien es el mismo 40para ambos tipos de matriz. Esta relacin se conoce como covarianza matricial. La covarianza matricial655Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

315

656Especificacin del lenguaje C#

1significa, en concreto, que un valor de un tipo de matriz A[R] puede ser en realidad una referencia a una 2instancia de un tipo de matriz B[R], siempre que exista una conversin de referencia implcita entre B y A. 3Debido a la covarianza de matrices, las asignaciones a elementos de matrices de tipo de referencia incluyen una 4comprobacin en tiempo de ejecucin que garantiza que el valor que se asigna al elemento de matriz es 5realmente de un tipo permitido (7.13.1). Por ejemplo: 6 c lass Tes t 7 { 8 s ta t i c vo id F i l l ( ob jec t [ ] ar ray , i n t i ndex , i n t count , ob jec t va lue ) { 9 f o r ( i n t i = i ndex ; i < i ndex + count ; i++) ar ray [ i ] = va lue ; 10 11 s ta t i c vo id Main ( ) { 12 s t r i ng [ ] s t r i ngs = new s t r i ng [100] ; 13 F i l l ( s t r i ngs , 0 , 100 , "Unde f i ned" ) ; 14 F i l l ( s t r i ngs , 0 , 10 , nu l l ) ; 15 F i l l ( s t r i ngs , 90 , 10 , 0) ; 16 } 18La asignacin a ar ray [ ien el mtodo F i l incluye implcitamente una comprobacin en tiempo de ejecucin, ] l 17 19que garantiza que el objeto al que hace referencia value es null o bien una instancia de un tipo compatible con

20el tipo de elemento real de la matriz array. En Main, las dos primeras llamadas a Fill se ejecutan con xito, pero 21la tercera llamada provoca una excepcin System.ArrayTypeMismatchException al ejecutarse la primera 22asignacin a array[i]. La excepcin se produce porque no se puede almacenar un valor int boxed en una matriz 23string. 24La covarianza matricial no abarca las matrices de tipos de valor (value-types). Por ejemplo, no hay ninguna 25conversin que permita tratar un tipo int[] como object[]. 2612.6 Inicializadores de matrices 27Los inicializadores de matrices se pueden especificar en declaraciones de campo (10.4), declaraciones de 28variable local (8.5.1) y expresiones de creacin de matrices (7.5.10.2): 29 30 31 32 33 34 35 36 37array-initializer: { variable-initializer-listopt } { variable-initializer-list , } variable-initializer-list: variable-initializer variable-initializer-list , variable-initializer variable-initializer: expression array-initializer

38Un inicializador de matriz se compone de una secuencia de inicializadores de variable, que figuran entre los 39smbolos { y } y separados por ,. Cada inicializador de variable es una expresin o, en el caso de una 40matriz multidimensional, un inicializador de matriz anidado. 41El contexto en que se utiliza un inicializador de matriz determina el tipo de la matriz que se inicializa. En una 42expresin de creacin de matriz, el tipo de matriz precede inmediatamente al inicializador. En una declaracin 43de campo o de variable, el tipo de matriz es el tipo del campo o variable que se est declarando. Cuando se 44utiliza un inicializador de matriz en una declaracin de campo o de variable, como: 45657316

i n t [ ] a = {0 , 2 , 4 , 6 , 8} ;

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

658

Captulo 18 Cdigo no seguro

1equivale a la siguiente expresin de creacin de matriz: 2 int[] a = new int[] {0, 2, 4, 6, 8}; 3Para una matriz unidimensional, el inicializador de matriz debe estar compuesto de una secuencia de 4expresiones que sean compatibles en materia de asignacin con el tipo de elemento de la matriz. Las expresiones 5inicializan los elementos de matriz por orden creciente, comenzando a partir del elemento en el ndice cero. El 6nmero de expresiones del inicializador de matriz determina la longitud de la instancia de matriz que se est 7creando. Por ejemplo, el inicializador de matriz anterior crea una instancia i n t [ de longitud 5 y a continuacin ] 8inicializa la instancia con los siguientes valores: 9 a[0] = 0; a[1] = 2; a[2] = 4; a[3] = 6; a[4] = 8; 10Para una matriz multidimensional, el inicializador de matriz debe tener tantos niveles de anidamiento como 11dimensiones tenga la matriz. El nivel de anidamiento superior se corresponde con la dimensin situada en el 12extremo izquierdo y el nivel de anidamiento inferior se corresponde con la dimensin situada en el extremo 13derecho. La longitud de cada una de las dimensiones de la matriz est determinada por el nmero de elementos 14del nivel de anidamiento correspondiente en el inicializador de la matriz. Por cada inicializador de matriz 15anidado, el nmero de elementos debe ser igual al de los dems inicializadores de matriz que estn situados en el 16mismo nivel. En el ejemplo: 17 int[,] b = {{0, 1}, {2, 3}, {4, 5}, {6, 7}, {8, 9}}; 18se crea una matriz bidimensional con una longitud de cinco para la dimensin del extremo izquierdo y una 19longitud de dos para la dimensin del extremo derecho: 20 int[,] b = new int[5, 2]; 21y a continuacin se inicializa la instancia de la matriz con los valores siguientes: 22 23b[0, 0] = 0; b[0, 1] = 1; b[1, 0] = 2; b[1, 1] = 3;

24 b[2, 0] = 4; b[2, 1] = 5; 27 25Cuando una expresin de creacin de matriz incluye tanto longitudes de dimensin explcitas como un 28inicializador de matriz, las longitudes deben ser expresiones constantes, y el nmero de elementos en cada nivel 26de anidamiento debe coincidir con la longitud de dimensin correspondiente. A continuacin se describen 29 30algunos ejemplos: 31 32int i = 3; int[] x = new int[3] {0, 1, 2}; // OK

33 int[] y = new int[i] {0, 1, 2}; // Error, i not a constant 35Aqu, el inicializador de y es un error de compilacin porque la expresin de longitud de dimensin no es una 36constante, y el inicializador de z es un error de compilacin porque la longitud y el nmero de elementos del 34 37inicializador no coinciden.

659Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

317

660Especificacin del lenguaje C#

1

13.Interfaces

2Una interfaz define un contrato. Una clase o estructura que implementa una interfaz debe adherirse a su 3contrato. Una interfaz puede derivarse de varias interfaces base, y una clase o estructura puede implementar 4varias interfaces. 5Las interfaces pueden contener mtodos, propiedades, eventos e indizadores. La propia interfaz no proporciona 6implementaciones para los miembros que define. La interfaz slo especifica los miembros que las clases o 7estructuras deben proporcionar, y que implementan la interfaz. 813.1 Declaraciones de interfaz 9Una declaracin de interfaz (interface-declaration) es una declaracin de tipo (type-declaration) (9.5) que 10declara un nuevo tipo de interfaz. 11 12interface-declaration: attributesopt interface-modifiersopt i n te r faceidentifier interface-baseopt interface-body ;opt

13Una declaracin de interfaz (interface-declaration) consiste en un conjunto de atributos (attributes) (17) 14opcionales, seguidos de un conjunto de modificadores de interfaz (interface-modifiers) (13.1.1), de la palabra 15clave i n te r face de un identificador (identifier) que da nombre a la interfaz, de una especificacin opcional de y 16base de interfaz (interface-base) (13.1.2), de un cuerpo de interfaz (interface-body) (13.1.3) y de un punto y 17coma opcional. 1813.1.1 Modificadores de interfaz 19Una declaracin de interfaz (interface-declaration) puede incluir opcionalmente una secuencia de modificadores 20de interfaz: 21 22 23 24 25 26 27 28 29interface-modifiers: interface-modifier interface-modifiers interface-modifier interface-modifier:new pub l i c pro tec ted i n te rna l private

30Cuando el mismo modificador aparece varias veces en una declaracin de interfaz, se produce un error en 31tiempo de compilacin. 32El modificador new slo se permite en interfaces definidas dentro de una clase. Especifica que la interfaz oculta 33un miembro heredado con el mismo nombre, como se describe en 10.2.2. 34Los modificadores public, protected, internal y private controlan la accesibilidad a la interfaz. Dependiendo 35del contexto en que se produzca la declaracin de interfaz, puede que slo se permitan algunos de estos 36modificadores (3.5.1).

661318

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

662

Captulo 18 Cdigo no seguro

113.1.2 Interfaces base 2Una interfaz puede no heredar de ninguna interfaz o heredar de varias, que se denominan interfaces base 3explcitas de la interfaz. Cuando una interfaz tiene una o ms interfaces base explcitas, el identificador de 4interfaz, en la declaracin, viene seguido de un carcter de dos puntos y una lista de identificadores de interfaz 5base separados por comas. 6 7interface-base: : interface-type-list

8Las interfaces base explcitas de una interfaz deben ser por lo menos tan accesibles como la propia interfaz 9(3.5.4). Por ejemplo, supone un error en tiempo de compilacin especificar una interfaz pr i va te i n te rnaen o l 10la interfaz base (interface-base) de una interfaz public. 11Igualmente, se produce un error en tiempo de compilacin cuando una interfaz hereda directa o indirectamente 12de s misma. 13Las interfaces base de una interfaz son las interfaces base explcitas y sus interfaces base. En otras palabras, el 14conjunto de interfaces base se compone de la terminacin transitiva completa de las interfaces base explcitas, 15sus interfaces base explcitas, etc. Una interfaz hereda a todos los miembros de sus interfaces base. En el 16siguiente ejemplo: 17 i n te r face I Con t ro l 18 { 19 vo id Pa in t ( ) ; 20 } 21 i n te r face I Tex tBox : I Con t ro l 22 { 23 vo id Set Tex t ( s t r i ng t ex t ) ; 24 } 25 i n te r face I L i s tBox : I Con t ro l 26 { 27 vo id Set I tems(s t r i ng [ ] i t ems) ; 28 } 29 i n te r face I ComboBox : I Tex tBox , I L i s tBox {} 30las interfaces base de I ComboBox son I Con t ro, lITextBox e IListBox. 31Es decir, la interfaz IComboBox anterior hereda los miembros SetText y SetItems, as como Paint. 32Una clase o estructura que implementa una interfaz tambin implementa implcitamente todas las interfaces base 33de dicha interfaz. 3413.1.3 Cuerpo de interfaz 35El cuerpo de una interfaz (interface-body) define sus miembros respectivos. 36 37interface-body: { interface-member-declarationsopt }

3813.2 Miembros de interfaz 39Los miembros de una interfaz son los miembros heredados de las interfaces base y los miembros declarados por 40la propia interfaz. 41 42 43interface-member-declarations: interface-member-declaration interface-member-declarations interface-member-declaration319

663Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

664Especificacin del lenguaje C#

1 2 3 4 5

interface-member-declaration: interface-method-declaration interface-property-declaration interface-event-declaration interface-indexer-declaration

6Una declaracin de interfaz puede declarar cero o varios miembros. Los miembros de una interfaz pueden ser 7mtodos, propiedades, eventos o indizadores. Una interfaz no puede contener constantes, campos, operadores, 8constructores de instancia, destructores ni tipos, ni tampoco puede una interfaz contener miembros estticos de 9ningn tipo. 10Todos los miembros de interfaz tienen implcitamente acceso pblico. Supone un error en tiempo de 11compilacin que las declaraciones de miembros de interfaz contengan modificadores. En particular, los 12miembros de interfaces no pueden declararse con los modificadores abs t rac,tpub l i c protected, internal, , 13private, virtual, override o static. 14En el ejemplo 15 16 17 18 19 20 21public delegate void StringListEvent(IStringList sender); public interface IStringList { int Count { get; } event StringListEvent Changed; string this[int index] { get; set; }

22se declara una interfaz que contiene cada uno de los tipos posibles de miembro: un mtodo, una propiedad, un } 23 24evento y un indizador. 25Una declaracin de interfaz (interface-declaration) crea un nuevo espacio de declaracin (3.3), y las 26declaraciones de miembro de interfaz (interface-member-declarations) contenidas inmediatamente en la 27declaracin de interfaz agregan nuevos miembros al espacio de declaracin. Las siguientes reglas se aplican a 28las declaraciones de miembros de interfaz (interface-member-declarations): 29 30 31 32 33 34 35 36El nombre de un mtodo debe ser diferente del de cualquier otra propiedad o evento declarados en la misma interfaz. Adems, la firma (3.6) de un mtodo debe ser distinta de las firmas de todos los dems mtodos declarados en la misma interfaz, y dos mtodos declarados en la misma interfaz no pueden tener firmas que slo se diferencien por ref y out. El nombre de una propiedad o evento debe ser diferente de los nombres de todos los dems miembros declarados en la misma interfaz. La firma de un indizador debe ser diferente de las firmas de los dems indizadores declarados en la misma interfaz.

37Los miembros heredados de una interfaz no forman parte especficamente del espacio de declaracin de la 38interfaz. De esta forma, una interfaz puede declarar un miembro con el mismo nombre o firma que un miembro 39heredado. Cuando esto ocurre, se dice que el miembro de interfaz derivado oculta el miembro de interfaz base. 40Ocultar un miembro heredado no se considera un error, pero hace que el compilador emita una advertencia. Para 41evitar la advertencia, la declaracin del miembro de interfaz heredado debe incluir el modificador new para 42indicar que el miembro derivado est destinado a ocultar el miembro base. Este tema se explica con ms detalle 43en la seccin 3.7.1.2.

665320

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

666

Captulo 18 Cdigo no seguro

1Si se incluye un modificador new en una declaracin que no oculta un miembro heredado, se emite una 2advertencia a tal efecto. Esta advertencia se evita quitando el modificador new . 3Tenga en cuenta que los miembros de la clase ob jec tno son, estrictamente hablando, miembros de ninguna 4interfaz (13.2). Sin embargo, los miembros de la clase ob jec testn disponibles a travs de la bsqueda de 5miembros en cualquier tipo de interfaz (7.3). 613.2.1 Mtodos de interfaz 7Los mtodos de interfaz se declaran mediante declaraciones de mtodos de interfaz (interface-method8declarations): 9 10interface-method-declaration: attributesopt new opt return-type identifier ( formal-parameter-listopt ) ;

11Los atributos (attributes), el tipo de valor devuelto (return-type), el identificador (identifier) y la lista de 12parmetros formales (formal-parameter-list) de una declaracin de mtodo de interfaz pueden tener el mismo 13significado que los de una declaracin de mtodo perteneciente a una clase (10.5). No se permite que una 14declaracin de mtodo de interfaz especifique un cuerpo del mtodo, y la declaracin por tanto siempre termina 15con un punto y coma. 1613.2.2 Propiedades de interfaz 17Las propiedades de interfaz se declaran mediante declaraciones de propiedad de interfaz (interface-property18declaration): 19 20 21 22 23 24 25interface-property-declaration: attributesopt newopt type identifier { interface-accessors } interface-accessors: attributesopt get attributesopt set attributesopt get attributesopt set; ; ; attributesopt set ; ; attributesopt get ;

26Los atributos (attributes), el tipo (type) y el identificador (identifier) de una declaracin de propiedad de interfaz 27pueden tener el mismo significado que los de una declaracin de propiedad perteneciente a una clase (10.6). 28Los descriptores de acceso correspondientes a una declaracin de propiedad de interfaz son los descriptores de 29acceso de una declaracin de propiedad de clase (10.6.2), salvo que el cuerpo del descriptor de acceso siempre 30debe ser un punto y coma. As, el propsito de los descriptores de acceso es indicar si la propiedad es de lectura 31y escritura, de slo lectura o de slo escritura. 3213.2.3 Eventos de interfaz 33Los eventos de interfaz se declaran mediante declaraciones de evento de interfaz (interface-event-declaration): 34 35interface-event-declaration: attributesopt newopt event type identifier ;

36Los atributos (attributes), el tipo (type) y el identificador (identifier) de una declaracin de evento de interfaz 37pueden tener el mismo significado que los de una declaracin de evento perteneciente a una clase (10.7). 3813.2.4 Indizadores de interfaz 39Los indizadores de interfaz se declaran mediante declaraciones de indizador de interfaz (interface-indexer40declarations):

667Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

321

668Especificacin del lenguaje C#

1 2

interface-indexer-declaration: attributesopt new opt type th i s [ formal-parameter-list ] { interface-accessors }

3Los atributos (attributes), el tipo (type) y la lista de parmetros formales (formal-parameter-list) de una 4declaracin de indizador de interfaz pueden tener el mismo significado que los de una declaracin de indizador 5perteneciente a una clase (10.8). 6Los descriptores de acceso correspondientes a una declaracin de indizador de interfaz son los descriptores de 7acceso de una declaracin de indizador de clase (10.8), salvo que el cuerpo del descriptor de acceso siempre 8debe ser un punto y coma. As, el propsito de los descriptores de acceso es indicar si el indizador es de lectura 9y escritura, de slo lectura o de slo escritura. 1013.2.5 Acceso a miembros de interfaz 11El acceso a los miembros de interfaz tiene lugar mediante las expresiones de acceso a miembros (7.5.4) y 12expresiones de acceso a indizadores (7.5.6.2) de la forma I.M e I[A], donde I es un tipo de interfaz, M es un 13mtodo, propiedad o evento de dicho tipo de interfaz y A es una lista de argumentos del indizador. 14Para interfaces que son estrictamente de herencia simple (todas las interfaces de la cadena de herencia tienen 15exactamente cero o una sola interfaz base directa), los efectos de las reglas de bsqueda de miembros (7.3), 16llamadas a mtodos (7.5.5.1) y acceso a indizadores (7.5.6.2) son exactamente iguales que las aplicables a 17clases y estructuras: ms miembros derivados ocultan menos miembros derivados con el mismo nombre o firma. 18Sin embargo, para interfaces de herencia mltiple, pueden existir ambigedades cuando dos o ms interfaces 19base no relacionadas entre s declaran miembros con el mismo nombre o firma. Esta seccin muestra varios 20ejemplos de tales situaciones. En todos los casos, pueden utilizarse las conversiones implcitas para resolver las 21ambigedades. 22En el siguiente ejemplo: 23 24 25 27 26 28 29 31 30 32 33 34 35 36interface IList { int Count { get; set; } interface ICounter { void Count(int i); interface IListCounter: IList, ICounter {} class C { void Test(IListCounter x) { x.Count(1); x.Count = 1; // Error // Error

37las dos primeras ((IList)x).Counterrores en tiempo de compilacin, ya que la bsqueda de miembros (7.3) // Ok, invokes IList.Count.set 41 instrucciones causan = 1; 42de Count en IListCounter es ambigua. Como muestra el ejemplo, la ambigedad se resuelve convirtiendo x en 38 43el tipo de interfaz base apropiado. Tales conversiones no tienen costo de ejecucin; simplemente consisten en 39 44ver la instancia como un tipo menos derivado en tiempo de compilacin. 40En el siguiente ejemplo: 45

669322

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

670

Captulo 18 Cdigo no seguro

1 2 3 5 4 6 7 9 8 10 11 12 13 14

interface IInteger { void Add(int i); interface IDouble { void Add(double d); interface INumber: IInteger, IDouble {} class C { void Test(INumber n) { n.Add(1); n.Add(1.0); // Invokes IInteger.Add // Only IDouble.Add is applicable

15la llamada n .Add(1 )selecciona I I n tege r .Add // Only IInteger.Add is de sobrecargas de 7.4.2. De ((IInteger)n).Add(1); al aplicar las reglas de resolucin a candidate 19 20manera similar, la llamada n.Add(1.0) selecciona IDouble.Add. Cuando se insertan conversiones explcitas, 16 21slo hay un mtodo candidato y por ello no hay ambigedad. 17 22En el siguiente ejemplo: 18 23 i n te r face I Base 24 { 25 vo id F ( i n t i ) ; 26 } 27 i n te r face I Le f t : I Base 28 { 29 new vo id F ( i n t i ) ; 30 } 31 i n te r face I R igh t : I Base 32 { 33 vo id G( ) ; 34 } 35 i n te r face IDe r i ved : I Le f t , I R igh t {} 36 c lass A 37 { 38 vo id Tes t ( IDe r i ved d) { 39 d .F (1 ) ; / / I nvokes I Le f t . F 40 ( ( IBase )d ) . F (1 ) ; / / I nvokes I Base .F 41 ( ( I Le f t )d ) . F (1 ) ; / / I nvokes I Le f t . F 42 ( ( IR igh t )d ) . F (1 ) ; / / I nvokes I Base .F 43el miembro I Base .Fest oculto por el miembro I Le f t . F llamada d.F(1) selecciona ILeft.F, aunque IBase.F 45 La 46 44no parece quedar oculta en la ruta de acceso que conduce a IRight. 47La regla intuitiva para la ocultacin en interfaces de herencia mltiple es sencilla: si un miembros est oculto en 48cualquier ruta de acceso, queda oculto en todas las rutas de acceso. Debido a que la ruta de acceso desde

671Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

323

672Especificacin del lenguaje C#

1IDe r i ved hasta I Le f t IBase oculta IBase.F, el miembro tambin queda oculto en la ruta de acceso desde e 2IDerived hasta IRight e IBase. 313.3 Nombres completos de miembros de interfaz 4A menudo se conoce un miembro de interfaz por su nombre completo. El nombre completo de un miembro de 5interfaz se compone del nombre de la interfaz en que se declara el miembro, seguido de un punto y del nombre 6del miembro. El nombre completo de un miembro hace referencia a la interfaz donde se declara. Por ejemplo, 7dadas las declaraciones 8 9 10 12 11 13interface IControl { void Paint(); interface ITextBox: IControl {

14 void SetText(string text); 16el nombre completo de Paint es IControl.Paint y el de SetText es ITextBox.SetText. 15En el ejemplo anterior, no es posible hacer referencia a Paint como ITextBox.Paint. 17 18Cuando una interfaz forma parte de un espacio de nombres, el nombre completo de un miembro de interfaz 19incluye el espacio de nombres. Por ejemplo: 20 21 22 23namespace System { public interface ICloneable {

24Aqu, el nombreobject Clone(); Clone es System.ICloneable.Clone. 27 completo del mtodo 25 2813.4 Implementaciones de interfaces 26Las interfaces pueden implementarse mediante clases y estructuras. Para indicar que una clase o estructura 29 30implementa una interfaz, el identificador de la interfaz se incluye en la lista de clases base de la clase o 31estructura. Por ejemplo: 32 33 34 36 35 37 38 40 39 41 42 43 44673324

interface ICloneable { object Clone(); interface IComparable { int CompareTo(object other); class ListEntry: ICloneable, IComparable { public int CompareTo(object other) {...} }Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

674

Captulo 18 Cdigo no seguro

1Una clase o estructura que implementa una interfaz tambin implementa implcitamente todas las interfaces base 2de dicha interfaz. Esto es cierto aunque la clase o estructura no muestre explcitamente todas las interfaces base 3de la lista de clases base. Por ejemplo: 4 5 6 8 7 9 10 12 11 13 14 15interface IControl { void Paint(); interface ITextBox: IControl { void SetText(string text); class TextBox: ITextBox { public void SetText(string text) {...}

16Aqu, la } 17 clase Tex tBoximplementa I Con t ro e ITextBox. l 1813.4.1 Implementaciones de miembro de interfaz explcitas 19Para los fines de implementar interfaces, una clase o estructura puede declarar implementaciones explcitas de 20miembros de interfaz. Una implementacin explcita de miembro de interfaz es una declaracin de mtodo, 21propiedad, evento o indizador que hace referencia a un nombre completo de miembro de interfaz. Por ejemplo: 22 23 24 26 25 27 28 30 29 31 32 33interface ICloneable { object Clone(); interface IComparable { int CompareTo(object other); class ListEntry: ICloneable, IComparable { int IComparable.CompareTo(object other) {...}

34 } 35Aqu, ICloneable.Clone e IComparable.CompareTo son implementaciones explcitas de miembros de 36interfaz. 37En algunos casos, el nombre de un miembro de interfaz puede no ser apropiado para la clase que lo implementa, 38en cuyo caso puede implementarse con la implementacin explcita de miembros de interfaz. Es probable que 39una clase que implemente una abstraccin de archivo, por ejemplo, implemente una funcin miembro Close que 40tenga el efecto de liberar el recurso de archivo e implemente el mtodo Dispose de la interfaz IDisposable 41mediante la implementacin explcita de miembros de interfaz:42 43 44 45

interface IDisposable { void Dispose(); }

675Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

325

676Especificacin del lenguaje C#

1 2 3 4 5 6 7 8 9 10

class MyFile: IDisposable { void IDisposable.Dispose() { Close(); } public void Close() { // Do what's necessary to close the file System.GC.SuppressFinalize(this); }

}

11No es posible obtener acceso a una implementacin explcita de miembros de interfaz utilizando el nombre 12completo en una llamada a un mtodo, instruccin de acceso a propiedad o acceso a indizador. Slo se puede 13obtener acceso a una implementacin explcita de miembros de interfaz a travs de una instancia de interfaz, en 14cuyo caso se hace referencia a ella por el nombre del miembro. 15Si en una implementacin explcita de miembros de interfaz se incluyen modificadores de acceso o 16modificadores abs t rac,tv i r tua l , override o static, se producirn errores en tiempo de compilacin.

677326

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

678

Captulo 18 Cdigo no seguro

1Las implementaciones explcitas de miembros de interfaz tienen diferentes caractersticas de acceso respecto a 2otros miembros. Dado que este tipo de implementaciones nunca son accesibles por su nombre completo en una 3llamada a un mtodo o una instruccin de acceso a una propiedad, son en cierto sentido privadas. Sin embargo, 4debido a que se puede obtener acceso a ellas a travs de una instancia de propiedad, tambin son en otro sentido 5pblicas. 6Las implementaciones explcitas de miembros de interfaz tienen dos principales objetivos: 7 8 9 10 11 12 13 14 15Puesto que no se puede obtener acceso a ellas por medio de instancias de clase o estructura, permiten excluir las implementaciones de interfaz de la interfaz pblica de una clase o estructura. Esto resulta de especial utilidad cuando una clase o estructura implementa una interfaz interna que no es de inters para ningn consumidor de dicha clase o estructura. Las implementaciones explcitas de miembros de interfaz permiten la eliminacin de la ambigedad en los miembros de interfaz que tienen la misma firma. Sin ellas, una clase o estructura no podra contener diferentes implementaciones de los miembros de interfaz de idntica firma y tipo de valor devuelto; tampoco podra contener ninguna implementacin de los miembros de interfaz de igual firma pero distinto tipo de valor devuelto.

16Para que una implementacin explcita de miembros de interfaz sea vlida, la clase o estructura debe dar nombre 17a una interfaz en su clase base que contenga un miembro cuyo nombre completo, tipo y tipos de parmetro 18coincidan exactamente con los de la implementacin explcita de miembros de interfaz. As, en la clase siguiente 19 20 21 22class Shape: ICloneable { int IComparable.CompareTo(object other) {...} // invalid

23la declaracin de I Comparab le .Compare Toproduce un error en tiempo de compilacin, porque I Comparab le } 24 25no aparece en la lista de clases base de Shape y no es una interfaz base de ICloneable. Igualmente, en las 26declaraciones 27 28 29 31 30 32class Shape: ICloneable { object ICloneable.Clone() {...} class Ellipse: Shape {

33 object ICloneable.Clone() {...} // invalid 35la declaracin de ICloneable.Clone en Ellipse supone un error en tiempo de compilacin, ya que ICloneable 36no aparece expresamente citada en la lista de clases base de Ellipse. 34 37El nombre completo de un miembro de interfaz debe hacer referencia a la interfaz donde se declara. As, en las 38declaraciones 39 40 41 43 42 44 45 46interface IControl { void Paint(); interface ITextBox: IControl { void SetText(string text); 327

679Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

680Especificacin del lenguaje C#

1 2 3 4

class TextBox: ITextBox { void ITextBox.SetText(string text) {...}

5la implementacin explcita de miembro de interfaz de Pa in tdebe escribirse como I Con t ro l . Pa . t } 6 in 713.4.2 Asignacin de interfaces 8Una clase o estructura debe proporcionar implementaciones de todos los miembros de las interfaces enumeradas 9en su lista de clases base. El proceso de localizar implementaciones de miembros de interfaz en una clase o 10estructura de implementacin se conoce como asignacin de interfaz. 11La asignacin de interfaz para una clase o estructura C localiza una implementacin para cada uno de los 12miembros de todas las interfaces especificadas en la lista de clases base de C. La implementacin de un 13miembro de interfaz I.M concreto, donde I es la interfaz donde se declara el miembro M, se determina al 14examinar todas las clases o estructuras S, comenzando desde C y repitiendo el paso para cada clase base 15sucesiva de C, hasta encontrar una coincidencia: 16 17 18 19Si S contiene una declaracin de una implementacin explcita de miembros de interfaz que coincide con I y M, este miembro es la implementacin de I.M. Por otro lado, si S contiene una declaracin de un miembro pblico no esttico que coincide con M, este miembro es la implementacin de I.M.

20Se produce un error en tiempo de compilacin si no es posible localizar implementaciones de todos los 21miembros de cada interfaz especificada en la lista de clases base de C. Observe que los miembros de una 22interfaz incluyen aquellos miembros heredados de sus interfaces base. 23A efectos de la asignacin de interfaz, un miembro de clase A coincide con un miembro de interfaz B cuando: 24 25 26 27 28 29 30 31 33 34 35 36 38 39 40 41681328Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

A y B son mtodos, y el nombre, tipo y listas de parmetros formales de A y B son idnticos. A y B son propiedades, el nombre y tipo de A y B son idnticos y A posee los mismos descriptores de acceso que B (se permite que A tenga descriptores de acceso adicionales si no es una implementacin explcita de

miembros de interfaz).A y B son eventos, y el nombre y tipo de A y B son idnticos. A y B son indizadores, el tipo y listas de parmetros formales de A y B son idnticos y A posee los mismos descriptores de acceso que B (se permite que A tenga descriptores de acceso adicionales si no es una

implementacin explcita de miembros de interfaz). Las implementaciones explcitas de miembros de interfaz tienen prioridad sobre los dems miembros de una misma clase o estructura a la hora de determinar el miembro de clase o estructura que implementa a un miembro de interfaz. Ni los miembros no pblicos ni los no estticos participan en la asignacin de interfaz.

32Algunas de las principales implicaciones del algoritmo de asignacin de interfaz son:

37En el siguiente ejemplo:interface ICloneable { object Clone();

682

Captulo 18 Cdigo no seguro

1 2 3 4

class C: ICloneable { public object Clone() {...}

5el miembro I C l oneab le .C lone C se convierte en la implementacin de Clone en ICloneable, porque las } 6 de 7implementaciones explcitas de miembros de interfaz tienen prioridad sobre los dems miembros. 8Si una clase o estructura implementa dos o ms interfaces que contienen un miembro con el mismo nombre, tipo 9y tipos de parmetros, es posible asignar cada uno de los miembros de interfaz a un nico miembro de clase o 10estructura. Por ejemplo: 11 12 13 15 14 16 17 19 18 20interface IControl { void Paint(); interface IForm { void Paint(); class Page: IControl, IForm {

21 public void Paint() {...} 23Aqu, los mtodos Paint de IControl e IForm se asignan al mtodo Paint en Page. Naturalmente, tambin es 24 22posible trabajar con diferentes implementaciones explcitas de miembros de interfaz para los dos mtodos. 25Si una clase o estructura implementa una interfaz que contiene miembros ocultos, necesariamente debern 26implementarse algunos miembros por medio de la implementacin explcita de miembros de interfaz. Por 27ejemplo: 28 29 30 32 31 33interface IBase { int P { get; } interface IDerived: IBase {

34 new int P(); 36Una implementacin de esta interfaz requerira al menos una implementacin explcita de miembros de interfaz, 37 35y tomara una de las siguientes formas: 38 39 40 41 42 43 44 45 46 47} 329 class C: IDerived { int IDerived.P() {...} } class C: IDerived { int IDerived.P() {...}

683Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

684Especificacin del lenguaje C#

1 2 3 4 5

class C: IDerived { public int P() {...} }

685330

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

686

Captulo 18 Cdigo no seguro

1Cuando una clase implementa varias interfaces con la misma interfaz base, slo puede haber una 2implementacin de la interfaz base. En el siguiente ejemplo: 3 4 5 7 6 8 9 11 10 12 13 15 14 16 17 18 19interface IControl { void Paint(); interface ITextBox: IControl { void SetText(string text); interface IListBox: IControl { void SetItems(string[] items); class ComboBox: IControl, ITextBox, IListBox { void ITextBox.SetText(string text) {...} void IListBox.SetItems(string[] items) {...}

20no es posible que haya implementaciones independientes para el miembro de interfaz I Con t ro que figura en la } 21 l 22lista de clases base, el miembro I Con t ro heredado por ITextBox y el miembro IControl heredado por IListBox. l 23De hecho, no existe una identidad separada para estas interfaces. En realidad, las implementaciones de ITextBox 24e IListBox comparten la misma implementacin de IControl, y se considera que ComboBox nicamente 25implementa tres interfaces: IControl, ITextBox e IListBox. 26Los miembros de una clase base participan en la asignacin de interfaz. En el siguiente ejemplo: 27 28 29 31 30 32 33 34 35 36 37interface Interface1 { void F(); class Class1 { public void G() {} } class Class2: Class1, Interface1 {

38 new public void G() {} 40el mtodo F de Class1 se utiliza en la implementacin de Interface1 en Class2. 39 4113.4.3 Herencia de implementacin de interfaces 42Una clase hereda todas las implementaciones de interfaz proporcionadas por sus clases base. 43Sin reimplementar explcitamente una interfaz, una clase derivada no puede alterar de ningn modo las 44asignaciones de interfaz que hereda de sus clases base. Por ejemplo, en las declaraciones

687Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

331

688Especificacin del lenguaje C#

1 2 3 5 4 6 7 9 8 10

interface IControl { void Paint(); class Control: IControl { public void Paint() {...} class TextBox: Control {

11 new public void Paint() {...} 13el mtodo Pa in tde Tex tBoxoculta el mtodo Paint de Control, pero no altera la asignacin de Control.Paint a 14 12IControl.Paint, y las llamadas a Paint a travs de instancias de clase y de interfaz tendrn los efectos siguientes: 15 16 17 18Control c = new Control(); TextBox t = new TextBox(); IControl ic = c; IControl it = t;

19 c.Paint(); // invokes Control.Paint(); 23Sin embargo, cuando se asigna un mtodo de interfaz a un mtodo virtual de una clase, es posible que las clases 20derivadas reemplacen el mtodo virtual y alteren la implementacin de la interfaz. Por ejemplo, al rescribir las 24 25declaraciones anteriores de esta manera 21 22 26 27 28 30 29 31 32 34 33 35interface IControl { void Paint(); class Control: IControl { public virtual void Paint() {...} class TextBox: Control {

36 public override void Paint() {...} 38se observarn los siguientes efectos 37 39 Control c = new Control(); 40 41 42TextBox t = new TextBox(); IControl ic = c; IControl it = t;

43 c.Paint(); // invokes Control.Paint(); 47Dado que las implementaciones explcitas de miembros de interfaz no pueden declararse como virtuales, no es 44posible reemplazarlas. Sin embargo, es perfectamente vlido que una implementacin explcita de miembros de 48 45 46689332Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

690

Captulo 18 Cdigo no seguro

1interfaz llame a otro mtodo, y se puede declarar dicho mtodo como virtual para permitir que las clases 2derivadas lo reemplacen. Por ejemplo: 3 4 5 7 6 8 9 10 11 12 13interface IControl { void Paint(); class Control: IControl { protected virtual void PaintControl() {...} } class TextBox: Control {

14 protected override void PaintControl() {...} 16Aqu, las clases derivadas de Cont ro lpueden especializar la implementacin de I Con t ro l . Pa in t reemplazando 17 15el mtodo PaintControl. 1813.4.4 Reimplementacin de interfaces 19Una clase que hereda una implementacin de interfaz puede reimplementar la interfaz incluyndola en la lista 20de clases base. 21Una reimplementacin de una interfaz sigue exactamente las mismas reglas de asignacin de interfaz que la 22implementacin inicial de una interfaz. As, la asignacin de interfaz heredada no tiene efecto alguno en la 23asignacin de interfaz especificada para la reimplementacin de la interfaz. Por ejemplo, en las declaraciones 24 25 26 28 27 29 30 32 31 33interface IControl { void Paint(); class Control: IControl { void IControl.Paint() {...} class MyControl: Control, IControl {

34 public void Paint() {} 36el hecho de que Control asigne IControl.Paint a Control.IControl.Paint no afecta a la reimplementacin en 37 35MyControl, que asigna IControl.Paint a MyControl.Paint. 38Las declaraciones heredadas de miembros pblicos y las implementaciones explcitas heredadas de miembros de 39interfaz participan en el proceso de asignacin de interfaz para las interfaces implementadas. Por ejemplo: 40 41 42 43 44 45 46interface IMethods { void F(); void G(); void H(); 333

691Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

692Especificacin del lenguaje C#

1 2 3 4

class Base: IMethods { void IMethods.F() {} void IMethods.G() {}

5 public void H() {} 8 class Derived: Base, IMethods 6 9 { 7 10 public void F() {} 13Aqu, la implementacin de IMe thods en Der ivedasigna los mtodos de interfaz a Derived.F, 11 14Base.IMethods.G, Derived.IMethods.H y Base.I. 12 15Cuando una clase implementa una interfaz, tambin implementa implcitamente todas las interfaces base de 16dicha interfaz. De igual forma, una reimplementacin de una interfaz tambin es implcitamente una 17reimplementacin de todas sus interfaces base. Por ejemplo: 18 19 20 22 21 23 24 26 25 27 28 29 30 31 32 33 34interface IBase { void F(); interface IDerived: IBase { void G(); class C: IDerived { void IDerived.G() {...} } class D: C, IDerived { public void G() {...}

35Aqu, la } 36 reimplementacin de IDerived tambin reimplementa IBase, asignando IBase.F a D.F. 3713.4.5 Interfaces y clases abstractas 38Al igual que una clase no abstracta, una clase abstracta debe proporcionar implementaciones de todos los 39miembros de las interfaces que figuran en su lista de clases base. Sin embargo, una clase abstracta puede asignar 40mtodos de interfaz a mtodos abstractos. Por ejemplo: 41 42 43 44 45693334Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

interface IMethods { void F();

694

Captulo 18 Cdigo no seguro

1 2

abstract class C: IMethods {

3 public abstract void F(); 6 4Aqu, la implementacin de IMe thods asigna F y G a mtodos abstractos, que pueden reemplazarse en clases no 7abstractas que se deriven de C. 5 8Debe observarse que las implementaciones explcitas de miembros de interfaz no pueden ser abstractas, pero s 9pueden llamar a mtodos abstractos. Por ejemplo: 10 11 12 13 15 14 16 17 18 19 20{ void IMethods.G() { GG(); } protected abstract void FF(); protected abstract void GG(); interface IMethods { void F(); abstract class C: IMethods

21 } 22Aqu, las clases no abstractas que se derivan de C deberan reemplazar FF y GG, proporcionando de esa forma la 23propia implementacin de IMethods.

695Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

335

696Especificacin del lenguaje C#

1

14.Enumeraciones

2Un tipo enum es un tipo de valor distintivo (4.1) que declara un conjunto de constantes con nombre. 3En el ejemplo 4 5 6enum Color { Red,

7 Green, 10declara un tipo enum denominado Co lo rcon los miembros Red , Green y Blue. 8 1114.1 Declaraciones de enumeracin 9 12Una declaracin de enumeracin declara un nuevo tipo enum. Una declaracin de enumeracin comienza con la 13palabra clave enum y define su nombre, su tipo de acceso, su tipo subyacente y sus miembros. 14 15 16 17 18 19 20enum-declaration: attributesopt enum-modifiersopt enum identifier enum-baseopt enum-body ;opt enum-base: : integral-type enum-body: { enum-member-declarationsopt } { enum-member-declarations , }

21Cada tipo enum tiene un tipo integral correspondiente denominado tipo subyacente del tipo de enumeracin. 22Este tipo subyacente debe poder representar todos los valores de enumerador definidos en la enumeracin. Una 23declaracin de enumeracin puede declarar explcitamente un tipo subyacente byte, sbyte, short, ushort, int, 24uint, long o ulong. Observe que no se puede utilizar char como tipo subyacente. Una declaracin de 25enumeracin que no declara explcitamente un tipo subyacente tiene int como tipo subyacente. 26En el ejemplo 27 28 29enum Color: long { Red,

30 Green, 33declara una enumeracin con el tipo subyacente long. Un programador podra utilizar un tipo subyacente long, 31 34como en el ejemplo, para habilitar el uso de valores que estn en el intervalo de long, pero no en el de int, o 35para preservar esta opcin para el futuro. 32

697336

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

698

Captulo 18 Cdigo no seguro

114.2 Modificadores de enumeracin 2Una declaracin de enumeracin (enum-declaration) puede incluir opcionalmente una secuencia de 3modificadores de enumeracin: 4 5 6 7 8 9 10 11 12enum-modifiers: enum-modifier enum-modifiers enum-modifier enum-modifier:new pub l i c pro tec ted i n te rna l private

13Cuando el mismo modificador aparece varias veces en una declaracin de enumeracin, se produce un error en 14tiempo de compilacin. 15Los modificadores de una declaracin de enumeracin tienen el mismo significado que los de las declaraciones 16de clases (10.1.1). Observe, sin embargo, que los modificadores abstract y sealed no estn permitidos en una 17declaracin de enumeracin. Las enumeraciones no pueden ser abstractas y no permiten derivacin. 1814.3 Miembros de enumeracin 19El cuerpo de una declaracin de tipo enum define cero o varios miembros de enumeracin, que son las 20constantes con nombre del tipo enum. No puede haber dos miembros de enumeracin con el mismo nombre. 21 22 23 24 25 26enum-member-declarations: enum-member-declaration enum-member-declarations , enum-member-declaration enum-member-declaration: attributesopt identifier attributesopt identifier = constant-expression

27Cada miembro de enumeracin tiene un valor asociado constante. El tipo de este valor es el tipo subyacente de 28la enumeracin contenedora. El valor constante de cada miembro de enumeracin debe estar comprendido en el 29intervalo del tipo subyacente de la enumeracin. En el ejemplo 30 31 32enum Color: uint { Red = -1,

33 Green = -2, 36se produce un error en tiempo de compilacin, porque los valores constantes -1, -2 y 3 no estn en el intervalo 34del tipo integral subyacente uint. 37 35Varios miembros de enumeracin pueden compartir el mismo valor asociado. En el ejemplo 38 39 40 41 42 43699Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

enum Color { Red,

337

700Especificacin del lenguaje C#

1

Max = Blue

2muestra } enumeracin en la que dos de sus miembros (B lue y Max ) tienen el mismo valor asociado. 3 una 4El valor asociado de un miembro de enumeracin se asigna bien implcita o explcitamente. Si la declaracin del 5miembro de enumeracin tiene un inicializador de expresin constante (constant-expression), el valor de dicha 6expresin, convertido de manera implcita al tipo subyacente de la enumeracin, es el valor asociado del 7miembro de enumeracin. Si la declaracin del miembro de enumeracin no tiene inicializador, su valor 8asociado se establece de forma implcita, de la siguiente forma: 9 10 11 12 13Si el miembro de enumeracin es el primero de los declarados en el tipo enum, su valor asociado es cero. En cualquier otro caso, el valor asociado del miembro de enumeracin se obtiene al aumentar en uno el valor asociado del miembro de enumeracin precedente en el cdigo. Este valor aumentado debe estar incluido en el intervalo de valores que puede representar el tipo subyacente, en caso contrario, se produce un error de compilacin.

14En el ejemplo 15 us ing Sys tem; 16 enu Co lo r m 17 { 18 Red , 19 Green = 10 , 20 B lue 22 c lass Tes t 21 23 { 24 s ta t i c vo id Main ( ) { 25 Conso le .Wr i teL ine (S t r i ngFromCo lo r (Co lo r .Red) ) ; 26 Conso le .Wr i teL ine (S t r i ngFromCo lo r (Co lo r .G reen) ) ; 27 Conso le .Wr i teL ine (S t r i ngFromCo lo r (Co lo r .B lue ) ) ; 29 s ta t i c s t r i ng St r i ngFromCo lo r (Co lo r c ) { 28 30 sw i t ch ( c ) { 31 case Co lo r .Red : 32 re tu rn St r i ng . Fo rmat ( "Red = {0}" , ( i n t ) c ) ; 33 case Co lo r .G reen : 34 re tu rn St r i ng . Fo rmat ( "Green = {0}" , ( i n t ) c ) ; 35 case Co lo r .B lue : 36 re tu rn St r i ng . Fo rmat ( "B lue = {0}" , ( i n t ) c ) ; 37 de fau l t : 38 re tu rn " I nva l i d co lo r " ; 39 } 40 } 41 42se imprimen los nombres de los miembros de enumeracin y sus valores asociados. El resultado es: 43 Red = 0 44 Green = 10 45 B lue = 11 46por las siguientes razones:701338

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

702

Captulo 18 Cdigo no seguro

1 2 3 4 5

al miembro de enumeracin Red se le asigna automticamente el valor cero (puesto que no tiene inicializador y es el primer miembro de enumeracin); al miembro de enumeracin Green se le asigna explcitamente el valor 10 ; y al miembro de enumeracin B lue se le asigna automticamente el valor del miembro que le precede en el cdigo ms uno.

6El valor asociado de un miembro de enumeracin no puede, directa ni indirectamente, usar el valor de su propio 7miembro de enumeracin asociado. Aparte de esta restriccin de circularidad, los inicializadores de miembros 8de enumeracin pueden hacer referencia con libertad a otros inicializadores de miembros de enumeracin, sin 9importar su posicin en el cdigo. Dentro de un inicializador de miembro de enumeracin, los valores de los 10dems miembros de enumeracin siempre se tratan como si tuvieran el tipo de su tipo subyacente, de manera 11que no son necesarias las conversiones de tipos al hacer referencia a otros miembros de enumeracin. 12En el ejemplo 13 14enum Circular {

15 A = B, 18 16se produce un error en tiempo de compilacin, porque las declaraciones de A y B son circulares. Es decir, que A 19depende de B explcitamente y B depende de A implcitamente. 17 20Los miembros de enumeracin se denominan y se establece su mbito de manera exactamente anloga a los 21campos pertenecientes a clases. El mbito de un miembro de enumeracin es el cuerpo de su tipo enum 22contenedor. Dentro de ese mbito, se puede hacer referencia a los miembros de enumeracin por su nombre 23simple. Desde cualquier otra ubicacin del cdigo, debe calificarse el nombre de un miembro de enumeracin 24con el nombre de su tipo enum. Los miembros de enumeracin no tienen ninguna accesibilidad declarada: un 25miembro de enumeracin es accesible si el tipo enum que lo contiene es accesible. 2614.4 Tipo System.Enum 27El tipo System.Enum es la clase base abstracta de todos los tipos enum (es distinta y diferente del tipo 28subyacente del tipo enum), y los miembros heredados de System.Enum estn disponibles en cualquier tipo 29enum. Existe una conversin boxing (4.3.1) de cada tipo enum a System.Enum y tambin existe una 30conversin unboxing (4.3.2) de System.Enum a cualquier tipo enum. 31Observe que Sys tem.Enum no es en s mismo un tipo enum (enum-type). Al contrario, es un tipo de clase 32(class-type) del que se derivan todos los tipos enum (enum-types). El tipo Sys tem.Enum hereda del tipo 33System.ValueType (4.1.1), el cual, a su vez, hereda del tipo object. En tiempo de ejecucin, un valor de tipo 34System.Enum puede ser null o una referencia a un valor boxed de cualquier tipo enum. 3514.5 Valores y operaciones de enumeracin 36Cada tipo enum define un tipo distintivo; es necesaria una conversin explcita de enumeracin (6.2.2) para 37convertir un tipo enum a un tipo integral, o para convertir dos tipos enum. El conjunto de valores que puede 38tomar un tipo enum no est limitado por sus miembros de enumeracin. En concreto, cualquier valor del tipo 39subyacente de una enumeracin puede convertirse al tipo enum, y es un valor aceptado y distintivo de dicho tipo 40enum. 41Los miembros de enumeracin tienen el tipo de su tipo enum contenedor (salvo dentro de otros inicializadores 42de miembros de enumeracin: vea la seccin 14.3). El valor de un miembro de enumeracin declarado en el 43tipo enum E con un valor v asociado es (E)v.

703Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

339

704Especificacin del lenguaje C#

1Los operadores siguientes se pueden utilizar en los valores de tipos de enumeracin: == , !=, , = (7.9.5), binario + (7.7.4), binario - (7.7.5), ^, &, | (7.10.2), ~ (7.6.4), ++, -- (7.5.9 y 7.6.5), y 3sizeof (18.5.4). 4Cada tipo enum automticamente deriva de la clase Sys tem.Enum (que, a su vez, deriva de 5Sys tem.Va lueType object). As, los mtodos heredados y propiedades de esta clase se pueden utilizar en los y 6valores de un tipo de enumeracin.

705340

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

706

Captulo 18 Cdigo no seguro

1

15.Delegados

2Los delegados habilitan escenarios de programacin que otros lenguajes, como C++, Pascal y Modula, han 3resuelto mediante punteros a funcin. A diferencia de los punteros a funcin de C++, los delegados estn 4completamente orientados a objetos y, a diferencia de los punteros a funciones miembro de C++, los delegados 5encapsulan a la vez una instancia de objeto y un mtodo. 6Una declaracin de delegado define una clase que se deriva de la clase Sys tem.De legate Una instancia de . 7delegado encapsula una lista de llamadas, que consiste en una lista de uno o varios mtodos, a cada uno de los 8que se hace referencia como una entidad a la que se puede llamar. Para mtodos de instancia, una entidad a la 9que se puede llamar consta de una instancia y un mtodo de la instancia. Para los mtodos estticos, una entidad 10a la que se puede llamar est formada solamente por un mtodo. Invocar a una instancia delegada con un 11conjunto adecuado de argumentos, hace que se invoque a cada una de las entidades del delegado a las que se 12puede llamar, con el conjunto de argumentos dado. 13Una propiedad interesante y til de una instancia de delegado es que no necesita conocer las clases de los 14mtodos a los que encapsula; lo nico que importa es que los mtodos sean compatibles (15.1) con el tipo del 15delegado. Esto hace que los delegados sean perfectos para una invocacin annima. 1615.1 Declaraciones de delegados 17Una declaracin de delegado (delegate-declaration) es una declaracin de tipo (type-declaration) (9.5) que 18declara un nuevo tipo delegado. 19 20 21 22 23 24 25 26 27 28 29 30delegate-declaration: attributesopt delegate-modifiersopt de legate return-type identifier ( formal-parameter-listopt ) ; delegate-modifiers: delegate-modifier delegate-modifiers delegate-modifier delegate-modifier:new public protected internal private

31Cuando el mismo modificador aparece varias veces en una declaracin de delegado, se produce un error en 32tiempo de compilacin. 33El modificador new slo est permitido en delegados declarados dentro de otro tipo, en cuyo caso, ste 34especifica que tal delegado oculta un miembro heredado con el mismo nombre, como se describe en la seccin 3510.2.2. 36Los modificadores public, protected, internal y private controlan el acceso del tipo delegado. Dependiendo 37del contexto en el que ocurra la declaracin de delegado, algunos de estos modificadores pueden no estar 38permitidos (3.5.1). 39El nombre del tipo delegado es el identificador (identifier).

707Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

341

708Especificacin del lenguaje C#

1La lista opcional de parmetros formales (formal-parameter-list) especifica los parmetros del delegado, y el 2tipo de valor devuelto (return-type) corresponde al delegado. Un mtodo y un tipo delegado son compatibles si 3se cumplen las dos condiciones siguientes: 4 5 6Tienen el mismo nmero de parmetros, con los mismos tipos, en el mismo orden y los mismos modificadores de parmetro. Sus tipos de valor devuelto son iguales.

7Los tipos delegados en C# son equivalentes en su denominacin, no estructuralmente. En concreto, dos tipos 8delegados diferentes con la misma lista de parmetros y el mismo tipo de valor devuelto se consideran 9diferentes. Sin embargo, las instancias de dos tipos delegados distintos pero estructuralmente equivalentes se 10pueden considerar iguales (7.9.8). 11Por ejemplo: 12 13 14 15 17 16 18 19 20 21 22 23delegate int D1(int i, double d); class A { public static int M1(int a, double b) {...} class B { public static int M1(int f, double g) {...} public static void M2(int k, double l) {...} public static int M3(int g) {...} public static void M4(int g) {...}

24Los tipos delegados D1 y D2 son compatibles con los mtodos A.M1 y B.M1, ya que poseen el mismo tipo de } 25 26valor devuelto y la misma lista de parmetros; sin embargo, son tipos diferentes, por lo cual no son 27intercambiables entre s. Los tipos delegados D1 y D2 son incompatibles con los mtodos B.M2, B.M3 y B.M4, 28ya que poseen diferentes tipos de valor devuelto o diferentes listas de parmetros. 29La nica forma de declarar un tipo delegado es a travs de una declaracin de delegado (delegate-declaration). 30Un tipo delegado es un tipo de clase derivada de Sys tem.De legate Los tipos delegados son sea ledde manera . 31implcita, por lo que no est permitido derivar ningn tipo de un tipo delegado. Tampoco se permite derivar un 32tipo de clase no delegado a partir de System.Delegate. Observe que System.Delegate no es en s mismo un 33tipo delegado; es un tipo de clase del cual se derivan todos los tipos delegados. 34C# proporciona una sintaxis especial para la creacin y llamada de instancias de delegado. Salvo para la 35creacin de instancias, cualquier operacin que pueda aplicarse a una clase o instancia de clase tambin puede 36aplicarse a una clase o instancia de delegado, respectivamente. En particular, es posible obtener acceso a los 37miembros del tipo System.Delegate a travs de la sintaxis habitual de acceso a miembros. 38El conjunto de mtodos encapsulados por una instancia de delegado se denomina lista de llamadas. Cuando se 39crea una instancia de delegado (15.2) a partir de un nico mtodo, encapsula el mtodo y su lista de llamadas 40contiene una sola entrada. Sin embargo, cuando se combinan dos instancias de delegado no null, sus listas de 41llamadas se concatenan, por orden de operando izquierdo a operando derecho, para formar una nueva lista de 42llamadas, que contiene dos o ms entradas.

709342

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

710

Captulo 18 Cdigo no seguro

1Los delegados se combinan utilizando los operadores binarios + (7.7.4) y += (7.13.2). Se puede quitar un 2delegado de una combinacin de delegados utilizando los operadores binarios - (7.7.5) y -= (7.13.2). Los 3delegados se pueden comparar para comprobar si hay igualdad (7.9.8). 4El ejemplo siguiente muestra la creacin de instancias de un nmero de delegados y sus correspondientes listas 5de llamadas: 6 7 8 9 10 11 12 13 14 15 16delegate void D(int x); class C { public static void M2(int i) {...} } class Test { static void Main() { D cd1 = new D(C.M1); D cd2 = new D(C.M2); // M1 // M2

17 D cd3 = cd1 + cd2; // M1 + M2 21 } 18 22Al crear instancias de cd1 y cd2, cada una de ellas encapsula un mtodo. Cuando se crea una instancia de cd3, 23tiene una lista de llamadas de dos mtodos, M1 y M2, por ese orden. La lista de llamadas de cd4 contiene M1, 19 24M2 y M1, por ese orden. Por ltimo, la lista de llamadas de cd5 contiene M1, M2, M1, M1 y M2, por ese orden. 25 20Para ver ms ejemplos de combinacin (y eliminacin) de delegados, vea la seccin 15.3. 2615.2 Creacin de instancias de delegados 27Una instancia de un delegado se crea mediante una expresin de creacin de delegado (delegate-creation28expression) (7.5.10.3). La instancia de delegado recin creada hace referencia a alguno de los siguientes: 29 30 31 32 33 35 36 37 38 39 40El mtodo esttico a que se hace referencia en la expresin de creacin de delegado (delegate-creationexpression), o bien El objeto de destino (que no puede ser nu l ) y el mtodo de instancia a que se hace referencia en la l expresin de creacin de delegado (delegate-creation-expression), o bien Otro delegado.

34Por ejemplo:de legate vo id D( in t x ) ; c lass C { pub l i c s ta t i c vo id M1( in t i ) { . . . } pub l i c vo id M2( in t i ) { . . . }

711Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

343

712Especificacin del lenguaje C#

1 2 3 4 5 6 7 8 9

class Test { static void Main() { D cd1 = new D(C.M1); C t = new C(); D cd2 = new D(t.M2); // instance method // static method

713344

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

714

Captulo 18 Cdigo no seguro

1Una vez creadas las instancias de delegado, stas siempre hacen referencia al mismo objeto de destino y mtodo. 2Recuerde que, cuando se combinan dos delegados, o se quita uno de ellos en el otro, el resultado es un nuevo 3delegado con su propia lista de llamadas; las listas de llamadas de los delegados combinados o eliminados 4permanecen sin cambios. 515.3 Invocacin de delegados 6C++ proporciona una sintaxis especial para invocar un delegado. Cuando se invoca una instancia de delegado no 7null cuya lista de llamadas contiene un sola entrada, llama a ese mtodo con los mismos argumentos que recibi, 8y devuelve el mismo valor que el mtodo a que se hace referencia. (Vea la seccin 7.5.5.2 para obtener 9informacin detallada sobre la invocacin de delegados.) Si se produce una excepcin durante la llamada a un 10delegado y no se captura dentro del mtodo invocado, la bsqueda de una clusula de excepcin catch contina 11en el mtodo que llam al delegado, como si ese mtodo hubiera llamado directamente al mtodo al que haca 12referencia el delegado. 13La invocacin de una instancia de delegado cuya lista de llamadas contiene varias entradas contina llamando a 14cada uno de los mtodos de la lista, de forma sincrnica, por orden. A cada uno de los mtodos as llamados se 15le pasa el mismo conjunto de argumentos pasados a la instancia de delegado. Si tal invocacin de delegado 16incluye parmetros de referencia (10.5.1.2), cada invocacin de mtodo incluir una referencia a la misma 17variable; los cambios en dicha variable que realice un mtodo de la lista de llamadas sern visibles para todos 18los mtodos situados a continuacin en la lista. Si la invocacin de delegado incluye parmetros de salida o un 19valor devuelto, su valor final vendr dado por la invocacin del ltimo delegado de la lista. 20Si se produce una excepcin durante la llamada a dicho delegado y no se captura dentro del mtodo invocado, la 21bsqueda de una clusula de excepcin catch contina en el mtodo que llam al delegado, y no se invoca 22ninguno de los mtodos situados a continuacin en la lista de llamadas. 23Intentar invocar una instancia de delegado cuyo valor es null provoca una excepcin del tipo 24Sys tem.Nu l lRe fe renceExcept i.on 25En el siguiente ejemplo se muestra cmo crear instancias, combinar, quitar e invocar delegados: 26 27 28 29 30 31 33 32 34 35 36 37 38 40 39 41 42 43 45 44 46using System; delegate void D(int x); class C { public static void M1(int i) { public static void M2(int i) { Console.WriteLine("C.M2: " + i); public void M3(int i) { Console.WriteLine("C.M3: " + i); } class Test { static void Main() { D cd2 = new D(C.M2); cd2(-2); // call M2 345

715Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

716Especificacin del lenguaje C#

1 2 3 4 5 6 7 9 8 10 11 12 13 14 15 16 17 18 19

D cd3 = cd1 + cd2; cd3(10); cd3 += cd1; cd3(20); C c = new C(); cd3 += cd4; cd3 -= cd1; cd3(40); cd3 -= cd4; cd3(50); cd3 -= cd2; cd3(60); cd3 -= cd2; cd3(60); cd3 -= cd1; // cd3(70); cd3 -= cd1; // call M1 then M2 // call M1, M2, then M1

D cd4 = new D(c.M3); // remove last M1 // call M1, M2, then M3 // call M1 then M2 // call M1 // impossible removal is benign // call M1 // invocation list is empty so cd3 is null // System.NullReferenceException thrown // impossible removal is benign

20 } 22Tal como se muestra en la instruccin cd3 += cd1;, un delegado puede aparecer varias veces en una lista de 21 23llamadas. En este caso, se le llama una vez por cada aparicin. En una lista de llamadas como esta, cuando se 24quita el delegado, la ltima aparicin en la lista es la que se elimina realmente.; 25Inmediatamente antes de la ejecucin de la instruccin final, cd3 - = cd1el delegado cd3 hace referencia a una 26lista de llamadas vaca. Intentar quitar un delegado de una lista vaca (o quitar un delegado no existente de una 27lista que no est vaca) no es ningn error.

28El resultado producido es el siguiente: 29 30 31 32 33 34 35 36 37 38 39 40717346

C.M1: -1 C.M2: -2 C.M1: 10 C.M2: 10 C.M1: 20 C.M2: 20 C.M1: 20 C.M1: 30 C.M2: 30 C.M1: 30 C.M3: 30

41

42 43

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

718

Captulo 18 Cdigo no seguro

1

16.Excepciones

2Las excepciones de C# proporcionan una forma estructurada, uniforme y con seguridad de tipos de controlar 3situaciones de error del sistema y de las aplicaciones. El mecanismo de excepciones de C# es bastante similar al 4de C++, pero con unas cuantas diferencias importantes: 5 6 7 8 9 10 11 12En C#, todas las excepciones deben estar representadas por una instancia de un tipo de clase derivado de Sys tem.Except i onEn C++, cualquier valor de cualquier tipo puede utilizarse para representar una . excepcin. En C#, puede utilizarse un bloque finally (8.10) para crear cdigo de terminacin que se ejecute en condiciones normales y excepcionales. Ese tipo de cdigo es difcil de escribir en C++ sin duplicar cdigo. En C#, las excepciones del nivel de sistema, como desbordamiento, divisin por cero o eliminaciones de referencia nulas, tienen clases de excepcin bien definidas y estn al mismo nivel que los escenarios de error de aplicaciones.

1316.1 Causas de excepciones 14Una excepcin se puede iniciar de dos formas diferentes. 15 16 17 18 19 20 21Una instruccin th row (8.9.5) inicia una excepcin de manera inmediata e incondicional. El control nunca llega a la instruccin que sigue inmediatamente a th row . Algunas situaciones excepcionales que pueden surgir durante el procesamiento de instrucciones y expresiones de C# provocan una excepcin en ciertas circunstancias cuando no es posible completar normalmente una operacin. Por ejemplo, una operacin de divisin por cero (7.7.2) inicia una excepcin Sys tem.D iv ideByZeroExcept i on el denominador es cero. Vea la 16.4 para obtener una lista de las si diferentes excepciones que pueden producirse de esta forma.

2216.2 Clase System.Exception 23La clase Sys tem.Except i on el tipo base de todas las excepciones. Esta clase tiene unas cuantas propiedades es 24a resaltar que comparten todas las excepciones: 25 26 27 28 29 30 31Message es una propiedad de slo lectura de tipo s t r i ng contiene una descripcin legible por el que

hombre de la causa que provoc la excepcin.I nne rExcept i on una propiedad de slo lectura de tipo Except i on Si su valor no es null, se refiere a la es .

excepcin que caus la excepcin actual, es decir, que la excepcin actual se inici en un bloque catch que controlaba la excepcin InnerException. En cualquier otro caso, su valor es null, lo que indica que esta excepcin no fue causada por otra excepcin. El nmero de objetos de excepcin encadenados de esta forma puede ser arbitrario.

32El valor de estas propiedades puede especificarse en las llamadas al constructores de instancia de 33System.Exception.

719Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

347

720Especificacin del lenguaje C#

116.3 Cmo controlar excepciones 2Las excepciones se controlan mediante una excepcin t r y(8.10). 3Cuando se produce una excepcin, el sistema busca la clusula ca tch ms prxima que controla la excepcin, 4segn lo determina el tipo de la excepcin en tiempo de ejecucin. En primer lugar, se busca una instruccin t r y 5contenedora en el mtodo actual, y se consideran las clusulas catch asociadas de la instruccin try segn su 6ordenacin. Si ese primer paso falla, se busca el mtodo que llam al mtodo actual en una instruccin try que 7contenga el punto de la llamada al mtodo actual. Esta bsqueda contina hasta encontrar una clusula catch 8que puede controlar la excepcin actual, denominando una clase de excepcin que sea de la misma clase o clase 9base del tipo en tiempo de ejecucin de la excepcin iniciada. Una clusula catch que no denomina ninguna 10clase de excepcin puede controlar cualquier excepcin. 11Una vez hallada una clusula catch coincidente, el sistema se prepara para transferir el control a la primera 12instruccin de la clusula catch. Antes de comenzar la ejecucin de la clusula catch, el sistema ejecuta, por 13orden, todas las clusulas finally asociadas a instrucciones try cuyo nivel de anidamiento sea mayor que el de la 14que captur la excepcin. 15De no encontrarse ninguna clusula catch coincidente, se produce una de estas dos circunstancias: 16 17 18 19 20 21Si la bsqueda de una clusula catch coincidente llega hasta un constructor esttico (10.11) o un inicializador de campo esttico, se inicia una excepcin System.TypeInitializationException en el punto donde se desencaden la llamada al constructor esttico. La excepcin interna de System.TypeInitializationException contiene la excepcin iniciada en un principio. Si la bsqueda de clusulas catch coincidentes llega hasta el cdigo que inici el subproceso, termina la ejecucin del mismo. El impacto de esta terminacin se define segn la implementacin.

22Las excepciones que se producen durante la ejecucin de un destructor merecen especial atencin. Si se produce 23una excepcin durante la ejecucin de un destructor y la excepcin no es capturada, se termina la ejecucin de 24dicho destructor y se llama al destructor de la clase base (si existe). Si no hay clase base (como ocurre con el 25tipo object) o no hay un destructor de clase base, se descarta la excepcin. 2616.4 Clases de excepcin comunes 27A continuacin se muestran las excepciones iniciadas por algunas operaciones de C#.28

721348

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

722

Captulo 18 Cdigo no seguro

System.ArithmeticException

Clase base de las excepciones producidas durante operaciones aritmticas, como Sys tem.D iv ideByZeroExcept i on y Sys tem.Over f l owExcept i on . Se inicia cuando una operacin de almacenamiento en una matriz falla porque el tipo real del elemento almacenado es incompatible con el tipo de la matriz. Se inicia cuando se produce un intento de dividir un valor integral por cero. Se inicia cuando se produce un intento de indizar una matriz por medio de un ndice menor que cero o situado fuera de los lmites de la matriz. Se inicia cuando una conversin explcita de un tipo o interfaz base a un tipo derivado da un error en tiempo de ejecucin. Se inicia cuando se utiliza una referencia nu l lde manera que hace obligatorio el objeto al que se hace referencia. Se inicia cuando falla un intento de asignar memoria a travs de new . Se inicia cuando una operacin aritmtica en un contexto checked produce un desbordamiento. Se inicia cuando se agota la pila de excepciones debido a la existencia de demasiadas llamadas de mtodo pendientes; suele indicar un nivel de recursividad muy profundo o ilimitado. Se inicia cuando un constructor esttico inicia una excepcin sin que haya clusulas ca tch para capturarla.

System.ArrayTypeMismatchException

System.DivideByZeroException System.IndexOutOfRangeException

System.InvalidCastException

System.NullReferenceException

System.OutOfMemoryException System.OverflowException System.StackOverflowException

System.TypeInitializationException

29

723Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

349

724Especificacin del lenguaje C#

1

17.Atributos

2Gran parte del lenguaje C# permite al programador especificar informacin declarativa acerca de las entidades 3que se definen en el programa. Por ejemplo, la accesibilidad de un mtodo en una clase se especifica al 4decorarlo con los modificadores de mtodo (method-modifiers) pub l i c pro tec tedinternal y private. , , 5C# permite a los programadores inventar nuevas clases de informacin declarativa, denominadas atributos. Los 6programadores pueden entonces asociar atributos a varias entidades de programa y recuperar la informacin de 7atributos en un entorno en tiempo de ejecucin. Por ejemplo, un marco de trabajo podra definir un atributo 8He lpAt t r i bu te se pueda colocar en ciertos elementos del programa, como clases y mtodos, para que 9proporcionar una asignacin o correspondencia entre dichos elementos y su documentacin. 10Los atributos se definen mediante la declaracin de clases de atributo (17.1), que pueden contener parmetros 11posicionales y con nombre (17.1.2). Los atributos se asocian a entidades de un programa de C# mediante las 12especificaciones de atributos (17.2), y pueden recuperarse en tiempo de ejecucin como instancias de atributo 13(17.3). 1417.1 Clases de atributo 15Una clase de atributo es una clase que se deriva de la clase abstracta Sys tem.At t r i bu , ya sea directa o te 16indirectamente. La declaracin de una clase de atributo define un nuevo tipo de atributo que se puede insertar en 17una declaracin. Por convencin, las clases de atributos se denominan con el sufijo At t r i bu te usos de un . Los 18atributo pueden incluir u omitir este sufijo. 1917.1.1 Uso de los atributos 20El atributo At t r i bu teUsage (17.4.1) se utiliza para describir cmo se puede utilizar una clase de atributo. 21At t r i bu teUsage posee un parmetro posicional (17.1.2) que habilita a una clase de atributo para especificar 22los tipos de declaraciones en que se puede utilizar. En el ejemplo 23 us ing Sys tem; 24 [A t t r i bu teUsage(At t r i bu te Ta rge ts .C lass | At t r i bu te Ta rge ts . I n te r face ) ] 25 pub l i c c lass S imp leAt t r i bu te : At t r i bu te 26 { 27 ... 28se define una clase de atributo denominada SimpleAttribute que se puede colocar en declaraciones de clase 29 30(class-declarations) y en declaraciones de interfaz (interface-declarations). En el ejemplo 31 [S imp le ] c lass C lass1 { . . . } 32 [S imp le ] i n te r face I n te r face1 { . . . } 33muestra varios usos del atributo S imp le. Si bien el atributo se define con el nombre S imp leAt t r i bu ,te cuando 34se utiliza puede omitirse el sufijo Attribute, dando como resultado el nombre corto Simple. As, el ejemplo 35anterior es semnticamente equivalente al que se muestra a continuacin: 36 37[S imp leAt t r i bu te ] c lass C lass1 { . . . } [S imp leAt t r i bu te ] i n te r face I n te r face1 { . . . }

725350

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

726

Captulo 18 Cdigo no seguro

1At t r i bu teUsage tiene un parmetro con nombre (17.1.2) denominado A l l owMu l t i p ,le indica si puede que 2especificarse el atributo ms de una vez para una entidad dada. Si AllowMultiple para una clase de atributo es 3true, se trata de una clase de atributo de uso mltiple y se puede especificar ms de una vez en una entidad. Si 4AllowMultiple para una clase de atributo es false o no est especificado, se trata de una clase de atributo de uso 5nico y se puede especificar como mucho una vez en una entidad. 6En el ejemplo 7 8 9 10 12 11 13 14 15 16using System; [AttributeUsage(AttributeTargets.Class, AllowMultiple = true)] public class AuthorAttribute: Attribute { public AuthorAttribute(string name) { this.name = name; public string Name { get { return name; }

17 } 19define una clase de atributo de uso mltiple de nombre AuthorAttribute. En el ejemplo 18 20 [Author("Brian Kernighan"), Author("Dennis Ritchie")] 21class Class1

22 { 25muestra una declaracin de clase con dos usos del atributo Author. 23

26AttributeUsage tiene otro parmetro con nombre denominado Inherited, que especifica si el atributo, cuando 24 27se especifica en una clase base, tambin es heredado por las clases que se derivan de esta clase base. Si 28Inherited para una clase de atributo es true, se hereda dicho atributo. Si Inherited para una clase de atributo es 29false, dicho atributo no se hereda. Si no se especifica, su valor predeterminado es true. 30Una clase de atributo X sin atributo AttributeUsage asociado, como en 31 using System; 32 class X: Attribute {...} 33equivale a lo siguiente: 34 35 36 37using System; [AttributeUsage( AttributeTargets.All, AllowMultiple = false,

38 Inherited = true) 41 3917.1.2 Parmetros posicionales y con nombre 42Las clases de atributo pueden tener parmetros posicionales y parmetros con nombre. Cada constructor de 40 43instancia pblico de una clase de atributo define una secuencia vlida de parmetros posicionales para esa clase

727Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

351

728Especificacin del lenguaje C#

1de atributo. Cada campo o propiedad de lectura y escritura pblica y no esttica de una clase de atributo define 2un parmetro con nombre para la clase de atributo.

729352

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

730

Captulo 18 Cdigo no seguro

1En el ejemplo 2 3 4 5 6 9 7using System; [AttributeUsage(AttributeTargets.Class)] public class HelpAttribute: Attribute { public HelpAttribute(string url) { public string Topic { get {...} set {...} public string Url { get {...} // Positional parameter // Named parameter

10 8 11 13 12 14

15 } 17se define una clase de atributo denominada He lpAt t r i bu te posee un parmetro posicional, ur ly un que 18parmetro con nombre, Topic. Si bien es no esttica y pblica, la propiedad Url no define un parmetro con 16 19nombre porque no es de lectura y escritura. 20Esta clase de atributo podra utilizarse de la manera siguiente: 21 22 23 24 26 25 27 28[Help("http://www.mycompany.com/.../Class1.htm")] class Class1 { [Help("http://www.mycompany.com/.../Misc.htm", Topic = "Class2")] class Class2 {

2917.1.3 Tipos de parmetros de atributos 31 30Los tipos de los parmetros posicionales y con nombre de una clase de atributo se limitan a los tipos de 32 33parmetros de atributos, que son: 34 35 36 37 38 39 40Uno de los tipos siguientes: boo l, byte, char, double, float, int, long, sbyte, short, string, uint, ulong, ushort. El tipo object. El tipo System.Type. Un tipo enum, con la condicin de que ste y los tipos en los que est anidado (si los hubiera) tengan acceso pblico (17.2). Matrices unidimensionales de los tipos anteriores.

4117.2 Especificacin de atributos 42La especificacin de atributos es la aplicacin de un atributo previamente definido a una declaracin. Un 43atributo es una parte de informacin declarativa adicional que se especifica en una declaracin. Los atributos731Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

353

732Especificacin del lenguaje C#

1pueden especificarse en un mbito global (para especificar atributos en el ensamblado o mdulo que los 2contienen) y para declaraciones de tipo (type-declarations) (9.5), declaraciones de miembros de clase (class3member-declarations) (10.2), declaraciones de miembros de interfaz (interface-member-declarations) (13.2), 4declaraciones de miembros de estructura (struct-member-declarations) (11.2), declaraciones de miembros de 5enumeracin (enum-member-declarations) (14.3), declaraciones de descriptores de acceso (accessor6declarations) (10.6.2), declaraciones de descriptores de acceso a eventos (event-accessor-declarations) 7(10.7.1) y listas de parmetros formales (formal-parameter-lists) (10.5.1). 8Los atributos se especifican en secciones de atributos. Una seccin de atributos se compone de un par de 9corchetes, que encierran una lista separada por comas de uno o varios atributos. Ni el orden de los atributos en la 10lista, ni el de las secciones adjuntas a la misma entidad de programa son significativos. Por ejemplo, las 11especificaciones de atributos [A ] [B,][B ] [A,][A, B] y [B, A] son equivalentes. 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45global-attributes: global-attribute-sections global-attribute-sections: global-attribute-section global-attribute-sections global-attribute-section global-attribute-section: [ global-attribute-target-specifier attribute-list ] [ global-attribute-target-specifier attribute-list , ] global-attribute-target-specifier: global-attribute-target : global-attribute-target:assembly module

attributes: attribute-sections attribute-sections: attribute-section attribute-sections attribute-section attribute-section: [ attribute-target-specifieropt attribute-list ] [ attribute-target-specifieropt attribute-list , ] attribute-target-specifier: attribute-target : attribute-target:field event method param property return type

attribute-list: attribute attribute-list , attribute

733354

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

734

Captulo 18 Cdigo no seguro

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20

attribute: attribute-name attribute-argumentsopt attribute-name: type-name attribute-arguments: ( positional-argument-listopt ) ( positional-argument-list , named-argument-list ) ( named-argument-list ) positional-argument-list: positional-argument positional-argument-list , positional-argument positional-argument: attribute-argument-expression named-argument-list: named-argument named-argument-list , named-argument named-argument: identifier = attribute-argument-expression attribute-argument-expression: expression

21Un atributo se compone de un nombre de atributo (attribute-name) y una lista opcional de argumentos 22posicionales y con nombre. Los argumentos posicionales (si los hay) preceden a los argumentos con nombre. Un 23argumento posicional se compone de una expresin de argumentos de atributo (attribute-argument-expression). 24Un argumento con nombre consta de un nombre seguido por el signo igual, seguido de una expresin de 25argumentos de atributo (attribute-argument-expression) que, en conjunto, estn restringidos por las mismas 26reglas que la asignacin simple. El orden de los argumentos con nombre no es significativo. 27El nombre de atributo (attribute-name) identifica una clase de atributo. Si la forma del nombre de atributo 28(attribute-name) es un nombre de tipo (type-name), este nombre debe hacer referencia a una clase de atributo. 29En caso contrario, se producir un error en tiempo de compilacin. En el ejemplo 30 c lass C lass1 {} 31 [C lass1 ] c lass C lass2 {} / / Er ro r 32se produce un error en tiempo de compilacin, porque se intenta utilizar Class1 como clase de atributo a pesar 33de no serlo. 34Algunos contextos permiten especificar un atributo en ms de un destino. Un programa puede especificar 35explcitamente el destino incluyendo un especificador de destino de atributo (attribute-target-specifier). Cuando 36se coloca un atributo en el nivel global, es necesario un especificador de destino de atributo global (global37attribute-target-specifier). En todas las dems ubicaciones, se aplica un valor predeterminado razonable, pero es 38posible utilizar un especificador de destino de atributo (attribute-target-specifier) para afirmar o reemplazar el 39valor predeterminado en ciertos casos ambiguos (o slo para afirmar el valor predeterminado, en casos en que 40no haya ambigedad). De esta forma, pueden omitirse habitualmente los especificadores de destino de atributo 41(attribute-target-specifiers). Los contextos potencialmente ambiguos se resuelven de esta forma: 42 43 44 45Un atributo especificado en el mbito global se puede aplicar tanto al ensamblado de destino como al mdulo de destino. No existe un valor predeterminado para este contexto, por lo que siempre se requiere un especificador de destino de atributo (attribute-target-specifier). La presencia del especificador de destino de atributo (attribute-target-specifier) a continuacin de assemb ly indica que el atributo se aplica al355

735Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

736Especificacin del lenguaje C#

1 2

ensamblado de destino; la presencia del mismo especificador a continuacin de modu le indica que el atributo se aplica al mdulo de destino.

737356

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

738

Captulo 18 Cdigo no seguro

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41

Un atributo especificado en una declaracin de delegado se puede aplicar al delegado que se est declarando o a su valor devuelto. En ausencia del especificador de destino de atributo (attribute-target-specifier), el atributo se aplica al delegado. La presencia del especificador de destino de atributo (attribute-targetspecifier) a continuacin de t ype indica que el atributo se aplica al delegado; la presencia del mismo especificador a continuacin de re tu rnindica que el atributo se aplica al valor devuelto. Un atributo especificado en una declaracin de mtodo se puede aplicar al mtodo que se est declarando o a su valor devuelto. En ausencia del especificador de destino de atributo (attribute-target-specifier), el atributo se aplica al mtodo. La presencia del especificador de destino de atributo (attribute-target-specifier) a continuacin de method indica que el atributo se aplica al mtodo; la presencia del mismo especificador a continuacin de re tu rnindica que el atributo se aplica al valor devuelto. Un atributo especificado en una declaracin de operador se puede aplicar al operador que se est declarando o a su valor devuelto. En ausencia del especificador de destino de atributo (attribute-target-specifier), el atributo se aplica al operador. La presencia del especificador de destino de atributo (attribute-targetspecifier) a continuacin de method indica que el atributo se aplica al operador; la presencia del mismo especificador a continuacin de re tu rnindica que el atributo se aplica al valor devuelto. Un atributo especificado en una declaracin de evento que omite los descriptores de acceso de eventos se puede aplicar al evento que se est declarando, al campo asociado (si el evento no es abstracto) o a los mtodos add y remove. En ausencia del especificador de destino de atributo (attribute-target-specifier), el atributo se aplica al evento. La presencia del especificador de destino de atributo (attribute-target-specifier) a continuacin de event indica que el atributo se aplica al evento; la presencia del especificador a continuacin de f i e l d indica que el atributo se aplica al campo; y la presencia del mismo especificador a continuacin de method indica que el atributo se aplica a los mtodos. Un atributo especificado en una declaracin de descriptor de acceso get para una propiedad o una declaracin de indizador se puede aplicar al mtodo asociado o a su valor devuelto. En ausencia del especificador de destino de atributo (attribute-target-specifier), el atributo se aplica al mtodo. La presencia del especificador de destino de atributo (attribute-target-specifier) a continuacin de method indica que el atributo se aplica al mtodo; la presencia del mismo especificador a continuacin de return indica que el atributo se aplica al valor devuelto. Un atributo especificado en una declaracin de descriptor de acceso set para una propiedad o una declaracin de indizador se puede aplicar al mtodo asociado o a su parmetro implcito solo. En ausencia del especificador de destino de atributo (attribute-target-specifier), el atributo se aplica al mtodo. La presencia del especificador de destino de atributo (attribute-target-specifier) method indica que el atributo se aplica al mtodo; la presencia del especificador de destino de atributo param indica que el atributo se aplica al parmetro; y la presencia del especificador de destino de atributo return indica que el atributo se aplica al valor devuelto. Un atributo especificado en una declaracin de descriptor de acceso add o remove para una declaracin de evento se aplica al mtodo asociado o a su parmetro. En ausencia del especificador de destino de atributo (attribute-target-specifier), el atributo se aplica al mtodo. La presencia del especificador de destino de atributo (attribute-target-specifier) method indica que el atributo se aplica al mtodo; la presencia del especificador de destino de atributo param indica que el atributo se aplica al parmetro; y la presencia del especificador de destino de atributo return indica que el atributo se aplica al valor devuelto.

42En otros contextos se permite la inclusin de un especificador de destino de atributo (attribute-target-specifier), 43pero no es necesaria. Por ejemplo, una declaracin de clase puede incluir u omitir el especificador type: 44 45[ t ype : Author ( "B r i an Kern ighan" ) ] c lass C lass1 {}

739Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

357

740Especificacin del lenguaje C#

1

[Author("Dennis Ritchie")]

2Supone un error Class2 {}un especificador de destino de atributo (attribute-target-specifier) no vlido. Por class especificar 3 4ejemplo, el especificador param no se puede utilizar en una declaracin de clase: 5 [pa ram: Author ( "B r i an Kern ighan" ) ] / / Er ro r 6 c lass C lass1 {} 7Por convencin, las clases de atributos se denominan con el sufijo At t r i bu te nombre de atributo (attribute. Un 8name) de la forma de nombre de tipo (type-name) puede incluir u omitir este sufijo. Si se encuentra una clase de 9atributo tanto con este sufijo como sin l, existe una ambigedad y se produce un error de tiempo de 10compilacin. Si el nombre de atributo (attribute-name) se escribe de manera que su identificador (identifier) 11situado ms a la derecha es un identificador literal (2.4.2), slo se corresponder con un atributo sin sufijo, lo 12que supondr una ambigedad que se debe resolver. En el ejemplo 13 us ing Sys tem; 14 [A t t r i bu teUsage(At t r i bu te Ta rge ts .A l l ) ] 15 pub l i c c lass X: At t r i bu te 16 {} 17 [A t t r i bu teUsage(At t r i bu te Ta rge ts .A l l ) ] 18 pub l i c c lass XAt t r i bu te : At t r i bu te 19 {} 20 [X ] / / Er ro r : amb igu i ty 21 c lass C lass1 {} 22 [XAt t r i bu te ] / / Re fe rs to XAt t r i bu te 23 c lass C lass2 {} 24 [@X] / / Re fe rs to X 25 c lass C lass3 {} 26 [@XAt t r i bu te ] / / Re fe rs to XAt t r i bu te 27 c lass C lass4 {} 28se muestran dos clases de atributos denominadas X y XAt t r i bu te atributo [X] es ambiguo, puesto que podra . El 29referirse tanto a X como a XAttribute. El uso de un identificador literal permite especificar la intencin exacta 30en estos casos poco frecuentes. El atributo [XAttribute] no es ambiguo (aunque lo sera si hubiera una clase de 31atributo denominada XAttributeAttribute). Si se quita la declaracin de la clase X, ambos atributos hacen 32referencia a la clase de atributo Xattribute, de la manera siguiente: 33 us ing Sys tem; 34 [A t t r i bu teUsage(At t r i bu te Ta rge ts .A l l ) ] 35 pub l i c c lass XAt t r i bu te : At t r i bu te 36 {} 37 [X ] / / Re fe rs to XAt t r i bu te 38 c lass C lass1 {} 39 [XAt t r i bu te ] / / Re fe rs to XAt t r i bu te 40 c lass C lass2 {} 41 [@X] / / Er ro r : no at t r i bu te named "X" 42 c lass C lass3 {} 43Supone un error en tiempo de compilacin utilizar un atributo de uso nico ms de una vez en la misma entidad. 44En el ejemplo 45741358

us ing Sys tem;Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

742

Captulo 18 Cdigo no seguro

1 2 3 5 4 6 7 8 9

[AttributeUsage(AttributeTargets.Class)] public class HelpStringAttribute: Attribute { public HelpStringAttribute(string value) { this.value = value; public string Value { get {...}

10 } 12 [HelpString("Description of Class1")] 11 13 [HelpString("Another description of Class1")] 15se produce un error en tiempo de compilacin, porque intenta utilizar He lpS t r i nguna clase de atributo de uso , 14 16nico, ms de una vez en la declaracin de C lass1 . 17Una expresin E es una expresin de argumentos de atributo (attribute-argument-expression) si todas las 18instrucciones siguientes son verdaderas: 19 20 21 22 23 25 26 27 28 29 30 31 33 32 34 35 36 37 38 39 40 41 42 43El tipo de E es un tipo de parmetro de atributo (17.1.3). En tiempo de compilacin, el valor de E se puede calcular a travs de: o o o Un valor constante. Un objeto Sys tem. Type . Una matriz unidimensional de expresiones de argumento de atributo (attribute-argument-expressions).

24Por ejemplo:us ing Sys tem; [A t t r i bu teUsage(At t r i bu te Ta rge ts .C lass ) ] pub l i c c lass Tes tAt t r i bu te : At t r i bu te { pub l i c i n t P1 { get { . . . } se t { . . . } pub l i c Type P2 { get { . . . } se t { . . . } } pub l i c ob jec t P3 { get { . . . } se t { . . . } } [ Tes t (P1 = 1234 , P3 = new i n t [ ] {1 , 3 , 5} , P2 = t ypeo f ( f l oa t ) ) ] c lass MyC lass {}

743Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

359

744Especificacin del lenguaje C#

117.3 Instancias de atributo 2Una instancia de atributo es una instancia que representa un atributo en tiempo de ejecucin. Un atributo se 3define mediante una clase de atributo, argumentos posicionales y argumentos con nombre. Una instancia de 4atributo es una instancia de la clase de atributo que se inicializa con los argumentos posicionales y con nombre. 5La recuperacin de la instancia de atributo comprende el procesamiento en tiempo de compilacin y ejecucin, 6tal como se describe en las siguientes secciones: 717.3.1 Compilacin de un atributo 8La compilacin de un atributo (attribute) con clase de atributo T, una lista de argumentos posicionales 9(positional-argument-list) P y una lista de argumentos con nombre (named-argument-list) N se compone de los 10siguientes pasos: 11 12 13 14 15 16 17 18 19 20 21Para compilar una expresin de creacin de objeto de la forma new T(P), se siguen los pasos del procesamiento en tiempo de compilacin Estos pasos pueden producir un error en tiempo de compilacin o determinar un constructor de instancia C en T, que se puede invocar en tiempo de ejecucin. Si C no tiene acceso pblico, se produce un error en tiempo de compilacin. Para cada argumento con nombre Arg de N: o oName ser el identificador (identifier) del argumento con nombre (named-argument) Arg. Na me debe identificar a un campo o propiedad pblico, de lectura y escritura y no esttico en T. Si T no

tiene tal campo o propiedad, se producir un error en tiempo de compilacin. Mantenga la siguiente informacin para la creacin de instancias del atributo en tiempo de ejecucin: la clase de atributo T, el constructores de instancia C de T, la lista de argumentos posicionales (positionalargument-list) P y la lista de argumentos con nombre (named-argument-list) N.

2217.3.2 Recuperacin en tiempo de ejecucin de una instancia de atributo 23La compilacin de un atributo (attribute) da como resultado una clase de atributo T, un constructor de instancia 24C en T, una lista de argumentos posicionales (positional-argument-list) P y una lista de argumentos con nombre 25(named-argument-list) N. Dada esta informacin, se puede recuperar una instancia de atributo en tiempo de 26ejecucin siguiendo estos pasos: 27 28 29 30 31 32 33 34 35 36 37 38 39 40745360

Se siguen los pasos de procesamiento en tiempo de ejecucin para ejecutar una expresin de creacin de objeto (object-creation-expression) de la forma new T(P), utilizando el constructor de instancia C tal como se determina en tiempo de compilacin. Estos pasos dan como resultado una excepcin, o producen una instancia O de T. Para cada argumento con nombre (named-argument) Arg de N, con el orden: oName ser el identificador (identifier) del argumento con nombre (named-argument) Arg. Si Name no identifica a un campo o propiedad de lectura y escritura, pblico y no esttico en O, se inicia una

excepcin. o o o oValue ser el resultado de evaluar la expresin de argumentos de atributo (attribute-argumentexpression) de Arg.

Si Name identifica a un campo en O, establezca este campo en Value. En cualquier otro caso, Name identifica a una propiedad en O. Establezca esta propiedad en Value. El resultado es O, una instancia de la clase de atributo T inicializada con la lista de argumentos posicionales (positional-argument-list) P y la lista de argumentos con nombre (named-argument-list) N.Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

746

Captulo 18 Cdigo no seguro

117.4 Atributos reservados 2Un pequeo nmero de atributos afectan al lenguaje de alguna forma. Estos atributos incluyen: 3 4Sys tem.At t r i bu teUsageAt t r i bu te (17.4.1), que se utiliza para describir las formas en que puede usarse

una clase de atributo.

747Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

361

748Especificacin del lenguaje C#

1 2

Sys tem.D iagnos t i c s .Cond i t i ona lA t t r i bu te (17.4.2), que se utiliza para definir mtodos condicionales. Sys tem.Obso le teAt t r i bu (17.4.3), que se utiliza para marcar un miembro como obsoleto. te

317.4.1 Atributo AttributeUsage 4El atributo At t r i bu teUsage utiliza para describir la manera en que se puede utilizar la clase de atributo. se 5Una clase decorada con el atributo At t r i bu teUsage derivarse de Sys tem.At t r i bu , directa o debe te 6indirectamente. En caso contrario, se producir un error en tiempo de compilacin. 7 8 9 10 13 11 14 12 15 16 17 18 19 20 21 22 23 24 25namespace System { [AttributeUsage(AttributeTargets.Class)] public class AttributeUsageAttribute: Attribute public virtual bool AllowMultiple { get {...} set {...} } public virtual bool Inherited { get {...} set {...} } public virtual AttributeTargets ValidOn { get {...} } } public enum AttributeTargets { Assembly Module Class Struct Enum Method = 0x0001, = 0x0002, = 0x0004, = 0x0008, = 0x0010, = 0x0040,

Constructor = 0x0020,

26 Property = 0x0080, 33 All = Assembly | Module | Class | Struct | Enum | Constructor | 27 34 Method | Property | Field | Event | Interface | Parameter | 28 35 Delegate | ReturnValue 29 3617.4.2 Atributo Conditional 38 30 37 39El atributo Cond i t i onapermite la definicin de mtodos condicionales y clases de atributo condicional. l 31 40 namespace Sys tem.D iagnos t i c s 32 41 { 42 [A t t r i bu teUsage(At t r i bu te Ta rge ts .Method | At t r i bu te Ta rge ts .C lass , 43 A l l owMu l t i p le = t rue ) ] 44 pub l i c c lass Cond i t i ona lA t t r i bu te : At t r i bu te 45 { 46749362Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

750

Captulo 18 Cdigo no seguro

1 2}

public string ConditionString { get {...} }

317.4.2.1 Mtodos condicionales 4 5Un mtodo decorado con el atributo Cond i t i onaes un mtodo condicional. El atributo Cond i t i onaindica una l l 6condicin al comprobar un smbolo de compilacin condicional. Las llamadas a un mtodo condicional se 7incluyen u omiten dependiendo de si est definido este smbolo en el punto de la llamada. Si el smbolo se 8define, la llamada se incluye; en caso contrario, la llamada (incluida la evaluacin de los parmetros de la 9llamada) se omite. 10Un mtodo condicional est sujeto a las siguientes restricciones: 11 12 13 14 15 16 17 18 19El mtodo condicional debe ser un mtodo perteneciente a una declaracin de clase (class-declaration) o de estructura (struct-declaration). Si se especifica el atributo Cond i t i onaen un mtodo de declaracin de l interfaz, se produce un error en tiempo de compilacin. El mtodo condicional debe tener un tipo de valor devuelto vo id . El mtodo condicional no debe estar marcado con el modificador ove r r i deSin embargo, un mtodo . condicional puede marcarse con el modificador v i r tua l . Los reemplazos de dicho mtodo son condicionales de forma implcita, y no se deben marcar explcitamente con un atributo Conditional. El mtodo condicional no debe ser una implementacin de un mtodo de interfaz. En caso contrario, se producir un error en tiempo de compilacin.

20Asimismo, se produce un error en tiempo de compilacin si se utiliza un mtodo condicional en una expresin 21de creacin de delegado (delegate-creation-expression). En el ejemplo 22 #def ine DEBUG 23 us ing Sys tem; 24 us ing Sys tem.D iagnos t i c s ; 25 c lass C lass1 26 { 27 [Cond i t i ona l ( "DEBUG" ) ] 28 pub l i c s ta t i c vo id M() { 29 Conso le .Wr i teL ine ( "Executed C lass1 .M" ) ; 30 } 32 c lass C lass2 31 33 { 34 pub l i c s ta t i c vo id Tes t ( ) { 35 C lass1 .M( ) ; 36 } 38se declara Class1.M como mtodo condicional. El mtodo Test de Class2 llama a este mtodo. Dado que se 37 39define el smbolo de compilacin condicional DEBUG, si se llama a Class2.Test ste llamar a M. Si no se 40define el smbolo DEBUG, Class2.Test no llamar a Class1.M. 41Es importante observar que la inclusin o exclusin de una llamada a un mtodo condicional est controlada por 42los smbolos de compilacin condicional existentes en el lugar de la llamada. En el siguiente ejemplo: 43 44Archivo c lass1 . cs :us ing Sys tem.D iagnos t i c s ;

751Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

363

752Especificacin del lenguaje C#

1 2 3 4 5 8 6 9 10 7 11 12 13 14 16 15

class Class1 { [Conditional("DEBUG")] public static void F() { Console.WriteLine("Executed Class1.F"); Archivo c lass2 . cs : #def ine DEBUG c lass C lass2 { pub l i c s ta t i c vo id G( ) { C lass1 .F ( ) ; } / / F i s ca l l ed

Archivo c lass3 . cs :

17 #unde f DEBUG 18 c lass C lass3 19 { 20 pub l i c s ta t i c vo id H( ) { 21 C lass1 .F ( ) ; / / F i s not ca l l ed 22 } 24las clases C lass2y C lass3contienen llamadas al mtodo condicional Class1.F, que ser o no condicional, en 23 25funcin de si DEBUG est definido o no. Dado que este smbolo est definido en el contexto de Class2 pero no 26de Class3, la llamada a F en Class2 se mantiene, mientras que se omite la llamada a F en Class3. 27El uso de mtodos condicionales en una cadena de herencia puede resultar confuso. Las llamadas realizadas a un 28mtodo condicional mediante base, de la forma base.M, estn sujetas a las reglas normales de llamadas a 29mtodos condicionales. En el siguiente ejemplo: 30 31 32 33 34 35 36 37 38 40 39 41Archivo c lass1 . cs :us ing Sys tem; us ing Sys tem.D iagnos t i c s ; c lass C lass1 { [Cond i t i ona l ( "DEBUG" ) ] pub l i c v i r tua l vo id M() { Conso le .Wr i teL ine ( "C lass1 .M execu ted" ) ; } Archivo c lass2 . cs : us ing Sys tem;

753364

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

754

Captulo 18 Cdigo no seguro

1 2 3 4 5 8

class Class2: Class1 { public override void M() { Console.WriteLine("Class2.M executed"); base.M(); Archivo c lass3 . cs : // base.M is not called!

20en la consola Class2.M executed. Un uso juicioso de las declaraciones pp (pp-declarations) puede eliminar 21tales problemas. 2217.4.2.2 Clases de atributo condicional 23Una clase de atributo (17.1) decorada con uno o ms atributos Conditional es una clase de atributo 24condicional. Una clase de atributo condicional se asocia, por lo tanto, con los smbolos de compilacin 25condicional declarados en sus atributos Conditional. Este ejemplo: 26 us ing Sys tem; 27 us ing Sys tem.D iagnos t i c s ; 28 [Cond i t i ona l ( "ALPHA" ) ] 29 [Cond i t i ona l ( "BETA" ) ] 30declara TestAttribute como una clase de atributo condicional asociado a los smbolos de compilaciones 31 32condicionales ALPHA y BETA.

6 9 #def ine DEBUG 10 us ing Sys tem; 7 11 c lass C lass3 12 { 13 pub l i c s ta t i c vo id Tes t ( ) { 14 C lass2 c = new C lass2 ( ) ; 15 c .M( ) ; / / M i s ca l l ed 16 } 18C lass2incluye una llamada al mtodo M definido en su clase base. Esta llamada se omite porque el mtodo 17 19base es condicional debido a la presencia del smbolo DEBUG, que no est definido. As, el mtodo slo escribe

33Las especificaciones de atributos (17.2) de un atributo condicional se incluyen si uno o ms de sus smbolos de 34compilacin condicional asociado se define en el lugar de la especificacin; de lo contrario, se omite la 35especificacin de atributos. 36Es importante observar que la inclusin o exclusin de la especificacin de un atributo de una clase de atributo 37condicional est controlada por los smbolos de compilacin condicional existentes en el lugar de la 38especificacin. En el siguiente ejemplo: 39 40 41 42 43 44Archivo test.cs:us ing Sys tem; us ing Sys tem.D iagnos t i c s ; [Cond i t i ona l ( DEBUG ) ] pub l i c c lass Tes tAt t r i bu te : At t r i bu te {}

Archivo class1.cs:

755Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

365

756Especificacin del lenguaje C#

1 2 3 4

#define DEBUG [Test] // TestAttribute is specified class Class1 {}

Archivo c lass2 . cs :

5 #unde f DEBUG 6 [ Tes t ] / / Tes tAt t r i bu te i s not spec i f i ed 7 c lass C lass2 {} 8las clases C lass1y C lass2estn decoradas con el atributo Test, que es condicional en funcin de si DEBUG 9est o no definido. Dado que este smbolo est definido en el contexto de Class1 pero no de Class2, se incluye 10la especificacin del atributo Test de Class1, mientras que se omite la especificacin del atributo Test en 11Class2. 12

757366

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

758

Captulo 18 Cdigo no seguro

117.4.3 Atributo Obsolete 2El atributo Obso le tese utiliza para marcar tipos y miembros de tipos que ya no se deberan utilizar. 3 4 5 6 7 8 9 10 11 12namespace System { [AttributeUsage( AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Interface | AttributeTargets.Delegate | AttributeTargets.Method | AttributeTargets.Constructor |

13 AttributeTargets.Property | 21 public ObsoleteAttribute(string message) {...} 14 22 public ObsoleteAttribute(string message, bool error) {...} 15 23 public string Message { get {...} } 16 24 public bool IsError { get {...} } 17 25 } 18 27 , 26Si un programa utiliza un tipo o miembro decorado con el atributo Obso le te el compilador emite una 28advertencia o genera un error. En concreto, si no se proporciona ningn parmetro de error, o si se proporciona y 19 29su valor es f a l seel compilador emite una advertencia. Si se especifica un parmetro de error y su valor es true, , 30 20el compilador genera un error. 31En el siguiente ejemplo: 32 33 34 35 37 36 38 39 41 40 42 43 44 45 46 47 759Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.367 [Obsolete("This class is obsolete; use class B instead")] class A { class B { public void F() {} class Test { static void Main() { A a = new A(); a.F(); // Warning

760Especificacin del lenguaje C#

1la clase A est decorada con el atributo Obso le te Cada uso de A en Main da como resultado una advertencia . 2que incluye el mensaje especificado en el cdigo anterior, This class is obsolete; use class B instead. 317.5 Atributos para interoperabilidad 4Note: Esta seccin slo se aplica a la implementacin de C# de Microsoft .NET. 517.5.1 Interoperabilidad con componentes COM y Win32 6El motor de tiempo de ejecucin de .NET proporciona un gran nmero de atributos que permiten que los 7programas de C# interacten con componentes escritos mediante bibliotecas .dll COM y Win32. Por ejemplo, el 8atributo DllImport puede utilizarse en un mtodo static extern para indicar que la implementacin del mtodo 9se encuentra en una biblioteca DLL Win32. Estos atributos se encuentran en el espacio de nombres 10System.Runtime.InteropServices; se puede encontrar informacin detallada referente a estos atributos en la 11documentacin del motor de tiempo de ejecucin .NET. 1217.5.2 Interoperabilidad con otros lenguajes .NET 1317.5.2.1 Atributo IndexerName 14Los indizadores se implementan en .NET utilizando propiedades indizadas y tienen un nombre en los metadatos 15.NET. Si no hay ningn atributo IndexerName presente para un indizador, se utiliza de forma predeterminada 16el nombre Item. El atributo IndexerName permite al programador reemplazar este valor predeterminado y 17especificar un nombre distinto. 18 19 20 21 24 22 25 23 26namespace System.Runtime.CompilerServices.CSharp { [AttributeUsage(AttributeTargets.Property)] public class IndexerNameAttribute: Attribute public string Value { get {...} } }

761368

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

762

Captulo 18 Cdigo no seguro

1

18.Cdigo no seguro

2El lenguaje C# bsico, tal como se define en los captulos precedentes, difiere notablemente de C y C++ en su 3omisin de los punteros como un tipo de datos. C# proporciona en su lugar referencias, as como la capacidad de 4crear objetos administrados por un recolector de elementos no utilizados. Este diseo, unido a otras 5caractersticas, hace de C# un lenguaje mucho ms seguro que C o C++. En el lenguaje bsico de C# no es 6posible usar una variable no inicializada, un puntero pendiente o una expresin que indice una matriz ms all 7de sus lmites. De esta manera se eliminan categoras enteras de errores que suelen afectar a los programas 8desarrollados en C y C++. 9Si bien casi todas las construcciones de tipos de puntero en C o C++ poseen un tipo de referencia equivalente en 10C#, hay situaciones donde el acceso a tipos de puntero se convierte en una necesidad. Por ejemplo, al desear 11interactuar con el sistema operativo subyacente, obtener acceso a un dispositivo asignado a memoria o 12implementar un algoritmo sensible al tiempo puede no lograrse nuestro objetivo sin disponer de acceso a 13punteros. Para solucionar esta necesidad, C# proporciona la capacidad de crear cdigo no seguro. 14En el cdigo no seguro es posible declarar y operar con punteros, realizar conversiones de punteros a tipos 15integrales, tomar las direcciones de variables, etc. En cierto sentido, escribir cdigo no seguro se parece mucho a 16escribir cdigo C dentro de un programa en C#. 17El cdigo no seguro es, en realidad, una caracterstica segura desde el punto de vista tanto de programadores 18como de usuarios. El cdigo no seguro debe estar marcado con claridad mediante el modificador unsa fe, de 19manera que los programadores no puedan usar caractersticas no seguras por accidente, y el motor de ejecucin 20garantice que no se pueda ejecutar el cdigo no seguro en un entorno que no sea de confianza. 2118.1 Contextos no seguros 22Las caractersticas no seguras de C# estn disponibles slo en contextos no seguros (unsafe contexts). Se 23introduce un contexto no seguro incluyendo un modificador unsa fe en la declaracin de un tipo o miembro, o 24utilizando una instruccin unsafe (unsafe-statement). 25 26 27 28 29 30 31 32Una declaracin de una clase, estructura, interfaz o delegado puede incluir un modificador unsa fe, en cuyo caso toda la extensin textual de la declaracin (incluido el cuerpo de la clase, estructura o interfaz) se considera como contexto no seguro. Una declaracin de un campo, mtodo, propiedad, evento, indizador, operador, constructor de instancia, constructor esttico o destructor puede incluir el modificador unsa fe, en cuyo caso toda la extensin textual de dicha declaracin de miembro se considera como contexto no seguro. Una instruccin unsafe (unsafe-statement) habilita el uso de un contexto no seguro dentro de un bloque (block). Toda la extensin textual del bloque (block) asociado se considera como contexto no seguro.

33Las extensiones de gramtica asociadas se muestran a continuacin. Para mayor brevedad, se utilizan puntos 34suspensivos (...) para representar elementos que aparecen explicados en captulos anteriores. 35 class-modifier: 36 ... 37 unsa fe

763Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

369

764Especificacin del lenguaje C#

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45

struct-modifier: ...unsa fe

interface-modifier: ...unsa fe

delegate-modifier: ...unsa fe

field-modifier: ...unsa fe

method-modifier: ...unsa fe

property-modifier: ...unsa fe

event-modifier: ...unsa fe

indexer-modifier: ...unsa fe

operator-modifier: ...unsa fe

constructor-modifier: ...unsa fe

destructor-declaration: attributesopt ex te rn unsa feopt ~ identifier ( ) opt attributesopt unsafeopt externopt ~ identifier ( ) static-constructor-modifiers:externopt unsafeopt static unsafeopt externopt static externopt static unsafeopt unsafeopt static externopt static externopt unsafeopt static unsafeopt externopt

destructor-body destructor-body

embedded-statement: ... unsafe-statement unsafe-statement: unsafe block

765370

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

766

Captulo 18 Cdigo no seguro

1En el siguiente ejemplo: 2 3 4public unsafe struct Node { public int Value;

5 public Node* Left; 8el modificador unsa fe especificado en la declaracin de estructura hace que toda la extensin textual de la 6declaracin sea un contexto no seguro. As, es posible declarar los campos Le f ty Right como tipo de puntero. 9 10El ejemplo anterior tambin se puede escribir de la siguiente forma: 7 11 12 13public struct Node { public int Value;

14 public unsafe Node* Left; 17Aqu, los modificadores unsafe de las declaraciones de campo convierten a stas en contextos no seguros. 15 18Aparte de establecer un contexto no seguro, que permite as el uso de tipos de puntero, el modificador unsafe 16 19no tiene ningn efecto en un tipo o miembro. En el siguiente ejemplo: 20 21 22 23 24 27 25 28 26 29 30public class A { public unsafe virtual void F() { char* p; ... public class B: A { public override void F() { base.F();

31 ... 34el modificador unsa fe del mtodo F en A simplemente hace que la extensin textual de F se convierta en un 35contexto no seguro en el cual pueden utilizarse las caractersticas no seguras del lenguaje. En el reemplazo de F 32 36en B, no hay necesidad de volver a especificar el modificador unsafe, a menos que el propio mtodo F de B 37 33requiera el acceso a caractersticas no seguras. 38Esta situacin es ligeramente diferente cuando un tipo de puntero forma parte de la firma del mtodo. 39 40 41 42 43 44 45 46pub l i c unsa fe c lass A { pub l i c v i r tua l vo id F (char* p) { . . . } } pub l i c c lass B: A { pub l i c unsa fe ove r r i de vo id F (char* p) { . . . } }

767Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

371

768Especificacin del lenguaje C#

1Aqu, debido a que la firma de F incluye un tipo de puntero, slo se puede escribir en un contexto no seguro. Sin 2embargo, el contexto no seguro se puede introducir convirtiendo toda la clase en no segura, como en el caso de 3A, o al incluir un modificador unsafe en la declaracin de mtodo, como en el caso de B. 418.2 Tipos de punteros 5En un contexto no seguro, un tipo (type) (4) puede ser un tipo de puntero (pointer-type), as como un tipo de 6valor (value-type) o un tipo de referencia (reference-type). Sin embargo, un tipo de puntero (pointer-type) 7tambin puede utilizarse en una expresin t ypeo f(7.5.11) fuera de un contexto no seguro ya que dicho uso no 8es no seguro. 9 10 11 12type: value-type reference-type pointer-type

13Un tipo de puntero (pointer-type) se escribe como tipo no administrado (unmanaged-type) o como la palabra 14clave vo id seguida de un smbolo (token) *: 15 16 17 18 19pointer-type: unmanaged-type *void *

unmanaged-type: type

20El tipo especificado antes del asterisco en un tipo de puntero se denomina tipo referente del tipo de puntero. 21Representa el tipo de la variable a la que seala un valor del tipo de puntero. 22Al contrario que las referencias (valores de tipos de referencia), los punteros no estn sometidos al seguimiento 23del recolector de elementos no utilizados, el cual no conoce los punteros ni los datos a los que estos apuntan. Por 24este motivo, un puntero no puede sealar a una referencia o una estructura que contenga referencias, y el tipo 25referente de un puntero debe ser un tipo no administrado (unmanaged-type). 26Un tipo no administrado (unmanaged-type) es cualquier tipo que no sea un tipo de referencia (reference-type) y 27no contenga campos de tipo de referencia en ningn nivel de anidamiento. En otras palabras, un tipo no 28administrado (unmanaged-type) es uno de los siguientes: 29 30 31 32 33sbyte, byte, short, ushort, int, uint, long, ulong, char, float, double, decimal o bool.

Cualquier tipo enum (enum-type). Cualquier tipo de puntero (pointer-type). Cualquier tipo de estructura (struct-type) definido por el usuario que contenga nicamente campos de tipos no administrados (unmanaged-types).

34La regla intuitiva para mezclar punteros y referencias es que los referentes de las referencias (objetos) pueden 35contener punteros, pero los referentes de punteros no pueden contener referencias. 36En la tabla siguiente se dan algunos ejemplos de tipos de punteros:37

769372

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

770

Captulo 18 Cdigo no seguro

Ejemplobyte* char* int** int*[] void*

Descripcin Puntero a byte Puntero a char Puntero a un puntero a i n t Matriz unidimensional de punteros a i n t Puntero a un tipo desconocido

38 39Para una implementacin dada, todos los tipos de puntero deben tener el mismo tamao y representacin. 40A diferencia de C y C++, cuando se declaran mltiples punteros en una misma declaracin, en C# el carcter * 41se escribe junto al tipo subyacente nicamente, no como puntuacin de prefijo en cada nombre de puntero. Por 42ejemplo:43

int* pi , pj ;

/ / NOT as i n t *p i , *p j ;

44El valor de un puntero de tipo T* representa la direccin (address) de una variable de tipo T. El operador de 45direccionamiento indirecto de puntero * (18.5.1) puede usarse para obtener acceso a esta variable. Por ejemplo 46dada una variable P de tipo int*, la expresin *P denota la variable int hallada en la direccin contenida en P. 47Al igual que una referencia de objeto, un puntero puede ser null. Aplicar el operador de direccionamiento 48indirecto a un puntero null da como resultado un comportamiento definido segn la implementacin. Un 49puntero con el valor null se representa por medio de todos los bits cero. 50El tipo void* representa un puntero a un tipo desconocido. Dado que el tipo referente es desconocido, el 51operador de direccionamiento indirecto no se puede aplicar a un puntero de tipo void*, ni se pueden realizar 52operaciones aritmticas en este tipo de puntero. Sin embargo, un puntero de tipo void* se puede convertir a 53cualquier otro tipo de puntero (y viceversa). 54Los tipos de puntero forman una categora independiente de tipos. A diferencia de los tipos de referencia y los 55tipos de valor, los tipos de puntero no se derivan de object y no existen conversiones entre tipos de puntero y 56object. En particular, las operaciones boxing y unboxing (4.3) no se permiten en punteros. Sin embargo, se 57permiten las conversiones entre diferentes tipos de punteros y entre tipos de punteros y tipos integrales. Este 58proceso se describe en 18.4. 59Puede utilizarse un tipo de puntero (pointer-type) como tipo de un campo voltil (10.4.3). 60Si bien pueden pasarse punteros como parmetros ref u out, hacerlo puede causar un comportamiento 61indefinido, ya que un puntero puede sealar a una variable local que ya no existe cuando el mtodo llamado 62devuelve un valor, o el objeto fijo al que apuntaba ya no es fijo. Por ejemplo:63 64 65 66 67 68 69 70 71 72 73 74

us ing Sys tem; c lass Tes t { s ta t i c i n t va lue = 20 ; unsa fe s ta t i c vo id F (ou t i n t * p i1 , re f i n t * p i2 ) { i n t i = 10 ; p i1 = &i ; f i xed ( i n t * p j = &va lue ) { // ... p i2 = p j ; }

}

771Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

373

772Especificacin del lenguaje C#

1 2 3 4 6 5 7 8

static void Main() { int i = 10; unsafe { F(out px1, ref px2); Console.WriteLine("*px1 = {0}, *px2 = {1}", *px1, *px2); // undefined behavior

9 } 12Un mtodo puede devolver un valor de un tipo, y ese tipo puede ser un puntero. Por ejemplo, dado un puntero a 10 13una secuencia contigua de valores i n t el nmero de elementos de la secuencia y otro valor i n t el mtodo , , 11siguiente devuelve la direccin del valor indicado en la secuencia, si se encuentra una coincidencia; en cualquier 14 15otro caso devuelve null: 16 17 18 19unsafe static int* Find(int* pi, int size, int value) { for (int i = 0; i < size; ++i) { if (*pi == value) return pi;

20 ++pi; 24En un contexto no seguro, hay varias construcciones disponibles para operar con punteros: 21 25 Puede utilizarse el operador * para realizar direccionamiento indirecto de punteros (18.5.1). 22 26 Puede utilizarse el operador -> para obtener acceso a un miembro de una estructura a travs de un puntero 23 27 (18.5.2). 28 29 30 31 32 33 34Puede utilizarse el operador [] para indizar un puntero (18.5.3). Puede utilizarse el operador & para obtener la direccin de una variable (18.5.4). Pueden utilizarse los operadores ++ y -- para incrementar y disminuir punteros (18.5.5). Se pueden utilizar los operadores + y - para realizar aritmtica de punteros (18.5.6). Pueden utilizarse los operadores ==, !=, , para comparar punteros (18.5.7). El operador stackalloc puede utilizarse para asignar memoria de la pila de llamadas (18.7). Puede utilizarse la instruccin fixed para fijar temporalmente una variable y obtener su direccin (18.6).

3518.3 Variables fijas y mviles 36El operador de direccin (18.5.4) y la instruccin fixed (18.6) dividen las variables en dos categoras: 37variables fijas y variables mviles. 38Las variables fijas se encuentran en ubicaciones de almacenamiento que no se ven afectadas por el 39funcionamiento del recolector de elementos no utilizados. Los ejemplos de variables fijas incluyen variables 40locales, parmetros de valor y variables creados mediante punteros de eliminacin de referencias. Las variables 41mviles, por otro lado, se encuentran en ubicaciones de almacenamiento sujetas a la reubicacin o eliminacin 42por parte del recolector de elementos no utilizados. Los ejemplos de variables mviles incluyen campos de 43objetos y elementos de matrices.773374Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

774

Captulo 18 Cdigo no seguro

1El operador & (18.5.4) permite obtener la direccin de una variable fija sin restricciones. Sin embargo, debido 2a que una variable mvil est sujeta a la reubicacin o eliminacin por el recolector de elementos no utilizados, 3slo se puede obtener su direccin mediante una instruccin f i xed (18.6), y la direccin es vlida slo durante 4el ciclo de duracin de esa instruccin fixed. 5En trminos precisos, una variable fija es una de las siguientes: 6 7 8 9 10 11 12Una variable resultante de un nombre simple (simple-name) (7.5.2) que hace referencia a una variable local o un parmetro de valor. Una variable resultante de un acceso a miembro (member-access) (7.5.4) de la forma V. ,I donde V es una variable fija de tipo de estructura (struct-type). Una variable resultante de una expresin de direccionamiento indirecto de puntero (pointer-indirectionexpression) (18.5.1) de la forma *P, un acceso a miembro de puntero (pointer-member-access) (18.5.2) de la forma P - >Io un acceso a elemento de puntero (pointer-element-access) (18.5.3) de la forma P[E].

13Todas las dems variables se clasifican como variables mviles. 14Observe que un campo esttico se clasifica tambin como variable mvil. Observe, igualmente, que un 15parmetro ref o out se clasifica como variable mvil, aun cuando el argumento dado para ese parmetro sea una 16variable fija. Por ltimo, debe sealarse que una variable producida mediante la eliminacin de referencia a un 17puntero siempre se clasifica como una variable fija. 1818.4 Conversiones de puntero 19En un contexto no seguro, el conjunto de conversiones implcitas disponibles (6.1) se extiende hasta incluir las 20siguientes conversiones implcitas de puntero: 21 22De cualquier tipo de puntero (pointer-type) al tipo void*. Del tipo null a cualquier tipo de puntero (pointer-type).

23En un contexto no seguro, el conjunto de conversiones explcitas disponibles (6.2) se extiende hasta incluir las 24siguientes conversiones explcitas de puntero: 25 26 27De cualquier tipo de puntero (pointer-type) a cualquier otro tipo de puntero. De sbyte, byte, short, ushort, int, uint, long o ulong a cualquier tipo de puntero (pointer-type). De cualquier tipo de puntero (pointer-type) a sbyte, byte, short, ushort, int, uint, long o ulong.

28Por ltimo, en un contexto no seguro, el conjunto de conversiones implcitas estndar (6.3.1) incluye la 29siguiente conversin de puntero: 30De cualquier tipo de puntero (pointer-type) al tipo void*.

31Las conversiones entre dos tipos de puntero nunca afectan al valor real del puntero. En otras palabras, una 32conversin de un tipo de puntero a otro no tiene efecto en la direccin subyacente dada por el puntero. 33Cuando se convierte un tipo de puntero a otro, si el puntero resultante no est correctamente alineado para el 34tipo a que se apunta, el comportamiento ser indefinido si se elimina la referencia al resultado. En general, el 35concepto correctamente alineado es transitivo: si un puntero a un tipo A est correctamente alineado para un 36puntero a un tipo B que, a su vez, est correctamente alineado para un puntero a un tipo C, entonces un puntero a 37un tipo A est correctamente alineado para un puntero a un tipo C. 38Considrese el siguiente caso en el que se obtiene acceso a una variable de un tipo determinado mediante un 39puntero a otro tipo:

775Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

375

776Especificacin del lenguaje C#

1 2 3

char c = 'A'; char* pc = &c; void* pv = pc;

4 int* pi = (int*)pv; 7Cuando se convierte un tipo de puntero a un puntero a byte, el resultado apunta al byte de direccin inferior de 5la variable. Los sucesivos incrementos del resultado, hasta alcanzar el tamao de la variable, dan como resultado 8 9punteros a los bytes restantes de dicha variable. Por ejemplo, el mtodo siguiente muestra cada uno de los ocho 6 10bytes de un tipo double como un valor hexadecimal:

777376

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

778

Captulo 18 Cdigo no seguro

1 2 3 4 5 6 7 8

using System; class Test { unsafe static void Main() { double d = 123.456e23; unsafe { byte* pb = (byte*)&d; for (int i = 0; i < sizeof(double); ++i)

14Por supuesto, los resultados producidos dependen del carcter big-endian o little endian. 9 15Las asignaciones entre punteros y enteros se definen segn su implementacin. Sin embargo, en arquitecturas de 10 16CPU de 32 y 64 bits, con un espacio de direcciones lineal, las conversiones de punteros a o desde tipos 11integrales tienen lugar exactamente igual que las conversiones de valores u in to u long, respectivamente, a o 17 18desde dichos tipos integrales. 12 1318.5 Punteros en expresiones 19 20En un contexto no seguro, una expresin puede dar como resultado un tipo de puntero, pero fuera de ese 21contexto supone un error en tiempo de compilacin que una expresin sea del tipo de puntero. En trminos ms 22precisos, fuera de un contexto no seguro se produce un error en tiempo de compilacin si cualquier nombre 23simple (simple-name) (7.5.2), acceso a miembro (member-access) (7.5.4), expresin de invocacin 24(invocation-expression) (7.5.5) o acceso a elemento (element-access) (7.5.6) es de un tipo de puntero. 25En un contexto no seguro, una expresin primaria sin creacin de matriz (primary-no-array-creation26expression) (7.5) y una expresin unaria (unary-expression) (7.6) permiten las siguientes construcciones 27adicionales: 28 29 30 31 32 33 34 35 36primary-no-array-creation-expression: ... pointer-member-access pointer-element-access sizeof-expression unary-expression: ... pointer-indirection-expression addressof-expression

37Estas construcciones se describen en las siguientes secciones. La precedencia y asociatividad de los operadores 38no seguros est implicada en la gramtica del lenguaje. 3918.5.1 Direccionamiento indirecto de punteros 40Una expresin de direccionamiento indirecto de punteros (pointer-indirection-expression) se compone de un 41asterisco (*) seguido de una expresin unaria (unary-expression). 42 43pointer-indirection-expression: * unary-expression

44El operador unario * indica el direccionamiento indirecto de punteros (pointer indirection) y se utiliza para 45obtener la variable a la que apunta un puntero. El resultado de evaluar *P, donde P es una expresin de un tipo779Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

377

780Especificacin del lenguaje C#

1de puntero T*, es una variable de tipo T. Se produce un error en tiempo de compilacin al aplicar el operador 2unario * a una expresin de tipo void* o a una expresin que no sea de tipo de puntero. 3El efecto de aplicar el operador unario * a un puntero null se define por su implementacin. En particular, no 4hay garanta de que esta operacin inicie una excepcin System.NullReferenceException. 5Si se asign un valor no vlido al puntero, el comportamiento del operador unario * es indefinido. Entre los 6valores no vlidos para eliminar la referencia a un puntero desde un operador unario * se encuentran una 7direccin incorrectamente alineada para el tipo al que se apunta (vea el ejemplo de la 18.4) y la direccin de 8una variable despus de finalizar su vida til. 9A los efectos del anlisis definitivo de asignaciones, una variable producida al evaluar una expresin de la forma 10*P se considera inicialmente asignada (5.3.1). 1118.5.2 Acceso a miembros de puntero 12Un acceso a miembros de puntero (pointer-member-access) se compone de una expresin primaria (primary13expression), seguida de un smbolo - >, que a su vez viene seguido de un identificador (identifier). 14 15pointer-member-access: primary-expression -> identifier

16En un acceso a miembro de puntero de la forma P->I, P debe ser una expresin de un tipo de puntero diferente 17de void*, e I debe denotar un miembro accesible del tipo al que apunta P. 18Un acceso a miembro de puntero de la forma P->I se evala exactamente como (*P).I. Para obtener una 19descripcin del operador de direccionamiento indirecto de puntero (*), vea la seccin 18.5.1. Para obtener una 20descripcin del operador de acceso a miembros (.), vea la seccin 7.5.4. 21En el siguiente ejemplo: 22 us ing Sys tem; 23 s t ruc t Po in t 24 { 25 pub l i c i n t x ; 26 pub l i c i n t y ; 27 pub l i c ove r r i de s t r i ng ToS t r i ng ( ) { 28 re tu rn " ( " + x + " , " + y + " ) " ; 29 } 30 } 31 c lass Tes t 32 { 33 s ta t i c vo id Main ( ) { 34 Po in t po in t ; 35 unsa fe { 36 Po in t * p = &po in t ; 37 p ->x = 10 ; 38 p ->y = 20 ; 39 Conso le .Wr i teL ine (p - >ToSt r i ng ( ) ) ; 40el operador -> se utiliza para obtener acceso a campos e invocar un mtodo de una estructura a travs de un } 43 41puntero. Dado que la operacin P->I es precisamente equivalente a (*P).I, podra haberse escrito igualmente el 44 45 42mtodo Main:

781378

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

782

Captulo 18 Cdigo no seguro

1 2 3 4 5 6 7

class Test { static void Main() { Point point; unsafe { Point* p = &point; (*p).x = 10;

8 1318.5.3 Acceso a elementos de puntero 9 14Un acceso a elementos de puntero (pointer-element-access) se compone de una expresin primaria sin creacin 15de matriz seguida de una expresin (primary-no-array-creation-expression) delimitada por [ y ]. 10

16 pointer-element-access: 11 17 primary-no-array-creation-expression [ expression ] 12En un acceso a elemento de puntero de la forma P[E ] P debe ser una expresin de un tipo de puntero diferente 18 , 19de void*, y E debe ser una expresin de un tipo que pueda convertirse implcitamente a int, uint, long o ulong. 20Un acceso a elemento de puntero de la forma P[E] se evala exactamente como *(P + E). Para obtener una 21descripcin del operador de direccionamiento indirecto de puntero (*), vea la seccin 18.5.1. Para obtener una 22descripcin del operador de suma de punteros (+), vea la seccin 18.5.6. 23En el siguiente ejemplo: 24 c lass Tes t 25 { 26 s ta t i c vo id Main ( ) { 27 unsa fe { 28 char* p = s tacka l l oc char [256] ; 29 f o r ( i n t i = 0 ; i < 256 ; i++) p[ i ] = ( cha r ) i ; 30 } 31 33se utiliza un acceso a elemento de puntero para inicializar el bfer de caracteres de un bucle for. Dado que la 34operacin P[E] es precisamente equivalente a *(P + E), el ejemplo podra haberse escrito igualmente de esta 32 35forma: 36 c lass Tes t 37 { 38 s ta t i c vo id Main ( ) { 39 unsa fe { 40 char* p = s tacka l l oc char [256] ; 41 f o r ( i n t i = 0 ; i < 256 ; i++) * (p + i ) = ( cha r ) i ; 42 } 43El operador de acceso a elementos de puntero no comprueba errores de tipo "fuera de lmite", por otro lado, el 45 46 44comportamiento al obtener acceso a un elemento fuera de lmites no est definido. Ocurre lo mismo en C y C++.

783Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

379

784Especificacin del lenguaje C#

118.5.4 Operador de direccin 2Una expresin de direccin (addressof-expression) se compone de un smbolo de Y comercial (&) seguido de 3una expresin unaria (unary-expression). 4 5addressof-expression: & unary-expression

6Dada una expresin E que es del tipo T y se clasifica como una variable fija (18.3), la construccin &E calcula 7la direccin de la variable proporcionada por E. El tipo del resultado es T* y se clasifica como un valor. Se 8produce un error en tiempo de compilacin si no se clasifica E como una variable, si se clasifica como una 9variable local de slo lectura o si denota una variable mvil. En este ltimo caso, se puede usar una instruccin 10fija (18.6) para fijar temporalmente la variable antes de obtener su direccin. Como se afirmaba en la seccin 117.5.4, fuera de un constructor de instancia o constructor esttico de una clase o estructura que define un campo 12readonly, dicho campo se considera un valor, no una variable. Como tal, no se puede capturar su direccin. 13Igualmente, no se puede tomar la direccin de una constante. 14El operador & no requiere que est asignado su argumento definitivamente, pero despus de una operacin &, la 15variable a la que se aplica el operador se considera definitivamente asignada en la ruta de ejecucin donde tiene 16lugar la operacin. Es responsabilidad del programador asegurarse de que se produce una correcta inicializacin 17de la variable en esta situacin. 18En el siguiente ejemplo: 19 us ing Sys tem; 20 c lass Tes t 21 { 22 s ta t i c vo id Main ( ) { 23 int i ; 24 unsa fe { 25 i n t * p = &i ; 26 *p = 123 ; 27 } 28 Conso le .Wr i teL ine ( i ) ; 31i se considera definitivamente asignada despus de la operacin &i utilizada para inicializar p. La asignacin a 29*p tiene como resultado la inicializacin de i, pero la inclusin de esta inicializacin corresponde al 32 30 33programador, y no habr ningn error en tiempo de compilacin si se quita la asignacin. 34Las reglas de asignacin definitiva para el operador & permiten evitar tal inicializacin redundante de variables 35locales. Por ejemplo, muchas interfaces API externas toman un puntero a una estructura que rellena la API. Las 36llamadas a esas API suelen pasar la direccin de una variable de estructura local, y sin esta regla, se requerira 37una inicializacin redundante de la variable. 3818.5.5 Incremento y decremento de punteros 39En un contexto no seguro, los operadores ++ y -- (7.5.9 y 7.6.5) se pueden aplicar a las variables de todos los 40tipos de puntero excepto void*. As, por cada tipo de puntero T*, se definen de manera implcita los siguientes 41operadores: 42 43T* opera to r + +(T* x ) ; T* opera to r - - (T* x ) ;

785380

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

786

Captulo 18 Cdigo no seguro

1Los operadores generan los mismos resultados que x+1 y x - 1 respectivamente (18.5.6). En otras palabras, , 2para una variable de puntero de tipo T*, el operador ++ agrega sizeof(T) a la direccin contenida en la 3variable, y el operador -- resta sizeof(T) de la direccin contenida en la variable. 4Si una operacin de incremento o disminucin de puntero desborda el dominio del tipo de puntero, se define 5dependiendo de la implementacin, pero no se producen excepciones. 618.5.6 Aritmtica con punteros 7En un contexto no seguro, los operadores + y - (7.7.4 y 7.7.5) se pueden aplicar a los valores de todos los 8tipos de puntero excepto void*. As, por cada tipo de puntero T*, se definen de manera implcita los siguientes 9operadores: 10 11 12 14 13 15 16 18 17 19T* operator +(T* x, int y); T* operator +(T* x, uint y); T* operator +(T* x, long y); T* operator +(int x, T* y); T* operator +(uint x, T* y); T* operator +(long x, T* y); T* operator (T* x, int y); T* operator (T* x, uint y);

20 T* operator (T* x, long y); 22 long operator (T* x, T* y); 21 23Dada una expresin P de un tipo de puntero T* y una expresin N de tipo int, uint, long o ulong, las 24expresiones P + N y N + P calculan el valor de puntero de tipo T* que resulta de agregar N * sizeof(T) a la 25direccin dada por P. De igual forma, la expresin P - N calcula el valor de puntero de tipo T* que resulta de 26restar N * sizeof(T) de la direccin dada por P. 27Dadas dos expresiones, P y Q, de un tipo de puntero T*, la expresin P Q calcula la diferencia entre las 28direcciones dadas por P y Q y a continuacin divide la diferencia por sizeof(T). El tipo del resultado siempre es 29long. En efecto, P - Q se calcula como ((long)(P) - (long)(Q)) / sizeof(T). 30Por ejemplo: 31 32 33 34 35 36 37 38using System; class Test { static void Main() { unsafe { int* values = stackalloc int[20]; int* p = &values[1]; int* q = &values[15];

39 Console.WriteLine("p - q = {0}", p - q); 44produce el resultado: 40 41 45 42 46p - q = -14 q - p = 14 381

787Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos. 43

788Especificacin del lenguaje C#

1Si una operacin de aritmtica de punteros desborda el dominio del tipo de puntero, se trunca el resultado 2dependiendo de la implementacin, pero no se producen excepciones.

789382

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

790

Captulo 18 Cdigo no seguro

118.5.7 Comparacin de punteros 2En un contexto no seguro, los operadores == , !=, , (7.9) pueden aplicarse a valores de todos 3los tipos de puntero. Los operadores de comparacin de punteros son: 4 bool operator ==(void* x, void* y); 5 bool operator !=(void* x, void* y); 6 bool operator (void* x, void* y); 8 bool operator =(void* x, void* y); 10Dado que existe una conversin implcita entre cualquier tipo de puntero y el tipo void*, pueden compararse 11operandos de cualquier tipo de puntero mediante estos operadores. Los operadores de comparacin comparan 12las direcciones proporcionadas por los dos operandos como si fueran enteros sin signo. 1318.5.8 Operador Sizeof 14El operador s i zeo f devuelve el nmero de bytes ocupados por una variable de un tipo dado. El tipo especificado 15como uno de los operandos de s i zeo f debe ser de un tipo no administrado (unmanaged-type) (18.2). 16 17sizeof-expression: sizeof ( unmanaged-type )

18El resultado del operador sizeof es un valor de tipo int. Para ciertos tipos predefinidos, el operador sizeof 19produce un valor constante, como se muestra en la tabla siguiente.20

Expresinsizeof(sbyte) sizeof(byte) sizeof(short) sizeof(ushort) sizeof(int) sizeof(uint) sizeof(long) sizeof(ulong) sizeof(char) sizeof(float) sizeof(double) sizeof(bool)

Resultado1 1 2 2 4 4 8 8 2 4 8 1

21 22Para todos los dems tipos, el resultado del operador sizeof se define segn la implementacin y se clasifica 23como un valor, no como una constante. 24El orden en que se empaquetan los miembros en una estructura no est especificado.

791Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

383

792Especificacin del lenguaje C#

1Para fines de alineacin, puede haber un relleno sin nombre al comienzo de una estructura, dentro de una 2estructura y al final de una estructura. El contenido de los bits utilizados para el relleno es indeterminado. 3Al aplicarse a un operando con tipo de estructura, el resultado es el nmero total de bytes de una variable de ese 4tipo, incluidos los bytes de relleno. 518.6 Instruccin fixed 6En un contexto no seguro, la instruccin incrustada (embedded-statement) (8) permite una construccin 7adicional, la instruccin f i xedque se utiliza para fijar una variable mvil de manera que su direccin , 8permanece constante en toda la duracin de la instruccin. 9 10 11 12 13 14 15 16 17 18 19 20 21embedded-statement: ... fixed-statement fixed-statement: f i xed ( pointer-type fixed-pointer-declarators ) embedded-statement fixed-pointer-declarators: fixed-pointer-declarator fixed-pointer-declarators , fixed-pointer-declarator fixed-pointer-declarator: identifier = fixed-pointer-initializer fixed-pointer-initializer: & variable-reference expression

22Cada declarador de puntero fijo (fixed-pointer-declarator) declara una variable local del tipo de puntero 23(pointer-type) dado e inicializa dicha variable con la direccin calculada por el inicializador de puntero fijo 24(fixed-pointer-initializer) correspondiente. Una variable local declarada en una instruccin f i xed accesible en es 25cualquier inicializador de puntero fijo (fixed-pointer-initializer) situado a la derecha de la declaracin de la 26variable, y en la instruccin incrustada (embedded-statement) de la instruccin f i xedUna variable local . 27declarada por una instruccin fixed se considera de slo lectura. Se producir un error en tiempo de compilacin 28si la instruccin incrustada intenta modificar esta variable local (por medio de asignacin o utilizando los 29operadores ++ y --) o bien si la pasa como un parmetro ref o out. 30Un inicializador de puntero fijo (fixed-pointer-initializer) puede ser uno de los siguientes: 31 32 33 34 35 36 37 38 39 40 41 42 43 44793384

El smbolo (token) & seguido de una referencia de variable (variable-reference) (5.3.3) a una variable mvil (18.3) de un tipo no administrado T, siempre que el tipo T* sea implcitamente convertible al tipo de puntero proporcionado en la instruccin fixed. En este caso, el inicializador calcula la direccin de la variable dada, y se garantiza que sta permanecer en una direccin fija durante toda la ejecucin de la instruccin fixed. Una expresin de un tipo de matriz (array-type) con elementos de un tipo no administrado T, siempre que el tipo T* sea implcitamente convertible al tipo de puntero proporcionado por la instruccin fixed. En este caso, el inicializador calcula la direccin del primer elemento de la matriz, y se garantiza que toda la matriz permanecer en una direccin fija durante toda la ejecucin de la instruccin fixed. El comportamiento de la instruccin fixed se define segn sea su implementacin si la expresin de matriz es nula o la matriz contiene cero elementos. Una expresin de tipo string, siempre que el tipo char* sea implcitamente convertible al tipo de puntero proporcionado en la instruccin fixed. En este caso, el inicializador calcula la direccin del primer carcter de la cadena, y se garantiza que toda la cadena permanecer en una direccin fija durante toda la ejecucin

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

794

Captulo 18 Cdigo no seguro

1 2

de la instruccin f i xedEl comportamiento de la instruccin f i xed define segn sea su implementacin si . se la expresin de cadena es nula.

3Por cada direccin calculada por un inicializador de puntero fijo (fixed-pointer-initializer), la instruccin f i xed 4garantiza que la variable a la que hace referencia la direccin no est sujeta a reubicacin o eliminacin por el 5recolector de elementos no utilizados en toda la duracin de la instruccin f i xedPor ejemplo, si la direccin . 6calculada por un inicializador de puntero fijo (fixed-pointer-initializer) hace referencia a un campo de un objeto 7o un elemento de una instancia de matriz, la instruccin fixed garantiza que la instancia de objeto contenedora 8no se reubicar ni eliminar en toda la duracin de la instruccin. 9Es responsabilidad del programador asegurarse de que los punteros creados mediante instrucciones f i xed no 10permanecen tras la ejecucin de dichas instrucciones. Por ejemplo, cuando se pasan punteros creados con 11instrucciones f i xed interfaces API externas, es responsabilidad del programador asegurarse de que las API no a 12retienen memoria de estos punteros. 13Los objetos fijos pueden provocar la fragmentacin del montn al no poder moverse. Por este motivo, los 14objetos deben ser fijos slo cuando sea absolutamente necesario y por el menor tiempo posible. 15En el ejemplo 16 c lass Tes t 17 { 18 s ta t i c i n t x ; 19 int y; 20 unsa fe s ta t i c vo id F ( i n t * p) { 21 *p = 1 ; 22 } 23 s ta t i c vo id Main ( ) { 24 Tes t t = new Tes t ( ) ; 25 i n t [ ] a = new i n t [10 ] ; 26 unsa fe { 27 f i xed ( i n t * p = &x) F (p ) ; 28 f i xed ( i n t * p = &t .y ) F (p ) ; 29 f i xed ( i n t * p = &a[0 ] ) F (p ) ; 30 f i xed ( i n t * p = a) F (p ) ; 31 } 34se muestran varios usos de la instruccin f i xedLa primera instruccin fija y obtiene la direccin de un campo . 32esttico, la segunda fija y obtiene la direccin de un campo de instancia, y la tercera fija y obtiene la direccin 35 33de un elemento de matriz. En cada caso hubiera sido un error utilizar el operador & habitual, ya que las variables 36 37se clasifican todas como variables mviles. 38La tercera y cuarta instruccin f i xed ejemplo anterior producen idnticos resultados. En general, para una del 39instancia de matriz a, especificar &a[0] en una instruccin fixed es lo mismo que especificar simplemente a. 40Este es otro ejemplo de la instruccin fixed, esta vez utilizando string: 41 42 43 44 45 46 47c lass Tes t { s ta t i c s t r i ng name = "xx" ; unsa fe s ta t i c vo id F (char* p) { f o r ( i n t i = 0 ; p[ i ] != ' \ 0 ' ; + ) +i Conso le .Wr i teL ine (p [ i ] ) ; } 385

795Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

796Especificacin del lenguaje C#

1 2 3 4

static void Main() { unsafe { fixed (char* p = name) F(p); fixed (char* p = "xx") F(p);

5En una matriz de contexto no seguro, los elementos de matrices multidimensionales se almacenan por orden de } 8 9ndice creciente, comenzando con el ndice 0 y terminando con el ndice Length 1. Los elementos de matrices 6 10multidimensionales se almacenan de manera que los ndices de la dimensin del extremo derecho se 11incrementan en primer lugar, a continuacin la dimensin situada inmediatamente a su izquierda, etc., siguiendo 7 12por la izquierda. Dentro de una instruccin fixed que obtiene un puntero p a una instancia de matriz a, los 13valores de puntero comprendidos entre p y p + a.Length - 1 representan direcciones de los elementos de la 14matriz. De igual forma, las variables comprendidas en el intervalo de p[0] a p[a.Length - 1] representan los 15propios elementos de la matriz. Dada la forma en que se almacenan las matrices, se puede tratar una matriz de 16cualquier dimensin como si fuera lineal. 17Por ejemplo: 18 19 20 21 22 23 24 25 29 26 30 27 31 28 32using System; class Test { static void Main() { int[,,] a = new int[2,3,4]; unsafe { fixed (int* p = a) { for (int i = 0; i < 2; ++i) for (int j = 0; j < 3; ++j) { for (int k = 0; k < 4; ++k) Console.Write("[{0},{1},{2}] = {3,2} ", i, j, k, a[i,j,k]);

33 Console.WriteLine(); 37produce el resultado: 34 38 [0,0,0] = 0 [0,0,1] = 1 [0,0,2] = 35 39 36 40[0,1,0] = [0,2,0] = 4 [0,1,1] = 8 [0,2,1] = 5 [0,1,2] =

2 [0,0,3] = 6 [0,1,3] =

3 7

9 [0,2,2] = 10 [0,2,3] = 11

41 [1,0,0] = 12 [1,0,1] = 13 [1,0,2] = 14 [1,0,3] = 15 44En el siguiente ejemplo: 42 45 class Test 43 46 { 47 48797386

unsafe static void Fill(int* p, int count, int value) {

49

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

798

Captulo 18 Cdigo no seguro

1 2 3 4

static void Main() { int[] a = new int[100]; unsafe { fixed (int* p = a) Fill(p, 100, -1);

5se utiliza una instruccin f i xed } 8 para fijar una matriz de manera que pueda pasarse su direccin a un mtodo que 9toma un puntero. 6 7

799Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

387

800Especificacin del lenguaje C#

1Un valor char* producido al fijar una instancia de cadena siempre apunta a una cadena terminada en null. 2Dentro de una instruccin fixed que obtiene un puntero p a una instancia de cadena s, los valores de puntero 3comprendidos entre p y p + s.Length - 1 representan direcciones de los caracteres de la cadena, y el valor de 4puntero p + s.Length siempre apunta a un carcter null (el carcter con valor '\0'). 5La modificacin de objetos de tipo administrado mediante punteros fijos puede producir un comportamiento 6indefinido. Por ejemplo, dado que las cadenas son invariables, es responsabilidad del programador asegurarse de 7que los caracteres de una cadena fija a los que hace referencia un puntero no se modifiquen. 8La terminacin automtica en null de cadenas es especialmente cmoda al llamar a interfaces API externas que 9esperan cadenas de estilo C. Observe, sin embargo, que no se permite una instancia de cadena que contenga 10caracteres null. Si se detectan dichos caracteres null, la cadena aparecer truncada al tratarla como char* 11terminada en null. 1218.7 Asignacin de pila 13En un contexto no seguro, una declaracin de variable local (8.5.1) puede incluir un inicializador de asignacin 14de pila que asigne memoria de la pila de llamadas. 15 16 17 18 19 20local-variable-initializer: expression array-initializer stackalloc-initializer stackalloc-initializer: stackalloc unmanaged-type [ expression ]

21El tipo no administrado (unmanaged-type) indica el tipo de los elementos que se almacenarn en la ubicacin 22recin asignada, y la expresin (expression) indica el nmero de estos elementos. Tomados juntos, especifican el 23tamao de asignacin requerido. Dado que el tamao de una asignacin de pila no puede ser negativo, supone 24un error en tiempo de compilacin especificar el nmero de elementos como una expresin constante (constant25expression) que se evala como un nmero negativo. 26Un inicializador de asignacin de pila de la forma stackalloc T[E] requiere que T sea un tipo no administrado 27(18.2) y E sea una expresin de tipo int. La construccin asigna E * sizeof(T) bytes de la pila de llamadas y 28devuelve un puntero de tipo T* al bloque recin asignado. Si E es un valor negativo, el comportamiento es 29indefinido. Si E es cero, no se realiza ninguna asignacin, y el puntero devuelto se define segn su 30implementacin. Si no hay memoria suficiente disponible para asignar un bloque del tamao dado, se inicia una 31excepcin System.StackOverflowException. 32El contenido de la memoria recin asignada es indefinido. 33No se permiten los inicializadores de asignacin de pila en bloques catch o finally (8.10). 34No hay forma de liberar explcitamente la memoria asignada con stackalloc. Todos los bloques asignados de 35memoria de la pila y creados durante la ejecucin de un miembro de funcin se descartan automticamente 36cuando ste devuelve un valor. Esto se corresponde con la funcin alloca, una extensin habitual en las 37implementaciones de C y C++.

801388

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

802

Captulo 18 Cdigo no seguro

1En el siguiente ejemplo: 2 3 4 5 6 7 8 9 10 11 18 12 19 13using System; class Test { static string IntToString(int value) { int n = value >= 0? value: -value; unsafe { char* buffer = stackalloc char[16]; char* p = buffer + 16; do { *--p = (char)(n % 10 + '0'); static void Main() { Console.WriteLine(IntToString(12345));

20 Console.WriteLine(IntToString(-999)); 14 23se utiliza un inicializador s tacka l l oc el mtodo I n t ToS t r i ng asignar un bfer de 16 caracteres en la pila. en para 21 15 24El bfer queda descartado automticamente cuando el mtodo devuelve un valor. 22 16 2518.8 Asignacin dinmica de memoria 17 26Salvo por el operador s tacka l l oc no proporciona construcciones predefinidas para administrar memoria no , C# 27recolectada por el recolector de elementos no utilizados. Tales servicios suelen proporcionarlos bibliotecas de 28clases auxiliares o importadas directamente del sistema operativo subyacente. Por ejemplo, la clase Me mory de 29abajo muestra cmo es posible obtener acceso desde C# a las funciones del montn de un sistema operativo 30subyacente: 31 32 33 34 35 37 36 38 39 40 41 42 43 44 45803Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

using System; using System.Runtime.InteropServices; public unsafe class Memory { // Handle for the process heap. This handle is used in all calls to the static int ph = GetProcessHeap(); // Private instance constructor to prevent instantiation. private Memory() {} // Allocates a memory block of the given size. The allocated memory is // automatically initialized to zero. public static void* Alloc(int size) { void* result = HeapAlloc(ph, HEAP_ZERO_MEMORY, size); if (result == null) throw new OutOfMemoryException();

46

389

804Especificacin del lenguaje C#

1 2 3 4 5 6 7 8 9 13 14 10 15 11 16 17 12 18 19 20 21 22 23 25 24 26 27 28 29 31 30 32 33 34 35 36 37 38 39 40 41 42 43 44 45

// Copies count bytes from src to dst. The source and destination // blocks are permitted to overlap. public static void Copy(void* src, void* dst, int count) { byte* ps = (byte*)src; byte* pd = (byte*)dst; if (ps > pd) { for (; count != 0; count--) *pd++ = *ps++; } // Frees a memory block. public static void Free(void* block) { if (!HeapFree(ph, 0, block)) throw new InvalidOperationException(); // Re-allocates a memory block. If the reallocation request is for a // larger size, the additional region of memory is automatically public static void* ReAlloc(void* block, int size) { void* result = HeapReAlloc(ph, HEAP_ZERO_MEMORY, block, size); if (result == null) throw new OutOfMemoryException(); // Returns the size of a memory block. public static int SizeOf(void* block) { int result = HeapSize(ph, 0, block); if (result == -1) throw new InvalidOperationException(); // Heap API flags const int HEAP_ZERO_MEMORY = 0x00000008; // Heap API functions [DllImport("kernel32")] static extern int GetProcessHeap(); [DllImport("kernel32")] static extern void* HeapAlloc(int hHeap, int flags, int size); [DllImport("kernel32")] static extern bool HeapFree(int hHeap, int flags, void* block); [DllImport("kernel32")] static extern void* HeapReAlloc(int hHeap, int flags, [DllImport("kernel32")] static extern int HeapSize(int hHeap, int flags, void* block);

805390

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

806

Captulo 18 Cdigo no seguro

1A continuacin se muestra un ejemplo que utiliza la clase Me mory : 2 3 4 5 6 7 8 9 10class Test { static void Main() { unsafe { byte* buffer = (byte*)Memory.Alloc(256); try { for (int i = 0; i < 256; i++) buffer[i] = (byte)i; byte[] array = new byte[256]; fixed (byte* p = array) Memory.Copy(buffer, p, 256);

11 } 19 mory.A l l oce inicializa el bloque de memoria con valores 12El ejemplo asigna 256 bytes de memoria mediante Me 20crecientes de 0 a 255. A continuacin, asigna una matriz de bytes de 256 elementos y utiliza Me mory.Copy para 13copiar el contenido del bloque de memoria en la matriz de bytes. Por ltimo, se libera el bloque de memoria 21 22mediante Memory.Free y se enva el contenido de la matriz de bytes como resultado a la consola. 14 15 16 17 18

807Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

391

808Especificacin del lenguaje C#

1

A.Comentarios de documentacin

2C# proporciona un mecanismo para que los programadores puedan documentar el cdigo mediante una sintaxis 3de comentarios que contiene texto XML. En los archivos de cdigo fuente, es posible utilizar comentarios con 4un cierto formato para indicar a una herramienta que genere texto XML a partir de estos comentarios y de los 5elementos de cdigo fuente a los que precede. Los comentarios que utilizan esta sintaxis se denominan 6comentarios de documentacin. Deben preceder inmediatamente a un tipo definido por el usuario (como una 7clase, una estructura o una interfaz) o a un miembro (como un campo, un evento, una propiedad o un mtodo). 8La herramienta de generacin de XML se denomina generador de documentacin. (Este generador podra ser, 9pero no es necesario que as sea, el propio compilador de C#.) El resultado producido por el generador de 10documentacin se denomina archivo de documentacin. Un archivo de documentacin se utiliza como entrada 11a un visor de documentacin, una herramienta pensada para generar alguna ordenacin de presentacin visual 12de informacin de tipo y su documentacin asociada. 13Esta especificacin sugiere el uso de un conjunto de etiquetas en los comentarios de esta clase de 14documentacin, sin embargo, siempre que se respete la correcta sintaxis del lenguaje XML, se puede utilizar el 15conjunto de etiquetas que se desee para este fin. 16A.1 Introduccin 17Es posible utilizar comentarios con un formato determinado para indicar a una herramienta que genere texto 18XML a partir de los mismos y de los elementos de cdigo fuente a los que preceden. Tales comentarios pueden 19ser: comentarios de una sola lnea que comienzan con tres barras diagonales (/ / ), o comentarios delimitados que / 20van precedidos de una barra diagonal y dos asteriscos (/ * * Deben preceder inmediatamente al tipo definido por ). 21el usuario (como una clase, un delegado o una interfaz) o al miembro (como un campo, un evento, una 22propiedad o un mtodo) al que hacen referencia los comentarios. Las secciones de atributos (17.2) se 23consideran parte de las declaraciones; por lo tanto, los comentarios de documentacin deben preceder a los 24atributos que se aplican a un tipo o a un miembro. 25Sintaxis: 26 27 28 29single-line-doc-comment: / / / input-charactersopt delimited-doc-comment: / * * delimited-comment-charactersopt * /

30En un comentario de una sola lnea (single-line-doc-comment), si aparece un carcter de espacio en blanco 31(whitespace) a continuacin de los caracteres / / / cada uno de los comentarios de documentacin de una sola en 32lnea (single-line-doc-comments), adyacentes al comentario de documentacin de una sola lnea (single-line33doc-comment) actual, el carcter de espacio en blanco (whitespace) no se incluir en los resultados XML. 34En un comentario de documentacin delimitado (delimited-doc-comment), si el primer carcter distinto del 35espacio en blanco (whitespace) es un asterisco y el mismo patrn de caracteres opcionales de espacio en blanco 36y un carcter de asterisco se repite al principio de cada una de las lneas dentro del comentario de 37documentacin delimitado (delimited-doc-comment), entonces los caracteres del patrn repetido no se incluyen 38en el cdigo XML resultante. El patrn puede incluir caracteres de espacio en blanco (whitespace) antes y 39despus del carcter de asterisco.

809392

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

810

Apndice A Comentarios de documentacin

1Ejemplo: 2 3 4 5/// Class Point models a point in a two-dimensional /// plane. /// public class Point

6 { 10El texto de los comentarios de documentacin debe estar correctamente estructurado segn las reglas del 7 11lenguaje XML (http://www.w3.org/TR/REC-xml). Si hay incorrecciones en el texto XML, se generar una 12advertencia y el archivo de documentacin incluir un comentario que har referencia al error encontrado. 8 13Aunque los desarrolladores pueden crear su propio juego de etiquetas, existe un juego recomendado en la 9 14seccin 18.8. Algunas de las etiquetas recomendadas tienen significados especiales: 15 16 17 18 19 20 21 22 23 24 25 26La etiqueta se utiliza para describir parmetros. Si se utiliza dicha etiqueta, el generador de documentacin deber comprobar que el parmetro especificado existe y que todos los parmetros se encuentran descritos en los comentarios de documentacin. Si esta comprobacin encuentra algn error, el generador de documentacin emitir una advertencia. El atributo c re fse puede asociar a cualquier etiqueta para proporcionar una referencia a un elemento de cdigo. El generador de documentacin debe comprobar si existe dicho elemento de cdigo. Si la comprobacin no tiene xito, el generador de documentacin emite una advertencia. Al buscar un nombre descrito en un atributo c re f el generador de la documentacin debe respetar la visibilidad de espacio de , nombres segn las instrucciones using que aparecen dentro del cdigo fuente. La etiqueta est pensada para su uso en un visor de documentacin para mostrar informacin adicional sobre un tipo o un miembro. La etiqueta incluye informacin de un archivo XML externo.

27Observe que el archivo de documentacin no proporciona informacin completa sobre el tipo y los miembros 28(por ejemplo, no contiene ninguna informacin de tipos). Para obtener tal informacin acerca de un tipo o un 29miembro, el archivo de documentacin debe utilizarse conjuntamente con el mecanismo de reflexin sobre el 30tipo o el miembro real. 31A.2 Etiquetas recomendadas 32El generador de documentacin debe aceptar y procesar todas aquellas etiquetas que sean vlidas segn las 33reglas de XML. Las siguientes etiquetas proporcionan la funcionalidad habitual en la documentacin de usuario. 34(Por supuesto, se pueden utilizar otras etiquetas).35

811Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

393

812Especificacin del lenguaje C#

Etiqueta

Seccin18.8 18.8 18.8 18.8 18.8 18.8 18.8 18.8 18.8 18.8 18.8 18.8 18.8 18.8 18.8 18.8

Finalidad Establecer un tipo de fuente de cdigo para un texto Establecer una o ms lneas de cdigo fuente o indicar el final de un programa Indicar un ejemplo Identifica las excepciones que pueden iniciar un mtodo Incluye XML procedente de un archivo externo Crear una lista o una tabla Permite agregar una estructura al texto Describe un parmetro para un mtodo o constructor Identifica una palabra como nombre de parmetro Documenta la accesibilidad de seguridad de un miembro Describe un tipo Describe el valor devuelto de un mtodo Especifica un vnculo Genera una entrada de tipo Vea tambin Describe un miembro de un tipo Describe una propiedad

36

37A.2.1 38Esta etiqueta proporciona un mecanismo para indicar que se debe establecer una fuente especial para un 39fragmento de texto dentro de una descripcin, tal como la que se usa para un bloque de cdigo. Para lneas de 40cdigo real, utilice (18.8). 41Sintaxis: 42 text 43Ejemplo: 44 / / / C lass Po in t< /c> mode l s a po in t i n a two - d imens iona l m 45 / / / p lane .< /sum mary> 46 pub l i c c lass Po in t 47 { 48 // ... 49 } 50A.2.2 51Esta etiqueta se utiliza para establecer una o ms lneas de cdigo fuente o para indicar el final de un programa 52en alguna fuente especial. Para pequeos fragmentos de cdigo en texto narrativo, utilice (18.8). 53Sintaxis:

813394

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

814

Apndice A Comentarios de documentacin

1 source code or program output 2Ejemplo: 3 4 5 6 7 8 9 13 10 14/// This method changes the point's location by /// the given x- and y-offsets. /// For example: /// /// /// Point p = new Point(3,5); p.Translate(-1,3);

public void Translate(int xor, int yor) { X += xor;

11 15 Y += yor; 17 12A.2.3 16 18Esta etiqueta permite cdigo de ejemplo dentro de un comentario, para especificar cmo puede utilizarse un 19mtodo u otro miembro de biblioteca. Generalmente, esto tambin supone la utilizacin de la etiqueta 20(18 .8). 21Sintaxis: 22 description 23Ejemplo: 24Vea ( 18.8) para obtener un ejemplo. 25A.2.4 26Esta etiqueta proporciona un medio para documentar las excepciones que puede iniciar un mtodo. 27Sintaxis: 28 description 29donde30

cref="m mber " e

31 3233

El nombre de un miembro. El generador de documentacin comprueba si el miembro en cuestin existe y traduce member al nombre del elemento cannico en el archivo de documentacin.description

34

Descripcin de las circunstancias en las que se inicia la excepcin.

35Ejemplo:

815Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

395

816Especificacin del lenguaje C#

1 2 3 4 5 6 7

public class DataBaseOperations { /// /// public static void ReadRecord(int flag) { if (flag == 1) throw new MasterFileFormatCorruptException();

8 13A.2.5 9 14Esta etiqueta permite incluir informacin de un documento XML externo al archivo de cdigo fuente. El archivo 15externo debe ser un documento XML sin errores; al documento se aplica una expresin XPath para especificar 10 16qu parte de la sintaxis XML del documento debe incluirse. La etiqueta se sustituye entonces por el 11texto XML seleccionado del documento externo. 17 18 12Sintaxis: 19 20donde 21 22 23 24 25f i l e="filename"

Nombre de un archivo XML externo. El nombre del archivo se interpreta en relacin con el archivo que contiene la etiqueta include.path=" xpath"

Una expresin XPath que selecciona parte del cdigo XML del archivo XML externo.

26Ejemplo: 27Si el cdigo fuente contuviera una declaracin como la siguiente: 28 / / / 29 pub l i c c lass I n tL i s t { } 30y el archivo externo docs .xml tuviera el siguiente contenido: 31 32 33 34 m 35 Conta ins a l i s t o f i n tegers . 36 37 38 39 m 40 Conta ins a l i s t o f i n tegers . 41 44entonces la documentacin resultante sera la misma que si el cdigo fuente contuviera: 42 43817396Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

818

Apndice A Comentarios de documentacin

1 2

/// /// Contains a list of integers.

3 /// 5A.2.6 4 6Esta etiqueta se utiliza para crear una lista o tabla de elementos. Puede contener un bloque para 7definir la fila de encabezado de una tabla o de una lista de definiciones. (Cuando se define una tabla, slo es 8necesario suministrar una entrada para te rm en el encabezado.) 9Cada elemento de la lista se especifica con un bloque . Al crear una lista de definiciones, es necesario 10especificar tanto te rm como description. Sin embargo, para una tabla, lista con vietas o lista numerada, slo 11es necesario especificar description.

819Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

397

820Especificacin del lenguaje C#

1Sintaxis: 2 3 4 5 6 7 8 9 10 17donde 11 12 19 1320 18

term description term description

term

El trmino que se desea definir, cuya definicin se encuentra en desc r i p t i on .description

14 21 Puede ser el elemento de una lista numerada o con vietas, o la definicin de un te rm. 15Ejemplo: 22 16 23 24 25 26 27 28 29 30 31public class MyClass { /// Here is an example of a bulleted list: /// /// /// Item 1. /// /// /// Item 2.

32 /// 39A.2.7 33 40Este etiqueta debe utilizarse dentro de otras, como (18 .8) o (18.8) y permite 34agregar la estructura al texto. 41 35Sintaxis: 42 36 43 conten t 44donde 3745 38 46

content

Texto del prrafo.

821398

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

822

Apndice A Comentarios de documentacin

1Ejemplo: 2 3 4 5/// This is the entry point of the Point class testing program. /// This program tests each method and operator, and /// is intended to be run after any non-trvial maintenance has /// been performed on the Point class.

6 public static void Main() { 9A.2.8 7 10Esta etiqueta se utiliza para describir un parmetro para un mtodo, constructor o indizador. 8 11Sintaxis: 12 description 13donde14

name

1516

Nombre del parmetro.description

17 19 20 21 22 23

Una descripcin del parmetro.

18Ejemplo:/// This method changes the point's location to /// the given coordinates. /// the new x-coordinate. /// the new y-coordinate. public void Move(int xor, int yor) {

24A.2.9 27 28 25Esta etiqueta se utiliza para indicar que una palabra es un parmetro. El archivo de documentacin se puede 29procesar de manera que aplique un formato diferente a este parmetro. 26 30Sintaxis: 31 32donde33

name

34 36 37 38 39

Nombre del parmetro.

35Ejemplo:/// This constructor initializes the new Point to /// (,). /// the new Point's x-coordinate.

823Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

399

824Especificacin del lenguaje C#

1 2

public Point(int xor, int yor) { X = xor;

3 Y = yor; 5A.2.10 4 6Esta etiqueta permite documentar la accesibilidad de seguridad de un miembro. 7Sintaxis: 8 description 9donde10

cref="m mber " e

11 1213

El nombre de un miembro. El generador de documentacin comprueba si el elemento de cdigo dado existe y traduce member al nombre del elemento cannico en el archivo de documentacin.description

14

Descripcin del acceso al miembro.

15Ejemplo: 16 / / / Everyone can 17 / / / access th i s method .< /pe rmiss ion> 18 pub l i c s ta t i c vo id Tes t ( ) { 19 // ... 20 } 21A.2.11 22Esta etiqueta se utiliza para especificar informacin general sobre un tipo. (Utilice (18 .8) para 23describir los miembros de un tipo.) 24Sintaxis:25

desc r i p t i on description

26donde27

2830 31 32 33 34 35

Incluye el texto del resumen./ / / C lass Po in t< /c> mode l s a po in t i n a m / / / two - d imens iona l p lane .< /sum mary> pub l i c c lass Po in t { // ... }

29Ejemplo:

36A.2.12 37Esta etiqueta se utiliza para describir el valor devuelto de un mtodo. 38Sintaxis:39

desc r i p t i on

825400

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

826

Apndice A Comentarios de documentacin

1donde2

description

3

Descripcin del valor devuelto.

827Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

401

828Especificacin del lenguaje C#

1Ejemplo: 2 3 4/// Report a point's location as a string. /// A string representing a point's location, in the form (x,y), /// without any leading, trailing, or embedded whitespace.

5 public override string ToString() { 8A.2.13 6 9Esta etiqueta permite especificar un vnculo dentro del texto. Utilice (18 .8) para indicar el texto 7 10que debe aparecer en una seccin Vea tambin. 11Sintaxis: 12 13donde14

cref="m mber " e

15 16

El nombre de un miembro. El generador de documentacin comprueba si el elemento de cdigo dado existe y cambia member por el nombre del elemento en el archivo de documentacin generado.

17Ejemplo: 18 / / / Th i s method changes the po in t ' s l oca t i on to m 19 /// the g iven coord ina tes .< /sum mary> 20 / / / 21 pub l i c vo id Move( in t xor , i n t yor ) { 22 X = xor ; 23 Y = yor ; 25 / / / Th i s method changes the po in t ' s l oca t i on by m 24 26 /// the g iven x - and y - o f f se ts . 27 / / / 28 / / / 29 pub l i c vo id Trans la te ( i n t xor , i n t yor ) { 30 X + xor ; = 31 Y + yor ; = 33 32A.2.14 34Esta etiqueta permite generar una entrada para la seccin Vea tambin. Utilice (18 .8) para especificar 35un vnculo desde dentro del texto. 36Sintaxis: 37 38donde39

cref="m mber " e

40 41

El nombre de un miembro. El generador de documentacin comprueba si el elemento de cdigo dado existe y cambia member por el nombre del elemento en el archivo de documentacin generado.

829402

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

830

Apndice A Comentarios de documentacin

1Ejemplo: 2 3 4 5/// This method determines whether two Points have the same /// location. /// ///

6 public override bool Equals(object o) { 9A.2.15 7 10Esta etiqueta se utiliza para describir un miembro de un tipo. Utilice (18 .8) para describir el 11propio tipo. 8 12Sintaxis: 13 description 14donde15

description

16

Un resumen del miembro.

17Ejemplo: 18 / / / Th i s cons t ruc to r i n i t i a l i zes the new Po in t to (0 ,0 ) .< / sum m mary> 19 pub l i c Po in t ( ) : th i s (0 ,0 ) { 20 } 21A.2.16 22Esta etiqueta permite describir una propiedad. 23Sintaxis: 24 proper ty desc r i p t i on 25donde26

property description

27

Descripcin de la propiedad.

28Ejemplo: 29 / / / Proper ty X rep resen ts the po in t ' s x - coord ina te .< /va lue> 30 pub l i c i n t X 31 { 32 get { re tu rn x ; } 33 se t { x = va lue ; } 34 35A.3 Procesar el archivo de documentacin 36El generador de documentacin genera una cadena de id. por cada elemento del cdigo fuente marcado con un 37comentario de documentacin. Esta cadena de id. identifica de forma nica un elemento fuente. Un visor de 38documentacin puede utilizar una cadena de id. para identificar el correspondiente elemento de 39metadatos/reflexin al que se aplica la documentacin. 40El archivo de documentacin no es una representacin jerrquica del cdigo fuente, es una lista sencilla con una 41cadena de id. generada para cada elemento.831Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

403

832Especificacin del lenguaje C#

1A.3.1 Formato de cadena de Id. 2El generador de documentacin cumple las siguientes reglas cuando genera las cadenas de id.: 3 4 56

No se coloca ningn espacio en blanco en la cadena. La primera parte de la cadena identifica el tipo de miembro que se desea documentar por medio de un nico carcter seguido de dos puntos. Se definen los siguientes tipos de miembros: Carcter E F M N P T ! Descripcin Evento Campo Mtodo (incluidos constructores, destructores y operadores) Espacio de nombres Propiedad (incluidos los indizadores) Tipo (tal como class, delegate, enum, interface y struct) Cadena de error; el resto de la cadena proporciona informacin acerca del error. Por ejemplo, el generador de documentacin genera informacin de error para vnculos que no se pueden resolver.

7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24

La segunda parte de la cadena es el nombre completo del elemento, empezando en la raz del espacio de nombres. El nombre del elemento, los tipos contenedores y el espacio de nombres se separan mediante puntos. Si el nombre del elemento ya contiene puntos, stos se reemplazan por caracteres # (U+0023 ). (Se asume que ningn elemento tiene este carcter en su nombre). Para los mtodos y propiedades con argumentos, sigue la lista de argumentos entre parntesis. Si no existen argumentos, los parntesis se omiten. Los argumentos se separan por comas. La codificacin de cada argumento es la misma que una firma CLI, como sigue: los argumentos se representan por su nombre completo. Por ejemplo, i n tse convierte en Sys tem. In t32string se convierte en System.String, object , se convierte en System.Object, y as sucesivamente. Los argumentos que contienen el modificador out o ref llevan un signo @ tras su nombre de tipo. Los argumentos que se pasan por valor o a travs de params no tienen una notacin especial. Los argumentos que son matrices se representan como [ lowerbound : size , , lowerbound : size ], donde el nmero de comas es el rango menos 1, y los lmites inferiores y tamaos de cada dimensin, si se conocen, se representan en formato decimal. Si no se especifica un lmite inferior ni un tamao, se omite. Si el lmite inferior (lowerbound) y el tamao (size) de una dimensin particular se omiten, tambin se omite el signo :. Las matrices escalonadas se representan con un [] por nivel. Los argumentos con tipos de puntero distintos de void se representan con un * a continuacin del nombre de tipo. Un puntero void se representa mediante un nombre de tipo de System.Void.

25A.3.2 Ejemplos de cadena de Id. 26Los siguientes ejemplos muestran cada uno un fragmento de cdigo C#, junto con la cadena de id. que se 27produce a partir de cada elemento de cdigo fuente que puede tener un comentario de documentacin: 28 29Los tipos se representan con su nombre completo.enum Color { Red, Blue, Green }

833404

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

834

Apndice A Comentarios de documentacin

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 21 18 22 19 23 20 24 25 28 26 29 27 30 31 34 32 35 33 36 37 38 39 40 41 42 43

namespace Acme { struct ValueType {...} class Widget: IProcess { public interface IMenuItem {...} public delegate void Del(int i); public enum Direction { North, South, East, West } } "T:Color" "T:Acme.IProcess" "T:Acme.ValueType" "T:Acme.Widget" "T:Acme.Widget.NestedClass" namespace Acme { struct ValueType { { public class NestedClass { private string message; private static Color defaultColor; private const double PI = 3.14159; protected readonly double monthlyAverage; private long[] array1; private Widget[,] array2; class Widget: IProcess

Los campos se representan con su nombre completo.

835Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

405

836Especificacin del lenguaje C#

1 2 3 4 5 6 7 8 9 10

"F:Acme.ValueType.total" "F:Acme.Widget.NestedClass.value" "F:Acme.Widget.message" "F:Acme.Widget.defaultColor" "F:Acme.Widget.PI" "F:Acme.Widget.monthlyAverage"

837406

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

838

Apndice A Comentarios de documentacin

1 2 3 4 5 7 6 8 9 10 11 12 14 13 15 16 17 18 19 22 23 20 21 24 25 26 27 30 28 31 29 32 33 36 34 37 35 38 39 40 41 42 43 44

Constructores.namespace Acme { class Widget: IProcess public Widget() {...} public Widget(string s) {...} } "M:Acme.Widget.#cctor" "M:Acme.Widget.#ctor"

Destructores.namespace Acme { class Widget: IProcess { ~Widget() {...} "M:Acme.Widget.Finalize" namespace Acme { struct ValueType { { public class NestedClass { public static void M0() {...} public void M1(char c, out float f, ref ValueType v) {...} public void M2(short[] x1, int[,] x2, long[][] x3) {...} public void M3(long[][] x3, Widget[][,,] x4) {...} public unsafe void M4(char *pc, Color **pf) {...} public unsafe void M5(void *pv, double *[][,] pd) {...} class Widget: IProcess

Mtodos.

839Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

407

840Especificacin del lenguaje C#

1 2 3 4 5 6 7 8 9

"M:Acme.ValueType.M(System.Int32)" "M:Acme.Widget.NestedClass.M(System.Int32)" "M:Acme.Widget.M0" "M:Acme.Widget.M1(System.Char,System.Single@,Acme.ValueType@)" "M:Acme.Widget.M2(System.Int16[],System.Int32[0:,0:],System.Int64[][])" "M:Acme.Widget.M3(System.Int64[][],Acme.Widget[0:,0:,0:][])"

841408

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

842

Apndice A Comentarios de documentacin

1 2 3 4 5 6 7 11 8 12 9 14 13 10 15 16 17 18 19 22 23 20 21 24 25 26 27 28 31 32 29 33 30 34 35 36 37 38 39 40 43 44 41 45 42 46 47

Propiedades e indizadores.namespace Acme { class Widget: IProcess { public int Width { get {...} set {...} } public int this[int i] { get {...} set {...} } "P:Acme.Widget.Width" "P:Acme.Widget.Item(System.Int32)"

Eventos.namespace Acme { class Widget: IProcess { public event Del AnEvent; "E:Acme.Widget.AnEvent" namespace Acme { class Widget: IProcess { public static Widget operator+(Widget x) {...} "M:Acme.Widget.op_UnaryPlus(Acme.Widget)"

Operadores unarios.

El conjunto completo de nombres de funcin de operadores unarios es el siguiente: op_UnaryP lus , op_UnaryNegat i on op_LogicalNot, op_OnesComplement, op_Increment, op_Decrement, op_True , y op_False. Operadores binarios.namespace Acme { class Widget: IProcess { public static Widget operator+(Widget x1, Widget x2) {...} "M:Acme.Widget.op_Addition(Acme.Widget,Acme.Widget)" El conjunto completo de nombres de funciones de operadores binarios es el siguiente: op_Addition, op_Subtraction, op_Multiply, op_Division, op_Modulus, op_BitwiseAnd, op_BitwiseOr, op_ExclusiveOr, op_LeftShift, op_RightShift, op_Equality, op_Inequality, op_LessThan, op_LessThanOrEqual, op_GreaterThan y op_GreaterThanOrEqual.

843Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

409

844Especificacin del lenguaje C#

1 2 3 4 5 6 10 7

Los operadores de conversin tienen un carcter final ~ seguido del tipo de valor devuelto.namespace Acme { class Widget: IProcess { public static explicit operator int(Widget x) {...} "M:Acme.Widget.op_Explicit(Acme.Widget)~System.Int32"

11 "M:Acme.Widget.op_Implicit(Acme.Widget)~System.Int64" 8 12A.4 Un ejemplo 9 13A.4.1 Cdigo fuente C# 14El ejemplo siguiente muestra el cdigo fuente de una clase Po in t : 15 16 17 18 19 22 20 23 21 24 25 26 27 28 29 30 31 34 32 35 33 36 37 40 38 41 39 42/// Class Point models a point in a two-dimensional plane. /// /// Instance variable x represents the point's /// x-coordinate. namespace Graphics {

/// Instance variable y represents the point's /// y-coordinate.

/// Property X represents the point's x-coordinate. public int X { /// Property Y represents the point's y-coordinate. public int Y { /// This constructor initializes the new Point to /// (0,0). get { return y; } get { return x; }

845410

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

846

Apndice A Comentarios de documentacin

1 2 3 4 5 9 6 10 7 11 8 12 13 14 18 15 19 16 20 17 21 22 23 24 25 26 27 28 35 29 36 30 37 31 38 32 39 33 40 34 41 42 47 43 48

/// This constructor initializes the new Point to /// (,). /// xor is the new Point's x-coordinate. /// yor is the new Point's y-coordinate. public Point(int xor, int yor) { /// This method changes the point's location to /// the given coordinates. /// xor is the new x-coordinate. /// yor is the new y-coordinate. /// public void Move(int xor, int yor) { /// This method changes the point's location by /// the given x- and y-offsets. /// For example: /// /// /// Point p = new Point(3,5); p.Translate(-1,3);

/// /// results in p's having the value (2,8). /// /// /// This method determines whether two Points have the same /// location. /// o is the object to be compared to the current object. /// /// True if the Points have the same location and they have /// the exact same type; otherwise, false. /// if (this == o) { return true;

44 49 45 46

847Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

411

848Especificacin del lenguaje C#

1 2 3 4 7 5 8 6 9 10 13 11

if (GetType() == o.GetType()) { Point p = (Point)o; return (X == p.X) && (Y == p.Y); /// Report a point's location as a string. /// A string representing a point's location, in the form (x,y), /// without any leading, training, or embedded whitespace. public override string ToString() { /// location. }

/// This operator determines whether two Points have the same /// p1 is the first Point to be compared. /// p2 is the second Point to be compared. /// True if the Points have the same location and they have /// the exact same type; otherwise, false. /// /// public static bool operator==(Point p1, Point p2) { if ((object)p1 == null || (object)p2 == null) { return false; /// This operator determines whether two Points have the same /// location. /// p1 is the first Point to be compared. /// p2 is the second Point to be compared. /// True if the Points do not have the same location and the /// exact same type; otherwise, false. /// /// This is the entry point of the Point class testing /// program. /// This program tests each method and operator, and /// is intended to be run after any non-trvial maintenance has /// been performed on the Point class. public static void Main() {

14 12 15 16 17 18 19 20 21 22 23 24 32 25 33 26 34 27 35 28 36 29 37 30 38 43 31 39

44 40 45 41 46 42 47 48 49849412

50 51 52

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

850

Apndice A Comentarios de documentacin

1A.4.2 XML resultante 2ste es el resultado producido por un generador de documentacin habindose proporcionado al mismo el 3cdigo fuente para la clase Po in t como se mostr anteriormente: , 4 5 6 7 8 9 10 15 11 16 12 17 13 19 18 14 20 21 23 22 24 25 27 26 28 29 30 33 31 34 32 35 36 37 38 39 40 Point Instance variable x represents the point's x-coordinate. Instance variable y represents the point's y-coordinate. This constructor initializes the new Point to (0,0). This constructor initializes the new Point to (,). This method changes the point's location to the given coordinates. xor is the new x-coordinate. yor is the new y-coordinate. xor is the new Point's x-coordinate.

851Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

413

852Especificacin del lenguaje C#

1 2 3 4 5 6 7 8 9 10 17 11 18 12 19 13 20 14 21 15 22 16 23 24 30 25 31 26 32 27 33 28 36 34 29 37 35 38 39 40 41 42 43 44 45 46 47853414 48

This method changes the point's location by the given x- and y-offsets. For example: Point p = new Point(3,5); p.Translate(-1,3); results in p's having the value (2,8). This method determines whether two Points have the same location. o is the object to be compared to the current object. True if the Points have the same location and they have the exact same type; otherwise, false. Report a point's location as a string. A string representing a point's location, in the form This operator determines whether two Points have the same location. p1 is the first Point to be compared. p2 is the second Point to be compared. True if the Points have the same location and they have

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

854

Apndice A Comentarios de documentacin

1 2 3 4 5 6 7 8 9 15 10 16 11 17 12 18 13 19 22 14 20 23 21 24 26 25 27 28 29 30 31

This operator determines whether two Points have the same location. p1 is the first Point to be compared. p2 is the second Point to be compared. True if the Points do not have the same location and the This is the entry point of the Point class testing program. This program tests each method and operator, and is intended to be run after any non-trvial maintenance has Property X represents the point's x-coordinate. Property Y represents the point's y-coordinate.

855Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

415

856Especificacin del lenguaje C#

1

B.Gramtica

2Este apndice contiene resmenes de las gramticas lxicas y sintcticas que pertenecen al documento principal, 3as como de las extensiones de gramtica del contexto no seguro. Las construcciones de gramtica aparecen aqu 4en el mismo orden en que aparecen en el documento principal. 5B.1 Gramtica lxica 6 input: 7 input-sectionopt 8 9 10 11 12 13 14 15 16 17 18 19 20input-section: input-section-part input-section input-section-part input-section-part: input-elementsopt new-line pp-directive input-elements: input-element input-elements input-element input-element: whitespace comment token

21B.1.1 Terminadores de lnea 22 new-line: 23 Carcter de retorno de carro (U+000D ) 24 Carcter de salto de lnea (U+000A ) 25 Carcter de retorno de carro (U+000D) seguido de un carcter de salto de lnea (U+000A) 26 Carcter de lnea siguiente (U+0085) 27 Carcter separador de lnea (U+2028) 28 Carcter separador de prrafo (U+2029) 29B.1.2 Espacio en blanco 30 whitespace: 31 Cualquier carcter con clase Unicode Zs 32 Carcter de tabulacin horizontal (U+0009) 33 Carcter de tabulacin vertical (U+000B) 34 Carcter de avance de pgina (U+000C) 35B.1.3 Comentarios 36 comment: 37 single-line-comment 38 delimited-comment857416Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

858

Apndice C Referencias

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28

single-line-comment: / / input-charactersopt input-characters: input-character input-characters input-character input-character: Cualquier carcter Unicode salvo un carcter de nueva lnea (new-line-character) new-line-character: Carcter de retorno de carro (U+000D ) Carcter de salto de lnea (U+000A ) Carcter de lnea siguiente (U+0085) Carcter separador de lnea (U+2028) Carcter separador de prrafo (U+2029) delimited-comment:: / * delimited-comment-textopt asterisks / delimited-comment-text:: delimited-comment-section delimited-comment-text delimited-comment-section delimited-comment-section:: not-asterisk asterisks not-slash asterisks:: * asterisks * not-asterisk: Cualquier carcter Unicode excepto * not-slash: Cualquier carcter Unicode excepto /

29B.1.4 Smbolos 30 token: 31 identifier 32 keyword 33 integer-literal 34 real-literal 35 character-literal 36 string-literal 37 operator-or-punctuator 38B.1.5 Secuencias de escape de caracteres Unicode 39 unicode-escape-sequence: 40 \u hex-digit hex-digit hex-digit hex-digit 41 \U hex-digit hex-digit hex-digit hex-digit hex-digit hex-digit hex-digit hex-digit

859Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

417

860Especificacin del lenguaje C#

1B.1.6 Identifiers 2 identifier: 3 available-identifier 4 @ identifier-or-keyword 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40available-identifier: Un elemento identifier-or-keyword que no sea keyword identifier-or-keyword: identifier-start-character identifier-part-charactersopt identifier-start-character: letter-character _ (carcter de subrayado U+005F ) identifier-part-characters: identifier-part-character identifier-part-characters identifier-part-character identifier-part-character: letter-character decimal-digit-character connecting-character combining-character formatting-character letter-character: Un carcter Unicode de clases Lu, Ll, Lt, Lm, Lo, o Nl Una secuencia de escape Unicode (unicode-escape-sequence) que representa un carcter de clases Lu, Ll, Lt, Lm, Lo o Nl combining-character: Un carcter Unicode de clases Mn o Mc Una secuencia de escape Unicode (unicode-escape-sequence) que representa un carcter de clases Mn o Mc decimal-digit-character: Un carcter Unicode de la clase Nd Una secuencia de escape Unicode (unicode-escape-sequence) que representa un carcter de la clase Nd connecting-character: Un carcter Unicode de la clase Pc Una secuencia de escape Unicode (unicode-escape-sequence) que representa un carcter de la clase Pc formatting-character: Un carcter Unicode de la clase Cf Una secuencia de escape Unicode (unicode-escape-sequence) que representa un carcter de la clase Cf

861418

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

862

Apndice C Referencias

1B.1.7 Palabras clave 2 keyword: una de las siguientes 3 abs t rac t as base boo l break 4 byte case ca tch char checked 5 c lass cons t cont inue dec ima l de fau l t 6 de legate do doub le e l se enu m 7 event exp l i c i t exte rn f a l se f i na l l y 8 f i xed f l oa t fo r f o reach goto 9 if imp l i c i t in int i n te r face 10 i n te rna l is l ock l ong namespace 11 new nu l l ob jec t opera to r out 12 ove r r i de params pr i va te pro tec tedpub l i c 13 readon ly re f re tu rn sby te sea led 14 shor t s i zeo f s tacka l l oc ta t i c s s t r i ng 15 s t ruc t sw i t ch th i s th row t rue 16 t ry t ypeo f u in t u long unchecked 17 unsa fe ushor t us ing v i r tua l vo id 18 vo la t i l e whi l e 19B.1.8 Literales 20 literal: 21 boolean-literal 22 integer-literal 23 real-literal 24 character-literal 25 string-literal 26 null-literal 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44boolean-literal:t rue f a l se

integer-literal: decimal-integer-literal hexadecimal-integer-literal decimal-integer-literal: decimal-digits integer-type-suffixopt decimal-digits: decimal-digit decimal-digits decimal-digit decimal-digit: uno de los siguientes0 U 1 u 2 L 3 l 4 UL 5 Ul 6 7 uL 8 ul 9 LU Lu lU lu

integer-type-suffix: uno de los siguientes hexadecimal-integer-literal: 0x hex-digits integer-type-suffixopt 0X hex-digits integer-type-suffixopt

863Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

419

864Especificacin del lenguaje C#

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44

hex-digits: hex-digit hex-digits hex-digit hex-digit: uno de los siguientes0 1 2 3 4 5 6 7 8 9 A B C D E F a b c d e f

real-literal: decimal-digits . decimal-digits exponent-partopt real-type-suffixopt . decimal-digits exponent-partopt real-type-suffixopt decimal-digits exponent-part real-type-suffixopt decimal-digits real-type-suffix exponent-part: e signopt decimal-digits E signopt decimal-digits sign: uno de los siguientes+ -

real-type-suffix: uno de los siguientesF f D d M m

character-literal: ' character ' character: single-character simple-escape-sequence hexadecimal-escape-sequence unicode-escape-sequence single-character: Cualquier carcter excepto ' (U+0027 ), \ (U+005C), y carcter de nueva lnea (new-linecharacter) simple-escape-sequence: una de las siguientes\' \" \\ \0 \a \b \f \n \r \t \v

hexadecimal-escape-sequence: \x hex-digit hex-digitopt hex-digitopt hex-digitopt string-literal: regular-string-literal verbatim-string-literal regular-string-literal: " regular-string-literal-charactersopt " regular-string-literal-characters: regular-string-literal-character regular-string-literal-characters regular-string-literal-character regular-string-literal-character: single-regular-string-literal-character simple-escape-sequence hexadecimal-escape-sequence unicode-escape-sequence

865420

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

866

Apndice C Referencias

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17

single-regular-string-literal-character: Cualquier carcter excepto " (U+0022 ), \ (U+005C), y un carcter de nueva lnea (new-linecharacter) verbatim-string-literal: @" verbatim -string-literal-charactersopt " verbatim-string-literal-characters: verbatim-string-literal-character verbatim-string-literal-characters verbatim-string-literal-character verbatim-string-literal-character: single-verbatim-string-literal-character quote-escape-sequence single-verbatim-string-literal-character: cualquier carcter excepto " quote-escape-sequence:""

null-literal:null

18B.1.9 Operadores y signos de puntuacin 19 operator-or-punctuator: uno de los siguientes 20 { } [ ] ( ) 21 + * / % & 22 = < > ? ++ -23 == != = += -= 24 |= ^= = -> 25B.1.10 Directivas de preprocesamiento 26 pp-directive: 27 pp-declaration 28 pp-conditional 29 pp-line 30 pp-diagnostic 31 pp-region 32 33 34 35 36 37 38 39 40 41 42 43pp-new-line: whitespaceopt single-line-commentopt new-line

. | && *=

, ^ || /=

: ! > &=

conditional-symbol: Cualquier elemento identifier-or-keyword excepto true o false pp-expression: whitespaceopt pp-or-expression whitespaceopt pp-or-expression: pp-and-expression pp-or-expression whitespaceopt || whitespaceopt pp-and-expression pp-and-expression: pp-equality-expression pp-and-expression whitespaceopt && whitespaceopt pp-equality-expression

867Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

421

868Especificacin del lenguaje C#

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43

pp-equality-expression: pp-unary-expression pp-equality-expression whitespaceopt = = whitespaceopt pp-unary-expression pp-equality-expression whitespaceopt != whitespaceopt pp-unary-expression pp-unary-expression: pp-primary-expression ! whitespaceopt pp-unary-expression pp-primary-expression:t rue f a l se

conditional-symbol ( whitespaceopt pp-expression whitespaceopt ) pp-declaration: whitespaceopt # whitespaceopt define whitespace conditional-symbol pp-new-line whitespaceopt # whitespaceopt undef whitespace conditional-symbol pp-new-line pp-conditional: pp-if-section pp-elif-sectionsopt pp-else-sectionopt pp-endif pp-if-section: whitespaceopt # whitespaceopt if whitespace pp-expression pp-new-line conditionalsectionopt pp-elif-sections: pp-elif-section pp-elif-sections pp-elif-section pp-elif-section: whitespaceopt # whitespaceopt elif whitespace pp-expression pp-new-line conditionalsectionopt pp-else-section: whitespaceopt # whitespaceopt else pp-new-line conditional-sectionopt pp-endif: whitespaceopt # whitespaceopt endif pp-new-line conditional-section: input-section skipped-section skipped-section: skipped-section-part skipped-section skipped-section-part skipped-section-part: skipped-charactersopt new-line pp-directive skipped-characters: whitespaceopt not-number-sign input-charactersopt not-number-sign: Cualquier carcter de entrada (input-character) excepto #

869422

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

870

Apndice C Referencias

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25

pp-line: whitespaceopt # whitespaceopt l i ne whitespace line-indicator pp-new-line line-indicator: decimal-digits whitespace file-name decimal-digitsde fau l t

file-name: " file-name-characters " file-name-characters: file-name-character file-name-characters file-name-character file-name-character: Cualquier carcter de entrada (input-character) excepto " pp-diagnostic: whitespaceopt # whitespaceopt er ro r pp-message whitespaceopt # whitespaceopt warning pp-message pp-message: new-line whitespace input-charactersopt new-line pp-region: pp-start-region conditional-sectionopt pp-end-region pp-start-region: whitespaceopt # whitespaceopt region pp-message pp-end-region: whitespaceopt # whitespaceopt endregion pp-message

26B.2 Gramtica sintctica 27B.2.1 Conceptos bsicos 28 namespace-name: 29 namespace-or-type-name 30 31 32 33 34type-name: namespace-or-type-name namespace-or-type-name: identifier namespace-or-type-name . identifier

35B.2.2 Tipos 36 type: 37 value-type 38 reference-type 39 40 41value-type: struct-type enum-type

871Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

423

872Especificacin del lenguaje C#

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45

struct-type: type-name simple-type simple-type: numeric-typeboo l

numeric-type: integral-type floating-point-typedec ima l

integral-type:sby te byte shor t ushor t int u in t l ong u long char

floating-point-type:f l oa t doub le

enum-type: type-name reference-type: class-type interface-type array-type delegate-type class-type: type-nameob jec t s t r i ng

interface-type: type-name array-type: non-array-type rank-specifiers non-array-type: type rank-specifiers: rank-specifier rank-specifiers rank-specifier rank-specifier: [ dim-separatorsopt ]

873424

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

874

Apndice C Referencias

1 2 3 4 5

dim-separators:,

dim-separators , delegate-type: type-name

6B.2.3 Variables 7 variable-reference: 8 expression 9B.2.4 Expresiones 10 argument-list: 11 argument 12 argument-list , argument 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45argument: expression re f variable-reference out variable-reference primary-expression: primary-no-array-creation-expression array-creation-expression primary-no-array-creation-expression: literal simple-name parenthesized-expression member-access invocation-expression element-access this-access base-access post-increment-expression post-decrement-expression object-creation-expression delegate-creation-expression typeof-expression checked-expression unchecked-expression simple-name: identifier parenthesized-expression: ( expression ) member-access: primary-expression . identifier predefined-type . identifier predefined-type: uno deboo l byte ob jec t sby te char shor t dec ima l s t r i ngu in t doub lef l oa t int u long ushor t l ong

875Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

425

876Especificacin del lenguaje C#

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43

invocation-expression: primary-expression ( argument-listopt ) element-access: primary-no-array-creation-expression [ expression-list ] expression-list: expression expression-list , expression this-access:th i s

base-access:base . identifier base [ expression-list ]

post-increment-expression: primary-expression ++ post-decrement-expression: primary-expression -object-creation-expression: new type ( argument-listopt ) array-creation-expression: new non-array-type [ expression-list ] rank-specifiersopt array-initializeropt new array-type array-initializer delegate-creation-expression: new delegate-type ( expression ) typeof-expression: typeof ( type )typeof ( void )

checked-expression: checked ( expression ) unchecked-expression: unchecked ( expression ) unary-expression: primary-expression + unary-expression - unary-expression ! unary-expression ~ unary-expression pre-increment-expression pre-decrement-expression cast-expression pre-increment-expression: ++ unary-expression pre-decrement-expression: -- unary-expression

877426

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

878

Apndice C Referencias

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45

cast-expression: ( type ) unary-expression multiplicative-expression: unary-expression multiplicative-expression * unary-expression multiplicative-expression / unary-expression multiplicative-expression % unary-expression additive-expression: multiplicative-expression additive-expression + multiplicative-expression additive-expression multiplicative-expression shift-expression: additive-expression shift-expression > additive-expression relational-expression: shift-expression relational-expression relational-expression relational-expression relational-expression relational-expression relational-expression

< shift-expression > shift-expression = shift-expression is type as type

equality-expression: relational-expression equality-expression == relational-expression equality-expression != relational-expression and-expression: equality-expression and-expression & equality-expression exclusive-or-expression: and-expression exclusive-or-expression ^ and-expression inclusive-or-expression: exclusive-or-expression inclusive-or-expression | exclusive-or-expression conditional-and-expression: inclusive-or-expression conditional-and-expression && inclusive-or-expression conditional-or-expression: conditional-and-expression conditional-or-expression || conditional-and-expression conditional-expression: conditional-or-expression conditional-or-expression ? expression : expression

879Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

427

880Especificacin del lenguaje C#

1 2 3 4 5 6 7 8 9 10 11

assignment: unary-expression assignment-operator expression assignment-operator: uno de= + = -= *= /= % = & = |= ^ = = >

expression: conditional-expression assignment constant-expression: expression boolean-expression: expression

12B.2.5 Instrucciones 13 statement: 14 labeled-statement 15 declaration-statement 16 embedded-statement 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45881428

embedded-statement: block empty-statement expression-statement selection-statement iteration-statement jump-statement try-statement checked-statement unchecked-statement lock-statement using-statement block:{ statement-listopt }

statement-list: statement statement-list statement empty-statement:;

labeled-statement: identifier : statement declaration-statement: local-variable-declaration ; local-constant-declaration ; local-variable-declaration: type local-variable-declarators local-variable-declarators: local-variable-declarator local-variable-declarators , local-variable-declarator

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

882

Apndice C Referencias

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43

local-variable-declarator: identifier identifier = local-variable-initializer local-variable-initializer: expression array-initializer local-constant-declaration: cons t type constant-declarators constant-declarators: constant-declarator constant-declarators , constant-declarator constant-declarator: identifier = constant-expression expression-statement: statement-expression ; statement-expression: invocation-expression object-creation-expression assignment post-increment-expression post-decrement-expression pre-increment-expression pre-decrement-expression selection-statement: if-statement switch-statement if-statement: i f ( boolean-expression ) embedded-statement if ( boolean-expression ) embedded-statement else embedded-statement boolean-expression: expression switch-statement: switch ( expression ) switch-block switch-block: { switch-sectionsopt } switch-sections: switch-section switch-sections switch-section switch-section: switch-labels statement-list switch-labels: switch-label switch-labels switch-label

883Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

429

884Especificacin del lenguaje C#

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44

switch-label: case constant-expression :default :

iteration-statement: while-statement do-statement for-statement foreach-statement while-statement: while ( boolean-expression ) embedded-statement do-statement: do embedded-statement while ( boolean-expression ) ; for-statement: for ( for-initializeropt ; for-conditionopt ; for-iteratoropt ) embedded-statement for-initializer: local-variable-declaration statement-expression-list for-condition: boolean-expression for-iterator: statement-expression-list statement-expression-list: statement-expression statement-expression-list , statement-expression foreach-statement: foreach ( type identifier in expression ) embedded-statement jump-statement: break-statement continue-statement goto-statement return-statement throw-statement break-statement:break ;

continue-statement:continue ;

goto-statement: goto identifier ; goto case constant-expression ;goto default ;

return-statement: return expressionopt ; throw-statement: throw expressionopt ;

885430

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

886

Apndice C Referencias

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27

try-statement: t r y block catch-clauses t r y block finally-clause try block catch-clauses finally-clause catch-clauses: specific-catch-clauses general-catch-clauseopt specific-catch-clausesopt general-catch-clause specific-catch-clauses: specific-catch-clause specific-catch-clauses specific-catch-clause specific-catch-clause: catch ( class-type identifieropt ) block general-catch-clause: catch block finally-clause: finally block checked-statement: checked block unchecked-statement: unchecked block lock-statement: lock ( expression ) embedded-statement using-statement: using ( resource-acquisition ) embedded-statement resource-acquisition: local-variable-declaration expression

28B.2.6 Espacios de nombres 29 compilation-unit: 30 using-directivesopt global-attributesopt namespace-member-declarationsopt 31 32 33 34 35 36 37 38 39 40 41 42 43namespace-declaration: namespace qualified-identifier namespace-body ;opt qualified-identifier: identifier qualified-identifier . identifier namespace-body: { using-directivesopt namespace-member-declarationsopt } using-directives: using-directive using-directives using-directive using-directive: using-alias-directive using-namespace-directive

887Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

431

888Especificacin del lenguaje C#

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16

using-alias-directive: us ing identifier = namespace-or-type-name ; using-namespace-directive: using namespace-name ; namespace-member-declarations: namespace-member-declaration namespace-member-declarations namespace-member-declaration namespace-member-declaration: namespace-declaration type-declaration type-declaration: class-declaration struct-declaration interface-declaration enum-declaration delegate-declaration

17B.2.7 Clases 18 class-declaration: 19 attributesopt class-modifiersopt class identifier class-baseopt class-body ;opt 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42class-modifiers: class-modifier class-modifiers class-modifier class-modifier:new public protected internal private abstract sealed

class-base: : class-type : interface-type-list : class-type , interface-type-list interface-type-list: interface-type interface-type-list , interface-type class-body: { class-member-declarationsopt } class-member-declarations: class-member-declaration class-member-declarations class-member-declaration

889432

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

890

Apndice C Referencias

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45

class-member-declaration: constant-declaration field-declaration method-declaration property-declaration event-declaration indexer-declaration operator-declaration constructor-declaration destructor-declaration static-constructor-declaration type-declaration constant-declaration: attributesopt constant-modifiersopt cons t type constant-declarators ; constant-modifiers: constant-modifier constant-modifiers constant-modifier constant-modifier:new pub l i c protected internal private

constant-declarators: constant-declarator constant-declarators , constant-declarator constant-declarator: identifier = constant-expression field-declaration: attributesopt field-modifiersopt type variable-declarators ; field-modifiers: field-modifier field-modifiers field-modifier field-modifier:new public protected internal private static readonly volatile

variable-declarators: variable-declarator variable-declarators , variable-declarator

891Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

433

892Especificacin del lenguaje C#

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46893434

variable-declarator: identifier identifier = variable-initializer variable-initializer: expression array-initializer method-declaration: method-header method-body method-header: attributesopt method-modifiersopt return-type member-name ( formal-parameter-listopt ) method-modifiers: method-modifier method-modifiers method-modifier method-modifier:new pub l i c pro tec ted i n te rna l pr i va te s ta t i c v i r tua l sea led ove r r i de abs t rac t exte rn

return-type: typevo id

member-name: identifier interface-type . identifier method-body: block;

formal-parameter-list: fixed-parameters fixed-parameters , parameter-array parameter-array fixed-parameters: fixed-parameter fixed-parameters , fixed-parameter fixed-parameter: attributesopt parameter-modifieropt type identifier parameter-modifier:re f out

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

894

Apndice C Referencias

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38

parameter-array: attributesopt params array-type identifier property-declaration: attributesopt property-modifiersopt type member-name { accessor-declarations } property-modifiers: property-modifier property-modifiers property-modifier property-modifier:new pub l i c pro tec ted i n te rna l pr i va te s ta t i c v i r tua l sea led ove r r i de abs t rac t exte rn

member-name: identifier interface-type . identifier accessor-declarations: get-accessor-declaration set-accessor-declarationopt set-accessor-declaration get-accessor-declarationopt get-accessor-declaration: attributesopt get accessor-body set-accessor-declaration: attributesopt se t accessor-body accessor-body: block;

event-declaration: attributesopt event-modifiersopt event type variable-declarators ; attributesopt event-modifiersopt event type member-name { event-accessor-declarations } event-modifiers: event-modifier event-modifiers event-modifier

895Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

435

896Especificacin del lenguaje C#

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47897436

event-modifier:new pub l i c pro tec ted i n te rna l pr i va te s ta t i c v i r tua l sea led ove r r i de abs t rac t exte rn

event-accessor-declarations: add-accessor-declaration remove-accessor-declaration remove-accessor-declaration add-accessor-declaration add-accessor-declaration: attributesopt add block remove-accessor-declaration: attributesopt remove block indexer-declaration: attributesopt indexer-modifiersopt indexer-declarator { accessor-declarations } indexer-modifiers: indexer-modifier indexer-modifiers indexer-modifier indexer-modifier:new pub l i c pro tec ted i n te rna l pr i va te v i r tua l sea led ove r r i de abs t rac t exte rn

indexer-declarator: type th i s [ formal-parameter-list ] type interface-type . this [ formal-parameter-list ] operator-declaration: attributesopt operator-modifiers operator-declarator operator-body operator-modifiers: operator-modifier operator-modifiers operator-modifier operator-modifier:public static extern

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

898

Apndice C Referencias

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42

operator-declarator: unary-operator-declarator binary-operator-declarator conversion-operator-declarator unary-operator-declarator: type opera to r overloadable-unary-operator ( type identifier ) overloadable-unary-operator: uno de+ - ! ~ ++ -- true false

binary-operator-declarator: type operator overloadable-binary-operator ( type identifier , type identifier ) overloadable-binary-operator: uno de+ - * / % & | ^ > == != > < >= identifier443

911Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

912Especificacin del lenguaje C#

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25

pointer-element-access: primary-no-array-creation-expression [ expression ] addressof-expression: & unary-expression sizeof-expression: s i zeo f ( unmanaged-type ) embedded-statement: ... fixed-statement fixed-statement: fixed ( pointer-type fixed-pointer-declarators ) embedded-statement fixed-pointer-declarators: fixed-pointer-declarator fixed-pointer-declarators , fixed-pointer-declarator fixed-pointer-declarator: identifier = fixed-pointer-initializer fixed-pointer-initializer: & variable-reference expression local-variable-initializer: expression array-initializer stackalloc-initializer stackalloc-initializer: stackalloc unmanaged-type [ expression ]

913444

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

914

Apndice C Referencias

1

C.Referencias

2Unicode Consortium. The Unicode Standard, Version 3.0. Addison-Wesley, Reading, Massachusetts (EE.UU.), 32000, ISBN 0-201-616335-5. 4IEEE. IEEE Standard for Binary Floating-Point Arithmetic. ANSI/IEEE Standard 754-1985. Disponible en 5http://www.ieee.org. 6ISO/IEC. C++. ANSI/ISO/IEC 14882:1998.

915Copyright Microsoft Corporation 1999-2003. Reservados todos los derechos.

445