Metoda je pojmenovaný blok kódu, který vykonává určitou logiku. V .NET (a obecně v programování) slouží k:
- zapouzdření opakovaného kódu
- zjednodušení programu na menší logické celky
- znovu použitelnosti logiky
- organizaci kódu (lepší čitelnost a údržba)
Metoda vs. Funkce
Metoda Blok kódu, který je umístěn v rámci třídy.
Funkce Blok kódu, který je nezávislý na třídě. Jako funkce se v C# označují delegáty
Func<>.
Vstupním bodem každého C# programu je metoda Main.
private static void Main(string[] args) { }Struktura metody
Ukázka metody
public int Add(int a, int b)
{
return a + b;
}Vysvětlení
- hlavička metody
public→ modifikátor přístupuint→ návratový typ- Pokud metoda nic nevrací, tak se využívá klíčové slovo
void
- Pokud metoda nic nevrací, tak se využívá klíčové slovo
Add→ název metody(int a, int b)→ parametry metody
- tělo metody →
return a + b;
Parametr vs. Argument metody
- Parametr = proměnná definovaná v deklaraci (hlavičce) metody.
- Argument = hodnota, která se parametru předává při volání metody.
void PrintMessage(string message) // message je parametr
{
Console.WriteLine(message);
}
PrintMessage("Hello!"); // "Hello!" je argumentDělení parametrů
Parametry metod lze dělit na:
- Vstupní parametry
- Výstupní parametry
- Vstupně výstupní parametry
Výchozím typem parametru je vstupní parametr (in klíčové slovo, které se nemusí psát). Změnu typu parametru lze realizovat napsáním příslušného klíčového slova před datový typ parametru.
1. Vstupní parametry
Nejběžnější způsob – parametry se do metody pouze předávají.
public void Greet(string name)
{
Console.WriteLine($"Hello, {name}!");
}
// Explicitně pak takhle, ale nepoužívá se:
public void Greet(in string name)
{
Console.WriteLine($"Hello, {name}!");
}
// Volání
Greet("Alice");“
2. Výstupní parametry – out
Metoda vrací hodnotu přes parametr. Parametr nemusí mít hodnotu před voláním. Tento typ parametrů je velmi využíván pro bezpečné parsování vstupu - např. int.TryParse(input, out int result), kde metoda vrací true/false dle toho, jestli se povedlo zparsovat vstup. Samotný výsledek parsování je pak přítomný v druhém parametru.
Před opuštěním metody je nutné výstupnímu parametru nastavit hodnotu.
public class User
{
public int Id { get; set; }
public string Name { get; set; }
}
public class UserRepository
{
private List<User> _users = new List<User>
{
new User { Id = 1, Name = "Alice" },
new User { Id = 2, Name = "Bob" }
};
public bool TryGetUserById(int id, out User user)
{
user = _users.FirstOrDefault(u => u.Id == id);
return user != null;
}
}3. Vstupně-výstupní parametry – ref
Metoda používá aktuální hodnotu parametru a může ji změnit. Hodnota musí být inicializována před voláním. Změna hodnoty v metodě ovlivní hodnotu i ve volajícím.
void MultiplyByTwo(ref int number)
{
number = number * 2;
}
int num = 5;
Console.WriteLine(num); // 5
MultiplyByTwo(ref num);
Console.WriteLine(num); // 10Extension metody (Rozšiřující metody)
Rozšiřující (extension) metody umožňují rozšiřovat funkcionalitu již existujících typů, aniž by bylo nutné je měnit nebo z nich dědit. Typicky se využívají pokud je potřeba do již existujícího typu, kde není možné měnit zdrojový kód, přidat nějakou vlastní logiku (např. metodu).
Fungování
- Musí být definované ve statické třídě.
- Samotná metoda musí být statická.
- První parametr je speciální – začíná klíčovým slovem
this.- Říká, který typ se rozšiřuje.
Ukázka
Metoda, která zjistí, jestli je string číslo v rozsahu datového typu int.
public static class StringExtensions
{
public static bool IsNumeric(this string input)
{
return int.TryParse(input, out _);
}
}Ukázka použití:
string value = "12345";
bool result = value.IsNumeric(); // true
Console.WriteLine(result);Přetěžování metod
Metody se mohou přetížit (více informací v Polymorfismu na stránce o Polymorfismu, tj. mít stejný název, ale různé parametry:
public void Print(string message)
{
Console.WriteLine(message);
}
public void Print(int number)
{
Console.WriteLine(number);
}Rekurze
Rekurze znamená, že funkce (nebo metoda) volá sama sebe, aby vyřešila podproblém původního problému. Tedy například problém sečtení tří čísel lze rozpadnout na dva menší problémy sečtení dvou čísel.
Převod rekurze na iteraci a obráceně
Platí, že každou iteraci (cykly) lze převést na rekurzi a obráceně.
Rekurze musí vždy obsahovat
Podmínka ukončení (base case)
- říká, kdy se rekurze má zastavit
- chrání před nekonečným voláním funkce
- pokud tato podmínka chybí, tak programy končí zpravidla
StackOverflowException- přetečením zásobníku, jelikož každé volání metody na zásobníku tvoří nový záznam s parametry metody
Rekurzivní volání (recursive case)
- část, kde funkce volá sama sebe s jinými (menšími) vstupními hodnotami
Jednoduchá ukázka - Faktoriál
Faktoriál je definován rekurzivně:
public int Factorial(int n)
{
if (n == 0)
return 1; // Base case
return n * Factorial(n - 1); // Recursive case
}Typy rekurze
- Přímá rekurze - metoda volá přímo sama sebe
- Např.: Faktoriál
- Nepřímá rekurze - Metoda nevolá sama sebe přímo, ale zprostředkovaně přes jiné metody.
Ukázka nepřímé rekurze:
public void MethodA(int n)
{
if (n <= 0)
return;
Console.WriteLine("A");
MethodB(n - 1);
}
public void MethodB(int n)
{
if (n <= 0)
return;
Console.WriteLine("B");
MethodA(n - 1);
}Kdy rekurzi používat?
Rekurze je skvělá pro problémy, které mají přirozenou hierarchickou nebo opakující se strukturu, např.:
- průchody stromů (DOM, souborové systémy)
- algoritmy pro kombinace, permutace
- matematické výpočty (faktoriál, Fibonacciho čísla)
- řešení úloh typu divide and conquer (quicksort, mergesort)