TOC

This article has been localized into Czech by the community.

Třídy:

Parametry metody

V předchozím článku jsme mluvili o metodách a dostali jsme stručný úvod do konceptu parametrů metody/funkce. V tomto článku se do tohoto tématu ponoříme hlouběji ve všech jeho variacích. Jak bylo zmíněno, metody mohou fungovat bez parametrů, ale obvykle budou mít jeden nebo více parametrů, které metodě pomohou v plnění jejího úkolu.

Už jsme viděli velmi jednoduchý scénář použití pro parametry v předchozím článku: Naše metoda AddNumbers(), která bere dvě čísla jako parametry a vrací součet těchto dvou čísel:

public int AddNumbers(int number1, int number2)
{
	return number1 + number2;
}

To ukazuje, jak chytrý koncept metody je, protože s metodami můžete zapouzdřit funkcionalitu v metodě, ale být schopni ovlivnit výsledek při volání této metody prostřednictvím parametrů:

AddNumbers(2, 3);

Result: 5

AddNumbers(38, 4);

Result: 42

To je základní typ parametrů, ale pojďme si více povědět o všech různých modifikátorech a možnostech, které můžete použít ke změně chování parametrů.

Všimněte si, že v tomto článku se opravdu ponoříme do všech různých typů parametrů a jak vám mohou pomoci, ale pokud teprve začínáte s C# a chcete jen vidět nějaké výsledky, následující může být prozatím příliš složité a technické. Neváhejte zbytek článku přeskočit a vrátit se později, až budete připraveni.

Volitelné parametry

Ve výchozím nastavení, když voláte metodu s jedním nebo několika parametry, musíte pro všechny tyto parametry dodat hodnoty. Nicméně v některých situacích můžete potřebovat, aby byl jeden nebo několik parametrů volitelných. V některých programovacích jazycích by vám bylo dovoleno to udělat jednoduše označením parametru jako volitelného, ale v C# se parametr stává volitelným tím, že se pro něj v deklaraci metody dodá výchozí hodnota. To je ve skutečnosti pěkné řešení, protože vás ušetří psaní extra kódu pro zvládání situací, kdy volající nedodá parametr.

Zde je příklad metody s volitelným parametrem:

public int AddNumbers(int number1, int number2, int number3 = 0)
{
	return number1 + number2 + number3;
}

Poslední parametr (number3) je nyní volitelný, protože jsme pro něj poskytli výchozí hodnotu (0). Při volání můžete nyní dodat dvě nebo tři hodnoty, takto:

public void Main(string[] args)
{
	AddNumbers(38, 4);
	AddNumbers(36, 4, 2);
}

Můžete mít více než jeden volitelný parametr - ve skutečnosti vaše metoda může obsahovat pouze volitelné parametry, pokud je to potřeba. Jen si pamatujte, že volitelné parametry musí být v deklaraci metody uvedeny jako poslední - nikoli první nebo mezi nevolitelnými parametry.

Modifikátor parametrů

Jako alternativu k několika volitelným parametrům můžete použít modifikátor parametrů (params), který umožňuje libovolný počet parametrů. Může to vypadat takto:

public void GreetPersons(params string[] names) { }

Volání by pak mohlo vypadat takto:

GreetPersons("John", "Jane", "Tarzan");

Další výhodou použití přístupu params je, že metodě nemusíte předat žádné parametry. Metody s params mohou také přijímat běžné parametry, pokud je parametr s modifikátorem params poslední. Kromě toho lze v jedné metodě použít pouze jeden parametr s klíčovým slovem params. Zde je kompletní příklad, kde používáme modifikátor params k vytisknutí proměnlivého počtu jmen s naší metodou GreetPersons():

public void Main(string[] args)
{
	GreetPersons("John", "Jane", "Tarzan");
}

public void GreetPersons(params string[] names)
{
	foreach(string name in names)
		Console.WriteLine("Hello " + name);
}

Typy parametrů: hodnota nebo odkaz

C# a také další programovací jazyky rozlišují mezi dvěma typy parametrů: "podle hodnoty" a "podle odkazu". Ve výchozím nastavení v C# je "podle hodnoty", což v podstatě znamená, že když předáte proměnnou do volání metody, ve skutečnosti posíláte kopii objektu, místo odkazu na něj. To také znamená, že můžete provádět změny na parametru zevnitř metody, aniž by to ovlivnilo původní objekt, který jste předali jako parametr.

