2010-02-02 14 views
41

He visto muchos ejemplos de indexadores C#, pero de qué manera me ayudará en situaciones de la vida real.casos de uso del mundo real para indexadores de C#?

Sé que el gurú C# no habría agregado esto si no fuera una característica seria, pero no puedo pensar en una situación del mundo real (no en la barra foo) para usar indexadores.

Nota: Me doy cuenta de que existe related question, pero no me ayuda demasiado.

+0

¿Aparte del List-type, el LinkedList-type, el Dictionary-type o las otras colecciones? ;) A menudo, cuando tiene una lista de algo, se considera útil proporcionar un indizador, por lo que uno puede hacer myList [k] en lugar de myList.Get (k) o la versión de VB myList.Item (k) – Skurmedel

+0

@Skurmedel Please explicar, obviamente me falta algo –

+0

Righto, actualicé mi comentario. – Skurmedel

Respuesta

32

La forma en que veo los indexadores es que (acierta o no!), Acceder a algo por índice debe ser más eficiente que acceder de otra forma, porque de alguna forma, forma o forma, la clase cuyo indexador soy utilizando tiendas de algún tipo de índice que le permite buscar valores rápidamente cuando se accede de esa manera.

El ejemplo clásico es una matriz, cuando accede al elemento n de una matriz mediante el uso del código myarray [3], el compilador/intérprete sabe cuán grandes (en cuanto a la memoria) los elementos de la matriz son y pueden tratarlo como un desplazamiento desde el inicio de la matriz. También podría llamar al "for(int i = 0; i < myarray.length; i++) { if (i = 3) then { .. do stuff } }" (¡no es que lo desee!), Que sería menos eficiente. También muestra cómo una matriz es un mal ejemplo.

Supongamos que tenía una clase de colección que almacena, umm, DVD, por lo que:

public class DVDCollection 
{ 
    private Dictionary<string, DVD> store = null; 
    private Dictionary<ProductId, string> dvdsByProductId = null; 

    public DVDCollection() 
    { 
     // gets DVD data from somewhere and stores it *by* TITLE in "store" 
     // stores a lookup set of DVD ProductId's and names in "dvdsByProductid" 
     store = new Dictionary<string, DVD>(); 
     dvdsByProductId = new Dictionary<ProductId, string>(); 
    } 

    // Get the DVD concerned, using an index, by product Id 
    public DVD this[ProductId index] 
    { 
     var title = dvdsByProductId[index]; 
     return store[title]; 
    } 
} 

Sólo mi 2p, pero, como he dicho, .. Siempre he considerado un "paso a paso" como una manera conveniente de obtener datos de algo.

5

Supongamos que tiene una colección de objetos que desea poder indexar por un orden distinto al orden en que se colocó en una colección. En el ejemplo siguiente, puede ver cómo puede usar la propiedad 'Ubicación' de algún objeto y usar el indexador, devolver todos los objetos de la colección que coinciden con su ubicación o, en el segundo ejemplo, todos los objetos que contienen un determinado Conteo () de objetos.

class MyCollection { 

    public IEnumerable<MyObject> this[string indexer] { 
    get{ return this.Where(p => p.Location == indexer); } 
    } 

    public IEnumerable<MyObject> this[int size] { 
    get{ return this.Where(p => p.Count() == size);} 
    } 
} 
5

Una vez .NET tiene genéricos, la razón más importante para mí para implementar un indexador (para implementar una colección de tipado fuerte) se fue.

+12

¿Por qué la necesidad de un indexador disminuye con los genéricos? ¿O quiere decir que ya no tiene la necesidad de escribir sus propias colecciones? – Skurmedel

8

Microsoft has an example usando un indexador para tratar un archivo como una matriz de bytes.

public byte this[long index] 
{ 
    // Read one byte at offset index and return it. 
    get 
    { 
     byte[] buffer = new byte[1]; 
     stream.Seek(index, SeekOrigin.Begin); 
     stream.Read(buffer, 0, 1); 
     return buffer[0]; 
    } 
    // Write one byte at offset index and return it. 
    set 
    { 
     byte[] buffer = new byte[1] {value}; 
     stream.Seek(index, SeekOrigin.Begin); 
     stream.Write(buffer, 0, 1); 
    } 
} 
+0

Creo que este es un buen ejemplo, porque los indexadores permiten recuperar o almacenar elementos, simulando así el comportamiento de la matriz. En este caso, se usa para persistir (serializar y deserializar) los datos, ocultando la complejidad para acceder a un archivo. Podría ser una base de datos también. También he visto que el serializador .NET JSON lo usa para simular arreglos de estilo JavaScript que le permiten usar cadenas y números como índices en la misma clase (al sobrecargar el indexador). Al final, por supuesto, es azúcar sintáctica, pero ayuda a simplificar los pensamientos y hacerlos más fáciles de leer (y más cómodos de usar). – Matt

3

