Come lavorare con gli indicizzatori in C #

Il linguaggio di programmazione C # include il supporto per gli indicizzatori, una funzionalità che consente di utilizzare un oggetto come un array. Gli indicizzatori sono noti anche come array intelligenti e possono essere definiti in modo simile a come viene definita una proprietà. L'MSDN afferma: "Gli indicizzatori consentono di indicizzare le istanze di una classe o di una struttura proprio come le matrici. Gli indicizzatori assomigliano a proprietà tranne per il fatto che le loro funzioni di accesso accettano parametri".

Sebbene gli indicizzatori e le proprietà abbiano somiglianze in più di un modo, ci sono sottili differenze tra loro. A differenza delle proprietà, puoi accedere a un indicizzatore utilizzando gli indici. Ricorda che devi accedere a una proprietà utilizzando il suo nome. Inoltre, gli indicizzatori sono membri di istanza di una classe e quindi non possono essere statici. Puoi avere proprietà statiche e non statiche.

Il frammento di codice seguente illustra come viene dichiarato un indicizzatore:

this [argument list]

{

  get

  {

  }

  Set

  {

  }

}

Notare che il modificatore come mostrato nella dichiarazione di sintassi di un indicizzatore può essere privato, pubblico, protetto o interno.

Considera la seguente classe:

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 contiene un membro privato denominato address e definisce un indicizzatore. Il membro dell'indirizzo è un array di tipo stringa. Ecco come puoi creare un'istanza della classe Contact e utilizzare l'indicizzatore.

Contact contact = new Contact();

 contact[0] = "Begumpet";

 contact[1] = "Hyderabad";

 contact[2] = "Telengana";

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

Console.WriteLine (contact[i]);

Va notato che è necessario utilizzare la parola chiave "this" per definire gli indicizzatori. Tieni presente che non sei vincolato a utilizzare solo numeri interi come indici per accedere agli indicizzatori: puoi anche utilizzare altri meccanismi di ricerca. Un indicizzatore viene in genere utilizzato quando la classe rappresenta una raccolta o più oggetti. È quindi possibile utilizzare indexer per accedere a un elemento specifico utilizzando index.

Facciamo un esempio. Considera la seguente classe denominata 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 definisce un indicizzatore di tipo Order. Contiene anche una proprietà pubblica che è un elenco di tipo Order. Ecco la classe Order come riferimento.

public class Order

    {

        public int OrderID

        {

            get; set;

        }

    }

Il frammento di codice seguente illustra come accedere all'indicizzatore della classe Customer per recuperare un ordine particolare.

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

Fare riferimento allo snippet di codice sopra. Notare come un elenco generico di tipo Order è stato creato e assegnato alla proprietà Orders di un'istanza della classe Customer. Successivamente, basta passare OrderId come parametro per recuperare la particolare istanza di ordine.

Gli indicizzatori supportano l'ereditarietà, possono essere polimorfici e possono anche essere astratti. Considera la seguente classe che definisce un indicizzatore virtuale. La classe ContactBase è la versione modificata della classe Contact discussa in precedenza in questo articolo.

 public class ContactBase

    {

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

        public virtual string this[int index]

        {

            get

            {

                return address[index];

            }

            set

            {

                address[index] = value;

            }

        }

    }

È ora possibile derivare una classe dalla classe ContactBase e sovrascrivere l'indicizzatore come mostrato di seguito.

public class ConcreteContact: ContactBase

    {

       public override string this[int index]

        {

            get

            {

                return address[index];

            }

            set

            {

                address[index] = value;

            }

        }

    }

Quindi, nell'esempio di codice sopra, abbiamo esplorato come possono essere usati gli indicizzatori mentre ereditano i tipi e come possono mostrare un comportamento polimorfico.

Puoi anche definire un indicizzatore come astratto. Per fare ciò, è necessario creare una classe astratta e quindi definire un indicizzatore come astratto al suo interno. Modifichiamo la classe ContactBase e definiamo l'indicizzatore come astratto. Ecco come apparirà ora la versione modificata della classe ContactBase:

 public abstract class ContactBase

    {

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

        public abstract string this[int index]

        {

            get; set;

        }

}

Non è comunque necessario modificare la classe ConcreteContact. È ora possibile sfruttare l'indicizzatore per assegnare valori stringa a un'istanza della classe ConcreteContact come mostrato di seguito.

ConcreteContact contact = new ConcreteContact();

contact[0] = "Begumpet";

contact[1] = "Hyderabad";

contact[2] = "Telengana";