Minisérie odhalování tajů jazyka C# pokračuje. Po minulém zjištění, co vlastně dělá záhadný zavináč, následuje modifikátor parametrů metod – out.
Použití
Běžné je, že metody jsou izolované od okolního programu a nemění přímo hodnotu proměnných, které jsou jim předány coby parametry (vytvářejí si lokální kopie, s kterými pracují). Modifikátor out
, stejně jako jeho kolega ref
, toto mění a dá se použít, pokud chceme z metody vrátit více hodnot najednou.
Na rozdíl od ref
ovšem nemusí být proměnné před předáním metodě inicializovány (tedy nemusí mít přiřazenou hodnotu) a jsou-li, uvnitř metody se to nijak neprojeví. Podívejme se na primitivní příklad:
class Program { static void Main(string[] args) { const int c = 4; // inicializace čísla, s kterým budeme počítat int m; // proměnná pro uložení jednoho výsledku - bez výchozí hodnoty double o; // proměnná pro uložení druhého výsledku - bez výchozí hodnoty Pocty(c, out m, out o); // provedení výpočtu - výsledky uloženy do m a o Console.WriteLine("{0} -> {1}, {2}", c, m, o); } static void Pocty(int cislo, out int mocnina, out double odmocnina) { mocnina = cislo * cislo; odmocnina = Math.Sqrt(cislo); } }
Metoda Pocty má v signatuře jeden klasický parametr (cislo) a dva s přidaným modifikátorem out
(mocnina, odmocnina). Návratový typ je void
, takže v těle chybí i return
, k „vrácení“ hodnot se využije pozměnění předaných parametrů.
V metodě Main je definována konstanta představující číslo, na kterém se budou provádět výpočty, a dvě proměnné bez inicializace výchozí hodnoty. Tyto tři prvky pak předáme metodě Pocty a nesmíme při tom zapomenout opět uvést klíčové slovo out
.
Jakmile program opustí Pocty, bude v proměnné m druhá mocnina čísla c, v proměnné o bude jeho druhá odmocnina a výsledkem bude výpis:
4 -> 16, 2
Při použití ref
je možné s hodnotou proměnné pracovat jakkoliv – metoda, které je předána, ji může používat k dalším výpočtům nebo upravovat. U out
toto neplatí – dá se použít pouze k získávání hodnoty z metody. Pokud bychom na začátku inicializovali např. m na 6, tak uvnitř Pocty tato hodnota nebude přístupná, dokud ji nenastavíme přímo v metodě. Jakmile se tak ale stane, přetrvává i mimo ni.
static void Main(string[] args) { const int c = 4; int m = 6; // inicializujeme i "m" double o; Pocty(c, out m, out o); // "m" má hodnotu, kterou dostala v metodě, bez ohledu na inicializaci Console.WriteLine("{0} -> {1}, {2}", c, m, o); } static void Pocty(int cislo, out int mocnina, out double odmocnina) { // tady je "mocnina" unassigned mocnina = cislo * cislo; // a teď už má hodnotu odmocnina = Math.Sqrt(cislo); // a nyní získala hodnotu i "odmocnina" }
Omezení
Než metoda s modifikátorem parametru out
skončí, daná proměnná musí mít nastavenou nějakou hodnotu. Pokud bychom v příkladu nahoře vynechali řádek s výpočtem mocniny nebo odmocniny, překladač by okamžitě zahlásil chybu.
Vlastnosti objektů se neberou jako proměnné a nelze je tímto způsobem předat.
Z hlediska signatur se považují jako totožné metody, které se liší pouze parametry ref
a out
, a nelze je tedy takto přetěžovat. Příklad napoví více. První metoda je výchozí, zápis druhé je nedovolené přetížení a teprve třetí je v pořádku.
static void Pocty(int cislo, out int mocnina, out double odmocnina); // první metoda static void Pocty(int cislo, ref int mocnina, out double odmocnina); // nelze static void Pocty(int cislo, int mocnina, out double odmocnina); // v pořádku
Závěr
Tolik tedy další ze zákoutí jazyka C#. Na závěr podotýkám, že klíčové slovo out
má ještě jeden význam, a to v generických rozhraních a delegátech. Jeho protějškem je pak modifikátor in
.
Klasický odkaz na oficiální dokumentaci na MSDN: http://msdn.microsoft.com/en-us/library/ee332485.aspx.
Skvělej článek, díky!
Děkuji za vysvětlení !