Własne metody — nazwij czynność i używaj jej wiele razy
Program kilka razy liczy koszt biletów tym samym wzorem. Zamiast kopiować rachunek, zapiszesz go raz pod własną nazwą — i przy zmianie ceny poprawisz jedno miejsce zamiast dziesięciu.
Czego się dziś nauczysz
- Zadeklarujesz metodę z parametrami i typem wyniku.
- Wywołasz ją i wykorzystasz zwróconą wartość.
- Odróżnisz parametr od argumentu.
- Dobierzesz metodę zwracającą wartość albo
void. - Rozpoznasz komunikat CS0161 i będziesz wiedział, co go powoduje.
Przygotowanie: lekcje 01–18. Przewidywany czas: 45–90 minut z zadaniami. Przykłady wymagają .NET 8 lub nowszego, z włączonymi ImplicitUsings i Nullable.
Trzy razy ten sam rachunek
Program sprzedaje bilety na trzy wydarzenia. Za każdym razem liczy to samo: liczba sztuk razy cena, plus opłata za rezerwację, zaokrąglona do dwóch miejsc.
int sztukiA = 3;
decimal cenaA = 18.50m;
decimal kosztA = sztukiA * cenaA + 2.00m;
Console.WriteLine($"Turniej retro: {kosztA:C}");
int sztukiB = 5;
decimal cenaB = 12.00m;
decimal kosztB = sztukiB * cenaB + 2.00m;
Console.WriteLine($"Noc robotow: {kosztB:C}");
int sztukiC = 2;
decimal cenaC = 24.00m;
decimal kosztC = sztukiC * cenaC + 2.00m;
Console.WriteLine($"Druk 3D: {kosztC:C}");
Kod działa. Problem pojawia się w dniu, w którym opłata za rezerwację rośnie do 2,50 zł — trzeba ją poprawić w trzech miejscach. Przy dziesięciu wydarzeniach w dziesięciu, a jedno na pewno zostanie pominięte.
Metoda to ten rachunek zapisany raz, pod własną nazwą. Reszta programu tylko z niej korzysta:
static decimal Koszt(int sztuki, decimal cena)
{
return sztuki * cena + 2.00m;
}
Console.WriteLine($"Turniej retro: {Koszt(3, 18.50m):C}");
Console.WriteLine($"Noc robotow: {Koszt(5, 12.00m):C}");
Console.WriteLine($"Druk 3D: {Koszt(2, 24.00m):C}");
Trzy powody, dla których warto
Po pierwsze: poprawka w jednym miejscu. Po drugie: nazwa Koszt mówi, co się dzieje — czytelnik nie musi rozszyfrowywać wzoru. Po trzecie: metodę da się sprawdzić osobno, bez uruchamiania całego programu. Do tego wrócimy w lekcji 56 przy testach.
Z czego składa się metoda
static decimal Koszt(int sztuki, decimal cena)
// ^^^^^^^ ^^^^^ ^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^
// | | | |
// | | | +-- lista parametrow
// | | +--------------- nazwa metody
// | +---------------------- typ zwracanej wartosci
// +----------------------------- modyfikator
| Element | Co oznacza |
|---|---|
static | metodę wywołujemy bez tworzenia obiektu. W programach z tej części kursu zawsze piszemy static; dlaczego — wyjaśni lekcja 44. |
decimal | typ wartości, którą metoda oddaje. Może to być każdy typ; void oznacza „nic nie oddaje”. |
Koszt | nazwa. Piszemy ją PascalCase i tak, żeby mówiła o czynności albo o wyniku (lekcja 05). |
(int sztuki, decimal cena) | parametry — dane, które metoda dostaje przy każdym wywołaniu. Lista może być pusta: (). |
Parametr a argument
To dwa różne słowa na dwie różne rzeczy i warto je rozróżniać, bo komunikaty kompilatora ich używają.
| Pojęcie | Gdzie występuje | Przykład |
|---|---|---|
| parametr | w deklaracji metody | int sztuki — nazwa i typ, bez wartości |
| argument | w miejscu wywołania | Koszt(3, 18.50m) — konkretna wartość, tu 3 |
Kolejność argumentów ma znaczenie
Wywołanie Koszt(18.50m, 3) nie skompiluje się, bo typy nie pasują — i całe szczęście. Gdyby oba parametry były typu int, kompilator przyjąłby zamianę bez słowa, a program liczyłby bzdury. Argumenty trafiają do parametrów po kolei, a nie po nazwie.
Oddawanie wyniku
return robi dwie rzeczy naraz: kończy wykonanie metody i oddaje wartość do miejsca wywołania.
static int Wieksza(int a, int b)
{
if (a > b)
{
return a; // tutaj metoda sie konczy
}
return b; // ta linia wykona sie tylko wtedy, gdy a <= b
}
Instrukcje zapisane po wykonanym return nigdy się nie wykonają — kompilator zgłosi je jako kod nieosiągalny (ostrzeżenie CS0162).
Metoda void
Gdy metoda ma coś zrobić, a nie coś policzyć, jej typem wyniku jest void.
static void Naglowek(string tytul)
{
Console.WriteLine();
Console.WriteLine(tytul.ToUpper());
Console.WriteLine(new string('-', tytul.Length));
}
Taką metodę wywołujemy jako osobną instrukcję: Naglowek("Sprzedaż");. Nie da się jej użyć w wyrażeniu, bo nie ma czego wstawić.
Najczęstsze pytanie tej lekcji
„Dlaczego metoda nic nie wypisuje?” — bo return nie wypisuje. Oddaje wartość temu, kto metodę wywołał, a ten musi z nią coś zrobić: przypisać do zmiennej albo wstawić do Console.WriteLine. Samo Koszt(3, 18.50m); jako instrukcja policzy wynik i natychmiast go wyrzuci.
| Zadanie metody | Typ wyniku | Jak wywołać |
|---|---|---|
| policzyć i oddać liczbę | int, decimal, double | decimal x = Koszt(3, 18.50m); |
| odpowiedzieć tak albo nie | bool | if (CzyPelnoletni(wiek)) … |
| zbudować tekst | string | Console.WriteLine(Opis(3)); |
| wypisać, narysować, zapisać | void | Naglowek("Sprzedaż"); |
Gdzie w pliku umieścić metodę
Od lekcji 03 znasz dwa sposoby zapisania programu. Metody można pisać w obu, ale wyglądają trochę inaczej.
W klasie Program — zapis klasyczny
class Program
{
static decimal Koszt(int sztuki, decimal cena)
{
return sztuki * cena + 2.00m;
}
static void Main()
{
Console.WriteLine(Koszt(3, 18.50m));
}
}
Koszt i Main są na tym samym poziomie — obie wewnątrz klasy, żadna wewnątrz drugiej. Kolejność nie ma znaczenia: metoda może być zapisana pod Main i i tak zostanie znaleziona.
W instrukcjach najwyższego poziomu
Console.WriteLine(Koszt(3, 18.50m));
static decimal Koszt(int sztuki, decimal cena)
{
return sztuki * cena + 2.00m;
}
Tutaj metody zapisujemy pod instrukcjami wykonywalnymi. To ta sama metoda, tylko krócej zapisana.
Metoda w metodzie
Wklejenie definicji Koszt wewnątrz klamer Main też się skompiluje — powstanie wtedy funkcja lokalna, widoczna tylko w Main. W tym kursie tak nie robimy: metody mają być dostępne dla całego programu. Sprawdź wcięcia — klamra zamykająca Main musi stać przed nagłówkiem kolejnej metody.
Przykład: kasa biletowa
Wklej cały przykład do nowego projektu konsolowego jako Program.cs. Zanim uruchomisz — przewidź wynik.
class Program
{
static decimal Koszt(int sztuki, decimal cena)
{
return sztuki * cena + 2.00m; // 2 zl oplaty za rezerwacje
}
static bool CzyZnizka(int wiek)
{
return wiek < 18 || wiek >= 65;
}
static string Opis(string wydarzenie, int sztuki)
{
if (sztuki == 1)
{
return $"{wydarzenie}: jeden bilet";
}
return $"{wydarzenie}: {sztuki} biletow";
}
static void Naglowek(string tytul)
{
Console.WriteLine();
Console.WriteLine(tytul.ToUpper());
Console.WriteLine(new string('-', tytul.Length));
}
static void Main()
{
Naglowek("Kasa biletowa");
Console.WriteLine(Opis("Turniej retro", 3));
Console.WriteLine($"Do zaplaty: {Koszt(3, 18.50m):F2} zl");
Console.WriteLine(Opis("Noc robotow", 1));
Console.WriteLine($"Do zaplaty: {Koszt(1, 12.00m):F2} zl");
Naglowek("Znizki");
int[] wieki = { 15, 30, 70 }; // tablice poznasz w lekcji 23
foreach (int wiek in wieki)
{
Console.WriteLine($"wiek {wiek,2}: znizka {CzyZnizka(wiek)}");
}
}
}
KASA BILETOWA
-------------
Turniej retro: 3 biletow
Do zaplaty: 57,50 zl
Noc robotow: jeden bilet
Do zaplaty: 14,00 zl
ZNIZKI
------
wiek 15: znizka True
wiek 30: znizka False
wiek 70: znizka True
Co dzieje się po kolei
- Cztery metody, cztery różne typy wyniku:
decimal,bool,stringivoid. Każda robi jedną rzecz i tyle. Naglowekwywołujemy dwa razy z różnym argumentem — linia pod tytułem sama dopasowuje długość, bo powstaje ztytul.Length.CzyZnizkazwracabool, więc wynik wyrażenia logicznego wystarczy oddać przezreturn— nie trzeba pisaćif … return true; else return false;.Opisma dwareturn. Pierwszy kończy metodę dla jednego biletu; drugi wykona się tylko w pozostałych przypadkach.- Metody stoją nad
Main, ale wykonują się dopiero wtedy, gdyMainje wywoła. Sama definicja niczego nie uruchamia.
Co robi każdy użyty element
| Element | Zwraca | Działanie i ograniczenia |
|---|---|---|
static typ Nazwa(parametry) | — | Deklaracja metody. Bez static w tej części kursu metoda nie zostanie znaleziona z Main. |
return wartosc; | — | Kończy metodę i oddaje wartość. Typ musi zgadzać się z nagłówkiem, inaczej błąd CS0029. |
return; | — | W metodzie void: wcześniejsze zakończenie. Przydatne do odrzucenia błędnych danych na początku. |
void | typ | Metoda nic nie oddaje. Nie wolno jej użyć w wyrażeniu ani przypisać do zmiennej. |
Nazwa(argumenty) | zależnie od metody | Wywołanie. Argumenty trafiają do parametrów po kolei, nie po nazwie. |
new string(znak, n) | string | Napis z n powtórzeń znaku — wygodna linia oddzielająca. |
tekst.ToUpper() | string | Wersja wielkimi literami; oryginału nie zmienia (lekcja 08). |
{liczba:F2} | tekst | Formatowanie do dwóch miejsc po przecinku (lekcja 13). |
Zanim utkniesz
| Zapis | Problem |
|---|---|
Koszt(3, 18.50m); jako osobna instrukcja | Wynik zostaje policzony i wyrzucony. Przypisz go albo wstaw do Console.WriteLine. |
Brak return na którejś ścieżce | CS0161: „nie wszystkie ścieżki kodu zwracają wartość”. Każde rozgałęzienie if musi kończyć się return albo trzeba dopisać jeden na końcu metody. |
Console.WriteLine zamiast return | Metoda wypisze wynik, ale odda void — nie da się go użyć w dalszych obliczeniach. Licz w metodzie, wypisuj w Main. |
Definicja metody wewnątrz Main | Powstaje funkcja lokalna widoczna tylko tam. Sprawdź, gdzie stoi klamra zamykająca Main. |
Brak static | CS0120: „wymagane jest odwołanie do obiektu”. W tej części kursu wszystkie metody są static. |
| Zamienione argumenty tego samego typu | Kompilator nie ma jak tego wykryć. Program policzy coś innego niż zamierzałeś — sprawdź kolejność w nagłówku. |
| Metoda robiąca trzy rzeczy naraz | Kompiluje się, ale nazwać ją sensownie już się nie da. Jeśli w nazwie musi być „i”, to są dwie metody. |
Zadania
Napisz metodę static int Pole(int a, int b) zwracającą pole prostokąta i wywołaj ją trzy razy z różnymi wymiarami. Wypisz wyniki w Main, nie w metodzie.
Napisz metodę static void Powitaj(string imie), która wypisuje Czesc, Ala!. Wywołaj ją dla trzech imion. Wyjaśnij w komentarzu, dlaczego ta metoda ma typ void, a poprzednia int.
Napisz metodę static int Wieksza(int a, int b). Sprawdź ją dla par (3, 8), (8, 3) i (5, 5). Zapisz, co metoda zwraca dla liczb równych i czy to poprawne.
Napisz metodę static string Slownie(int ocena), która dla liczb od 1 do 6 zwraca nazwę oceny, a dla pozostałych napis brak oceny. Wypisz wyniki dla 0, 1, 4, 6 i 7. Metoda nie może niczego wypisywać samodzielnie.
Napisz program kasy biletowej z trzema metodami: Netto(int sztuki, decimal cena), Vat(decimal netto) licząca 23 procent i Brutto(decimal netto) korzystająca z Vat. Wypisz wszystkie trzy kwoty dla 4 biletów po 15 zł. Żadna z metod nie wypisuje wyniku.
Napisz program z menu: dodawanie, odejmowanie, mnożenie i dzielenie. Każde działanie ma być osobną metodą zwracającą wynik, a pętla z menu ma tylko wczytywać dane, wywoływać właściwą metodę i wypisywać wynik. Dzielenie przez zero obsłuż tak, żeby program się nie przerwał, i zapisz w komentarzu, którą drogę wybrałeś oraz dlaczego.
Co trzeba zapamiętać
- Metoda to nazwany fragment programu, który można wywołać wiele razy z różnymi danymi.
- Nagłówek metody to modyfikator, typ wyniku, nazwa i lista parametrów.
- Parametr stoi w deklaracji, argument w wywołaniu; trafiają do siebie po kolei.
returnkończy metodę i oddaje wartość — nie wypisuje jej.- Metoda
voidcoś robi, zamiast coś oddawać, i nie da się jej użyć w wyrażeniu. - Jedna metoda ma robić jedną rzecz; obliczenia trzymaj w metodach, a wypisywanie w
Main.
Dokumentacja: Microsoft Learn — temat tej lekcji.