Indexery - náhrada za přetížení operátoru [] (Zajímavé konstrukce jazyka C# II.)
- Vložil Trupík 8/23/2006 11:25:06 PM
-
Operátor [] (hranatice) se používá snad ve všech programovacích
jazycích pro přímý přístup k položkám pole. Dovnitř hranatic se
píše index prvku, na který chceme přistoupit.
Programátor občas ale zatouží po podobném principu u vlastních
tříd. K tomu se dá v některých jazycích využít třeba mechanismus
přetěžování operátorů, například v jazyce C++ to jde – tam
jdou přetěžovat skoro všechny operátory, až na pár vyjímek. Pokud jste
ale zkoušeli někdy skutečně robustně přetěžovat operátor []
u nějaké třídy, která se například kvůli realokacím může
pohybovat po paměti (příkladem takové třídy může být např. pole
proměnné velikosti), víte, jaký je to vopruz.
Problémem při přetěžování tohoto operátoru je totiž to, že ho
programátor může v kódu použít na obou stranách rovnítka. Dokonce
na obou stranách rovnítka najednou, na pravé ještě k tomu
několikrát, když k tomu ještě připočtem to, že by mohl někdo
používat hodnotu, vrácenou operátorem přiřazení v nějakém
nadřazeném výrazu, je už oheň na střeše.
Asi kvůli častým chybám v přetěžování operátoru []
v jazyce C++ se rozhodli autoři C# tento operátor mezi přetížitelné
nezahrnout (v C# je narozdíl od C++ množina přetížitelných
operátorů velmi malá – ale aspoň něco, taková Java to nemá
vůbec). Místo toho nabízí jiný způsob – takzvaný indexer. Indexer
se deklaruje podobně jako se deklarují properties – tedy
s modifikátory get a set. Příklad:
class MyClass
{
private int[] _a = new int[10];
public int this[int i]
{
get
{
return _a[i];
}
set
{
_a[i] = value;
}
}
}
Klíčové slovo this značí, že se jedná o indexer, za ním
v hranaticích může být libovolný počet proměnných libovolných
typů (ano, můžete indexovat pomocí více proměnných – tím můžete
simulovat vícerozměrné pole – treba Sachovnice[X,Y] nebo provádět
jiné kousky). Uvnitř těla indexeru pak je jeden nebo oba
z modifikátorů přístupu get a set. (díky tomu, že jsou tu dva
modifikátory přístupu, se vyřeší C++ problém s rozlišením toho,
zda operátor stojí na levé nebo pravé straně rovnítka). Navíc
u obou modifikátorů můžete kromě vlastního vrácení/nastavení
hodnoty provádět jiné operace (kontroly na indexy a podobně).
Na závěr ještě jedna konstrukce, kterou překladač nezkousne.
class InvalidClass
{
private int[] _a = new int[10];
public int AsArray[int i]
{
get
{
return _a[i];
}
set
{
_a[i] = value;
}
}
}
//
//...
//
InvalidClass c = new InvalidClass;
c.AsArray[i] = 1;
Tedy v hlavičce indexeru je vždy klíčové slovo this a řádek
public int AsArray
je špatně. Taková volnost v indexerech totiž není.
Indexerů může být v jedne třídě definováno několik –
musí se ale lišit počtem nebo typem parametrů nebo návratovou
hodnotou.
Používáním indexerů se váš kód stane přehlednějším a
elegantnějším. Mnoho z tříd FCL indexery používá (typicky
kolekce).
Ohodnoťte prosím užitečnost článku