Tema 10: Indizadores
Concepto de
indizador
Un indizador es una definición de cómo se
puede aplicar el operador de acceso a tablas ([ ]) a los
objetos de un tipo de dato. Esto es especialmente útil para
hacer más clara la sintaxis de acceso a elementos de objetos
que puedan contener colecciones de elementos, pues permite
tratarlos como si fuesen tablas normales.
Los indizadores permiten definir código a ejecutar cada vez
que se acceda a un objeto del tipo del que son miembros usando la
sintaxis propia de las tablas, ya sea para leer o escribir. A
diferencia de las tablas, los índices que se les pase entre
corchetes no tiene porqué ser enteros, pudiéndose
definir varios indizadores en un mismo tipo siempre y cuando cada
uno tome un número o tipo de índices diferente.
Definición de
indizador
A la hora de definir un indizador se usa una sintaxis parecida a la
de las propiedades:
<tipoIndizador> this[<índices>]
{
set
{
<códigoEscritura>
}
get
{
<códigoLectura>
}
}
Las únicas diferencias entre esta sintaxis y la de las
propiedades son:
-
El nombre dado a un indizador siempre ha de ser this,
pues carece de sentido poder darle cualquiera en tanto que a un
indizador no se accede por su nombre sino aplicando el operador
[ ] a un objeto. Por ello, lo que diferenciará a
unos indizadores de otros será el número y tipo de
sus <índices>
-
En <índices> se indica cuáles son los
índices que se pueden usar al acceder al indizador. Para
ello la sintaxis usada es casi la misma que la que se usa para
especificar los parámetros de un método,
sólo que no se admite la inclusión de
modificadores ref, out o params y que
siempre ha de definirse al menos un parámetro.
Obviamente, el nombre que se dé a cada índice
será el nombre con el que luego se podrá acceder
al mismo en los bloques set/get.
-
No se pueden definir indizadores estáticos, sino
sólo indizadores de objetos.
Por todo lo demás, la sintaxis de definición de los
indizadores es la misma que la de las propiedades: pueden ser de
sólo lectura o de sólo escritura, da igual el orden
en que se definan sus bloques set/get, dentro del
bloque set se puede acceder al valor a escribir a
través del parámetro especial value del tipo
del indizador, el código del bloque get ha de
devolver un objeto de dicho tipo,
etc.
A continuación se muestra un ejemplo de definición de
una clase que consta de dos indizadores: ambos permiten almacenar
elementos de tipo entero, pero uno toma como índice un
entero y el otro toma dos cadenas:
using System;
public class A
{
public int this[int índice]
{
set
{
Console.WriteLine("Escrito {0} en posición {1}", value, índice);
}
get
{
Console.WriteLine("Leído 1 de posición {0}", índice);
return 1;
}
}
public int this[string cad1, string cad2]
{
set
{
Console.WriteLine("Escrito {0} en posición ({1},{2})", value, cad1, cad2);
}
get
{
Console.WriteLine("Leído prueba de posición ({0},{1})", cad1, cad2);
return 2;
}
}
}
Acceso a indizadores
Para acceder a un indizador se utiliza exáctamente la misma
sintaxis que para acceder a una tabla, sólo que los
índices no tienen porqué ser enteros sino que pueden
ser de cualquier tipo de dato que se haya especificado en su
definición. Por ejemplo, accesos válidos a los
indizadores de un objeto de la clase A definida en el
epígrafe anterior son:
A obj = new A();
obj[100] = obj["barco", "coche"];
La ejecución de la asignación de este ejemplo
producirá esta salida por pantalla:
Leído prueba de posición (barco, coche)
Escrito 2 en posición 100
Implementación
interna de indizadores
Al igual que las propiedades, para facilitar la interoperabilidad
entre lenguajes los indizadores son también convertidos por
el compilador en llamadas a métodos cuya definición
se deduce de la definición del indizador. Ahora los
métodos son de la forma:
<tipoIndizador> get_Item(<índices>)
{
<códigoLectura>
}
void set_Item(<índices>, <tipoIndizador> value)
{
<códigoEscritura>
}
Nuevamente, hay que tener cuidado con la signatura de los
métodos que se definan en una clase ya que como la de alguno
coincida con la generada automáticamente por el compilador
para los indizadores se producirá un error de
ambigüedad.