Comment travailler avec des indexeurs en C #

Le langage de programmation C # inclut la prise en charge des indexeurs - une fonctionnalité qui vous permet d'utiliser un objet comme un tableau. Les indexeurs sont également appelés tableaux intelligents et peuvent être définis de la même manière qu'une propriété est définie. Le MSDN déclare: «Les indexeurs permettent d'indexer les instances d'une classe ou d'une structure comme des tableaux. Les indexeurs ressemblent à des propriétés, sauf que leurs accesseurs prennent des paramètres».

Bien que les indexeurs et les propriétés présentent des similitudes à plus d'un titre, il existe des différences subtiles entre eux. Contrairement aux propriétés, vous pouvez accéder à un indexeur à l'aide d'index. N'oubliez pas que vous devez accéder à une propriété en utilisant son nom. De plus, les indexeurs sont des membres d'instance d'une classe et ne peuvent donc pas être statiques. Vous pouvez avoir à la fois des propriétés statiques et non statiques.

L'extrait de code suivant illustre comment un indexeur est déclaré:

this [argument list]

{

  get

  {

  }

  Set

  {

  }

}

Notez que le modificateur indiqué dans la déclaration de syntaxe d'un indexeur peut être privé, public, protégé ou interne.

Considérez la classe suivante:

public class Contact

    {

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

        public string this[int index]

        {

            get

            {

                return address[index];

            }

            set

            {

                address[index] = value;

            }

        }

    }

La classe Contact contient un membre privé nommé adresse et définit un indexeur. Le membre d'adresse est un tableau de type chaîne. Voici comment vous pouvez créer une instance de la classe Contact et utiliser l'indexeur.

Contact contact = new Contact();

 contact[0] = "Begumpet";

 contact[1] = "Hyderabad";

 contact[2] = "Telengana";

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

Console.WriteLine (contact[i]);

Il est à noter que vous devez utiliser le mot clé "this" pour définir les indexeurs. Notez que vous n'êtes pas obligé d'utiliser uniquement des entiers comme index pour accéder aux indexeurs - vous pouvez même utiliser d'autres mécanismes de recherche. Un indexeur est généralement utilisé lorsque votre classe représente une collection ou des objets. Vous pouvez ensuite utiliser l'indexeur pour accéder à un élément spécifique à l'aide de l'index.

Essayons un exemple. Considérez la classe suivante nommée Customer.

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 classe Customer définit un indexeur de type Order. Il contient également une propriété publique qui est une liste de type Order. Voici la classe Order pour votre référence.

public class Order

    {

        public int OrderID

        {

            get; set;

        }

    }

L'extrait de code suivant illustre comment vous pouvez accéder à l'indexeur de la classe Customer pour récupérer une commande particulière.

   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];

Reportez-vous à l'extrait de code ci-dessus. Notez comment une liste générique de type Order a été créée et affectée à la propriété Orders d'une instance de la classe Customer. Ensuite, vous passez simplement le OrderId en tant que paramètre pour récupérer l'instance de commande particulière.

Les indexeurs prennent en charge l'héritage, peuvent être polymorphes et peuvent également être abstraits. Considérez la classe suivante qui définit un indexeur qui est virtuel. La classe ContactBase est une version modifiée de la classe Contact dont nous avons parlé plus haut dans cet article.

 public class ContactBase

    {

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

        public virtual string this[int index]

        {

            get

            {

                return address[index];

            }

            set

            {

                address[index] = value;

            }

        }

    }

Vous pouvez maintenant dériver une classe de la classe ContactBase et remplacer l'indexeur comme indiqué ci-dessous.

public class ConcreteContact: ContactBase

    {

       public override string this[int index]

        {

            get

            {

                return address[index];

            }

            set

            {

                address[index] = value;

            }

        }

    }

Ainsi, dans l'exemple de code ci-dessus, nous avons exploré comment les indexeurs peuvent être utilisés lors de l'héritage de types et comment ils peuvent montrer un comportement polymorphe.

Vous pouvez tout aussi bien définir un indexeur comme abstrait. Pour ce faire, vous devez créer une classe abstraite, puis définir un indexeur comme abstrait à l'intérieur. Modifions la classe ContactBase et définissons l'indexeur comme abstrait. Voici à quoi ressemblerait désormais la version modifiée de la classe ContactBase:

 public abstract class ContactBase

    {

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

        public abstract string this[int index]

        {

            get; set;

        }

}

De toute façon, vous n'avez pas besoin de modifier la classe ConcreteContact. Vous pouvez désormais utiliser l'indexeur pour attribuer des valeurs de chaîne à une instance de la classe ConcreteContact comme indiqué ci-dessous.

ConcreteContact contact = new ConcreteContact();

contact[0] = "Begumpet";

contact[1] = "Hyderabad";

contact[2] = "Telengana";