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

Tento díl bude věnován implementaci struktur a výčtových typů v jazyku C#.

Struktury v C#

Jak bylo řečeno dříve, v prostředí .NET frameworku jsou typy děleny do dvou skupin na hodnotové typy a referenční typy. Pokud vytváříme strukturu, vytváříme nový hodnotový typ. Použití struktur je vhodné při vytváření reprezentace jednoduchých objektů. Hlavní výhoda hodnotových typů je v jejich rychlé alokaci paměti a v nepřítomnosti režie, která je vlastní typům referenčním.

Pokud totiž máme proměnnou referenčního typu, je jako její hodnota, která je alokována v části paměti jménem zásobník, pouze odkaz na objekt, který se nachází v části pamětí nazývané hromada. U hodnotových typu tomu tak není a hodnota je uložena přímo v proměnné, tedy na zásobníku, což má za následek vyšší rychlost práce s nimi. Zjednodušeně řečeno, alokace místa pro objekt na hromadě zabere běhovému prostředí další čas a také s objekty na hromadě je spojena další režie pro její údržbu.

Poznámka: Předchozí výklad rozdílu mezi hodnotovými a referenčními (odkazovými) typy je zjednodušený a je zde pro pochopení toho nejdůležitějšího rozdílu, kterým tedy je, že použití struktur místo tříd s sebou přináší méně režie běhového prostředí. Podrobněji se problematikou referenčních a hodnotových typů zabýval kolega Milan Petřík v díle svého seriálu o VB.NET - Programujeme ve Visual Basic .NET - 18. díl - přehled datových typů.

Jelikož proměnné pro hodnotové typy neobsahují žádný odkaz na objekt, ale hodnotu nemohou nabývat hodnoty null, které mohou nabývat proměnné pro referenční typy. Hodnota null znamená, že referenční proměnná neukazuje na žádnou instanci třídy.

K vytváření struktur použijeme v jazyce C# klíčové slovo struct. Realizace struktury bod by mohla vypadat takto:

public struct Bod
{
 public int x,y;
 public Bod(int x, int y)
 {
  //jelikoz jsou parametry konstruktoru
  //pojmenovany stejne jako clenske promenne
  //je nutne pouzit klicove slovo this, ktere
  //predstavuje aktualni instanci objektu
  this.x = x;
  this.y = y;
 }
}

Vytvořili jsme strukturu představující bod. Kromě toho, že je místo klíčového slova class použito slovo struct se implementace v tomto případě na pohled nijak neliší od implementace referenčního typu. Struktury s sebou, na rozdíl od tříd, nesou několik omezení. Struktury totiž nelze od žádného typu odvodit a žádný typ nemůže být odvozen od nich.

Struktury a konstruktory

Konstruktory u struktur fungují poněkud odlišně od konstruktorů u tříd. V případě tříd je to tak, že dokud nevytvoříme novou instanci pomocí new a zavoláním příslušného konstruktoru, referenční proměnná má hodnotu null, tedy na žádnou instanci neukazuje a tím pádem není možné v danou chvíli objekt použít. Protože u struktur neexistují odkazy, tak zavolání implicitního (bezparametrického) konstruktoru pomocí new v jejich případě zajistí vytvoření nové instance, která má všechny své datové členy vynulovány. To znamená, že není nutné použít new před použitím struktury, ale pokud jej nepoužijeme, je nutné, aby datové členy struktury byli inicializovány předtím než jsou použity, jinak program nebude možné zkompilovat.

Bod b1;
//zavolani konstruktoru neni nutne,
//ale datove cleny musí pred pouzitim byt inicializovany
b1.x = 4;
b1.y = 5;
//souradnice x je 4
Console.WriteLine(b1.x);
//volani implicitniho konstruktoru
//zapricini vytvoreni nove instance
//s vynulovanymi datovymi cleny
b1 = new Bod();
//souradnice x je nyni 0
Console.WriteLine(b1.x);

Definovat implicitní konstruktor struktury je v .NET frameworku zakázáno a to z důvodu, že by bylo možné datovým členům struktury nastavit odlišné výchozí hodnoty, než je počáteční vynulovaný stav. Pokud definujeme konstruktor struktury, tak tento konstruktor musí inicializovat všechny datové členy struktury. Pokud tak neučiníme, nebude možné kód přeložit. Je tomu tak proto, aby bylo zajištěno, že po zavolání konstruktoru je instance struktury plně připravena k použití.

Výčtové typy

Dalším druhem hodnotového typu jsou výčtové typy, jejichž využití je vhodné v případech, kdy potřebujeme definovat výčet nějakých konkrétních hodnot, které jsou představovány konstantami a proměnné v programu budou nabývat pouze hodnot těchto konstant. Pro vytváření výčtových typů je v C# k dispozici klíčové slovo enum. Následující příklad ukazuje možné použití výčtového typu pro výčet dnů v týdnu.

public enum DnyTydnu
{
 Pondeli,
 Utery,
 Streda,
 Ctvrtek,
 Patek,
 Sobota,
 Nedele
}

Později je možné deklarovat proměnnou typu DnyTydnu , která bude moci nabývat pouze stanovené hodnoty.

DnyTydnu den = DnyTydnu.Nedele;

Také je samozřejmě možné napsat metodu jejímž parametrem bude nějaký výčtový typ.

public static void NejakaMetoda(DnyTydnu den)
{
 //implementace metody
}

Číselná reprezentace a bázové typu výčtů

Každý výčtový typ je založen na jednom ze základních celočíselných typů. Výchozím bázovým typem pro výčtové typy je int (neboli typem Int32 v CTS). První hodnota výčtu je implicitně představována hodnotou nula, která je vždy s definicí další konstanty o jedničku vyšší. V příkladu se dny v týdnu je tedy vlastně pondělí představováno nulou, úterý jedničkou a tak dále. O tom se může přesvědčit použitím explicitního přetypováni na typ int.

int intDen = (int)DnyTydnu.Nedele;
//vystup bude 6
Console.WriteLine(intDen);

Počáteční hodnotu číselné reprezentace výčtu je možné změnit následujícím způsobem:

public enum DnyTydnu          
{
 Pondeli = 1,
 Utery,
 Streda,
 Ctvrtek,
 Patek,
 Sobota,
 Nedele
}

Po této změně bude číselná reprezentace výčtu začínat hodnotou 1.

Možné je specifikovat nejen počáteční hodnotu číselné reprezentace výčtu, ale i reprezentaci pro další hodnoty výčtu.

public enum DnyTydnu
{
 Pondeli = 1,
 Utery = 3,
 Streda = 5,
 Ctvrtek = 7,
 Patek = 9,
 Sobota = 11,
 Nedele   = 13
}

Pokud chceme ušetřit paměť nebo nám pro náš výčet nestačí počet hodnot typu int je možné explicitně definovat jiný bázový typ pro výčet. Možné bázové typy, které lze pro výčtové typy použít jsou pouze celočíselné typy.

Pokud bychom tedy chtěli snížit náročnost našeho výčtu na paměť použili bychom jako bázový například typ byte.

public enum DnyTydnu : byte
{
 Pondeli,
 Utery,
 Streda,
 Ctvrtek,
 Patek,
 Sobota,
 Nedele
}

Zdrojové kódy příkladů jsou pohromadě v tomto ZIP archivu.

V příštím díle seriálu se budeme zabývat vytvářením a použitím polí v C#.

Diskuze (18) Další článek: Symantec představil Norton Internet Security 2005 v češtině

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