Poznáváme C# a Microsoft.NET – 12. díl

Po minulém seznámení s poli se pokusím v tomto díle osvětlit třídu System.Array a její užitečné metody. Pozornost bude také věnována použití cyklu for each, který se pro procházení polí nezřídka užívá.

System.Array

Jak jsem zmínil v předcházejícím díle, každé námi vytvořené pole je instance třídy, která je odvozena od třídy System.Array. Díky tomu je nám umožněno na vzniklých instancích používat členy, definované v této třídě. Mimo to, obsahuje tato třída i několik statických metod, které nám v mnoha situacích mohou být nápomocné pří užívání polí. Na některé užitečné statické i instanční členy se nyní podíváme blíže.

Zjištění počtu rozměrů pole

Někdy při práci s poli může být užitečné zjistit počet rozměrů daného pole. K tomuto účelu slouží instanční vlastnost Rank.

int[,,] triRozmernePole = new int[2,3,4];
//vysledek je tri
Console.WriteLine(triRozmernePole.Rank);

Další možnost vytvoření pole

Protože jsou pole objekty (stejně jako vše ostatní v .NET), je možné vytvořit instanci pole jinak než použitím zápisu pro deklaraci pole v daném jazyku. Můžeme toho dosáhnout použitím statické metody CreateInstance. 

//vytvoreni pole o delce 5 prvku
int[] mojePole = (int[])Array.CreateInstance(typeof(Int32),5);
//vytvoreni trirozmerneho pole
int[] lDelkyRozmeru = new int[3]{4,3,2};
int[,,] triRozmernePole = (int[,,])Array.CreateInstance(typeof(Int32),lDelkyRozmeru);

Při vytváření pole touto cestou, je nutné použít odpovídající explicitní přetypování na konkrétní typ pole. Typ pole, které má být vytvořeno je metodě CreateInstance předán jako parametr. 

Poznámka: Datový typ je v prostředí .NET frameworku představován třídou System.Type. Právě instanci této třídy očekává mimo jiné metoda CreateInstance třídy System.Array. operátoru typeof jak je ukázáno v ukázce.

Převrácení pořadí prvků pole

V případě, že z nějakého důvodu potřebujeme převrátit pořadí prvků pole, použijeme statickou metodu Reverse, jíž je jako parametr předána proměnná pole. 

int[] ciselnePole = new int[]{1,2,3,4,5};
Array.Reverse(ciselnePole);                   
for (int i = 0; i < ciselnePole.Length;i++)
  Console.WriteLine(ciselnePole[i]);

Výstup bude vypadat takto:

5
4
3
2
1 

Získáni indexů okrajů pole

V určitých případech může být užitečné mít k dispozici indexy spodního nebo vrchního okraje pole. Pro tyto případy tu jsou instanční metody GetLowerBound a GetUpperBound, jimž se ve formě parametru předá číslo rozměru pole, jehož spodní respektive vrchní index potřebujeme zjistit. Následující příklad demonstruje možné použití těchto metod pro výpis pole pomocí cyklu for.

int[] ciselnePole = new int[]{1,2,3,4,5};
int spodek = ciselnePole.GetLowerBound(0);
int vrsek = ciselnePole.GetUpperBound(0);
for (int i = spodek; i <= vrsek;i++)
 
Console.WriteLine(ciselnePole[i]);

Mělká kopie pole

Při použití takzvané mělké kopie pole je do nově vzniklé kopie pole zkopírován pouze obsah prvků originálu. Následkem tohoto jevu jsou v případě klonování polí, jejichž prvky představují objekty referenčního typu, zkopírovány pouze reference ukazující na tentýž objekt na což je třeba brát ohledy. V případě polí obsahující prvky hodnotových typů jsou do kopie pole zkopírovány objekty. K vytvoření mělké kopie slouží instanční metoda Clone.

public static void CloneIntPriklad()
{
 
int[] prvniPole = new int[5]{1,2,3,4,5};
 
int[] druhePole = new int[5];
 
druhePole = (int[])prvniPole.Clone();
 
//jelikoz jsou prvky hodnotoveho typu
 
//zmena prvku v prvnim poli neovlivni
 
//hodnotu prvku druheho pole
 
prvniPole[0] = 10;
 
for (int i = 0; i < druhePole.Length;i++)
 
Console.WriteLine(druhePole[i]);
}

