Metody

Website: Moodle ZČU
Kurs: KPV/TI Technická informatika ve strojírenství - šablona
Buch: Metody
Gedruckt von: Nepřihlášený host
Datum: Sonntag, 8. November 2026, 16:33

1. Metoda

Metodu lze definovat jako posloupnost příkazů, která je podobná funkci (má zpravidla jeden výstup) nebo proceduře (nemá žádný výstup, jeden nebo až několik výstupů). Metoda má svůj název (identifikátor by měl být smysluplný, ze kterého odvodíme, co metoda provádí) a tělo uzavřené do složených závorek. V těchto složených závorkách jsou umístěny příkazy, které jsou provedeny po spuštění metody. Do metody můžete předávat i data, se kterými metoda pracuje. Metoda také může navracet výsledek zpracování dat – informace.

2. Deklarace metody s výstupem a bez parametrů

Deklarace metody s návratem (výstupem) v jazyce C# vypadá bez parametrů (bez argumentů metody) obecně takto:

návratovýDatovýTyp identifikátorMetody( )
{
     //Tělo metody - zde jsou umístěny příkazy oddělené středníkem
     return výstup;
}

kde:

  • návratovýDatovýTyp - určuje, jaký datový typ vrací metoda jako výsledek, např. int, float apod. Pokud metoda nenavrací žádný výsledek, místo návratového datového typu píšeme klíčové slovo void
  • identifikátorMetody - určuje název metody, lépe řečeno její identifikátor. Pro identifikátor platí jistá pravidla, která jsme si definovali dříve (používáme Velbloudí notaci)
  • Tělo metody - je zapsáno mezi složené závorky. Příkazy uvnitř těla metody jsou řádky kódu oddělené středníkem. Tyto příkazy jsou prováděny, když je metoda spuštěna – volána. V těle metody, se mohou používat všechny objekty existující vně metody (třídní proměnné) a jejichž deklarace předcházejí deklaraci metody. Pomocí takových objektů (tzv. nelokálních objektů) může procedura komunikovat s okolím (tj. s jinými částmi programu). Uvnitř složeného příkazu jsou tzv. lokální deklarace, např. proměnných, které platí pouze pro metodu a nemají žádný účinek vně metody a ani tam nejsou známy. Lokální deklarace se často používají pro pomocné proměnné určené pro uložení mezivýsledků nebo pro řídící proměnné cyklů
  • return - klíčové slovo pomocí něhož přiřazujeme výstup deklarované metodě
  • výstup - výstup deklarované metody


Ilustrativní příklad SectiHodnotyBezParametru

Algoritmus SectiHodnotyBezParametru


Jak jste si zřejmě všimli, v mezní značce podprogramu nejsou podprogramu předány žádné vstupní parametry - viz Obrázek 1. V tomto případě představuje podprogram funkci s celočíselným návratem v podobě hodnoty uložené v lokální proměnné z (tři tečky představují tělo podprogramu, tj. příkazy, výrazy, atd. uvedené ve vývojovém diagramu algoritmu SectiHodnotyBezParametru). 

Deklarace podprogramu SectiHodnotyBezParametru - funkce bez vstupu s 1 výstupem

Obrázek 1: Deklarace podprogramu SectiHodnotyBezParametru - funkce bez vstupu a s výstupem

Na základě vývojového diagramu SectiHodnotyBezParametru vytvoříme v konzolové aplikaci program, na kterém si vysvětlíme deklaraci metody s návratem (výstupem) a bez předání parametrů.

Program SectiHodnotyBezParametru
  • Popis: Metoda navracející součet hodnot dvou lokálních proměnných
  • Zadání: Vymyslete, jak byste v C# naprogramovali podprogram SectiHodnotyBezParametru jako konzolovou aplikaci
  • Řešení: Bude postupně probráno v následujícím textu a finální verze řešení bude zobrazeno v další kapitole


Podívejme se na příklad zdrojového kódu metody (funkce) SectiHodnotyBezParametru, kde jsou sečteny hodnoty dvou lokálních celočíselných proměnných x a y – viz Kód 1. 

//Deklarace statické metody s celočíselným výstupem a třemi lokálními proměnnými
static int SectiHodnotyBezParametru()
{
    //Deklarace lokálních celočíselných proměnných
    int x;
    int y;
    int z;
    //Inicializace proměnných
    x = 7;
    y = 2;
    //Součet hodnot lokálních proměnných a uložení do proměnné
    z = x + y;
    //Návrat - výstup metody je součet hodnot lokálních proměnných - hodnota v proměnné
    return z;
}

Kód 1: Příklad deklarace metody se třemi lokálními proměnnými a celočíselným výstupem

Metodu jsme označili jako statickou (klíčové slovo static), protože jsme ji chtěli volat ze statické metody Main, která představuje metodu vykonávanou v programu jako první. Zatím je zbytečné vysvětlovat podstatu statické metody, protože jsme se nedostali k definici třídy (statická metoda není závislá na konkrétní instanci třídy, ale přistupujeme k ní v rámci celé třídy). Berme prozatím, že pokud voláme danou metodu ze statického metody Main, musíme označit danou metodu jako statickou klíčovým slovem static. Všechny lokální proměnné jsou datového typu int (celé číslo). Lokální proměnnou x jsme inicializovali hodnotou 7 a lokální proměnnou y jsme inicializovali hodnotou 2 přímo v části jejich deklarace. U metody chceme, aby výsledek získaný součtem obou hodnot uložených v proměnných byl předán dále do metody, která danou metodu spustila. Použijeme proto klíčové slovo return, které nám zajistí výstup součtu z metody, který je uložen v z. Datový typ výsledku musí být vždy shodný s datovým typem uváděným před názvem metody, což v našem případě vyhovuje – datový typ int. 

Pro součet dvou hodnot uložených v proměnných můžeme využít úspornějšího přístupu, kdy lze ve zdrojovém kódu přímo deklarovat a inicializovat proměnné a zároveň není zapotřebí deklarovat pomocnou proměnnou z, která nám sloužila pro uložení hodnoty součtu. Výraz x + y lze přímo přiřadit výstupu naší metody, tzn. můžeme výraz umístit za klíčové slovo return - viz Kód 2. Výraz x + y bychom mohli také uzavřít do kulatých závorek.

//Deklarace statické metody s celočíselném výstupem a dvěma lokálními proměnnými
static int SectiHodnotyBezParametru()
{
    //Deklarace lokálních celočíselných proměnných včetně inicializace
    int x = 7, y = 2;
    //Návrat - výstup metody je součet hodnot lokálních proměnných
    return x + y;
}

Kód 2: Příklad deklarace metody se dvěma lokálními proměnnými a celočíselným výstupem

3. Deklarace metody s výstupem a s parametry

Komunikace metody s okolím pomocí nelokálních proměnných, zejména u složitějších programů se obecně nedoporučuje. Není totiž příliš zřejmé, které údaje do metody vstupují a které vystupují. Proto je vhodné používat tzv. parametry (představují argumenty metody), které fungují v rámci metody a lze do nich uložit hodnoty z vnějšku metody a pracovat s nimi.

Deklarace metody s návratem využívající parametry vypadá obecně takto:

návratovýDatovýTyp identifikátorMetody(seznamFormálníchParametrů)
{
      //Tělo metody - zde jsou umístěny příkazy
      return výstup;
}

kde: 

  • návratovýDatovýTyp a identifikátorMetody - mají stejné významy, které byly popsány v předchozí kapitole
  • seznamFormálníchParametrů je uzavřen v kulatých závorkách a seznam nemusí být povinný, tzn., že do metody nemusí vstupovat žádná data. Vstupním datům se říká parametry. Tyto parametry zatím nemusí nabývat konkrétní hodnoty, proto název formální parametry. Tyto parametry nabývají konkrétních hodnot až v rámci provádění metody. Každý parametr má svůj datový typ uváděný před název parametru. Tento datový typ musí být vždy určen. Pokud má metoda více parametrů, jsou od sebe odděleny čárkami
  • result - popsáno v předchozí kapitole
  • výstup - popsáno v předchozí kapitole


Ilustrativní příklad SectiHodnotyParametru

Algoritmus SectiHodnotyParametru


V tomto případě algoritmu je v mezní značce podprogramu SectiHodnotyParametru definováno, že podprogramu jsou předány dva vstupní formální parametry x a y - viz Obrázek 1. V tomto případě představuje podprogram funkci s celočíselným návratem v podobě hodnoty uložené v lokální proměnné z. 

Deklarace podprogramu SectiHodnotyParametru - funkce se 2 vstupními parametry a výstupem

