Dneska se podívám trochu na novinku v C# 4 a to na parametry metod. Pokud vzpomenu na programování v C++, vybaví se mi možnost definovat parametrům výchozí hodnoty. Když jsem začal programovat v programovacím jazyce C# v dobách kdy vládl .NET Framework 1.0 velmi jsem se po této vlastnosti sháněl a byl jsem zklamán, když jsem zjistil, že není podporována. Nicméně, stačilo několik verzí počkat a tato šikovná vlastnost je na světě a je dotažena k dokonalosti.
O co se vlastně jedná? Jde o možnost kterémukoliv parametru přiřadit výchozí hodnotu, která se použije v okamžiku, pokud není daný parametr při volání metody použit. Pojďme se na to podívat. Vezměme si příklad jednoduché třídy, která bude reprezentovat osobu a bude zapouzdřovat jméno, příjmení, titul před jménem a titul za jménem. Problém je v tom, že ne každá osoba má titul před jménem a ne každý má titul za jménem případně kombinaci těchto. O proti tomu jméno a příjmení má každý. Dříve bychom mohli popsaný problém řešit například takto:
class Osoba
{
public Osoba(string TitulPred, string Jmeno, string Prijmeni, string TitulZa)
{
//inicializace osoby
}
public Osoba(string Jmeno, string Prijmeni, string TitulZa)
: this(string.Empty, Jmeno, Prijmeni, TitulZa)
{
//inicializace osoby probiha pres prvni konstruktor v rade
}
public Osoba(string Jmeno, string Prijmeni)
: this(string.Empty, Jmeno, Prijmeni, string.Empty)
{
//inicializace osoby probiha pres prvni konstruktor v rade
}
//dalsi kod tridy...
}
Jak je vidět z kódu, tak vytváříme jeden plnohodnotný konstruktor, který obsahuje všechny parametry a ostatní konstruktory ho pouze přetěžují a volají tak, že chybějící parametry doplňují přednastavenými hodnotami, v našem případě hodnotou prázdného řetězce. Nyní, když se na daný kód podíváme, musíme si přiznat, že to není nic moc přehledného a v podstatě dva ze tří konstruktorů jsou “zbytečné”. Pro úplnost ještě příklad toho jak vytvářet instance takovéto třídy:
Osoba PrvniOsoba=new Osoba("Jan", "Novák");
Osoba DruhaOsoba=new Osoba("Ing.", "Jan", "Novák");
Osoba TretiOsoba=new Osoba("Jan", "Novák", "DiS.");
Osoba CtvrtaOsoba=new Osoba("Ing.", "Jan", "Novák", "PhDr.");
Všechny tyto způsoby jsou možné a co více, jsou reálné. (Více o titulech naleznete zde)
Co bylo bylo, teď se pojďme podívat jak je to možné řešit dnes. Jako první věc si ukážeme výchozí hodnotu parametru. Zůstaňme u třídy Osoba, pouze ji lehce zmodernizujme:
class Osoba
{
public Osoba(string Jmeno, string Prijmeni, string TitulPred = "", string TitulZa = "")
{
//inicializace osoby
}
//dalsi kod tridy...
}
Přiřazením výchozí hodnoty některým parametrům (těm u kterých to má smysl) jsme snížili potřebný počet konstruktorů na jeden. Možná jste si ale všimli, že se změnilo pořadí parametrů, což je bohužel daň za použití výchozích hodnot parametrů. Je to tak, že prvně se deklarují parametry bez výchozí hodnoty a poté se definují parametry s výchozí hodnotou. Takovéto pořadí se může zdát při volání konstruktoru jako nelogické a nezbývá než s tím souhlasit. Naštěstí i tento stav má řešení, a to pojmenováním parametrů. Fungujete tak, že můžeme u parametru při volání, v našem případě konstruktoru, říci překladači jaký parametr právě přiřazujeme. Celé je to patrné z následujícího příkladu:
Osoba PrvniOsoba = new Osoba("Jan", "Novák");
Osoba DruhaOsoba = new Osoba("Jan", "Novák", "Ing.", "PhDr.");
Osoba TretiOsoba = new Osoba(TitulPred: "Ing.", Jmeno: "Jan", Prijmeni: "Novák");
Osoba CtvrtaOsoba = new Osoba(Jmeno: "Jan", Prijmeni: "Novák", TitulZa: "DiS.");
Osoba PataOsoba = new Osoba(TitulPred: "Ing.", Jmeno: "Jan", Prijmeni: "Novák", TitulZa: "PhDr.");
Pokud se na kód podíváme tak první volání je prosté volání konstruktoru osoby se jménem a příjmením. Druhou osobu voláme se všemi možnými parametry a to tak, že dodržujeme implicitní pořadí jednotlivých parametrů. Od třetí až do páté osoby používáme pojmenované parametry, což je mnohem přehlednější a v případě vynechání některých parametrů i nezbytné.
Za sebe musím říct, že mi tato vlastnost chyběla a jsem velmi rád, že nyní je už k dispozici a věřím že v tomto přesvědčení nejsem sám.