C#

Indeksatory

darek963

Zrozumienie artykułu wymaga znajomości: tablic, Klasy, Właściwości, akcesorów.

Indeksator

Dobra praktyka programowania obiektowego mówi, że zmienne deklarowane na poziomie klasy powinny być prywatne. Jeżeli chcemy odwoływać się do nich z kodu umieszczonego poza klasą powinniśmy zaimplementować publiczne właściwości, które będą na nich operować. A co zrobić jeśli mamy tablicę zadeklarowaną na poziomie klasy? W języku C# z pomocą przychodzą nam indeksatory (ang. indexers). Zaimplementowanie indeksatora pozwala nam odwoływać się do tablicy w klasie po samej nazwie obiektu i indeksie. Istnieje tutaj jednak pewne ograniczenie, klasa zawierająca indeksator może mieć zadeklarowaną tylko jedną tablicę. Podobnie jak właściwość, indeksator musi zawierać conajmniej jeden akcesor (GET lub SET). Warto przypomnieć, że w akcesorach SET występuje niejawnie zadeklarowana zmienna przechowująca wartość przypisywaną do indeksatora.

Przykład

Poniżej przedstawiam program (aplikacja konsolowa), który pokazuje jak używać przedmiotowego mechanizmu:

using System;
using System.Collections.Generic;
using System.Text;

namespace programPrzykladowy
{
    class Program
    {
        static void Main(string[] args)
        {
            KlasaDniTygodnia objDniTygodnia = new KlasaDniTygodnia(); // <deklaracja i inicjalizacja obiektu />
            Console.WriteLine( objDniTygodnia[5] ); // <odwołanie się do tablicy w klasie za pomocą indeksatora />
            Console.ReadKey();
        }
    }

    // <przykładowa klasa implementująca indeksator>
    public class KlasaDniTygodnia
    {        

        private string[] nazwyDni; // <deklaracja tablicy />

    // <konstruktor>
        public KlasaDniTygodnia()
        {
            nazwyDni = new string[7]; // <inicjalizacja tablicy />

        // <przypisanie wartości elementom tablicy> 
            nazwyDni[0] = "Poniedziałek";
            nazwyDni[1] = "Wtorek";
            nazwyDni[2] = "Środa";
            nazwyDni[3] = "Czwartek";
            nazwyDni[4] = "Piątek";
            nazwyDni[5] = "Sobota";
            nazwyDni[6] = "Niedziela";
        // </przypisanie wartości elementom tablicy>    
        }
    // </konstruktor>

    // <indeksator>
        public string this[int indeks]
        {
        // <akcesor zwracający wartosc tablicy>
            get
            {
                return this.nazwyDni[indeks - 1];
            }
        // </akcesor zwracający wartosc tablicy>

        // <akcesor zapisujący wartości do tablicy>
            set
            {
                this.nazwyDni[indeks-1] = value;
            }
        // </akcesor zapisujący wartości do tablicy>
        }
    // </indeksator>
    }
    // </przykładowa klasa implementująca indeksator>

}
C#

7 komentarzy

Zmienna value jest deklarowana niejawnie i przechowuje wartość przypisywaną do indeksera. Jeśli zapiszemy:

objDniTygodnia[1] = "Monday";

to string "Monday" będzie przechowywany w zmiennej value.

A co się stanie w takim wypadku? [sorki, że sam nie sprawdzę, chwilowe problemy ze środowiskiem]

set
{int value;
this.nazwyDni[indeks-1] = value;
}

PS
ciekawy sposób komentarzy XMLowych - to jakiś Twój standard czy ogólny? Jak pisałem w VS 2k3 to tagi były tylko w komentarzach ///

set
{this.nazwyDni[indeks-1] = value;}

zmienna 'value' jest odgórnie narzucona? nigdzie się jej nie deklaruje?

Teraz nie mam dostępu do VS więc nie sprawdzę, ale wydaje mi się, że kompilator powinien wyrzucić błąd. Standard komentarzy "zapożyczony" z pewnego projektu, w którym brałem udział. Moim zdaniem bardzo przejrzysty sposób komentowania kodu.

Komentarze XML po /// to mechanizm środowiska - tworzą one automatycznie dokumentację pisanego programu (opisy metod, parametrów, itd...).

Wiem, bo taką dokumentację sam tworzę. Myślałem, że to jakiś inny sposób :)

Tak wiem, zostałem górnikiem, ale robię to dla potomności!

@Marooned value to słowo kluczowe, więc zapewne przy takiej konstrukcji zostanie wyrzucony błąd.

Nie zgadam się z " Istnieje tutaj jednak pewne ograniczenie, klasa zawierająca indeksator może mieć zadeklarowaną tylko jedną tablicę."
Klasa zawierająca indeksator może mieć wiele tablic, po prostu indeksator można zrobic na jednej tablicy, a do pozostałych odnosić się przez metody.