Es sólo azúcar sintáctica para las clases de tipo colección. Nunca tuve una razón para escribir tal clase. Así que creo que hay usos muy raros de él en "la vida real", porque las clases que lo usan ya están implementadas.

+0

No olvide que la rareza de un hombre es otro requisito. Si bien son azúcar sintáctico ... podrías decir eso sobre la mayor parte del marco. (Enum, Propiedades, Sobrecarga del operador, Linq, WCF, etc.) –

+0

@Matthew: ¿hay alguna diferencia entre tener un indexador o tener un método 'GetElement'? El indexador es más corto de usar. –

+0

No hay diferencia entre usar una propiedad y un método GetProperty tampoco. Si en el código compilado esto sucede para usted en la parte de atrás. Cada palabra clave que usamos (más allá de los OpCodes para la CPU o Runtime) es una forma de azúcar sintáctica ... y yo, por mi parte, amo el azúcar. Por ejemplo...cuando usa un indexador en C#, lo declara en la clase con la palabra clave this. En VB.Net solo selecciona una propiedad y agrega un parámetro de entrada. –

24

Los ejemplos más obvios, como lo menciona Skurmedel, son List<T> y Dictionary<TKey, TValue>. ¿Qué preferirías sobre: ​​

List<string> list = new List<string> { "a", "b", "c" }; 
string value = list[1]; // This is using an indexer 

Dictionary<string, string> dictionary = new Dictionary<string, string> 
{ 
    { "foo", "bar" }, 
    { "x", "y" } 
}; 
string value = dictionary["x"]; // This is using an indexer 

? Ahora puede ser relativamente raro que necesite escribir un indexador (generalmente cuando está creando una clase similar a una colección), pero sospecho que usa con bastante frecuencia.

+1

Esto significa que no pueden existir varios indexadores. o en otras palabras, ¿pueden estar sobrecargados? –

+1

@Vivek Bernard: Pueden estar sobrecargados. – OregonGhost

+0

@OregonGhost gracias me acabo de dar cuenta :) –

3

En ASP.Net, hay algunas ocasiones diferentes en las que se usa un indexador, como leer algo de cualquiera de los objetos Solicitud, Sesión o Aplicación.He visto a menudo dónde se almacena algo en el objeto Session o Application solo para usarlo una y otra vez.

2
using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 

namespace IndexerSample 
{ 
    class FailSoftArray 
    { 
     int[] a; // reference to underlying array 
     public int Length; // Length is public 
     public bool ErrFlag; // indicates outcome of last operation 
     // Construct array given its size. 
     public FailSoftArray(int size) 
     { 
      a = new int[size]; 
      Length = size; 
     } 
     // This is the indexer for FailSoftArray. 
     public int this[int index] 
     { 
     // This is the get accessor. 
      get 
      { 
       if (ok(index)) 
       { 
        ErrFlag = false; 
        return a[index]; 
       } 
       else 
       { 
        ErrFlag = true; 
        return 0; 
       } 
      } 
      // This is the set accessor. 
      set 
      { 
       if (ok(index)) 
       { 
        a[index] = value; 
        ErrFlag = false; 
       } 
       else ErrFlag = true; 
      } 
     } 
     // Return true if index is within bounds. 
     private bool ok(int index) 
     { 
      if (index >= 0 & index < Length) return true; 
      return false; 
     } 
    } 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      FailSoftArray fs = new FailSoftArray(5); 
      int x; 
      // Show quiet failures. 
      Console.WriteLine("Fail quietly."); 
      for (int i = 0; i < (fs.Length * 2); i++) 
       fs[i] = i * 10; 
      for (int i = 0; i < (fs.Length * 2); i++) 
      { 
       x = fs[i]; 
       if (x != -1) Console.Write(x + " "); 
      } 
      Console.WriteLine(); 
      // Now, display failures. 
      Console.WriteLine("\nFail with error reports."); 
      for (int i = 0; i < (fs.Length * 2); i++) 
      { 
       fs[i] = i * 10; 
       if (fs.ErrFlag) 
        Console.WriteLine("fs[" + i + "] out-of-bounds"); 
      } 
      for (int i = 0; i < (fs.Length * 2); i++) 
      { 
       x = fs[i]; 
       if (!fs.ErrFlag) Console.Write(x + " "); 
       else 
        Console.WriteLine("fs[" + i + "] out-of-bounds"); 
      } 
      Console.ReadLine(); 
     } 
    } 
} 
2

http://code-kings.blogspot.in/2012/09/indexers-in-c-5.html

indexadores son elementos de un programa de C# que permite que una clase se comporte como una matriz. Podrías usar toda la clase como una matriz. En este conjunto, puede almacenar cualquier tipo de variables. Las variables se almacenan en una ubicación separada, pero se direccionan por el nombre de la clase en sí. Crear índices para enteros, cadenas, booleanos, etc. sería una idea viable. Estos indexadores actuarían efectivamente sobre los objetos de la clase.