Obrázek 1: Deklarace podprogramu SectiHodnotyParametru - funkce se 2 vstupními parametry a výstupem

Na základě vývojového diagramu SectiHodnotyParametru vytvoříme v konzolové aplikaci program, na kterém si vysvětlíme deklaraci metody s návratem (výstupem) a s předáním parametrů do podprogramu.

Program SectiHodnotyParametru

  • Popis: Metoda navracející součet hodnot dvou lokálních proměnných 
  • Zadání: Vymyslete, jak byste v C# naprogramovali podprogram SectiHodnotyParametru jako konzolovou aplikaci
  • Řešení: Bude postupně probráno v následujícím textu


Podívejme se na zdrojový kód statické metody SectiHodnotyParametru, kde jsou sečteny hodnoty dvou vstupních celočíselných parametrů x a y – viz Kód 1. Tuto metodu voláme ze statické metody Main, která představuje metodu vykonávanou v programu jako první (proto jsme ji deklarovali jako statickou). Oba parametry jsou datového typu int (celé číslo), ale u každého parametru musíme uvádět samostatně datový typ. U metody chceme, aby výsledek získaný součtem obou hodnot uložených v parametrech, byl předán dále do metody, která danou metodu spustila. Použijeme proto klíčové slovo return, které nám zajistí výstup hodnoty součtu z metody. Do pomocné proměnné z uložíme hodnotu výrazu x + y, která je celočíselný (součet dvou hodnot celočíselných parametrů představuje znovu celé číslo). Tento datový typ výsledku musí být vždy shodný s datovým typem uváděným před názvem metody, což v našem případě vyhovuje – datový typ int. 

//Deklarace statické metody s celočíselném výstupem a se dvěma vstupními parametry
static int SectiHodnotyParametru(int x, int y)
{
    //Deklarace lokální pomocné celočíselné proměnné
    int z;
    //Součet hodnot parametrů
    z = x + y;
    //Návrat - výstup metody je součet hodnot parametrů
    return z;
}

Kód 1: Příklad deklarace metody se dvěma vstupními parametry a celočíselným výstupem

4. Deklarace metody bez výstupu a s parametry

V předchozích případech jsme si ukázali, jak vypadá metoda s výstupem - návratem (funkce). Pokud metoda nemá žádný výstup (jedná se o proceduru), uvedeme její datový typ klíčovým slovem void. V následujícím příkladu zobrazíme aktuální hodnotu parametrů, tj. vypíšeme aktuální hodnoty uložené v parametrech.

Deklarace metody bez návratu využívající parametry vypadá obecně takto:

void identifikátorMetody(seznamFormálníchParametrů)
{
      //Tělo metody - zde jsou umístěny příkazy
}

kde: 

  • void - definuje, že metoda nemá výstup (není definován návratový typ)
  • identifikátorMetody - popsáno v předchozích kapitolách
  • seznamFormálníchParametrů - popsáno v předchozích kapitolách


Ilustrativní příklad ZobrazHodnotyParametru

Algoritmus ZobrazHodnotyParametru


Jak jste si zřejmě všimli, v mezní značce podprogramu ZobrazHodnotyParametru jsou podprogramu předány dva vstupní formální parametry x a y - viz Obrázek 1. V tomto případě je podprogram bez návratu, tzn. představuje proceduru, která nám pouze vypisuje hodnoty vstupních parametrů. 

Deklarace podprogramu ZobrazHodnotyParametru - procedura se 2 vstupy

Obrázek 1: Deklarace podprogramu ZobrazHodnotyParametru - procedura se 2 vstupy

Na základě vývojového diagramu ZobrazHodnotyParametru vytvoříme v konzolové aplikaci program, na kterém si vysvětlíme deklaraci metody bez návratu (výstupu) s předáním parametrů do metody.

Program ZobrazHodnotyParametru
  • Popis: Metoda pro výpis hodnot dvou vstupních parametrů x a y
  • Zadání: Vymyslete, jak byste v C# naprogramovali podprogram ZobrazHodnotyParametru jako konzolovou aplikaci
  • Řešení: Bude postupně probráno v následujícím textu

V následujícím zdrojovém kódu vidíme, že jsme pro výpis využili příkaz Console.WriteLine. Do závorky za tento příkaz umístíme text, který chceme vypsat. Je vhodné, aby uživatel věděl, co se mu právě zobrazuje v konzoli, proto jsme před hodnoty parametrů umístili text, o který parametr se jedná - viz Kód 1. Pokud metoda nevrací žádný výsledek, můžeme také použít příkaz return, za kterým nebude uveden žádný výraz nebo kulaté závorky. Bude za ním uveden pouze středník. To ale v našem případě není zapotřebí, protože naše metoda po vykonání příkazu výpisu končí (dosáhla druhé složené závorky).
//Deklarace statické metody bez výstupu se dvěma vstupními parametry
static void ZobrazHodnotyParametru(int x, int y)
{
    //Výpis textu a hodnot obou parametrů
    Console.WriteLine("Hodnota x:" + x + ", y:" + y);
}

Kód 1: Příklad deklarace metody bez návratu výsledku se dvěma vstupními parametry a výpisem

Výpis lze realizovat přehlednějším způsobem za pomoci indexů parametrů. Každý index parametru je uzavřen do složených závorek. Za čárku umístíme název parametru, jehož aktuální hodnotu chceme vypsat v textu na místě, kde je jeho příslušný index. Indexování parametrů je prováděno od čísla 0 a následný index parametru je o 1 vyšší. Princip výpisu hodnot parametrů naleznete v následujícím kódu – viz Kód 2. 

//Deklarace statické metody bez výstupu se dvěma vstupními parametry
static void ZobrazHodnotyParametru(int x, int y)
{
    //Výpis textu a hodnot obou parametrů
    Console.WriteLine("Hodnota x: {0}, y:{1}", x, y);
}

Kód 2: Příklad deklarace metody bez návratu výsledku se dvěma vstupními parametry a výpisem pomocí indexů

5. Volání metody

Jak již bylo několikrát řečeno, metody je vhodné rozdělit na menší pomocné metody - podprogramy, které postupně budeme volat (spouštět) v rámci rozsáhlejší metody. Tyto pomocné metody nám zejména pomohou tím, že je snadněji můžeme verifikovat (ověřit jejich správnou funkčnost). Zvyšujeme tím také čitelnost zdrojového kódu a usnadňujeme údržbu rozsáhlé metody, která implementuje pomocné metody. Pokud jsme pomocné metody definovali v rámci třídy, mohou být tyto metody zavolány i jinými metodami v rámci této třídy.

Volání metody tedy znamená její spuštění. Metoda je volána jejím názvem. Pokud byla metoda deklarována způsobem, že potřebuje vstupy, musíme ji tyto vstupy naplnit, při jejím volání. Pokud metoda žádný vstup nepotřebuje, nesmíme jí při jejím volání do závorky uvádět jakákoliv data. Obecně lze syntaxi v jazyku C# popsat volání metody následovně:

výsledek = identifikátorMetody(seznamSkutečnýchParametrů);

kde:

  • výsledek - je volitelný, nemusí být uveden, např. pokud metoda nenavrací žádný výsledek (je typu void), pak je klauzule výsledek zcela vypuštěna. Je-li výsledek uveden, pak představuje proměnnou, do níž je uložen vrácený výsledek ze zavolané metody. Pokud zavolaná metoda vrací výsledek, ale my bychom klauzuli výsledek neuvedli, vrácený výsledek bude ztracen

  • seznamSkutečnýchParametrů - představuje seznam parametrů (argumentů), které mohou do metody vstupovat, ale zároveň i vystupovat. Pokud do metody potřebujeme předat tzv. skutečné parametry, tzn., již skutečné hodnoty předdefinovaných formálních parametrů metody, jejich datové typy musí být shodné s formálními parametry deklarovaných ve volané metodě. Záleží na pořadí předávaných parametrů. Pokud do metody žádný parametr nevstupuje, je uvedena pouze prázdná závorka. Je nutné uvést vždy kulaté závorky, ať už volaná metoda parametry přijímá, či nikoliv


Ilustrativní příklad VolaniMetod

Algoritmus VolaniMetod


Ve vývojovém diagramu hlavního programu (Main) našeho algoritmu jsme našli značky volání podprogramů - funkce (podprogram s návratem) a procedury (podprogram bez návratu). V případě funkce je ve značce za názvem funkce SectiHodnotyParametru umístěna závorka, která představuje předání hodnot (první hodnota 7 uložená ve skutečném parametru a a druhá hodnota představuje číslo 5) z hlavního programu do formálních parametrů x a y v podprogramu. Jedná se v podstatě o překopírování hodnot - viz Obrázek 1. Návrat (spočtený výstup) funkce je uložen do parametru vysledek. 

