V tomto dieli sa budeme zaoberať praktickým použitím Generics a ukážeme si základné triedy, ktoré nám umožňujú prácu so zoznamami, zásobníkmi, frontami, poliami atď...
Dúfam, že Vás poteší tento nový diel, ktorý vychádza po dlhšej odmlke, za ktorú sa ospravedlňujem. Mal som dosť roboty, ale teraz som už oddýchnutý a plný elánu v pokračovaní série o programovaní v C# v2.0.
V minulom dieli sme si v jednoduchosti vysvetlili podstatu
Generics. Ako som už spomínal, veľa tried vhodných na zoznamy (diel 4. séria 2) je v C# implementovaných pomocou
Generics a dajú sa veľmi ľahko a dosť
efektívne použiť.
Postupne si prejdeme jednotlivé triedy,
pozrieme sa na ich klady, zápory a čo je hlavné :
oblasti použitia. Tento diel alebo možno aj budúci bude vo forme kuchárky, preto je tu hlavne veľa príkladov a už menej teórie.
>> List class - Zoznam Začínam s touto triedou, pretože patri medzi najpraktickejšie. Umožňuje nám jednoducho vytvárať
jednorozmerné polia, bez toho aby sme si sami museli písať funkcie
pre indexový operátor []. Túto triedu rozoberiem podrobnejšie, aby sme si ukázali niektoré zaujímavé funkcie, ktoré majú aj ostatné podobné triedy, o ktorých budem hovoriť.
Príklad 6.1
using System;
using System.Collections.Generic; // Nezabudnut pridat !!
//----------------------------------------------------
class MainClass
{
public static void Main(string[] args)
{
// Vytvorenie zoznamu
List<string> mena = new List<string>();
//Naplnenie zoznamu
mena.Add("Jano");
mena.Add("Lucia");
mena.Add("Imro");
mena.Add("Diana");
//Vypis pomocou indexu
for(int i = 0; i < mena.Count; i++)
Console.WriteLine(mena[i]);
// Vlozenie noveho prvku na lubovolne miesto
// Indexuje sa od nuly,index 2 == 3 pozicia
Console.WriteLine("\nPridame Ivana na 3. miesto");
mena.Insert(2,"Ivan");
for(int i = 0; i < mena.Count; i++)
Console.WriteLine(mena[i]);
Console.WriteLine();
// Ak prvok nenajde vrati -1
int pos = mena.IndexOf("Fero");
Console.WriteLine("Fero je na pozicii s indexom : {0}",pos);
pos = mena.IndexOf("Imro");
Console.WriteLine("Imro je na pozicii s indexom : {0}",pos);
// Odstranenie prvku z lubovolnej pozicie
// Konkretne Imra
Console.WriteLine("\nOdstranime prvok s indexom {0}",pos);
mena.RemoveAt(pos);
for(int i = 0; i < mena.Count; i++)
Console.WriteLine(mena[i]);
//Vymazanie zoznamu
mena.Clear();
//Pozastavnie vypisu
Console.ReadLine();
}
}
//----------------------------------------------------Príklad na stiahnutie Príklad je podľa mňa dostatočne okomentovaný a ukazuje základné operácie s triedou List.
>>Časová náročnosť pridania nového prvku
Takáto pohodlná práca so zoznamom je zaplatená väčšou časovou náročnosťou na jeho spravovanie. Aby sme tento čas, čo najviac skrátili, je dobré vedieť
ako vnútorne trieda List funguje.
1. Pri vytvorení prázdneho zoznamu si vnútorne rezervuje klasické pole o konštantnej dĺžke.
2. Ak pridávame nový prvok pomocou
.Add a nie sú ešte všetky políčka obsadené, všetko je v pohode a táto operácia trvá
1 časovú jednotku.
3. Ak už ale vo vnútornom poli nie je miesto, tak sa vytvorí nové pole s väčšou dĺžkou a všetky už uložené prvky sa doň ho skopírujú + nový prvok. A nakoniec sa staré pole zruší.
Ak staré vnútorne pole obsahovalo
n prvkov tak táto operácia pridania jedného prvku
trvá
n časových jednotiek.
Preto je vhodné už pri vytváraní zoznamu nastaviť
s akým približným maximálnym počtom prvkov rátate. Viď príklad.
Príklad 6.2
using System;
using System.Collections.Generic;
//----------------------------------------------------
class MainClass
{
public static void Main(string[] args)
{
List<string> samoNastavene = new List<string>();
// Ako ziskat aktualnu maximalnu kapacitu
int kap = samoNastavene.Capacity;
Console.WriteLine("Trieda List po inicializacii ma kapacitu {0}",
kap);
Console.WriteLine("Pridame jeden prvok");
samoNastavene.Add("Ahoj");
kap = samoNastavene.Capacity;
Console.WriteLine("Trieda List zvysila kapacitu na {0}",
kap);
// Vytvorime zoznam s vlastnou
// pociatocnou kapacitou 10 prvkov
Console.WriteLine("Vytvorime prazdny zoznam " +
"na zaciatok pre 10 prvkov");
List<int> rucneNastavene = new List<int>(10); //!!!!!
for(int i = 0; i < 10; i++)
rucneNastavene.Add(i);
kap = rucneNastavene.Capacity;
Console.WriteLine("Pridali sme 10 prvkov a kapacita je {0}",
kap);
Console.WriteLine("Pridame jeden prvok");
rucneNastavene.Add(55);
kap = rucneNastavene.Capacity;
Console.WriteLine("A kapacita sa zvysila na {0}",kap);
Console.ReadLine();
}
}
//----------------------------------------------------Príklad na stiahnutie V príklade vidíte, že ak chceme zoznam pripraviť na predpokladaná maximálnu veľkosť 10 prvkov, musíme tak urobiť v konštruktore.
Potom ak prekročíme rozsah tak sa nič zlé nestane, jednoducho pole zväčší svoju dĺžku na dvojnásobok pôvodnej a pridá nový prvok.
POZOR! Nezamieňajte si vlastnosť
Capacity a
Count!!!
Count je počet uložených prvkov.
Capacity – koľko maximálne prvkov môže byť uložených v zozname kým nenastane rozširovanie poľa.
>>Vyhľadávanie v zozname Príklad 6.3
using System;
using System.Collections.Generic;
//----------------------------------------------------
class MainClass
{
public static void Main(string[] args)
{
List<int> vysky = new List<int>(4);
vysky.Add(150);
vysky.Add(202);
vysky.Add(185);
vysky.Add(192);
int jednaNajdena = vysky.Find(HladajVysku); //!!!
Console.WriteLine("Prva vyska, ktora vyhovuje intervalu (150,200)");
Console.WriteLine("je {0}",jednaNajdena);
// Mozeme najst aj vsetky vyhovujuce vysky
// Vystupom je novy zoznam typu List
Console.WriteLine(" Vsetky vysky, ktore vyhovuju");
List<int> vsetky = vysky.FindAll(HladajVysku);
for(int i = 0; i < vsetky.Count; i++)
Console.WriteLine("{0}",vsetky[i]);
Console.ReadLine();
}
//---------------------------------------------------
// Napiseme vlastnu funkciu ako
// porovnavacie kriteriu a jej meno
// pouzijeme ako parameter pre .Find( );
private static bool HladajVysku(int vyska) //!!!
{
if (vyska > 150 && vyska < 200)
return true;
else
return false;
}
}
//----------------------------------------------------Príklad na stiahnutie Ak chceme vyhľadávať nejaký prvok, či množinu prvkov, musíme si napísať funkciu, ktorá vyhodnocuje naše kritérium. Vstupom môže byť iba jedna premenná a výstupom vždy
bool premenná (true alebo false).
>>Aplikácia jednej operácie na všetky prvky zoznamu Tu dám len jednoduchý príklad, pretože je to na spôsob predchádzajúceho problému, kde je potrebne si vytvoriť vlastne funkcie, ktoré sa potom aplikujú hromadne na všetky prvky.
Príklad 6.4
using System;
using System.Collections.Generic;
//---------------------------------------------------
class MainClass
{
public static void Main(string[] args)
{
List<string> pismena = new List<string>(4);
pismena.Add("za");
pismena.Add("as");
pismena.Add("de");
pismena.Add("tt");
//Aplikacia ForEach na vsetky prvky
Console.WriteLine("Vypis vsetkych prvkov vlastnou funkciou");
pismena.ForEach(VypisPrvok); //!!!!
Console.WriteLine();
bool result = pismena.TrueForAll(DvaZnaky); //!!!!
Console.WriteLine("Test ci vsetky prvky maju len dva znaky");
Console.WriteLine("skoncil s vysletkom : {0}",result);
// A nakoniec pole utriedime
// pouzije standartny operator porovnania
// ale mozeme si spravit aj vlastny
pismena.Sort();
Console.WriteLine("\nNa vsetky prvky aplikujeme triediaci algoritmus");
pismena.ForEach(VypisPrvok); //!!!!
Console.ReadLine();
}
//---------------------------------------------------
private static void VypisPrvok(string prvok)
{
Console.WriteLine(">> {0} <<",prvok);
}
//---------------------------------------------------
private static bool DvaZnaky(string prvok)
{
if (prvok.Length == 2 )
return true;
else
return false;
}
}
//---------------------------------------------------Príklad na stiahnutie >>Čo bude nabudúce?
Budeme pokračovať v podkapitole
Generics ďalšími triedami.
Michal Čižmármicitn@orangemail.sk
Neprehliadnite: