Cómo trabajar con indexadores en C #

El lenguaje de programación C # incluye soporte para indexadores, una característica que le permite usar un objeto como una matriz. Los indexadores también se conocen como matrices inteligentes y se pueden definir de forma similar a como se define una propiedad. MSDN dice: "Los indexadores permiten que las instancias de una clase o estructura se indexen como matrices. Los indexadores se parecen a las propiedades, excepto que sus descriptores de acceso toman parámetros".

Aunque los indexadores y las propiedades tienen similitudes en más de un sentido, existen diferencias sutiles entre ellos. A diferencia de las propiedades, puede acceder a un indexador mediante índices. Recuerde que necesita acceder a una propiedad usando su nombre. Además, los indexadores son miembros de instancia de una clase y, por lo tanto, no pueden ser estáticos. Puede tener propiedades estáticas y no estáticas.

El siguiente fragmento de código ilustra cómo se declara un indexador:

this [argument list]

{

  get

  {

  }

  Set

  {

  }

}

Tenga en cuenta que el modificador que se muestra en la declaración de sintaxis de un indexador puede ser privado, público, protegido o interno.

Considere la siguiente clase:

public class Contact

    {

        private string[] address = new string[3];

        public string this[int index]

        {

            get

            {

                return address[index];

            }

            set

            {

                address[index] = value;

            }

        }

    }

La clase Contact contiene un miembro privado llamado dirección y define un indexador. El miembro de dirección es una matriz de tipo cadena. A continuación, le mostramos cómo puede crear una instancia de la clase Contact y usar el indexador.

Contact contact = new Contact();

 contact[0] = "Begumpet";

 contact[1] = "Hyderabad";

 contact[2] = "Telengana";

for (int i = 0; i < 3; i++)

Console.WriteLine (contact[i]);

Cabe señalar que es necesario utilizar la palabra clave "this" para definir indexadores. Tenga en cuenta que no está obligado a usar solo números enteros como índices para acceder a los indexadores; incluso puede usar otros mecanismos de búsqueda. Un indexador se usa normalmente cuando su clase representa una colección u objetos. Luego puede usar el indexador para acceder a un elemento específico usando index.

Probemos con un ejemplo. Considere la siguiente clase denominada Cliente.

public class Customer

    {

       public List Orders

        {

            get; set;

        }

       public Order this[int orderID]

        {

            get

            {

                return (from o in Orders

                        where o.OrderID == orderID

                        select o).First();

            }

        }

    }

La clase Customer define un indexador de tipo Order. También contiene una propiedad pública que es una lista de tipo Orden. Aquí está la clase Order para su referencia.

public class Order

    {

        public int OrderID

        {

            get; set;

        }

    }

El siguiente fragmento de código ilustra cómo puede acceder al indexador de la clase Customer para recuperar un pedido en particular.

   List lstOrder = new List();

  Order o1 = new Order();

  o1.OrderID = 1;

  Order o2 = new Order();

  o2.OrderID = 2;           

  lstOrder.Add(o1);

  lstOrder.Add(o2);

  Customer customer = new Customer();

  customer.Orders = lstOrder;

  Order o = customer[1];

Consulte el fragmento de código anterior. Observe cómo se ha creado y asignado una lista genérica de tipo Pedido a la propiedad Pedidos de una instancia de la clase Cliente. A continuación, simplemente pasa el OrderId como parámetro para recuperar la instancia de pedido en particular.

Los indexadores admiten la herencia, pueden ser polimórficos y también pueden ser abstractos. Considere la siguiente clase que define un indexador que es virtual. La clase ContactBase es una versión modificada de la clase Contact que discutimos anteriormente en este artículo.

 public class ContactBase

    {

        protected string[] address = new string[3];

        public virtual string this[int index]

        {

            get

            {

                return address[index];

            }

            set

            {

                address[index] = value;

            }

        }

    }

Ahora puede derivar una clase de la clase ContactBase y anular el indexador como se muestra a continuación.

public class ConcreteContact: ContactBase

    {

       public override string this[int index]

        {

            get

            {

                return address[index];

            }

            set

            {

                address[index] = value;

            }

        }

    }

Entonces, en el ejemplo de código anterior, exploramos cómo se pueden usar los indexadores mientras se heredan tipos y cómo pueden mostrar un comportamiento polimórfico.

También puede definir un indexador como abstracto. Para hacer esto, necesita crear una clase abstracta y luego definir un indexador como abstracto dentro de ella. Modifiquemos la clase ContactBase y definamos el indexador como abstracto. Así es como se vería ahora la versión modificada de la clase ContactBase:

 public abstract class ContactBase

    {

        protected string[] address = new string[3];

        public abstract string this[int index]

        {

            get; set;

        }

}

No es necesario cambiar la clase ConcreteContact de todos modos. Ahora puede aprovechar el indexador para asignar valores de cadena a una instancia de la clase ConcreteContact como se muestra a continuación.

ConcreteContact contact = new ConcreteContact();

contact[0] = "Begumpet";

contact[1] = "Hyderabad";

contact[2] = "Telengana";