Volání podprogramu SectiHodnotyParametru - 2 vstupy a návrat

Obrázek 1: Volání podprogramu SectiHodnotyParametru - 2 vstupy a návrat

Po přiřazení výstupu funkce do parametru vysledek je zavolána procedura ZobrazHodnotyParametru, které předáme z hlavního programu dva parametry - viz Obrázek 2. V parametru vysledek je uložena hodnota 12, tj. 7 + 5 = 12 a v druhém parametru a je uložena hodnota 7. Tyto hodnoty se nakopírují do formálních parametrů x a y procedury a pak je v proceduře necháme společně vypsat, včetně textu definujícího, o který parametr se jedná.

Volání podprogramu ZobrazHodnotyParametru - 2 vstupy a žádný výstup

Obrázek 2: Volání podprogramu ZobrazHodnotyParametru - 2 vstupy a žádný výstup

Na základě vývojového diagramu VolaniMetod modifikujeme v konzolové aplikaci hlavní metodu Main, na které si vysvětlíme volání metody s návratem (funkce) a také volání metody bez návratu (procedura) včetně předání parametrů do těchto metod.

Program VolaniMetod_Main
  • Popis: Volání metod z metody Main 
  • Zadání: Vymyslete, jak byste v C# naprogramovali v konzolové aplikaci volání metody SectiHodnotyParametru a ZobrazHodnotyParametru v hlavní metodě Main 
  • Řešení: VolaniMetod_Main


V následujícím kódu v hlavním programu, tedy statické metodě Main zavoláme deklarovanou metodu a předáme jí dvě celočíselné hodnoty 7 uloženou v parametru a a hodnotu 5 – viz Kód 1. Takové formě se zápisu čísla říká literál (nevíme, jestli se jedná o celočíselnou hodnotu 5, nebo reálné číslo 5.0). Později se o literálu dozvíme více. Na druhém řádku našeho kódu v těle metody Main (komentáře nepovažujeme za kód) je uvedena deklarace parametru vysledek. Do tohoto parametru se nám uloží výsledek obdržený ze zavolané statické metody SectiHodnotyParametru. Tuto metodu jsme deklarovali jako statickou, protože jsme ji volali ze statické metody Main, která představuje metodu vykonávanou v programu jako první. Zatím je zbytečné vysvětlovat podstatu modifikátoru přístupu k metodě (jednou možností je použití klíčového slova static), protože jsme se nedostali k definici třídy (statická metoda není závislá na konkrétní instanci třídy, ale přistupujeme k ní v rámci celé třídy). Berme prozatím, že pokud voláme danou metodu ze statické metody Main, musíme označit danou metodu jako statickou klíčovým slovem static). O modifikátoru přístupu se později dozvíme více.

Příkaz Console.ReadKey() zajistí, že program bude čekat, až uživatel stiskne nějakou klávesu. Náš kompilovaný program by bez tohoto příkazu totiž skončil a my bychom si ani nestihli přečíst výsledek, pokud by byl v programu vypisován.

static void Main(string[] args)
{
 
    //Deklarace celočíselných parametrů
    int a;
    int vysledek;
    //Přiřazení hodnoty parametru
    a = 7;
    //Zavolání metody se vstupními parametry
    vysledek = SectiHodnotyParametru(a, 5);
    //Zavolání metody se vstupy ale bez výstupu
    ZobrazHodnotyParametru(vysledek, a);
    //Čekání na stisk klávesy -> ukončení programu
    Console.ReadKey();
}

Kód 1: Příklad zavolání statických metod se dvěma vstupními parametry s návratem (funkce SectiHodnotyParametru) a bez návratu (procedura ZobrazHodnotyParametru)

Na následujícím výpisu v konzoli vidíme vypsané hodnoty parametrů, jejichž vypsání se provádí v metodě ZobrazHodnotyParametru – viz Výstup programu - Kód 1.

Hodnota x: 12, y:7

Výstup programu - Kód 1: Ukázka výpisu hodnot parametrů v metodě ZobrazHodnotyParametru 

Pokud bychom metodě nepředali žádnou hodnotu, nebo jen jednu (kterou by si mohla uložit do parametr a dále s ním pracovat), kompilátor by nám nahlásil chybu „Chybí argument“ a program nebude spuštěn – viz Kód 2.

//Nelze zavolat metodu pouze s jedním parametrem -> K.O.
vysledek = SectiHodnotyParametru(, 5);

Kód 2: Příklad špatného zavolání metody – chybí první parametr

Pro úplnost uveďme zdrojový kód naší dříve deklarované metody SectiHodnotyParametru - viz Kód 3. Tato metoda přijímá vstupní celočíselné parametry a má celočíselný výstup.

//Deklarace statické metody s celočíselném výstupem a se dvěma vstupními parametry
static int SectiHodnotyParametru(int x, int y)
{
    //Deklarace lokální pomocné celočíselné proměnné
    int z;
    //součet hodnot parametrů
    z = x + y;
    //Návrat - výstup metody je součet hodnot parametrů
    return z;
}

Kód 3: Deklarace metody SectiHodnotyParametru se dvěma vstupními parametry a celočíselným výstupem

Další volanou metodou je ZobrazHodnotyParametru - viz Kód 4. Této metodě pro zobrazení vstupních parametrů x a y jsou předány z hlavní metody Main dva parametry - součet hodnot, tedy 12 uložený v parametru vysledek a parametr a, jehož hodnota je 7. 

//Deklarace statické metody bez výstupu se dvěma vstupními parametry
static void ZobrazHodnotyParametru(int x, int y)
{
    //Výpis hodnot textu s hodnotami obou parametrů
    Console.WriteLine("Hodnota x:" + x + ", y:" + y);
}

Kód 4: Příklad deklarace metody ZobrazHodnotyParametru bez návratu výsledku se dvěma vstupními parametry

6. Návrat více výstupů

Pravděpodobně nastane situace, kdy budeme potřebovat navrátit z metody více jak jeden výsledek (zatím jsme navraceli jeden výsledek pomocí příkazu return). K tomu můžeme využít následující syntaxi: 

(seznamDatovýchTypůVýstupů) identifikátorMetody(seznamFormálníchParametrů)
{
      //Tělo metody - zde jsou umístěny příkazy a přiřazení hodnot výstupům
      return (seznamVýstupů);
}

kde:

  • seznamDatovýchTypůVýstupů - představuje seznam jednotlivých datových typů jednotlivých výstupů (návratů) z metody uvedených v kulaté závorce před názvem metody. Jednotlivé datové typy návratů jsou odděleny čárkou
  • identifikátorMetody - princip popsán v předchozích kapitolách
  • seznamFormálníchParametrů - princip popsán v předchozích kapitolách
  • return - princip popsán v předchozích kapitolách
  • seznamVýstupů - představuje seznam jednotlivých výstupů (návratů) z metody uvedené v kulaté závorce za klíčovým slovem return
Ilustrativní příklad CelociselneDeleni

Program SectiHodnotyBezParametru
  • Popis: Metoda navracející více výstupů 
  • Zadání: Vymyslete, jak byste v C# naprogramovali metodu CelociselneDeleni jako konzolovou aplikaci. Tato metoda přijímá dva celočíselné parametry x a y. V této metodě deklarujte dvě celočíselné proměnné celociselneDeleni, do které uložíte hodnotu celočíselného dělení hodnot obou parametrů a zbytekCelociselnehoDeleni do níž uložíte zbytek po celočíselném dělení hodnot parametrů. Metodu CelociselneDeleni zavolejte v hlavní metodě Main. V metodě Main vypište výsledky aritmetických operací
  • Řešení: Bude postupně probráno v následujícím textu

V následujícím kódu ukážeme, jak deklarovat metodu se dvěma vstupními parametry a dvěma výstupy. První výstup představuje hodnotu celočíselného dělení dvou vstupních parametrů (argumentů metody) a druhý výstup představuje zbytek po celočíselném dělení těchto dvou parametrů – viz Kód 1.

/*Deklarace statické metody se dvěma celočíselnými výstupy 
  a se dvěma vstupními parametry*/
static (int, int) CelociselneDeleni(int x, int y)
{
    int celociselneDeleni, zbytekCelociselnehoDeleni;
    celociselneDeleni = x / y;
    zbytekCelociselnehoDeleni = x % y;
    return (celociselneDeleni, zbytekCelociselnehoDeleni);
}

