1. Wartości domyślne dla parametrów
Wyobraź sobie kawiarnię: jeśli nie powiesz, czy chcesz cukier do kawy, barista domyślnie wsypie jedną łyżeczkę. Ale czasem chcesz… dwie! Albo wcale bez cukru (hardkor!). Tak samo jest z metodami: czasem wygodnie, żeby niektóre parametry miały standardowe wartości, jeśli nie podasz ich jawnie.
A argumenty nazwane — to jak możliwość powiedzenia przy zamówieniu kawy: „A mleko poproszę sojowe, a nie zwykłe”, niezależnie od tego, w jakiej kolejności zwykle podaje się składniki.
W C# oba te mechanizmy sprawiają, że Twój kod jest czystszy, wygodniejszy i mniej podatny na błędy. Bardzo często spotkasz je w prawdziwych projektach: od bibliotek .NET po popularne frameworki — dlatego pracodawcy lubią widzieć, że ogarniasz ten temat.
Składnia
Wartość domyślną dla parametru funkcji ustalasz bezpośrednio w deklaracji metody za pomocą znaku =. Jeśli przy wywołaniu metody ten parametr nie zostanie podany, użyta zostanie właśnie ta wartość domyślna.
void PrintStudent(string name, int age = 18)
{
Console.WriteLine($"Student: {name}, wiek: {age}");
}
Jak to działa?
- Jeśli wywołasz PrintStudent("Alice"); — zostanie wypisane: Student: Alice, wiek: 18.
- Jeśli wywołasz PrintStudent("Alex", 22); — zostanie wypisane: Student: Alex, wiek: 22.
Działa dla wszystkich typów?
Wartość domyślną możesz ustawić dla dowolnego typu parametru, ale są pewne szczegóły:
- Dla typów referencyjnych (string, klasy itd.): domyślnie możesz podać null albo konkretny literał.
- Dla typów wartościowych (int, double, bool itd.): podajesz literał odpowiedniego typu.
- Dla wyliczeń (enum), struktur: też możesz użyć wartości domyślnych.
void AddStudent(string name, int course = 1, double averageScore = 5.0, string comment = null)
{
Console.WriteLine($"Dodano studenta: {name}, kurs: {course}, średnia ocen: {averageScore}, komentarz: {comment}");
}
Wywołania:
- AddStudent("Ivan");
- AddStudent("Maria", 2);
- AddStudent("Teodor", 2, 4.7, "Z wyróżnieniem");
Kolejność parametrów z wartościami
Wszystkie opcjonalne parametry (z wartością domyślną) muszą być po prawej (po wszystkich obowiązkowych). Jeśli spróbujesz dać parametr z wartością domyślną przed obowiązkowym, kompilator się obrazi.
// Błąd!
void Test(int a = 1, int b)
{
// ...
}
Dlaczego tak? Bo inaczej kompilator nie będzie wiedział, który argument do którego parametru przypisać przy wywołaniu metody.
2. Argumenty nazwane
Domyślnie, gdy wywołujesz metodę i przekazujesz argumenty, ich kolejność musi być dokładnie taka, jak w definicji metody. Ale czasem lista jest długa, niektóre parametry mają wartości domyślne i łatwo się pomylić.
Argumenty nazwane pozwalają Ci jasno wskazać, do którego parametru przekazujesz dany argument, w dowolnej kolejności.
AddStudent(name: "Eliza", averageScore: 4.2, comment: "Najlepszy student semestru");
- Tutaj nie podajemy kursu (course), więc będzie 1 (domyślnie).
- Nie musisz pamiętać, który z kolei był parametr comment — po prostu podajesz jego nazwę.
Możesz nawet zamienić miejscami parametry:
AddStudent(averageScore: 3.7, name: "George");
To mega wygodne i kod jest dużo czytelniejszy!
Łączenie z argumentami pozycyjnymi
Argumenty nazwane i pozycyjne (bez nazwy) możesz mieszać, ale wszystkie pozycyjne muszą być przed nazwanymi.
// OK
AddStudent("Stan", averageScore: 4.9);
// Błąd
AddStudent(course: 2, "Philipp");
Po pierwszym nazwanym parametrze wszystko dalej musi być już tylko nazwane. Kompilator pilnuje tej kolejności, żeby nie było niespodzianek.
Wygoda przy metodach z wieloma parametrami
To częsty trik przy metodach, które mają mnóstwo dodatkowych opcji. Na przykład, gdybyś pisał funkcję do dodawania użytkownika do jakiejś chmurowej bazy:
void RegisterUser(
string username,
string password,
string email = null,
bool admin = false,
bool sendWelcomeEmail = true,
string language = "ru"
)
Wywołanie bez argumentów nazwanych wyglądałoby strasznie:
RegisterUser("cat", "qwerty", null, false, true, "ru");
Z argumentami nazwanymi wszystko jest czytelne i bezpieczne:
RegisterUser("cat", "qwerty", admin: true, sendWelcomeEmail: false, language: "en");
Tip: używaj argumentów nazwanych, żeby kod był czytelny nawet bez dokumentacji!
3. Cechy implementacji i częste błędy
Gdy dopiero zaczynasz używać wartości domyślnych i argumentów nazwanych, łatwo się pomylić w kilku miejscach.
- Kolejność parametrów. Zawsze dawaj parametry z domyślnymi wartościami po obowiązkowych. Jeśli zamienisz je miejscami, kompilator wywali błąd.
- Zmiana wartości domyślnej w bibliotece. Jeśli zmienisz wartość domyślną w bibliotece, starzy klienci nie zaczną automatycznie używać nowej. Wartość domyślna jest kompilowana do kodu wywołującego. Więc pomyśl dwa razy, zanim zmienisz domyślne wartości w publicznych bibliotekach.
- Mieszanie argumentów pozycyjnych i nazwanych. Jeśli pomieszasz pozycyjne i nazwane, ale po nazwanym znowu spróbujesz podać pozycyjny — nie zadziała. Na przykład: Func(a: 1, 2) — wywali błąd.
- Literówka w nazwie parametru. Kompilator jest tu surowy: jeśli pomylisz literki (np. napiszesz naem: "Michael"), dostaniesz błąd w stylu: "Nie ma takiego parametru, co Ty w ogóle robisz?!".
GO TO FULL VERSION