Změna hodnoty prvku prvního pole po uskutečnění klonování neovlivnila hodnotu v druhém poli, jak je možno vidět na výstupu:

1
2
3
4
5

Jinak je to ovšem u prvků referenčního typu. 

public static void CloneRefPriklad()
{
 
//vytvoreni poli zarovek
 
Zarovka[] poleZarovek = new Zarovka[5];
 
Zarovka[] druhePoleZarovek = new Zarovka[5];
 
//vytvoreni zarovky s vykonem 120 W
 
//jako prvku prvniho pole
  poleZarovek[0] = new Zarovka(120);
 
druhePoleZarovek = (Zarovka[])poleZarovek.Clone();
 
//zmena vykonu zarovky pres prvek prvniho pole
 
poleZarovek[0].Vykon = 100;
 
//vykon zarovky v druhem poli bude take 100
 
//protoze prvek referencuje tu samou instanci
 
Console.WriteLine("Vykon zarovky v druhem poli : " + druhePoleZarovek[0].Vykon);
}

Vykon zarovky v druhem poli: 100 

Vyhledání prvku v jednorozměrném poli

Pokud potřebujeme vyhledat určitý prvek jednorozměrného pole nabízí se nám možnost použití statické metody BinarySearch. Tato metoda vrací index hledaného prvku nebo nulu, když pole hledaný prvek neobsahuje. V ukázce můžete vidět použití jedné z přetížených verzí metody BinarySearch. 

public static void BinarySearchPriklad()
{
 
int[] mojePole = new int[5];
 
//prirazeni hodnot prvku pole pouzitim
 
//metody SetValue
 
mojePole.SetValue(1,0);
 
mojePole.SetValue(2,1);
 
mojePole.SetValue(3,2);
 
mojePole.SetValue(4,3);
 
mojePole.SetValue(5,4);
 
NajdiPrvek(mojePole,3);
} 

private static void NajdiPrvek(Array pole, Object objektProNalezeni)
{
 
//prvni parametr je pole ve kterem se ma hledat
 
//a druhy hledany objekt
 
int lIndex = Array.BinarySearch(pole,objektProNalezeni);
 
if (lIndex == 0)
 
Console.WriteLine("Prvek nebyl v poli nalezen");
 
else
 
Console.WriteLine("Prvek {0} se v poli nachazi na indexu {1}",objektProNalezeni,lIndex);
}

Výstup: 

Prvek 3 se v poli nachazi na indexu 2

Cyklus foreach

Cylkus foreach je v jazyku C# předurčen k procházení polí a kolekcí. Z tohoto důvodu se o něm zmiňuji až v tomto díle a neuvedl jsem ho v díle, který pojednával o cyklech. Použití cyklu foreach s poli je jednoduché:

foreach(datový_typ identifikátor in pole)
{
 
operace
}

Cyklus provede definované operace pro každý prvek pole. K prvku je v těle cyklu přistupováno prostřednictvím identifikátoru, který je platný pouze v rámci cyklu. Pro pochopení použití uvedu příklad.

public static void VypisPole(int[] poleProVypsani)
{
 
foreach(int prvek in poleProVypsani)
 
{
   
//každý prvek bude vypsán
   
Console.WriteLine(prvek);
 
}
} 

Tento krátký zápis bude mít stejnou funkčnost jako tento cyklus for:

public static void VypisPoleFor(int[] poleProVypsani)
{
 
for (int i = 0; i < poleProVypsani.Length;i++)
 
Console.WriteLine(poleProVypsani[i]);
} 

Je patrné, že použití cyklu foreach pro procházení polí je elegantnější a méně náchylné k chybám.

Zdrojové kódy příkladu naleznete zde.

V příštím díle se zaměříme na výjimky.

Diskuze (12) Další článek: Intel snížil ceny procesorů až o 34 procent

Témata článku: , , , , , , , , , , ,