Kód 1: Příklad metody se dvěma výstupy a dvěma vstupy

Metoda CelociselneDeleni, které předáme jako první parametr hodnotu 7 a jako druhý parametr číslo 5, by se volala v metodě Main následujícím způsobem – viz Kód 2. 

static void Main(string[] args)
{ 
    //Deklarace lokálních celočíselných proměnných
    int celociselneDeleni, zbytekCelociselnehoDeleni;
    /*Zavolání metody pro celočíselné dělení se 2 vstupními parametry a dvěmi celočíselnými výstupy*/
    (celociselneDeleni, zbytekCelociselnehoDeleni) = CelociselneDeleni(7, 5);
    Console.WriteLine("Celočíselné dělení: {0}, zbytek po celočíselném dělení: {1}", celociselneDeleni, zbytekCelociselnehoDeleni);
    //Čekání na stisk klávesy -> ukončení programu
    Console.ReadKey();
}

Kód 2: Příklad volání metody CelociselneDeleni se dvěma výstupy a dvěma vstupy v hlavní metodě Main

Ve výpisu v konzole vidíme, že do první proměnné celociselneDeleni, představující výsledek celočíselného dělení, metoda uloží hodnotu 1. Do druhé proměnné zbytekCelociselnehoDeleni představující zbytek po celočíselném dělení bude uložena hodnota 2.

Celočíselné dělení: 1, zbytek po celočíselném dělení: 2

Výstup programu - Kód 2: Ukázka výpisu hodnot výstupních parametrů

7. Předání parametru

Obvykle se metody (podprogramu ve formě funkce nebo procedury) volají s tzv. parametry, což jsou vstupní a potažmo výstupní údaje, se kterými podprogramy pracují. Pro deklaraci podprogramu se parametr:

  • Specifikuje, tzn. že se určí jeho datový typ (např. reálné, celé číslo, znak)
  • Určí se způsob předávání vstupní, výstupní, konstantní parametry 
  • Určí se přidělování paměti:
    • Předávání hodnotou - kopíruje se do paměti přidělené volané metodě (podprogramu)
    • Předávání odkazem - k parametru se přistupuje nepřímo, pomocí reference na paměť, kde jsou ve volající části programu uloženy

Jak jsme již dříve zmínili, u metod existují dva druhy parametrů:

  • Formální - definované v rámci deklarace metody
  • Skutečné - když je metoda volána

Skutečné parametry musí podle určitých pravidel odpovídat formálním parametrům podle následujících pravidel:

  • Počet skutečných a formálních parametrů musí být stejný
  • Skutečné parametry musí být řazeny ve stejném pořadí jako jim odpovídající parametry formální
  • Odpovídající si parametry musí být stejného datového typu nebo musí být typově kompatibilní
  • Není žádný vztah mezi jmény formálních a skutečných parametrů, mohou být i stejné, někdy se to využívá, ale čistší jsou různá jména

Parametry jsou do nebo z metody předávány způsoby:

  • Parametry předávané (volané) hodnotou
  • Parametry předávané odkazem
  • Výstupní parametry


7.1. Parametry předávané hodnotou

Při předání skutečného parametru metodě hodnotou je jeho odpovídající formální parametr inicializován kopií tohoto vstupního argumentu metody. To platí bez ohledu na to, zda je parametrem hodnotový typ (například int), prázdný – nulovatelný (null) - typ, nebo jako referenční typ (forma odkazu). O hodnotových a referenčních typech se více dozvíme později. 

Pokud bychom chtěli předat metodě (v tomto případě funkci) jeden parametr hodnotou, mohla by deklarace metody vypadat následovně:

návratovýDatovýTyp identifikátorMetody(datovýTyp formálníParametr)
{
     //Tělo metody - zde jsou umístěny příkazy oddělené středníkem
     return výstup;
}

kde:

  • datovýTyp - datový typ formálního parametru metody
  • formálníParametr - identifikátor formálního parametru metody. Tento datový typ musí být vždy určen. Pokud do metody vstupuje více parametrů, každý parametr má svůj datový typ uváděný před identifikátorem (názvem) parametru. Tyto parametry, jsou od sebe odděleny čárkami
  • návratovýDatovýTyp, identifikátorMetody, Tělo metody, return, výstup - popsáno v předchozích kapitolách

Pro případ metody, která nenavrací žádný výsledek, místo návratového datového typu píšeme klíčové slovo void.

Syntaxe předání parametru hodnotou v případě volání metody vypadá:

výsledek = identifikátorMetody(seznamSkutečnýchParametrů);

kde

  • seznamSkutečnýchParametrů - představuje seznam skutečných parametrů (argumentů), které mohou do metody pouze vstupovat (již nevystupují z metody). U skutečných parametrů se v závorce neuvádí ve volání metody jejich datový typ. Hodnoty skutečných parametrů metody musí být shodné s datovými typy formálních parametrů deklarovaných ve volané metodě. Záleží na pořadí předávaných parametrů. Pokud do metody žádný parametr nevstupuje, je uvedena pouze prázdná závorka. Je nutné uvést vždy kulaté závorky, ať už volaná metoda parametry přijímá, či nikoliv
  • výsledek, identifikátorMetody - popsáno v předchozích kapitolách

V případě volání metody bez návratu (procedury) by odpadla levá strana od operátoru přiřazení včetně tohoto operátoru.


Předání hodnotou znamená, že je nemožné, aby jakákoli změna formálního parametru provedená uvnitř metody ovlivnila hodnotu skutečného parametru

Na místě formálního parametru, volaného hodnotou, může být jako skutečný parametr výraz stejného typu jako má formální parametr (konstanta, proměnná, výraz s operátory, které daný typ připouští a metoda, vracející hodnotu stejného datového typu). Naopak, hodnotou nemůže být volán parametr takového datového typu, kde neexistuje hodnota. Takový parametr musí být vždy předán odkazem.


Ilustrativní příklad InkrementaceParametruHodnotou
Program InkrementaceParametruHodnotou
  • Popis: Deklarace metody s celočíselným parametrem – předání parametru hodnotou
  • Zadání: Vymyslete, jak byste v C# naprogramovali podprogram InkrementaceParametruHodnotou jako konzolovou aplikaci. Metoda přijímá celočíselný parametr pojmenovaný formalniParametr, který je předán hodnotou. V těle metody se k tomuto parametru přičte hodnota 1. Hodnotu parametru vypište jak v deklarované metodě, tak i v metodě Main.
  • Řešení: Bude postupně probráno v následujícím textu

Následující příklad osvětluje princip, který jsme vysvětlili v předchozím odstavci. Deklarovali jsme statickou metodu InkrementaceParametruHodnotou, která bude zavolána ze statické metody Main. Metoda InkrementaceParametruHodnotou pouze přičte k formálnímu parametru hodnotu 1. V metodě necháme vypsat aktuálního hodnotu formálního parametru – viz Kód 1.

/*Deklarace statické metody s jedním celočíselným formálním parametrem -
  předání parametru hodnotou*/
static void InkrementraceParametruHodnotou(int formalniParametr)
{
    //Inkrementace parametru o hodnotu 1
    formalniParametr++;
    //Výpis aktuálního hodnoty argumentu
    Console.WriteLine("Formální parametr: {0}", formalniParametr);
}

Kód 1: Příklad deklarace metody InkrementaceParametruHodnotou s celočíselným parametrem – předání parametru hodnotou

V metodě Main zavoláme vytvořenou metodu InkrementaceParametruHodnotou - viz Kód 2. V metodě Main necháme vypsat aktuální hodnotu skutečného parametru. Po vypsání obou hodnot parametrů zjistíme, zda hodnota skutečného parametru v metodě Main byla změněna, či nikoliv.

