1. diel - Úvod do kolekcií a genericita
V dnešnej lekcii si povieme úvodnú teóriu ku kolekciám v C# .NET, ktoré si v tomto kurze podrobnejšie rozoberieme.
Kolekcia
Pojem kolekcia označuje súbor dát, ktoré sú väčšinou rovnakého typu
a slúžia na špecifický účel. Počas seriálu sme sa už stretli s dvoma
typmi kolekciou, bolo to pole a List
. Kolekcií existuje veľké
množstvo a hoci sa zvonku mnohokrát tvária podobne, vo vnútri fungujú
veľmi odlišne a vyberáme si ich podľa konkrétneho účelu. .NET disponuje
veľkým množstvom predpripravených kolekcií, s ktorými sa v tejto sekcii
postupne zoznámime a skúsime sa s nimi pracovať.
Generické a všeobecné kolekcie
Keď sa zamyslíme nad tým, ako by sme si urobili vlastnú kolekciu, určite
by sme po nejakej dobe dospeli k problému. Bol by ním dátový typ kolekcie.
Chceli by sme si napr. Naprogramovať vlastný List
, vytvorili by
sme triedu MujList.cs
, do nej pridali príslušnej metódy a
všetko potrebné. Pretože však chceme, aby bola naša kolekcia univerzálne a
vedela teda ukladať napr. Ako int
y, tak užívateľov, bude
problém s dátovým typom prvkov vnútri kolekcie. Existujú 2 varianty, ako
tento problém vyriešiť a aj samotný .NET obsahuje kolekcie týchto 2
typov.
Všeobecné kolekcia
Keďže vieme, že všetky dátové typy majú ako predka triedu
Object
, môžeme prvky v našej kolekcii ukladať práve do tohto
dátového typu. Do kolekcie teraz môžeme uložiť v podstate čokoľvek.
Nevýhodou je, že sama kolekcia skutočný dátový typ prvkov nepozná a preto
vie prvky navracať len ako všeobecné objekty. Po získaní prvku z kolekcie
si ho teda musíme pretypovať.
Uveďme si príklad negenerické kolekcie, je jej ArrayList
:
ArrayList list = new ArrayList(); list.Add("položka"); string polozka = (string)list[0];
Po vytvorení listu si doň pridáme položku typu string
. Aby
sme túto položky mohli z listu získať späť, treba ju na
string
spätne pretypovať.
Pre funkčnosť kódu musíme pridať using System.Collections;
.
Keďže tento menný priestor nie je v predvolenom projektu prítomný,
napovedá nám to, že negenerické kolekcia nebudú tá obvyklá voľba.
Generické kolekcia
Generické kolekcia rieši problém s dátovým typom na úrovni jazyka C #.
Zavádza tzv. Genericitu. Zjednodušene povedané sa jedná o možnosť
špecifikovať typ údajov až vo chvíli vytvorenie inštancie. V triede
samotnej kolekcie sa potom pracuje s generickým typom, ktorý slúži ako
zástupca pre budúce dátový typ. Môžeme si to predstaviť tak, že sa
generický typ v triede zmení napr. Na string
vo chvíli, keď
vytvoríme jej inštanciu. Jedná sa teda o možnosť triedy nejakým spôsobom
parametrizovať.
Generický List
už poznáme a onen dátový typ (parameter) sa
generickým triedam špecifikuje vo špicatých zátvorkách. Máme možnosť
špecifikovať dátový typ iba raz, pri vytvorení kolekcie. Akékoľvek
ďalšie pretypovanie odpadá:
List<string> list = new List<string>(); list.Add("položka"); string polozka = list[0];
Program funguje úplne rovnako, ako ten s negenerické kolekciou
ArrayList
, však čítať môžeme bez nepohodlného
pretypovanie.
Generické kolekcia nahradili kolekcia všeobecné a tie sa už príliš nepoužívajú. V kurze sa budeme venovať generickým kolekciám a ich negenerické verzie len zmienime.
Genericita
Genericita je samozrejme vlastnosť jazyka C# a my ju máme možnosť vo svojich triedach používať.
Zatiaľ sa nebudeme zaťažovať tvorbou vlastnej kolekcie. Vytvorme si
triedu, ktorá bude jednoducho spravovať jednu premennú. Premenná bude
generická, teda ľubovoľného dátového typu. Založte si nový projekt,
konzolovú aplikáciu s názvom Genericita
. Pridajte si novú
triedu, pomenujte ju teraz pre študijné účely iba Trida
. V jej
deklarácii pridáme generický parameter, ktorý pomenujeme T
:
public class Trida<T> { }
Generických parametrov môžeme zadať vo špicatých zátvorkách viac, oddelíme ich čiarkou. Niekedy sa to môže hodiť, my sa s tým stretneme ďalej u generických slovníkov.
Presunieme sa do metódy Main()
, kde si vytvoríme inštanciu
našej triedy:
Trida<int> instance = new Trida<int>();
Nezabudneme na špicaté zátvorky ako u dátového typu, tak u konstruktoru.
Teraz sme parametra T
v tejto inštanciu triedy určili dátový
typ int
. Rovnako tak si môžeme urobiť ďalší inštanciu tej
istej triedy a parametra T
dať úplne iný dátový typ, napr.
string
. Stačí nám teda 1 trieda pre viac dátových typov.
Pokračujme a vytvorme si v triede atribút. T
môžeme použiť
ako bežný dátový typ:
private T promenna;
Triede ešte dodáme konštruktor, ktorý premennú inicializuje:
public Trida(T promenna) { this.promenna = promenna; }
V Main()
aktualizujeme vytvorení inštancie:
Trida<int> instance = new Trida<int>(10);
Teraz inštancie obsahuje atribút promenna
, ktorý je typu
int
a nadobúda hodnoty 10
.
Môžeme dokonca pridať metódu, ktorá bude mať naviac ďalšie generický parameter (iný, než má trieda). Mohla by vyzerať napr. Nasledovne:
public bool Porovnej<T2>(T2 a) { return promenna.Equals(a); }
Skúsime si teda porovnať náš int
s nejakým iným typom:
instance.Porovnej<string>("15");
Ďalšie konštrukcie
Pre úplnosť si ešte uveďme niekoľko konštrukcií.
Generický parameter triedy je možné bližšie špecifikovať, presnejšie
obmedziť. Slúži na to kľúčové slovo where
. Môžeme tak
nastaviť, že udaný dátový typ musí napr. Obsahovať rozhranie
IComparable
:
public class Trida<T> where T: IComparable { ... }
Vďaka tomu môžeme na premenných typu T
teraz vnútri triedy
volať metódy z daného rozhrania. Samotné rozhranie môže opäť obsahovať
generický parameter, aby sme generické typy mohli používať aj v
hlavičkách jeho metód.
Keď uvedieme za where
ešte new()
, môžeme
vnútri typ T
instanciovat. Taká malá továreň na inštancie
ľubovoľného typu by mohla vyzerať takto:
public class Tovarna<T> where T : new() { public T VytvorInstanci() { return new T(); } }
Ak máme vo where
už nejaká rozhranie, new()
dáme jednoducho medzi ne a oddelíme čiarkou.
Nakoniec si ukážme, ako môžeme typ parametra obmedziť z hľadiska dedičnosti:
public class Trida<A, B, C> where A : B where B : C { }
Vyššie sme deklarovali triedu s tromi generickými parametrami, kde
A
je potomkom B
a B
je potomkom
C
.
V budúcej lekcii, Zoznam (List) pomocou poľa v C # , sa pozrieme na listy, predstavíme si rôzne implementácie tejto kolekcie a ich výhody a nevýhody.
Mal si s čímkoľvek problém? Stiahni si vzorovú aplikáciu nižšie a porovnaj ju so svojím projektom, chybu tak ľahko nájdeš.
Stiahnuť
Stiahnutím nasledujúceho súboru súhlasíš s licenčnými podmienkami
Stiahnuté 724x (21.23 kB)
Aplikácia je vrátane zdrojových kódov v jazyku C#