2010-01-06 18 views
11

Haciendo un poco de lectura de códigos y tropezamos con este fragmento que no he visto antes:C# ¿Cuál es el punto o beneficio de un indexador?

public SomeClass { 
    public someInterface this[String strParameter] { 
    get { 
     return SomeInternalMethod(strParameter); 
    } 
    } 
} 

Parece que se llama de la siguiente manera:

SomeClass _someClass = new SomeClass(); 
SomeInterface returnedValue = _someClass["someString"]; 

Estoy interesado en esta función donde haría ser apropiado o cuál es la intención de escribir en este estilo. Por ejemplo, ¿por qué se prefiere esto simplemente llamando a la función?

+1

Es natural, elegante, agrada a la vista, mejora la comprensión. Las llamadas a métodos son aburridas. Mira esto: http://steve-yegge.blogspot.com/2006/03/execution-in-kingdom-of-nouns.html –

Respuesta

19

Ver la especificación del lenguaje, sección 10.9, que establece:

Un Indexer es un miembro que permite un objeto para ser indexados de la misma manera como una matriz.

indexadores y propiedades son muy similares en concepto, pero difieren de las siguientes maneras:

  • Una propiedad se identifica por su nombre, mientras que un indexador se identifica por su firma.
  • Se accede a una propiedad a través de un nombre simple (§7.5.2) o un acceso de miembro (§7.5.4), mientras que a un elemento indexador se accede a través de un elemento de acceso (§7.5.6.2).
  • Una propiedad puede ser un miembro estático, mientras que un indexador siempre es un miembro de instancia.
  • Un acceso de obtención de una propiedad corresponde a un método sin parámetros, mientras que un acceso de obtención de un indexador corresponde a un método con la misma lista de parámetros formales que el indexador.
  • Un descriptor de acceso de una propiedad corresponde a un método con un único parámetro denominado valor, mientras que un descriptor de acceso de un indexador corresponde a un método con la misma lista formal de parámetros que el indexador, más un parámetro adicional denominado value.
  • Es un error en tiempo de compilación para un descriptor de acceso de usuario declarar una variable local con el mismo nombre que un parámetro del indexador.
  • En una declaración de propiedad primordial, se accede a la propiedad heredada usando la sintaxis base.P, donde P es el nombre de la propiedad. En una declaración de indizador primordial, se accede al indizador heredado utilizando la base de sintaxis [E], donde E es una lista de expresiones separadas por comas.
+2

Sé que no debería secuestrar esto, pero tal vez podría escribir sobre por qué no hay Indicadores estáticos? Me sorprendió cuando vi que no existen, solo porque es una forma muy buena y taquillera. (Antes de que Jon muestre el buen ejemplo de codificación ["UTF8"] :)) –

+3

Acabo de consultar el archivo de notas de diseño y no hay nada allí que justifique la decisión de no tener indexadores estáticos. Por lo tanto, debo recurrir a mi explicación habitual de por qué no tenemos una característica: nadie pensó que era una buena idea para gastar el dinero en hacerlo realidad. Me imagino que esta misma explicación también explica por qué los indexadores no pueden ser genéricos. –

+0

Genial :) Lo bueno de la explicación "predeterminada" es que no cierra completamente la puerta de que esto sea posible. No tengo idea de lo "pesada" que es esta característica (y no me descalificaré diciendo "¡pero es solo un pequeño cambio!" Sin saber cómo funcionan en realidad el compilador y CLR), pero es mejor que "No hicimos debido a X, Y y Z que hacen que sea imposible implementarlo alguna vez ". –

5

En muchos casos, el 'índice' de sintaxis tiene mucho sentido. Es particularmente útil si SomeClass representa algún tipo de colección.

3

Se le permite hacer búsquedas de matriz asociativa (también conocido como "estilo de diccionario"), al igual que usted ha mencionado en su pregunta.

Y ese es el punto. Algunas personas les gusta eso, especialmente las personas que provienen de idiomas que tienen incorporado, como Python o PHP

0

Es una implementación del operador de índice [ ].

0

Es una sobrecarga del operador. Es útil si está escribiendo una clase de colección, por ejemplo, donde tendría sentido acceder a ella utilizando la notación de matriz, p. colección [someIndex].

Se podría, por supuesto, escribir una función equivalente collection.GetElement (someIndex), pero es una cosa de estilo/legibilidad.

3

La palabra "this" es un indexador

de http://msdn.microsoft.com/en-us/library/6x16t2tx.aspx

"indexadores permiten que las instancias de una clase o estructura a ser indexados al igual que las matrices. Indexadores se asemejan a las propiedades excepto que sus descriptores de acceso toman parámetros."

+0

¿Qué quieres decir con: la palabra clave "this" es un indexador? – spender

0

Bien podría utilizar este método en una clase par clave-valor.

No estoy seguro de cuál es la clase análoga en C#, pero en C++ STL, existe la clase de mapa donde llama al método con SomeObject["key"] y devolverá el "valor" asociado con esa clave.

+0

La clase análoga en C# es System.Collections.Generic.Dictionary (excepto que el diccionario utiliza una búsqueda hash, mientras que el mapa ordena las claves) –

0

Se denomina indexador, le permiten usar List <>, ArrayList, Dictionary <> y todas las demás colecciones que utilizan una sintaxis de matriz.

Es sólo el azúcar sintáctica, pero da un poco de lectura cuando se utiliza bien.

1

Ya ha tropezado con algo similar antes:

var myList = new List<string>(); 
myList.Add("One"); 
myList.Add("Two"); 
myList.Add("Three"); 

for(int i = 0; i < myList.Count; i++) { 
    string s = myList[i]; 
} 

El indexador es la "clave principal" de un objeto que implementa una colección. Es solo una forma abreviada de escribir una función como .GetValue (índice) - azúcar sintáctico, si lo desea. Pero también hace que el intento sea claro.

13

Parece que muchas de las respuestas se centran en lo que es un indexador, no por qué desea usar uno.

En lo que a mí respecta, aquí es la motivación para usar un indexador:

Usted está trabajando en una clase que tiene una colección de algún tipo, pero que desea que aparezca la clase de usuarios (consumidores de la clase) como si es una colección.

El mejor ejemplo que puedo pensar es la clase DataRow en ADO.NET. Si desea obtener el valor de la quinta celda de DataRow, puede usar DataRow.Item[4] o DataRow[4]. La última forma es un atajo práctico y lógico, y muestra muy bien por qué querría usar un indexador. Para el usuario, el DataRow puede considerarse simplemente como una colección de celdas (aunque es realmente más que eso), por lo que tiene sentido poder obtener y establecer valores de celda directamente, sin tener que recordar que en realidad eres obteniendo/configurando un Item.

Espero que ayude.

0

En mi opinión, es solo una conveniencia de sintaxis. Dónde le NO lo utilizan:

public SomeClass { 
    private int[] nums; 
    public GetVal this[int ind] { 
    get { 
     return nums[ind]; // this is pointless since array is already indexed 
    } 
    } 
} 

¿Dónde beneficiarse de ella:

public Matrix { 
    private Dictionary<string, double> matrixData; // Matrix indecies, value 
    public double this[int row, int col] { 
    get { 
     return matrixData[string.Format("{0},{1}", row, col)]; 
    } 
    } 
} 

Como se puede ver, por alguna razón, sus datos es un diccionario indexada con una clave de cadena y desea llamar a esto con dos indefiniciones enteras y todavía no desea cambiar su tipo de datos:

Matrix m = new Matrix(); 
... 
Console.WriteLine(m[1,2]); 
Cuestiones relacionadas