static void Main(string[] args)
{
    //Deklarace skutečného parametru, tj. argument volané metody
    int skutecnyParametr = 7;
    /*Zavolání statické metody bez výstupu a předání skutečného parametru hodnotou/
    InkrementraceParametruHodnotou(skutecnyParametr);
    //Výpis aktuálního hodnoty skutečného parametru
    Console.WriteLine("Skutečný parametr: {0}", skutecnyParametr);
    //Čekání na stisk klávesy -> ukončení programu
    Console.ReadKey();
}

Kód 2: Příklad zavolání metody InkrementraceParametruHodnotou, do níž byl parametr předán hodnotou

Na základě výpisu v konzole vidíme, že pokud jsme předali parametr hodnotou, hodnota skutečného parametru nebyla v metodě Main změněna - viz Výstup programu - Kód 2.

Formální parametr: 8
Skutečný parametr: 7

Výstup programu - Kód 2: Ukázka výsledku předání parametru hodnotou

7.2. Parametry předávané odkazem

Někdy však potřebujeme, aby každá změna argumentu provedená ve volané metodě se promítla i vně volané metody. Tehdy můžeme využít způsob předání parametru odkazem pomocí klíčového slova ref (zkratka anglického slova „Reference“), které umístíme před skutečný parametr u volání metody, tak i před datový typ u formálního parametru v deklarované metodě. 

Při předávání parametrů odkazem je metodě předána adresa (tzv. odkaz na místo hodnoty uložené v paměti), kde se daná proměnná nachází. Metoda provádí úkony přímo s tímto argumentem, a proto může být použita jak pro vstup do metody, tak i pro výstup změněného argumentu z metody.

Skutečným (aktuálním) parametrem může být jen jméno proměnné, nelze použít konstantu, výraz a výsledek funkce.

Pokud bychom chtěli předat metodě (v tomto případě funkci) jeden parametr odkazem, mohla by deklarace metody vypadat následovně:

návratovýDatovýTyp identifikátorMetody(ref datovýTyp formálníParametr)
{
     //Tělo metody - zde jsou umístěny příkazy oddělené středníkem
     return výstup;
}

kde:

  • ref - klíčové slovo - slouží pro vytvoření odkazu na skutečné místo uložení hodnoty parametru v paměti (vytvoření odkazu - aliasu - na skutečný parametr, tzn. že každá operace provedená s parametrem je provedena na argumentu - skutečném parametru)
  • datovýTyp - datový typ formálního parametru metody
  • formálníParametr - identifikátor formálního parametru metody. Tento datový typ musí být vždy určen. Pokud do metody vstupuje více parametrů, každý parametr má svůj datový typ uváděný před identifikátorem (názvem) parametru. Tyto parametry, jsou od sebe odděleny čárkami
  • návratovýDatovýTyp, identifikátorMetody, Tělo metody, return, výstup - popsáno v předchozích kapitolách

Pro případ metody, která nenavrací žádný výsledek, místo návratového datového typu píšeme klíčové slovo void.

Syntaxe předání parametru odkazem v případě volání metody vypadá:

výsledek = identifikátorMetody(ref skutečnýParametr);

kde

  • ref - klíčové slovo - slouží pro vytvoření odkazu na skutečné místo uložení hodnoty parametru v paměti
  • skutečnýParametr - představuje skutečný parametr (argument), který může do metody jak vstupovat tak i vystupovat - v metodě lze nad ním provádět operace, které se budou odrážet na jeho hodnotě. Pokud je skutečných parametrů více, jednotlivé parametry jsou odděleny čárkou a v závorce za voláním metody se neuvádí  jejich datový typ. Hodnoty skutečných parametrů metody musí být shodné s datovými typy formálních parametrů deklarovaných ve volané metodě. Záleží na pořadí předávaných parametrů. Pokud do metody žádný parametr nevstupuje, je uvedena pouze prázdná závorka. Je nutné uvést vždy kulaté závorky, ať už volaná metoda parametry přijímá, či nikoliv
  • výsledek, identifikátorMetody - popsáno v předchozích kapitolách

V případě volání metody bez návratu (procedury) by odpadla levá strana od operátoru přiřazení včetně tohoto operátoru.

Ilustrativní příklad InkrementaceParametruOdkazem
Program InkrementaceParametruOdkazem
  • Popis: Deklarace metody s celočíselným parametrem – předání parametru odkazem
  • Zadání: Zkuste deklarovat metodu bez návratu (proceduru) nazvanou InkrementaceParametruOdkazem, která přijímá celočíselný parametr pojmenovaný formalniParametr, který je předán odkazem. V těle metody se k tomuto parametru přičte hodnota 1. Hodnotu parametru vypište jak v deklarované metodě, tak i v metodě Main
  • Řešení: Bude postupně probráno v následujícím textu

Následující příklad implementuje princip předání parametru odkazem. Deklarovali jsme statickou metodu InkrementaceParametruOdkazem, která bude zavolána ze statické metody Main. Metoda InkrementaceParametruOdkazem pouze k formálnímu parametru předaného odkazem přičte hodnotu 1. V metodě necháme vypsat aktuálního hodnotu formálního parametru – viz Kód 1.

/*Deklarace statické metody s jedním celočíselným formálním parametrem -
  předání parametru odkazem*/
static void InkrementraceParametruOdkazem(ref int formalniParametr)
{
    //Inkrementace parametru o hodnotu 1
    formalniParametr++;
    //Výpis aktuálního hodnoty argumentu
    Console.WriteLine("Formální parametr: {0}", formalniParametr);
}

Kód 1: Příklad deklarace metody InkrementraceParametruOdkazem s celočíselným parametrem – předání parametru odkazem

V metodě Main zavoláme vytvořenou metodu InkrementaceParametruOdkazem - viz Kód 2. V metodě Main necháme vypsat aktuální hodnotu skutečného parametru. Po vypsání obou hodnoty parametrů zjistíme, zda hodnota skutečného parametru v metodě Main byla změněna, či nikoliv.

static void Main(string[] args)
 {
     //Deklarace skutečného parametru, tj. argument volané metody
     int skutecnyParametr = 7;
     //Zavolání statické metody bez návratu a předání skutečného parametru odkazem
     InkrementraceParametruOdkazem(ref skutecnyParametr);
     //Výpis aktuálního hodnoty skutečného parametru
     Console.WriteLine("Skutečný parametr: {0}", skutecnyParametr);
     //Čekání na stisk klávesy -> ukončení programu
     Console.ReadKey();
 }

Kód 2: Příklad zavolání metody InkrementraceParametruOdkazem, do níž byl parametr předán odkazem

Na základě výpisu v konzole vidíme, že pokud jsme předali parametr odkazem, hodnota skutečného parametru byla v metodě Main změněna- viz Kód 2.

Formální parametr: 8
Skutečný parametr: 8

Výstup programu - Kód 2: Ukázka výsledku předání parametru odkazem

7.3. Výstupní parametry

Pokud předáváme parametr odkazem, kompilátor zkontroluje, zda byla skutečnému parametru přiřazena hodnota. Pokud tomu tak není, zdrojový kód není zkompilován. Co když ale potřebujeme v nějaké metodě inicializovat parametr. Pro tento případ jazyk C# nabízí možnost použít tzv. výstupní parametr pomocí klíčového slova out (zkratka anglického „Output“), které umístíme před skutečný parametr u volání metody, tak i před datový typ u formálního parametru v deklarované metodě (syntaxe je tedy podobná klíčovému slovu ref). Jde tedy o využití reference, tj. propojení skutečného a formálního parametru pomocí reference (odkaz na stejné místo v paměti). V těle volané metody musí před jejím ukončením proběhnout inicializace formálního parametru (pokud tomu tak není, neproběhne kompilace kódu)! Výstupní parametr lze využít i u metody s návratem, ale je spíše využit u metody bez návratu (procedury):

void identifikátorMetody(out datovýTyp formálníParametr)
{
     //Tělo metody - musí proběhnout inicializace výstupního parametru
}

kde:

  • out - klíčové slovo - slouží pro vytvoření odkazu na skutečné místo uložení hodnoty parametru v paměti (vytvoření odkazu  aliasu - na skutečný parametr, tzn. že každá operace provedená s parametrem je provedena na argumentu - skutečném parametru)
  • datovýTyp - datový typ výstupního formálního parametru metody
  • formálníParametr - identifikátor výstupního formálního parametru metody. Tento datový typ musí být vždy určen. Pokud do metody vstupuje více parametrů, každý parametr má svůj datový typ uváděný před identifikátorem (názvem) parametru spolu s klíčovým slovem out. Tyto parametry, jsou od sebe odděleny čárkami
  • Tělo metody - v těle metody musí proběhnout inicializace (přiřazení hodnoty) výstupního formálního parametru
  • návratovýDatovýTyp, identifikátorMetody, return, výstup - popsáno v předchozích kapitolách

Syntaxe volání metody bez návratu (procedury) u výstupního parametru vypadá syntaxe následovně:

identifikátorMetody(out skutečnýParametr);

kde

  • out - klíčové slovo - slouží pro vytvoření odkazu na skutečné místo uložení hodnoty parametru v paměti
  • identifikátorMetody, skutečnýParametr- popsáno v předchozích kapitolách

Ilustrativní příklad InicializaceVystupnihoParametru 
Program InicializaceVystupnihoParametru
  • Popis: Příklad deklarace metody s celočíselným parametrem – výstupní parametr
  • Zadání: Zkuste deklarovat metodu bez návratu nazvanou InicializaceVystupnihoParametru, která inicializuje výstupní celočíselný parametr pojmenovaný formalniParametr hodnotou 7. Hodnotu parametru vypište jak v deklarované metodě, tak i v metodě Main, ze které je metoda volána
  • Řešení: Bude postupně probráno v následujícím textu

Následující příklad ilustruje princip použití výstupního parametru – viz Kód 1. Deklarovali jsme statickou metodu bez návratu (proceduru) InicializaceVystupnihoParametru, která bude zavolána ze statické metody Main. Metoda InicializaceVystupnihoParametru ve svém těle metody formálnímu parametru počáteční hodnotu 7. V metodě necháme vypsat aktuálního hodnotu formálního parametru. Je důležité zmínit fakt, že se jedná o propojení skutečného a formálního parametru pomocí reference (odkazu). Pokud tedy něco provádíme s formálním parametrem, tyto změny jsou promítány i do skutečného parametru.

/*Deklarace statické metody s jedním celočíselným formálním parametrem -
  použití výstupního parametru*/
static void InicializaceVystupnihoParametru(out int formalniParametr)
{
    //Inicializace parametru
    formalniParametr = 7;
    //Výpis aktuálního hodnoty argumentu
    Console.WriteLine("Formální parametr: {0}", formalniParametr);
}

Kód 1: Příklad deklarace metody InicializaceVystupnihoParametru s celočíselným parametrem – výstupní parametr

V metodě Main zavoláme vytvořenou metodu InicializaceVystupnihoParametru, která nám do skutečného parametru přiřadí inicializovanou hodnotu uloženou ve formálním parametru - viz Kód 2. V metodě Main necháme vypsat aktuální hodnotu skutečného parametru. Vzhledem k tomu, že jsme v metodě kromě inicializace neprováděli žádné další operace s formálním parametrem, hodnota skutečného parametru a formálního parametru je stejná.

static void Main(string[] args)
{
    //Deklarace skutečného parametru, tj. argument volané metody
    int skutecnyParametr;
    //Zavolání statické metody bez návratu ve které proběhne inicializace parametru
    InicializaceVystupnihoParametru(out skutecnyParametr);
    //Výpis aktuálního hodnoty skutečného parametru
    Console.WriteLine("Skutečný parametr: {0}", skutecnyParametr);
    //Čekání na stisk klávesy -> ukončení programu
    Console.ReadKey();
}

Kód 2: Příklad zavolání metody InicializaceVystupnihoParametru s výstupním parametrem

Na základě výpisu v konzole vidíme, že pokud vypsaná hodnota výstupního parametru v deklarované metodě je stejná jako hodnotou skutečného parametru v metodě Main, protože jsme neprováděli žádnou aritmetickou operaci - viz Výstup programu - Kód 2.

Formální parametr: 7
Skutečný parametr: 7

Výstup programu - Kód 2: Ukázka výsledku předání parametru hodnotou

7.4. Metoda orientovaná na výraz

Těla některých metod mohou být velice jednoduchá, mohou např. provádět jeden úkol, vracet výsledky výpočtu, aniž by vyžadovaly jakoukoliv další logiku. C # podporuje zjednodušenou formu takových metod obsahující jeden výraz. Metoda orientovaná na výraz (anglicky „Expression-bodied Method“) může přijímat parametry a vracet hodnoty. Tento typ metod funguje stejně jako metody, které jsme dosud užívali, ale s tím rozdílem, že je užit operátor => který odkazuje na výraz, jenž je tělem metody a také chybí příkaz return používaný v předchozích metodách. Hodnota výrazu se používá jako návratová hodnota. Pokud metoda nevrací žádný výsledek, je typu void. Ve skutečnosti neexistuje žádný rozdíl mezi metodou orientovanou na výraz a deklarací běžné metody s tělem uzavřeným ve složených závorkách. Výhoda použití tohoto typu metody je pouze v jednoduchosti zápisu (nemusíme používat složené závorky, což usnadňuje čtení kódu). [8]

Ilustrativní příklad SectiHodnotyVyraz
Program SectiHodnotyVyraz
  • Popis: Příklad deklarace metody orientované na výraz se dvěma vstupními parametry a celočíselným výstupem
  • Zadání: Zkuste deklarovat metodu orientovanou na výraz nazvanou SectiHodnotyVyraz, která přijímá dva celočíselné parametry pojmenované x a y. Metoda navrátí součet obou parametrů. Hodnotu výstupu této metody uložte do lokální proměnné vysledek deklarované v metodě Main, kde také proběhne volání metody. Hodnoty parametrů: x = 7 a y = 5
  • Řešení: Bude postupně probráno v následujícím textu

Následující příklad kódu ukazuje zjednodušenou verzi takové metody zapsané pomocí výrazu, která načítá dva celočíselné vstupní parametry a navrací jejich celočíselný součet – viz Kód 1.

/*Deklarace statické metody orientované na výraz s celočíselném výstupem 
  a se dvěma vstupními parametry*/
static int SectiHodnotyVyraz(int x, int y) => x + y;

Kód 1: Příklad deklarace metody SectiHodnotyVyraz orientované na výraz se dvěma vstupními parametry a celočíselným výstupem

Volání metody SectiHodnotyVyraz orientované na výraz (viz Kód 1) ve statické metodě Main, které předáme dva vstupní parametry ve formě literálu a jejíž celočíselný výstup uložíme do proměnné výsledek, bychom provedli následujícím způsobem – viz Kód 2.

static void Main(string[] args)
{        
    //Deklarace lokální celočíselné proměnné
    int vysledek;
    //Zavolání metody orientované na výraz se 2 vstupními parametry a jedním celočíselným výstupem
    vysledek = SectiHodnotyVyraz(7, 5);
    //Čekání na stisk klávesy -> ukončení programu
    Console.ReadKey();
}

Kód 2: Příklad zavolání metody SectiHodnotyVyraz orientované na výraz se dvěma vstupními parametry (použití literálů) a s návratem výsledku

Ilustrativní příklad ZobrazHodnotyVyraz
Program ZobrazHodnotyVyraz
  • Popis: Příklad deklarace metody orientované na výraz bez návratu výsledku s jedním vstupním parametrem
  • Zadání: Zkuste deklarovat metodu bez návratu (proceduru) orientovanou na výraz nazvanou ZobrazHodnotyVyraz, která přijímá celočíselný parametr pojmenovaný x. Metoda vypíše hodnotu tohoto parametru ve svém těle. V metodě Main zavolejte předchozí deklarovanou metodu SectiHodnotyVyraz (navrací součet obou parametrů – viz Ilustrativní příklad SectiHodnotyVyraz) s hodnotami parametrů: x = 7 a y = 5. Hodnotu výstupu této metody uložte do lokální proměnné vysledek. V metodě Main zavolejte ZobrazHodnotyVyraz a předejte jí hodnotu získaného výsledku
  • Řešení: Bude postupně probráno v následujícím textu

Následující kód zobrazuje metodu orientovanou na výraz, která nenavrací žádný výsledek (datový typ návratu je tedy void). Tato metoda přijímá jeden vstupní parametr a pouze vypisuje hodnotu tohoto parametru – viz Kód 3.

//Deklarace statické metody bez výstupu orientované na výraz s 1 vstupním parametrem
static void ZobrazHodnotyVyraz(int x) => Console.WriteLine("Hodnota x: {0}", x);

Kód 3: Příklad deklarace metody ZobrazHodnotyVyraz orientované na výraz bez návratu výsledku s jedním vstupním parametrem

Ve statické metodě Main nyní zavolejme obě předchozí deklarované metody SectiHodnotyVyraz a ZobrazHodnotyVyraz – viz Kód 4.

static void Main(string[] args)
{        
    //Deklarace lokální celočíselné proměnné
    int vysledek;
    //Zavolání metody orientované na výraz se 2 vstupními parametry a jedním celočíselným výstupem
    vysledek = SectiHodnotyVyraz(7, 5);
    //Zavolání metody se vstupy ale bez výstupu
    ZobrazHodnotyVyraz(vysledek);
    //Čekání na stisk klávesy -> ukončení programu
    Console.ReadKey();
}

Kód 4: Příklad zavolání metody ZobrazHodnotyVyraz orientované na výraz bez návratu výsledku s jedním vstupním parametrem

Na základě výpisu v konzole vidíme, že vypsaná hodnota v metodě Main, odpovídá hodnotě součtu obou parametrů - viz Výstup programu - Kód 4.

Hodnota x: 12

Výstup programu - Kód 4: Ukázka výsledku metody ZobrazHodnotyVyraz orientované na výraz bez návratu výsledku

7.5. Přetížení metody

O přetížení (anglicky „Overloading“) metody se jedná, pokud ve stejném oboru platnosti, např. třídy, existuje stejný identifikátor metod (tzn. minimálně dva stejné názvy metod). Tyto metody se mohou od sebe lišit např. sadou parametrů – počtem vstupních parametrů. Uveďme jednoduchý příklad výpisu, ke kterému používáme příkaz WriteLine. Tato metoda má až 18 různých verzí přetížení (ve Visual Studio 2019) – od žádného seznamu parametrů (díky čemuž metoda vypíše prázdný řádek), dále vstup celočíselného, reálného parametru, až po vstup parametru datového typu bool. Při kompilaci se kompilátor podívá na datový typ parametru a volá odpovídající verzi této metody - viz Kód 1. Přetížit metodu lze pouze na základě parametrů, nikoliv na základě datového typu jejího návratu (tedy datového typu předávaného výsledku)!

//Deklarace přetížené metody (stejný název) - vstupní parametr typu int
public void PretizenaMetoda(int x)
{
    //...
}
 
//Deklarace přetížené metody (stejný název) - vstupní parametr typu double
public void PretizenaMetoda(double x)
{
    //...
}

Kód 1: Příklad přetížené metody

7.6. Volitelné parametry

Přetížení metod není nic specifického pro C#. Tento princip využívají i jiné objektově orientované jazyky. Klíčovým pro jazyk C# je spolupráce s jinými aplikacemi a komponentami jiných jazyků navržených pro prostředí .NET. Jednou z hlavních technologií používanou operačním systémem Windows je objektový model komponent COM (zkratka anglického „Component Object Model“). Bohužel COM nepodporuje přetížení metod, ale místo nich používá metody, které umí přijímat volitelné parametry. [6]

Volitelné parametry poskytují řešení, když kompilátor nedokáže od sebe nelze dostatečně odlišit datové typy předávaných parametrů. [6]

Představme si, že máme metodu, která přijímá dva celočíselné parametry s názvem parametr1 a parametr3 a jeden reálný parametr2. První metoda ukazuje, že kompilátor nemá problém rozlišit první (dva celočíselné parametry a jeden reálný), druhou (celočíselný parametr a reálný parametr) a třetí verzi přetížené metody (jeden celočíselný parametr). Problém nastává u čtvrté metody. Třetí metodě jsme totiž předávali parametr1 a ve čtvrté parametr3. V tuto chvíli kompilátor kód nezkompiluje, protože třetí a čtvrtou metodu od sebe nedokáže odlišit – viz Kód 1. 

//Deklarace přetížené metody (stejný název) -> O.K.
public void ZpracujData(int parametr1, double parametr2, int parametr3)
{
    //...
}
 
//Deklarace přetížené metody (stejný název) -> O.K.
public void ZpracujData(int parametr1, double parametr2)
{
    //...
}
 
//Deklarace přetížené metody (stejný název) -> O.K.
public void ZpracujData(int parametr1)
{
    //...
}
 
//Deklarace přetížené metody (stejný název) -> K.O.
public void ZpracujData(int parametr3)
{
    //...
}

Kód 1: Příklad přetížené metody a možný problém s odlišením metod

U takového případu lze při deklaraci metody použit tzv. volitelný parametr. První metodu můžeme nahradit metodou, které bude jedno, zda jí předáme jeden, dva nebo tři parametry. K parametru přidáme výchozí hodnotu pomocí operátoru přiřazení. První parametr bude povinný (neuvádí výchozí hodnotu) a ostatní mohou a nemusí být zadány – viz Kód 2. Pokud druhý a třetí parametr nebudou zadány, na začátku metody jim bude přiřazena počáteční hodnota.

//Deklarace metody(stejný název) s volitelnými parametry
public void ZpracujData(int parametr1, double parametr2 = 0.0, int parametr3 = 1)
{
    //...
}

Kód 2: Příklad metody s volitelnými parametry

Metodu tedy můžeme volat různými způsoby – viz Kód 3.

//Volání metody pouze s jedním parametrem
ZpracujData(0);
//Volání metody pouze se dvěma parametry
ZpracujData(0, 1.0);
//Volání metody pouze se třemi parametry
ZpracujData(0, 1.0, 2);

Kód 3: Příklad volání metody s volitelnými parametry

7.7. Pojmenování argumentů

Při volání metody jsme standardně předávali hodnoty (skutečných parametrů) do metody v takém pořadí, jak jsou deklarovány v metodě (formální parametry). Jazyk C# umožňuje při volání metody pojmenovat jednotlivé parametry, tudíž není zapotřebí předávat je přesně v pořadí, jak jsou deklarovány v metodě – viz Kód 1. Metody deklarované v předchozí kapitole (viz Kód 2) lze volat pouze např. se dvěma pojmenovanými parametry.

//Volání metody s pojmenovanými parametry
ZpracujData(parametr3: 2, parametr2: 1.0, parametr1: 0);
//Volání metody jen se dvěma pojmenovanými parametry
ZpracujData(parametr3: 2, parametr1: 0);

Kód 1: Příklad volání metody ZpracujData s pojmenovanými parametry

//Deklarace metody(stejný název) s volitelnými parametry
public void ZpracujData(int parametr1, double parametr2 = 0.0, int parametr3 = 1)
{
    //...
}

Kód 2: Příklad deklarace metody ZpracujData s volitelnými parametry

Měli bychom také upozornit na možné problémy, které mohou nastat s volitelnými parametry. Máme deklarovány dvě metody s volitelnými parametry – viz Kód 3. Problém nejednoznačnosti výběru metody by mohl nastat až při jejich volání.

//Deklarace metody (stejný název) s volitelnými parametry
public void ZpracujData(int parametr1, double parametr2 = 0.0,
    string parametr3 = "Text")
{
    //...
}
 
//Deklarace metody (stejný název) s volitelnými parametry
public void ZpracujData(int parametr1, double parametr2 = 0.0,
    string parametr3 = "Text", int parametr4 = 0)
{
    //...
}

Kód 3: Příklad metody ZpracujData s volitelnými parametry

Podívejme se nyní na případ volání deklarovaných metod - viz Kód 4. V případě prvního volání metody ZpracujData kompilátor zajistí volání metody, která se nejvíce shoduje s deklarovanými metodami. Spustí tedy metodu se třemi parametry. Druhému volání metody zase nejvíce vyhovuje metoda se čtyřmi parametry. Problém nastane při třetím volání metody. Kompilátor neví, kterou metodu spustit. Obě verze metody totiž vyhovují volání, protože mají volitelné parametry pro druhý, třetí i čtvrtý parametr. Volá se tedy verze metody se třemi parametry s tím, že se pro parametr3 použije výchozí hodnota, nebo se volá metoda se čtyřmi parametry s tím, že se výchozí hodnota použije u parametrů parametr3 a parametr4? Kompilátor díky této nejednoznačnosti tento kód nezkompiluje.

//Volání metody - parametry lze rozpoznat -> O.K.
ZpracujData(1, 0.5, "Nazdar");
//Volání metody - parametry lze rozpoznat -> O.K.
ZpracujData(1, parametr4: 10);
//Volání metody - parametry nelze rozpoznat -> K.O.
ZpracujData(1, 2.5);

Kód 4: Příklad nejednoznačnosti při volání metody ZpracujData s volitelnými pojmenovanými parametry

8. Rekurze

Objekt je rekurzivní, jestliže se skládá nebo je definován pomocí sebe samého. Co nám tato poučka říká, není nic jiného než, že v rámci těla metody deklarované metody, bude tato metoda znovu volána. Je provedeno tzv. rekurzivní volání metody. Jde o princip vnořování metody dovnitř sebe samé.

Podstatu rekurze zachycuje následující obrázek, který ilustruje obraz v obraze (metoda volá sama sebe, ta zase volá sama sebe atd.) – viz Obrázek 1.

Podobenství rekurze

Obrázek 1: Podobenství rekurze

Rekurzivní volání nastane dříve, než je předchozí vyvolání dokončeno. Rekurze může být přímá (metoda volá sama sebe) nebo vzájemná (2 nebo více metod se volá navzájem).

Metoda ale s vnořováním do sebe také musí někdy přestat, tzn., že pokud má mít výpočet smysl, musí být rekurzivní volání prováděno v konečném počtu kroků. Znamená to, že uvnitř metody s rekurzí musí být definována podmínka, že další rekurzivní volání skončí a dojde také k návratu ze všech rozpracovaných volání metody.

Ilustrativní příklad FaktorialRekurze 
Program FaktorialRekurze 
  • Popis: Příklad deklarace metody s využitím rekurze pro výpočet faktoriálu
  • Zadání: Zkuste deklarovat metodu s celočíselným návratem nazvanou FaktorialRekurze, která přijímá celočíselný parametr pojmenovaný n. Pomocí rekurze vypočtěte hodnotu faktoriálu pro tento parametr. Hodnotu výstupu této metody vypište v metodě Main
  • Řešení: Bude postupně probráno v následujícím textu

Procvičme si podstatu rekurze na typickém příkladu výpočtu faktoriálu. Z matematiky víme, že faktoriál čísla n (značeno jako n!) je roven součinu všech přirozených čísel menších nebo rovných n (přičemž platí 0! = 1) např. 3! = 3*2*1. Pomocí rekurze bychom mohli faktoriál kladného čísla rozepsat jako 3! = 3*2!, kde bychom 2! uvnitř výrazu mohli zase rozepsat 2! = 2*1! a další rozepsání již není zapotřebí, protože 1! je roven 1. Postupným zpětným dosazením nám tedy vznikl výraz 3! = 3*2*1!, tedy  3! = 3*2*1 = 6. Výpočet faktoriálu rekurzivním způsobem, lze zapsat jako n*(n-1)! . Pokud bychom použili metodu pro výpočet faktoriálu, nazvěme ji např. FaktorialRekurze, můžeme náš předchozí zápis výpočtu faktoriálu rekurzivním způsobem zapsat jako n*FaktorialRekurze(n-1). Tohoto principu využijeme v následujícím příkladu – viz Kód 1. 

/*Deklarace statické metody s využitím rekurze s jedním celočíselným výstupem 
 * a s jedním vstupním parametrem*/
static int FaktorialRekurze(int n)
{
    //Podmínka ukončení dalšího rekurzivního volání metody
    if (n == 1)
        //Faktorial 1 je roven 1
        return 1;
    //Nedosáhli jsme podmínky ukončení další rekurze (vnoření)
    else
        return (n * FaktorialRekurze(n - 1));
}

Kód 1: Příklad deklarace metody FaktorialRekurze s využitím rekurze pro výpočet faktoriálu

V těle této metody (funkce) je definována podmínka, která určuje, kdy se vnořování metody do sebe samé musí zastavit, tzn., že krok, kdy se metoda postupným snižováním parametru na základě výrazu (n – 1), dostane až do stavu, kdy je předávaná hodnota parametru rovna 1 (tehdy je 1! = 1). Rekurzi vidíme ve čtvrtém řádku kódu (bez komentářů), kdy metoda volá sama sebe (svým jménem FaktorialRekurze) a předává si postupně snižovanou hodnotu parametru o jedna. Až se volaná metoda dostane do stavu, že daný parametr už nejde snížit (splnění podmínky ukončení další rekurze v těle metody), hodnotu 1 předá zpět do metody, která ji naposledy volala. Pak tato volající metoda vypočte hodnotu svého výrazu a tuto hodnotu zase postupně dosazuje zpět do volající metody. Tento cyklus probíhá tak dlouho, dokud neobdržíme výsledek příkazu, který odstartoval volání vnořených metod.

Použití rekurze je velmi účinný ale často také nebezpečný trik!

Následující kód popisuje, jak bychom vytvořenou metodu používající rekurzi pro výpočet faktoriálu volali v metodě Main – viz Kód 2. Této metodě je do parametru předána hodnota 7 uložená v proměnné cislo, která byla inicializována přímo v deklaraci. Poslední řádek kódu ukazuje vypočtenou hodnotu faktoriálu a číslo, pro něhož byl faktoriál vypočten.

static void Main(string[] args)
{
    //Deklarace parametru
    int cislo = 7;
    //Zavolání metody s rekurzí s 1 vstupním parametrem a jedním celočíselným výstupem
    int faktorial = FaktorialRekurze(cislo);
    //Výpis čísla, ze kterého byl vypočten faktoriál a hodnota faktoriálu
    Console.WriteLine("Faktoriál čísla {0}: {1}", cislo, faktorial);
    //Čekání na stisk klávesy -> ukončení programu
    Console.ReadKey();
}

Kód 2: Příklad zavolání metody FaktorialRekurze využívající rekurzi pro výpočet faktoriálu včetně výpisu výsledku

Na následujícím výpisu v konzoli vidíme vypočtený faktoriál – viz Výstup programu - Kód 2.

Faktoriál čísla 7: 5040

Výstup programu - Kód 2: Ukázka výsledku použití rekurze

Co kdybychom zkusili zadat nějaké větší číslo jako vstup, např. 13. Pokud si vypočteme hodnotu faktoriálu pro toto číslo, zjistíme, že faktoriál by měl odpovídat číslu 6,227,020,800 (čárky oddělují řády tisíců). Ale co se stalo? Nám program vypsal jinou hodnotu. Jak již bylo řečeno, každý datový typ má svou horní mez a při výpočtu faktoriálu jsme bohužel horní mez datového typu int překročili (tato horní mez je 2,147,483,647). Jedná se o tzv. přetečení (o přetečení se více dozvíme později). Při volbě datového typu musíme tedy pečlivě zvážit, zda se nám do jeho rozsahu vypočtené hodnoty vejdou. Asi si říkáte, tak použiji jiný datový typ s větším rozsahem. Uvědomte si, že čím větší je rozsah hodnot, tím více zabírá paměti a tím více se obíráte o výpočetní výkon počítače.

9. Stručné shrnutí


Stručné shrnutí kapitol
Pro ... ... proveďte následující
Deklaraci metody s celočíselným výstupem Definujte datový typ návratu metody, poté uveďte název metody a do závorky uveďte parametry metody včetně jejich datových typů. Tělo metody uveďte do složených závorek, např.:
int SectiHodnoty(int x, int y)
{
    ...
}
Návrat hodnoty z metody Uveďte v těle metody příkaz return, např.:
return x + y;
Předčasné ukončení metody Uveďte v těle metody příkaz return, např.:
return;
Deklaraci metody bez výstupu Místo datového typ návratu metody definujte klíčové slovo void, poté uveďte název metody a do závorky uveďte parametry metody včetně jejich datových typů (pokud je jich zapotřebí). Tělo metody uveďte do složených závorek, např.:
void SectiHodnoty( ... )
{ 
    ...
}
Zavolání metody Uveďte název metody a do závorek potřebné parametry oddělené čárkou, např.:
SectiHodnoty(13, 5);
Deklaraci dvou výstupů metody Definujte oba datové typ návratů metody, poté uveďte název metody a do závorky uveďte parametry metody včetně jejich datových typů (pokud je jich zapotřebí). Tělo metody uveďte do složených závorek, např.:
(int, int) SectiOdecti(int x, int y)
{
    return (x + y, x - y);
}
Předání (vstupního) parametru hodnotou Za názvem metody v závorce uveďte u parametru jeho datový typ a název. Poté uveďte tělo metody, např.:
int PrictiJedna(int x)
{
    return x++;
}
 Předání (vstupního/výstupního) parametru odkazem Za názvem metody v závorce uveďte klíčové slovo ref před datovým typem parametru a jeho názvem. Poté uveďte tělo metody, např.:
void PrictiJedna(ref int x)
{
    x++;
}
Deklaraci výstupního parametru Za názvem metody v závorce uveďte klíčové slovo out před datovým typem parametru a jeho názvem. Poté uveďte tělo metody proveďte inicializaci parametru např.: 
void PrictiJedna(out int x)
{
    x = 0;
    x++;
}
Deklaraci metody orientované na výraz Definujte datový typ návratu metody, poté uveďte název metody a do závorky uveďte parametry metody včetně jejich datových typů. Uveďte operátor => a za ním výraz, např.:
int SectiHodnoty(int x, int y) => x + y;


Specifikaci volitelného parametru metody V deklaraci metody v závorce u parametrů uveďte výchozí hodnotu parametrů, např.: 
void ZpracujData(int parametr1, double parametr2 = 0.0, string parametr3 = "Ahoj")
{
    ...
}
Předání argumentů metodě jako pojmenovaný parametr Při volání metody uveďte název parametru a jeho hodnotu (pokud ji chcete specifikovat), např.
ZpracujData(parametr1 : 100, parametr3 : "Nazdar");
 Rekurze V těle metody si zavolá metoda sama sebe (nezapomeňte uvést podmínku ukončení vnoření), např.: 
int FaktorialRekurze(int n)
{
    if (n == 1)
        return 1;
    else
        return (n * FaktorialRekurze(n - 1));
}