Wprowadzenie – Po co nam instrukcje warunkowe?
Instrukcje warunkowe pozwalają programowi podejmować decyzje w zależności od tego, czy pewne warunki są spełnione (prawdziwe), czy nie. Dzięki nim program może wykonywać różne działania w zależności od danych wejściowych.
Analogia z życiem codziennym:
W życiu codziennym również podejmujemy decyzje na podstawie warunków:
- Jeśli pada deszcz, to biorę parasol
- Jeśli mam lekcje, to uczę się
- Jeśli jest zimno, to zakładam kurtkę, w przeciwnym razie wychodzę w koszulce
W programowaniu robimy to samo za pomocą instrukcji warunkowych – pozwalają one programowi „myśleć” i reagować na różne sytuacje.
Przepływ sterowania
Bez instrukcji warunkowych program wykonuje kod sekwencyjnie – linia za linią. Instrukcje warunkowe wprowadzają rozgałęzienia, pozwalając programowi wybrać różne ścieżki wykonania.
// Kod bez warunków - zawsze wykonuje wszystkie instrukcje
Console.WriteLine("Sprawdzam pogodę...");
Console.WriteLine("Wychodzę z domu");
// Kod z warunkami - może wykonać różne instrukcje
Console.WriteLine("Sprawdzam pogodę...");
if (padaDeszcz)
{
Console.WriteLine("Biore parasol");
}
Console.WriteLine("Wychodzę z domu");Instrukcja if – podstawa decyzji
Najprostsza instrukcja warunkowa to if, co w języku angielskim oznacza „jeśli”.
Składnia:
if (warunek)
{
// kod do wykonania, gdy warunek jest prawdziwy
}Podstawowy przykład:
int temperatura = 25;
if (temperatura > 20)
{
Console.WriteLine("Jest ciepło.");
}
Console.WriteLine("Program zakończony."); // Ta linia wykona się zawszeWyjaśnienie:
if (temperatura > 20)– program sprawdza, czy wartość zmiennejtemperaturajest większa niż 20- Jeśli warunek jest prawdziwy (25 > 20), wykonuje kod w nawiasach klamrowych
- Program kontynuuje wykonywanie pozostałych instrukcji
Warunki jako wyrażenia logiczne
Warunek w if musi być wyrażeniem logicznym – czyli zwracać true lub false:
int wiek = 17;
bool maLicencje = false;
string imie = "Anna";
// Różne typy warunków
if (wiek >= 18) // porównanie liczbowe
if (maLicencje == true) // porównanie logiczne (można skrócić do: if (maLicencje))
if (imie == "Anna") // porównanie tekstowe
if (imie.Length > 3) // wywołanie metody zwracającej boolGdy warunek jest fałszywy:
int temperatura = 15;
if (temperatura > 20) // 15 > 20 to false
{
Console.WriteLine("Jest ciepło."); // Ta linia się NIE wykona
}
Console.WriteLine("Sprawdzanie zakończone."); // Ta linia się wykonaInstrukcja else – alternatywa
Czasami chcemy, aby program zrobił coś innego, gdy warunek nie jest spełniony. Używamy wtedy instrukcji else.
Składnia:
if (warunek)
{
// kod gdy warunek prawdziwy
}
else
{
// kod gdy warunek fałszywy
}Przykład z else:
int temperatura = 15;
if (temperatura > 20)
{
Console.WriteLine("Jest ciepło.");
}
else
{
Console.WriteLine("Jest zimno.");
}
// Wynik: "Jest zimno." (bo 15 <= 20)Praktyczny przykład – system logowania:
string haslo = "abc123";
string wprowadzoneHaslo = "abc123";
if (wprowadzoneHaslo == haslo)
{
Console.WriteLine("✓ Logowanie udane! Witamy w systemie.");
}
else
{
Console.WriteLine("✗ Błędne hasło. Spróbuj ponownie.");
}Instrukcja else if – wiele warunków
Gdy chcemy sprawdzić więcej niż jeden warunek, używamy else if.
Składnia:
if (pierwszy_warunek)
{
// kod dla pierwszego warunku
}
else if (drugi_warunek)
{
// kod dla drugiego warunku
}
else if (trzeci_warunek)
{
// kod dla trzeciego warunku
}
else
{
// kod gdy żaden warunek nie jest spełniony
}Przykład z klasyfikacją temperatury:
int temperatura = 10;
if (temperatura > 30)
{
Console.WriteLine("🔥 Jest bardzo gorąco! Zostań w cieniu.");
}
else if (temperatura > 20)
{
Console.WriteLine("☀️ Jest ciepło. Idealny dzień na spacer.");
}
else if (temperatura > 10)
{
Console.WriteLine("🧥 Jest chłodno. Weź kurtkę.");
}
else if (temperatura > 0)
{
Console.WriteLine("🥶 Jest zimno. Ubierz się ciepło!");
}
else
{
Console.WriteLine("❄️ Mróz! Uważaj na oblodzone drogi.");
}Ważne: Warunki sprawdzane są po kolei. Gdy pierwszy prawdziwy warunek zostanie znaleziony, pozostałe nie są już sprawdzane.
Przykład – system ocen:
int punkty = 85;
char ocena;
if (punkty >= 90)
{
ocena = 'A';
Console.WriteLine($"Brawo! Otrzymujesz ocenę {ocena}");
}
else if (punkty >= 80)
{
ocena = 'B';
Console.WriteLine($"Dobrze! Otrzymujesz ocenę {ocena}");
}
else if (punkty >= 70)
{
ocena = 'C';
Console.WriteLine($"Przeciętnie. Otrzymujesz ocenę {ocena}");
}
else if (punkty >= 60)
{
ocena = 'D';
Console.WriteLine($"Słabo. Otrzymujesz ocenę {ocena}");
}
else
{
ocena = 'F';
Console.WriteLine($"Niestety, nie zdałeś. Ocena: {ocena}");
}Operatory logiczne – złożone warunki
Czasami potrzebujemy bardziej skomplikowanych warunków. Operatory logiczne pozwalają łączyć wiele warunków:
Operator && (AND – „i”)
Oba warunki muszą być prawdziwe:
int temperatura = 18;
bool deszcz = true;
if (temperatura > 15 && deszcz == true)
{
Console.WriteLine("🌧️ Jest ciepło, ale pada deszcz. Weź parasol!");
}
// Inne przykłady z &&
int wiek = 20;
bool maDownod = true;
if (wiek >= 18 && maDownod)
{
Console.WriteLine("✓ Możesz kupić alkohol");
}
// System dostępu
string uzytkownik = "admin";
string haslo = "pass123";
if (uzytkownik == "admin" && haslo == "pass123")
{
Console.WriteLine("🔓 Dostęp przyznany do panelu administratora");
}Operator || (OR – „lub”)
Przynajmniej jeden warunek musi być prawdziwy:
string dzienTygodnia = "Sobota";
if (dzienTygodnia == "Sobota" || dzienTygodnia == "Niedziela")
{
Console.WriteLine("🎉 Dzisiaj jest weekend! Masz wolne od szkoły.");
}
else
{
Console.WriteLine("📚 Dzisiaj jest dzień nauki. Musisz iść do szkoły.");
}
// Inne przykłady z ||
int wiek = 15;
bool maZezwolenie = true;
if (wiek >= 18 || maZezwolenie)
{
Console.WriteLine("✓ Możesz prowadzić pojazd");
}
// Pogoda
bool slonecznie = false;
bool cieplo = true;
if (slonecznie || cieplo)
{
Console.WriteLine("🏖️ Dobry dzień na wyjście na zewnątrz!");
}Operator ! (NOT – „nie”)
Zaprzecza warunkom:
bool padaDeszcz = false;
bool maMask = false;
if (!padaDeszcz) // jeśli NIE pada deszcz
{
Console.WriteLine("☀️ Możesz wyjść bez parasola");
}
if (!maMask) // jeśli NIE ma maski
{
Console.WriteLine("⚠️ Pamiętaj o masce!");
}
// Kombinowanie z innymi operatorami
bool jestWeekend = true;
bool maPrace = false;
if (jestWeekend && !maPrace) // jest weekend I nie ma pracy
{
Console.WriteLine("🎮 Czas na odpoczynek!");
}Złożone przykłady operatorów logicznych:
int wiek = 25;
bool maLicencje = true;
bool maSamochod = true;
bool jestTrzezwy = true;
// Wszystkie warunki muszą być spełnione
if (wiek >= 18 && maLicencje && maSamochod && jestTrzezwy)
{
Console.WriteLine("🚗 Możesz prowadzić!");
}
else
{
Console.WriteLine("🚫 Nie możesz prowadzić");
// Sprawdźmy dlaczego
if (wiek < 18)
Console.WriteLine("- Jesteś za młody");
if (!maLicencje)
Console.WriteLine("- Nie masz prawa jazdy");
if (!maSamochod)
Console.WriteLine("- Nie masz samochodu");
if (!jestTrzezwy)
Console.WriteLine("- Nie jesteś trzeźwy");
}Kolejność wykonywania operatorów
Ważne jest zrozumienie kolejności wykonywania operatorów:
!(NOT)&&(AND)||(OR)
bool a = true;
bool b = false;
bool c = true;
// Bez nawiasów
bool wynik1 = !a && b || c; // (!a && b) || c = (false && false) || true = true
// Z nawiasami dla czytelności
bool wynik2 = (!a && b) || c; // to samo co wyżej, ale jaśniejsze
bool wynik3 = !(a && b) || c; // !(true && false) || true = true || true = trueNajlepsza praktyka: Używaj nawiasów dla czytelności!
// Trudne do zrozumienia
if (wiek >= 18 && maLicencje || jestInstruktor && !jestPijany)
// Czytelne dzięki nawiasiem
if ((wiek >= 18 && maLicencje) || (jestInstruktor && !jestPijany))Porównywanie różnych typów danych
Porównywanie liczb:
int a = 10;
double b = 10.5;
decimal c = 15.25m;
if (a < b) Console.WriteLine("a jest mniejsze od b");
if (b < c) Console.WriteLine("b jest mniejsze od c");
if (a != b) Console.WriteLine("a nie równa się b");
if (a == 10) Console.WriteLine("a równa się 10");Porównywanie stringów:
string imie1 = "Anna";
string imie2 = "ANNA";
string imie3 = "anna";
// Porównanie z uwzględnieniem wielkości liter
if (imie1 == imie2) // false - "Anna" != "ANNA"
{
Console.WriteLine("Imiona są identyczne");
}
// Porównanie bez uwzględnienia wielkości liter
if (imie1.ToLower() == imie2.ToLower()) // true
{
Console.WriteLine("Imiona są takie same (ignorując wielkość liter)");
}
// Lub użycie Equals z parametrem
if (string.Equals(imie1, imie2, StringComparison.OrdinalIgnoreCase))
{
Console.WriteLine("Imiona są takie same");
}Porównywanie znaków:
char litera = 'A';
char cyfra = '5';
if (char.IsLetter(litera))
Console.WriteLine($"{litera} to litera");
if (char.IsDigit(cyfra))
Console.WriteLine($"{cyfra} to cyfra");
if (litera >= 'A' && litera <= 'Z')
Console.WriteLine($"{litera} to wielka litera");Skrócona składnia dla instrukcji if
Instrukcje jednoliniowe (bez nawiasów klamrowych):
int temperatura = 25;
// Pełna składnia
if (temperatura > 20)
{
Console.WriteLine("Jest ciepło");
}
// Skrócona składnia (tylko dla jednej instrukcji!)
if (temperatura > 20)
Console.WriteLine("Jest ciepło");
// UWAGA: To może być mylące, lepiej zawsze używać nawiasów:
if (temperatura > 20)
{
Console.WriteLine("Jest ciepło"); // ✅ Czytelne i bezpieczne
}Operator warunkowy (ternary operator):
Gdy mamy prostą decyzję if-else, możemy użyć skróconej formy:
// Tradycyjne if-else
int wiek = 17;
string status;
if (wiek >= 18)
{
status = "pełnoletni";
}
else
{
status = "niepełnoletni";
}
// Operator warunkowy (warunek ? wartość_jeśli_prawda : wartość_jeśli_fałsz)
string status2 = (wiek >= 18) ? "pełnoletni" : "niepełnoletni";
Console.WriteLine($"Status: {status2}");
// Inne przykłady
int a = 10, b = 20;
int wieksza = (a > b) ? a : b; // zwraca większą liczbę
string pogoda = "słonecznie";
string ubiór = (pogoda == "deszcz") ? "kurtka" : "koszulka";Zagnieżdżone instrukcje if
Możemy umieszczać instrukcje if wewnątrz innych instrukcji if:
int wiek = 20;
bool maLicencje = true;
int doswiadczenie = 2; // lata
if (wiek >= 18) // pierwszy poziom
{
Console.WriteLine("Jest pełnoletni");
if (maLicencje) // drugi poziom
{
Console.WriteLine("Ma prawo jazdy");
if (doswiadczenie >= 2) // trzeci poziom
{
Console.WriteLine("Może prowadzić samotnie");
}
else
{
Console.WriteLine("Powinien jeździć z doświadczonym kierowcą");
}
}
else
{
Console.WriteLine("Musi zdobyć prawo jazdy");
}
}
else
{
Console.WriteLine("Jest niepełnoletni - nie może prowadzić");
}Uwaga: Zbyt głębokie zagnieżdżenie (więcej niż 3-4 poziomy) sprawia, że kod staje się trudny do czytania. Lepiej używać else if lub podzielić na funkcje.
Instrukcja switch – alternatywa dla wielu else if
Gdy mamy wiele warunków sprawdzających tę samą zmienną, switch może być bardziej czytelny:
int dzienTygodnia = 3;
string nazwaDnia;
// Używając if-else if
if (dzienTygodnia == 1)
nazwaDnia = "Poniedziałek";
else if (dzienTygodnia == 2)
nazwaDnia = "Wtorek";
else if (dzienTygodnia == 3)
nazwaDnia = "Środa";
else if (dzienTygodnia == 4)
nazwaDnia = "Czwartek";
else if (dzienTygodnia == 5)
nazwaDnia = "Piątek";
else if (dzienTygodnia == 6)
nazwaDnia = "Sobota";
else if (dzienTygodnia == 7)
nazwaDnia = "Niedziela";
else
nazwaDnia = "Nieprawidłowy dzień";
// Używając switch (czytelniej!)
switch (dzienTygodnia)
{
case 1:
nazwaDnia = "Poniedziałek";
break;
case 2:
nazwaDnia = "Wtorek";
break;
case 3:
nazwaDnia = "Środa";
break;
case 4:
nazwaDnia = "Czwartek";
break;
case 5:
nazwaDnia = "Piątek";
break;
case 6:
nazwaDnia = "Sobota";
break;
case 7:
nazwaDnia = "Niedziela";
break;
default:
nazwaDnia = "Nieprawidłowy dzień";
break;
}
Console.WriteLine($"Dzisiaj jest {nazwaDnia}");Switch z string:
string komenda = "ZAPISZ";
switch (komenda.ToUpper()) // konwersja na wielkie litery
{
case "ZAPISZ":
Console.WriteLine("💾 Zapisywanie pliku...");
break;
case "OTWORZ":
Console.WriteLine("📂 Otwieranie pliku...");
break;
case "DRUKUJ":
Console.WriteLine("🖨️ Drukowanie...");
break;
case "WYJDZ":
Console.WriteLine("👋 Do widzenia!");
break;
default:
Console.WriteLine("❌ Nieznana komenda");
break;
}Najczęste błędy i pułapki
1. Przypisanie zamiast porównania:
int x = 5;
// ❌ Błąd - przypisanie zamiast porównania
if (x = 10) // Błąd kompilacji w C#! (na szczęście)
{
Console.WriteLine("x równa się 10");
}
// ✅ Poprawne porównanie
if (x == 10)
{
Console.WriteLine("x równa się 10");
}2.Porównywanie float/double:
double a = 0.1 + 0.2;
double b = 0.3;
// ❌ Może nie działać jak oczekujemy!
if (a == b) // może być false przez błąd zaokrąglenia
{
Console.WriteLine("Liczby są równe");
}
// ✅ Bezpieczne porównanie
if (Math.Abs(a - b) < 0.0001) // tolerancja błędu
{
Console.WriteLine("Liczby są w przybliżeniu równe");
}3.Logika De Morgana:
bool a = true;
bool b = false;
// Te warunki są równoważne:
if (!(a && b)) // NOT (a AND b)
if (!a || !b) // (NOT a) OR (NOT b)
if (!(a || b)) // NOT (a OR b)
if (!a && !b) // (NOT a) AND (NOT b)4.Short-circuit evaluation:
int x = 0;
int y = 10;
// Bezpieczne - jeśli x == 0, drugi warunek nie będzie sprawdzany
if (x != 0 && y / x > 2) // nie spowoduje dzielenia przez zero
{
Console.WriteLine("y/x jest większe od 2");
}
// Niebezpieczne!
if (y / x > 2 && x != 0) // może spowodować dzielenie przez zero!
{
Console.WriteLine("To się nie wykona");
}Najlepsze praktyki
1. Używaj nawiasów klamrowych zawsze:
// ❌ Może prowadzić do błędów
if (warunek)
Console.WriteLine("Tak");
Console.WriteLine("To nie należy do if!"); // To się zawsze wykona!
// ✅ Bezpieczne i czytelne
if (warunek)
{
Console.WriteLine("Tak");
Console.WriteLine("To należy do if");
}2. Używaj nawiasów dla czytelności:
// ❌ Trudne do zrozumienia
if (wiek >= 18 && maLicencje || jestInstruktor && !jestPijany)
// ✅ Czytelne dzięki nawiasem
if ((wiek >= 18 && maLicencje) || (jestInstruktor && !jestPijany))3. Pozytywne warunki są czytelniejsze:
// ❌ Negatywny warunek - trudniejszy do zrozumienia
if (!nieAktywny)
{
Console.WriteLine("Użytkownik jest aktywny");
}
// ✅ Pozytywny warunek - czytelniejszy
if (czyAktywny)
{
Console.WriteLine("Użytkownik jest aktywny");
}4. Używaj wczesnych zwrotów (early returns):
// ❌ Głębokie zagnieżdżenie
public string SprawdzDostep(int wiek, bool maLicencje, bool jestTrzeźwy)
{
if (wiek >= 18)
{
if (maLicencje)
{
if (jestTrzeźwy)
{
return "Dostęp przyznany";
}
else
{
return "Nie jest trzeźwy";
}
}
else
{
return "Brak licencji";
}
}
else
{
return "Za młody";
}
}
// ✅ Wczesne zwroty - płaskie i czytelne
public string SprawdzDostep(int wiek, bool maLicencje, bool jestTrzeźwy)
{
if (wiek < 18)
return "Za młody";
if (!maLicencje)
return "Brak licencji";
if (!jestTrzeźwy)
return "Nie jest trzeźwy";
return "Dostęp przyznany";
}5. Grupuj powiązane warunki:
// ❌ Rozproszone warunki
if (jestWeekend)
pusteUlice = true;
if (jestWeekend)
sklepyZamkniete = true;
if (jestWeekend)
ludzieSpia = true;
// ✅ Zgrupowane warunki
if (jestWeekend)
{
pusteUlice = true;
sklepyZamkniete = true;
ludzieSpia = true;
}6. Null-conditional operators (C# 6.0+):
string tekst = null;
// ❌ Może rzucić NullReferenceException
if (tekst.Length > 5) // BŁĄD jeśli tekst == null
{
Console.WriteLine("Długi tekst");
}
// ✅ Bezpieczne sprawdzanie
if (tekst != null && tekst.Length > 5)
{
Console.WriteLine("Długi tekst");
}
// ✅ Jeszcze krócej z operatorem ?.
if (tekst?.Length > 5)
{
Console.WriteLine("Długi tekst");
}
// Przykład z obiektami
Person person = null;
if (person?.Address?.City == "Warszawa")
{
Console.WriteLine("Osoba mieszka w Warszawie");
}