Supongamos que ha creado un indizador de clase que almacena el número de rollo de un alumno en una clase. Además, supongamos que ha creado un objeto de esta clase llamado obj1. Cuando dice obj1 [0], se refiere al primer alumno en rollo. Del mismo modo, obj1 [1] se refiere al 2º alumno en rollo.

Por lo tanto, el objeto toma valores indexados para hacer referencia a la variable Entero que se almacena de forma privada o pública en la clase. Supongamos que no disponen de este servicio, entonces probablemente se refieren de esta manera (que sería más larga):

obj1.RollNumberVariable[0] 
obj1.RollNumberVariable[1]. 

donde RollNumberVariable sería la variable entera que se refiere al rollo Número del objeto actual estudiante.

Para más detalles http://code-kings.blogspot.in/2012/09/indexers-in-c-5.html

0

http://code-kings.blogspot.in/2012/09/indexers-in-c-5.html

que utilizan el sistema;

espacio de nombres Indexers_Example

{

class Indexers 
{ 

    private Int16[] RollNumberVariable; 

    public Indexers(Int16 size) 
    { 
     RollNumberVariable = new Int16[size]; 

     for (int i = 0; i < size; i++) 
     { 
      RollNumberVariable[i] = 0; 
     } 
    } 

    public Int16 this[int pos] 
    { 
     get 
     { 
      return RollNumberVariable[pos]; 
     } 
     set 
     { 
      RollNumberVariable[pos] = value; 
     } 
    } 
} 

}

0

adición al código @ reyes-Post.

Además, al llamar al RollNumberVariable[0] se activará el comportamiento del indexador de la colección predeterminada. Mientras que indexadores son en realidad propiedades, es en su nombre para escribir su propia lógica al extraer datos. Puede delegar fácilmente la mayor parte del valor del parámetro de índice en la colección interna, pero también puede devolver cualquier valor arbitrario para ciertos valores de índice.

Solo un ejemplo: puede tener más de 2 colecciones internas en diferentes formatos, pero el usuario externo interactuará con ellas a través de un único indexador (que funcionará como despachador), , mientras que esas colecciones estarán ocultas. Esto más bien fomenta el principio de encapsulación.

1

He aquí un video que he creado http://www.youtube.com/watch?v=HdtEQqu0yOY y abajo hay una explicación detallada sobre el mismo.

Indexers ayuda a acceder a la colección contenida en una clase mediante una interfaz simplificada. Es un azúcar sintáctico.

Por ejemplo, digamos que tiene una clase de cliente con colección de direcciones dentro de ella. Ahora digamos que nos gustaría obtener la colección de direcciones por "Pincode" y "PhoneNumber".Por lo tanto, el paso lógico sería ir y crear dos funciones sobrecargadas, una que se obtiene utilizando "PhoneNumber" y la otra mediante "PinCode". Puedes ver en el siguiente código que tenemos dos funciones definidas.

Customer Customers = new Customer(); 
Customers.getAddress(1001); 
Customers.getAddress("9090"); 

Si utiliza el indexador, puede simplificar el código anterior con algo como se muestra en el siguiente código.

Customer Customers = new Customer(); 
Address o = Customers[10001]; 
o = Customers["4320948"]; 

Cheers.

+0

En mi humilde opinión el ejemplo no es el mejor, he aquí por qué: Los indexadores deben tener la semántica de una matriz, por lo que se espera que los clientes devuelvan un cliente y no otro tipo como Dirección. En su caso, es mejor que use getAddress para transmitir la intención correcta. De lo contrario, nombraría a la clase que implementa el indexador como direcciones y luego buscaría una dirección como direcciones [1001] – dotnetguy

0

Estoy tratando de obtener imágenes de un archivo de secuencia. Necesito algún tipo de matriz 2D o una matriz dentada para mantener los valores de píxeles. Estoy usando indexadores en lugar de matrices porque iterar sobre indizadores es más rápido que el bucle sobre matrices 2D o irregulares.

0

Puede usar un indexador para proporcionar lectura/escritura de sincronización multi-threading a un diccionario no seguro para subprocesos (o cualquier colección segura pero sin hilos) elegantemente:

internal class ThreadSafeIndexerClass 
{ 
    public object this[int key] 
    { 
     get 
     { 
      // Aquire returns IDisposable and does Enter() Exit() on a certain ReaderWriterLockSlim instance 
      using (_readLock.Aquire()) 
      { 
       object subset; 
       _dictionary.TryGetValue(key, out foundValue); 
       return foundValue; 
      } 
     } 
     set 
     { 
      // Aquire returns IDisposable and does Enter() Exit() on a certain ReaderWriterLockSlim instance 
      using (_writeLock.Aquire()) 
       _dictionary[key] = value; 
     } 
    } 
} 

útil especialmente cuando usted don' Quiero usar el ConcurrentDictionary pesado (o cualquier otra colección concurrente).

Cuestiones relacionadas