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í !