fel
le

Indexelők

A property úgy viselkedik, mintha fizikailag létező mező lenne. Van védelmi szintje (jellemzően 'public'), van típusa, és Kidolgozásától függően támogatja az adott típusú érték olvasásának (get) és írásának (set) műveletét.

Amennyiben a property-ből adatot olvasunk, úgy aktiválódik annak get része, és kiolvasásra kerül (return) egy megfelelő típusú érték. Amennyiben a property-be értéket kívánunk írni, úgy aktiválódik a set része, és az értéket ellenőrzi, majd feldolgozza (leggyakrabban tárolja).

A fenti műveletek végrehajtása a háttérben gyakorlatilag függvényhívásokat jelentenek, melyek aktiválását a property írás vagy olvasás művelete váltja ki.

Az indexelő, mint speciális property

Lehetőség van C#-ban egy speciális nevű property létrehozására, melynek a neve this. Ezt a property-t indexelő-nek nevezzük. Nemcsak nevében speciális, hanem abban is, hogy ezen property-nek kivételesen paramétere is lehet:

class Sajat
{
  public Object this[int index]
  {
    get
    {
       // kód kerül ide
    }
    set
    {
       // kód kerül ide
    }
  }
}
 
Az indexelő valójában egy property, melynek a neve kötött (this), és melynek legalább egy paramétere is van!

Mint látszik, a this property paraméterének a fenti példában a neve index, típusa int. Az is látszik, hogy nem a szokásos gömbölyű zárójelpárban kell feltüntetni a property paraméterét, hanem szögletes zárójelpárban!

Az indexelő property aktiválása is speciális módon történik:

Sajat s = new Sajat();
Object p = s[3];
s[2] = null;
 

Az p=s[3] során aktiválódik a this nevű property, és a paraméter index=3 értéket fog felvenni. Mivel ekkor a this nevű property olvasására van szükség, a get rész indul el. A get kódjában lehetőség van az index paraméter értékének kiolvasására, majd segítségével elő lehet állítani a megfelelő értéket, és visszaadni azt egy return segítségével.

A s[2]=null során a this property set része aktiválódik, az index=2 lesz, az elhelyezendő értéket pedig szokásos módon a value-ban fogjuk megtalálni.

A fenti példa a speciális property, a this indexelő használatát mutatta be. Mint láthatjuk, roppant speciális módon aktiválhatjuk ezt a property-t, a példányunkat mint egy vektort, tömböt kell használnunk, és ennek során tudjuk a get vagy a set részt indítani. Éppen ezért hívják ezt indexelő property-nek.

Ilyen indexelőt készítünk általában azon objektum-osztályainkhoz, amelyekben tárolt értékekre ilyen kényelmes szintaktikával kívánunk hivatkozni. A BCL is számtalan ilyet tartalmaz, mint pl. a string, ArrayList, Array stb. osztályok esetén:

class String
{
  public char this[int index]
  {
    get
    {
       return ('index'. betűje a szövegnek);
    }
  }
}
 

A String osztály esetén az indexelő egy karaktert ad vissza, a szóban forgó string n. betűjét. Ezen indexelőnek csak a get része van kidolgozva, vagyis nem tudjuk átírni az n. betűértékét:

String s = "Helló";
char c = s[4]; // 'ó' betű
s[2] = 'f';    // ez nem működik, nincs set !!!
 

Az indexelő paraméterezhetősége (1)

Minden indexelőnek kötelező paramétert adni, de a paraméterek típusára, számára nincs megszorítás. Ha az indexelőnknek mondjuk két int paramétere van, akkor az objektum-példány úgy viselkedik, mint egy mátrix:

class SajatMatrix
{
  private int sorokSzama
  private int oszlopokSzama
  private int[,] tarolas;
 
  public SajatMatrix(int sorokSzama, int oszlopokSzama)
  {
    if (sorokSzama<=0 || oszlopokSzama<=0)
      throw new Exception("Ilyen matrix nincs is!");
    this.sorokSzama = sorokSzama;
    this.oszlopokSzama = oszlopokSzama;
    tarolas = new int[sorokSzama, oszlopokSzama];
  }
 
  public this[int i, int j]
  {
    get
    {
      if (0<= i && i<sorokSzama && 0<=j && j<oszlopokSzama) return tarolas[i,j];
      else throw new IndexOutOfRangeException("Hibas indexeles!");
    }
    set
    {
      if (0<= i && i<sorokSzama && 0<=j && j<oszlopokSzama) tarolas[i,j]=value;
      else throw new IndexOutOfRangeException("Hibas indexeles!");
    }
  }
}
// .............
SajatMatrix m = new SajatMatrix(10,30);
m[3,2] = 12;
int x = m[4,1];
 

Az indexelő paraméterezhetősége (2)

A System.Collections.SortedList osztály egy név-érték párosokat tartalmazó asszociatív vektor szerepét képes ellátni. A példány létrehozása után elemeket adhatunk hozzá, majd lekérdezhetjük valamely elem értékét annak azonosítója segítségével:

SortedList mySL = new SortedList();
mySL.Add("Nev", "Kiss Antal");
mySL.Add("Eletkor", 12);
...
int eletkor = (int)mySL["Eletkor"]
 

Hogyan nézhet ki ez az osztály hogy ilyen intelligensen működik? Mind a kulcs mind az érték általános 'Object' típusú elem lehet, bár a fenti példában a kulcsok (azonosítók) mindegyik string volt:

class SortedList
{
 public void Add(Object azonosito, Object ertek) { ... }
 public Object this[Object azonosito]
 {
    get
    {
      // az 'azonosito' kikeresése a listában
      // a hozzá tartozó érték visszaadása
      // ha nem található, akkor 'null' visszaadása
    }
    set
    {
      // az 'azonosito' kikeresése a listában
      //  ha az létezik, akkor értékének cserélése 'value'-ra
      //  különben új elem hozzáadása a név-érték párosokhoz
    }
 }
}
 

A fenti példában látható, hogy az indexelő paramétere nem minden esetben int, sőt, általános esetben bármilyen típusú, akár valamely korábban deklarált saját objektum-osztályunk típusa is lehet.

Hernyák Zoltán
2013-03-17 19:03:16