Jak pracować z indeksatorami w C #

Język programowania C # obejmuje obsługę indeksatorów - funkcję, która umożliwia użycie obiektu tak samo jak tablicy. Indeksatory są również nazywane inteligentnymi tablicami i można je definiować podobnie do definiowania właściwości. MSDN stwierdza: „Indeksatory pozwalają na indeksowanie wystąpień klasy lub struktury tak samo jak tablice. Indeksatory przypominają właściwości, z tą różnicą, że ich metody dostępu pobierają parametry”.

Chociaż indeksatory i właściwości mają podobieństwa na więcej niż jeden sposób, istnieją między nimi subtelne różnice. W przeciwieństwie do właściwości możesz uzyskać dostęp do indeksatora przy użyciu indeksów. Pamiętaj, że musisz uzyskać dostęp do właściwości, używając jej nazwy. Ponadto indeksatory są członkami instancji klasy i dlatego nie mogą być statyczne. Możesz mieć właściwości statyczne i niestatyczne.

Poniższy fragment kodu ilustruje sposób deklarowania indeksatora:

this [argument list]

{

  get

  {

  }

  Set

  {

  }

}

Należy zauważyć, że modyfikator, jak pokazano w deklaracji składni indeksatora, może być prywatny, publiczny, chroniony lub wewnętrzny.

Rozważ następującą klasę:

public class Contact

    {

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

        public string this[int index]

        {

            get

            {

                return address[index];

            }

            set

            {

                address[index] = value;

            }

        }

    }

Klasa Contact zawiera prywatnego członka o nazwie address i definiuje indeksator. Element adresu jest tablicą typu string. Oto, jak możesz utworzyć wystąpienie klasy Contact i użyć indeksatora.

Contact contact = new Contact();

 contact[0] = "Begumpet";

 contact[1] = "Hyderabad";

 contact[2] = "Telengana";

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

Console.WriteLine (contact[i]);

Należy zauważyć, że aby zdefiniować indeksatory, należy użyć słowa kluczowego „this”. Pamiętaj, że nie jesteś ograniczony do używania tylko liczb całkowitych jako indeksów w celu uzyskania dostępu do indeksatorów - możesz nawet użyć innych mechanizmów wyszukiwania. Indeksator jest zwykle używany, gdy klasa reprezentuje kolekcję lub obiekty. Następnie możesz użyć indeksatora, aby uzyskać dostęp do określonego elementu za pomocą indeksu.

Spróbujmy na przykładzie. Rozważmy następującą klasę o nazwie 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();

            }

        }

    }

Klasa Customer definiuje indeksator typu Order. Zawiera również właściwość publiczną, która jest listą typu Order. Oto klasa Order w celach informacyjnych.

public class Order

    {

        public int OrderID

        {

            get; set;

        }

    }

Poniższy fragment kodu ilustruje, w jaki sposób można uzyskać dostęp do indeksatora klasy Customer w celu pobrania określonego zamówienia.

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

Zapoznaj się z powyższym fragmentem kodu. Zwróć uwagę, jak utworzono ogólną listę typu Order i przypisano ją do właściwości Orders instancji klasy Customer. Następnie wystarczy przekazać OrderId jako parametr, aby pobrać konkretną instancję zamówienia.

Indeksatory obsługują dziedziczenie, mogą być polimorficzne, a także abstrakcyjne. Rozważmy następującą klasę, która definiuje indeksator, który jest wirtualny. Klasa ContactBase jest zmodyfikowaną wersją klasy Contact, którą omówiliśmy wcześniej w tym artykule.

 public class ContactBase

    {

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

        public virtual string this[int index]

        {

            get

            {

                return address[index];

            }

            set

            {

                address[index] = value;

            }

        }

    }

Możesz teraz wyprowadzić klasę z klasy ContactBase i zastąpić indeksator, jak pokazano poniżej.

public class ConcreteContact: ContactBase

    {

       public override string this[int index]

        {

            get

            {

                return address[index];

            }

            set

            {

                address[index] = value;

            }

        }

    }

Tak więc w powyższym przykładzie kodu zbadaliśmy, w jaki sposób można używać indeksatorów podczas dziedziczenia typów i jak mogą wykazywać zachowanie polimorficzne.

Równie dobrze można zdefiniować indeksator jako abstrakcyjny. Aby to zrobić, musisz utworzyć klasę abstrakcyjną, a następnie zdefiniować w niej indeksator jako abstrakcyjny. Zmodyfikujmy klasę ContactBase i zdefiniujmy indeksator jako abstrakcyjny. Oto jak wyglądałaby teraz zmodyfikowana wersja klasy ContactBase:

 public abstract class ContactBase

    {

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

        public abstract string this[int index]

        {

            get; set;

        }

}

I tak nie musisz zmieniać klasy ConcreteContact. Możesz teraz wykorzystać indeksator, aby przypisać wartości ciągów do wystąpienia klasy ConcreteContact, jak pokazano poniżej.

ConcreteContact contact = new ConcreteContact();

contact[0] = "Begumpet";

contact[1] = "Hyderabad";

contact[2] = "Telengana";