Toto chování můžeme snadno demonstrovat na příkladu:

public void Main(string[] args)
{
	int number = 20;
	AddFive(number);
	Console.WriteLine(number);
}

public void AddFive(int number)
{
	number = number + 5;
}

Máme velmi základní metodu nazvanou AddFive(), která přidá 5 k číslu, které jí předáme. Takže v naší metodě Main() vytvoříme proměnnou nazvanou number s hodnotou 20 a poté zavoláme metodu AddFive(). Nyní na dalším řádku, když vypíšeme proměnnou number, mohl by někdo očekávat, že hodnota je nyní 25, ale místo toho zůstává 20. Proč? Protože ve výchozím nastavení byl parametr předán jako kopie původního objektu (podle hodnoty), takže když naše metoda AddFive() pracovala na parametru, pracovala na kopii a tím nikdy neovlivnila původní proměnnou.

Existují aktuálně dva způsoby, jak změnit toto chování, aby naše metoda AddFive() mohla upravovat původní hodnotu: Můžeme použít modifikátor ref nebo modifikátory in/out.

Modifikátor ref

Modifikátor ref je zkratka pro "reference" – „odkaz“ a v podstatě jen mění chování parametru z výchozího chování "podle hodnoty" na "podle odkazu", což znamená, že nyní předáváme odkaz na původní proměnnou místo kopie její hodnoty. Zde je upravený příklad:

public void Main(string[] args)
{
	int number = 20;
	AddFive(ref number);
	Console.WriteLine(number);
}

public void AddFive(ref int number)
{
	number = number + 5;
}

Všimnete si, že jsem přidal klíčové slovo "ref" na dvou místech: V deklaraci metody a při předávání parametru ve volání metody. S touto změnou nyní dostáváme chování, které bychom původně mohli očekávat - výsledek je nyní 25 místo 20, protože modifikátor ref umožňuje metodě pracovat s aktuální hodnotou předanou jako parametr místo s její kopií.

Modifikátor out

Stejně jako modifikátor ref, modifikátor out zajišťuje, že parametr je předán podle odkazu místo podle hodnoty, ale existuje jeden zásadní rozdíl: Při použití modifikátoru ref předáváte inicializovanou hodnotu, kterou si můžete změnit uvnitř metody, nebo ji nechat tak, jak je. Na druhé straně, při použití modifikátoru out jste nuceni inicializovat parametr uvnitř metody. To také znamená, že můžete předávat při použití modifikátoru out neinicializované hodnoty - kompilátor si postěžuje, pokud se pokusíte opustit metodu s out parametrem bez přiřazení hodnoty.

V C# může metoda vrátit pouze jednu hodnotu, ale pokud použijete modifikátor out, můžete to obejít předáním několika parametrů s modifikátorem out - když bude metoda zavolána, budou přiřazeny všechny parametry out. Zde je příklad, kde předáme dvě čísla a poté, pomocí modifikátorů out, vrátíme jak součet, tak rozdíl těchto čísel:

public void Main(string[] args)
{
	int addedValue, subtractedValue;
	DoMath(10, 5, out addedValue, out subtractedValue);
	Console.WriteLine(addedValue);
	Console.WriteLine(subtractedValue);
}

public void DoMath(int number1, int number2, out int addedValue, out int subtractedValue)
{
	addedValue = number1 + number2;
	subtractedValue = number1 - number2;
}
Output:

15
5

Jak vidíte na začátku příkladu, deklaruji dvě proměnné (addedValue a subtractedValue), před jejich předáním jako parametry out. To bylo požadavkem v předchozích verzích jazyka C#, ale od verze C# 6 je můžete deklarovat přímo ve volání metody, takto:

DoMath(10, 5, out int addedValue, out int subtractedValue);
Console.WriteLine(addedValue);
Console.WriteLine(subtractedValue);

Modifikátor in

Stejně jako modifikátor out, modifikátor in zajišťuje, že parametr je předán jako odkaz místo kopie hodnoty, ale na rozdíl od modifikátoru out vám modifikátor in zabrání v jakýchkoli změnách proměnné uvnitř metody.

Vaše první myšlenka může být: Pokud nemohu změnit hodnotu parametru, pak bych jej mohl stejně dobře předat jako běžný parametr, kde změny neovlivní původní proměnnou. A máte pravdu, výsledek by se zdál být přesně stejný, ale stále existuje velmi platný důvod pro použití modifikátoru in: Předáním jako odkaz místo hodnoty šetříte zdroje, protože framework nemusí trávit čas vytvářením kopie objektu při jeho předávání metodě jako běžný parametr.

Ve většině případů to nebude velký rozdíl, protože většina parametrů jsou jednoduché řetězce nebo celá čísla, ale v situacích, kdy opakovaně voláte stejnou metodu mnohokrát v cyklu, nebo když předáváte parametry s velkými hodnotami, např. velmi velké řetězce nebo struktury, může vám to poskytnout pěkné zvýšení výkonu.

Zde je příklad použití modifikátoru in:

public void Main(string[] args)
{
	string aVeryLargeString = "Lots of text...";
	InMethod(aVeryLargeString);
}

public void InMethod(in string largeString)
{
	Console.WriteLine(largeString);
}

V naší metodě, InMethod(), je parametr largeString nyní jen pro čtení a odkazem na původní proměnnou (aVeryLargeString), takže ji můžeme používat, ale nemůžeme ji modifikovat. Pokud se o to pokusíme, kompilátor si bude stěžovat:

public void InMethod(in string largeString)
{
	largeString = "We can't do this...";
}

Error: Cannot assign to variable 'in string' because it is a readonly variable

Pojmenované parametry

Jak jste viděli ve všech výše uvedených příkladech, každý parametr má v deklaraci metody jedinečný název. To vám umožňuje odkazovat se na parametr uvnitř metody. Avšak při volání metody tyto názvy nepoužíváte - pouze dodáte hodnoty ve stejném pořadí, v jakém jsou deklarovány. To není problém pro jednoduché metody, které přijímají 2-3 parametry, ale některé metody jsou složitější a vyžadují více parametrů. V těchto situacích může být poměrně těžké zjistit, na co se různé hodnoty ve volání metody vztahují, jako v tomto příkladu:

PrintUserDetails(1, "John", 42, null);

Není zcela jasné, co různé parametry ve volání metody znamenají, ale pokud se podíváte na deklaraci metody, uvidíte to:

public void PrintUserDetails(int userId, string name, int age = -1, List<string> addressLines = null)
{
	// Print details...
}

Ale je otravné, pokud musíte neustále vyhledávat deklaraci metody, abyste pochopili, co parametry dělají, takže pro složitější metody můžete přímo ve volání metody dodat názvy parametrů. To vám také umožňuje dodat názvy parametrů v libovolném pořadí, místo abyste byli donuceni používat pořadí deklarace. Zde je příklad:

PrintUserDetails(name: "John Doe", userId: 1);

Jako další bonus vám to umožní dodat hodnotu pro kterýkoli z vašich volitelných parametrů, aniž byste museli dodat hodnoty pro všechny předchozí volitelné parametry v deklaraci. Jinými slovy, pokud chcete v tomto příkladu dodat hodnotu pro parametr addressLines, museli byste také poskytnout hodnotu pro parametr age, protože je první v deklaraci metody. Pokud však použijete pojmenované parametry, pořadí již není důležité a můžete dodat hodnoty jen pro požadované parametry a také pro jeden nebo několik volitelných parametrů, např. takto:

PrintUserDetails(addressLines: new List<string>() { }, name: "Jane Doe", userId: 2);

Zde je kompletní příklad použití pojmenovaných parametrů:

public void Main(string[] args)
{
	PrintUserDetails(1, "John", 42, null);
	PrintUserDetails(name: "John Doe", userId: 1);
	PrintUserDetails(addressLines: new List<string>() { }, name: "Jane Doe", userId: 2);
}

public void PrintUserDetails(int userId, string name, int age = -1, List<string> addressLines = null)
{
	// Print details...
	Console.WriteLine(name + " is " + age + " years old...");
}

Shrnutí

Jak můžete vidět z tohoto článku, parametry existují v mnoha formách a typech. Naštěstí se s běžnými starými pravidelnými parametry dostanete daleko, ale jakmile začnete hlouběji pronikat do jazyka C#, prospěje vám znalost všech typů a modifikátorů, jak je vysvětleno v tomto článku.


This article has been fully translated into the following languages: Is your preferred language not on the list? Click here to help us translate this article into your language!