Gdy program ma wykonać określoną czynność przynajmniej raz, a dopiero potem zdecydować, czy powtórzyć operację, konstrukcja do while pasuje idealnie. W C# przydaje się między innymi przy walidacji danych, obsłudze menu konsolowego i ponawianiu prostych prób. Pokażę składnię, działanie, różnice względem while i for, a także błędy, przez które pętla potrafi nigdy się nie zakończyć.
Jedna pętla, która zawsze wykonuje pierwszą iterację
- Warunek jest sprawdzany na końcu, więc ciało pętli wykona się co najmniej raz.
- Składnia wymaga średnika po warunku zapisanym za słowem
while. - To dobry wybór do walidowania danych wejściowych i obsługi menu.
- Przed każdą kolejną iteracją trzeba zmienić stan, od którego zależy warunek zakończenia.
-
whilemoże nie wykonać się ani razu, natomiast do-while zawsze startuje.
Jak działa pętla do-while w C#
Pętla do-while najpierw wykonuje blok kodu, a dopiero później sprawdza wyrażenie logiczne. Jeśli warunek zwróci true, program wraca na początek bloku. Gdy otrzyma false, kończy działanie i przechodzi do instrukcji znajdującej się za pętlą.
do
{
// kod wykonywany przynajmniej raz
}
while (warunek);Najłatwiej zapamiętać tę konstrukcję jako „zrób operację, potem sprawdź, czy trzeba ją powtórzyć”. Właśnie kolejność ma tu największe znaczenie. Jeśli warunek od początku jest fałszywy, ciało i tak zostanie uruchomione jeden raz.
int liczba = 10;
do
{
Console.WriteLine(liczba);
liczba++;
}
while (liczba < 5);
Ten przykład wypisze 10, mimo że warunek liczba < 5 jest fałszywy już przy pierwszym sprawdzeniu. To zachowanie odróżnia tę pętlę od while i decyduje o tym, kiedy warto jej użyć.
Najlepszy praktyczny przykład to walidacja danych
Jeżeli użytkownik musi podać poprawną wartość, program powinien najpierw wyświetlić prośbę o dane, a dopiero potem ocenić wynik. Pętla do-while dobrze odzwierciedla ten scenariusz, bo pytanie pojawia się przynajmniej raz.
int wiek;
do
{
Console.Write("Podaj wiek od 1 do 120: ");
}
while (!int.TryParse(Console.ReadLine(), out wiek)
|| wiek < 1
|| wiek > 120);
Console.WriteLine($"Podany wiek: {wiek}");W tym kodzie metoda int.TryParse bezpiecznie sprawdza, czy tekst można zamienić na liczbę. Warunek pozostaje prawdziwy, gdy konwersja się nie powiedzie albo liczba wykracza poza dozwolony zakres, więc użytkownik dostaje kolejną szansę.
Menu konsolowe
Drugim naturalnym zastosowaniem jest menu, które ma działać aż do wybrania opcji wyjścia. W praktyce takie rozwiązanie jest czytelniejsze niż ręczne powtarzanie kilku instrukcji Console.ReadLine().
string? wybor;
do
{
Console.WriteLine("1 - Lista produktów");
Console.WriteLine("2 - Ustawienia");
Console.WriteLine("0 - Wyjście");
Console.Write("Wybierz opcję: ");
wybor = Console.ReadLine();
switch (wybor)
{
case "1":
Console.WriteLine("Wyświetlam produkty.");
break;
case "2":
Console.WriteLine("Otwieram ustawienia.");
break;
case "0":
Console.WriteLine("Koniec programu.");
break;
default:
Console.WriteLine("Nieprawidłowa opcja.");
break;
}
}
while (wybor != "0");Istotny jest tutaj stan zmiennej wybor. Każde przejście pętli pobiera nową wartość, więc warunek może w końcu stać się fałszywy. Bez tego program wpadłby w nieskończone powtarzanie menu.
Do-while, while czy for
Wybór pętli powinien wynikać z tego, co steruje powtarzaniem. Ja stosuję prostą zasadę: gdy operacja musi wydarzyć się raz, wybieram do-while; gdy może nie wydarzyć się ani razu, używam while; gdy znam liczbę przejść lub pracuję z indeksem, rozważam for.
| Konstrukcja | Kiedy sprawdza warunek | Minimalna liczba iteracji | Typowe zastosowanie |
|---|---|---|---|
do-while |
Po wykonaniu bloku | 1 | Menu, walidacja, pierwsza próba operacji |
while |
Przed wykonaniem bloku | 0 | Przetwarzanie do momentu spełnienia warunku |
for |
Przed każdą iteracją | 0 | Iterowanie po zakresie lub indeksach |
foreach |
Automatycznie dla elementów kolekcji | 0 | Odczyt elementów listy, tablicy lub zbioru |
Przykładowo, gdy odczytujesz elementy listy, foreach zwykle będzie bardziej czytelny. Gdy liczysz od 1 do 10, for jasno pokazuje zakres. Konstrukcja do-while wygrywa wtedy, gdy pierwsze wykonanie nie zależy jeszcze od warunku, bo warunek można ocenić dopiero po wykonaniu operacji.
Jak kontrolować przebieg pętli
Wewnątrz pętli możesz używać break i continue. Pierwsza instrukcja natychmiast kończy całą pętlę, a druga pomija resztę bieżącej iteracji i przechodzi do sprawdzenia warunku.
int suma = 0;
do
{
Console.Write("Podaj liczbę dodatnią lub 0, aby zakończyć: ");
string? tekst = Console.ReadLine();
if (!int.TryParse(tekst, out int liczba))
{
Console.WriteLine("To nie jest liczba.");
continue;
}
if (liczba == 0)
{
break;
}
if (liczba < 0)
{
Console.WriteLine("Liczba musi być dodatnia.");
continue;
}
suma += liczba;
}
while (true);
Console.WriteLine($"Suma: {suma}");Warunek while (true) sam w sobie tworzy pętlę bez naturalnego końca, dlatego program potrzebuje kontrolowanego break. Taki zapis bywa wygodny, ale stosuję go ostrożnie. Jeśli punkt wyjścia można wyrazić zwykłym warunkiem, czytelniejsza jest pętla z konkretnym wyrażeniem kończącym.
Pułapka nieskończonej pętli
Najczęstszy błąd polega na tym, że kod nie zmienia wartości używanej w warunku. W poniższym przykładzie zmienna pozostaje równa 1, więc program będzie wypisywał ją bez końca.
int licznik = 1;
do
{
Console.WriteLine(licznik);
}
while (licznik <= 3);Naprawa jest prosta, ale łatwo o niej zapomnieć. W każdej pętli sprawdź, co konkretnie doprowadzi do zakończenia oraz czy ta zmiana nastąpi także przy błędnych danych i użyciu continue.
Typowe błędy w kodzie C#
Brak średnika po warunku
W odróżnieniu od wielu innych instrukcji blokowych konstrukcja kończy się średnikiem. Jego brak powoduje błąd kompilacji.
do
{
Console.WriteLine("Test");
}
while (false);Nieprawidłowe miejsce aktualizacji stanu
Jeżeli wartość sterująca jest zmieniana dopiero w gałęzi, która nie zawsze się wykona, pętla może zachowywać się inaczej, niż zakładasz. Przy walidacji danych najlepiej jasno oddzielić pobranie wartości, sprawdzenie jej poprawności i decyzję o zakończeniu.
Zła pętla do zadania
Do przechodzenia po kolekcji nie potrzebujesz zwykle ręcznego indeksu ani konstrukcji do-while. Taki wybór zwiększa ryzyko błędu poza zakresem tablicy i utrudnia odczytanie intencji kodu. Czytelność warunku jest ważniejsza niż użycie konkretnego rodzaju pętli.
Brak ograniczenia prób
Przy formularzu lub menu można powtarzać działanie bez limitu, ale przy operacji zależnej od sieci, pliku albo zewnętrznej usługi trzeba rozważyć maksymalną liczbę prób. W przeciwnym razie chwilowy problem może zablokować cały proces na stałe.
int proba = 0;
bool sukces;
do
{
proba++;
sukces = WykonajOperacje();
if (!sukces)
{
Console.WriteLine($"Próba {proba} nie powiodła się.");
}
}
while (!sukces && proba < 3);Limit 3 prób nie jest uniwersalną regułą. Powinien wynikać z charakteru operacji, czasu oczekiwania i tego, czy ponowienie może bezpiecznie wykonać działanie drugi raz.
Jak zdecydować, czy ta pętla ma sens
Zadaj sobie jedno pytanie: czy kod powinien wykonać pierwszą operację, zanim pozna odpowiedź na warunek? Jeśli tak, do-while będzie naturalnym wyborem. Jeśli odpowiedź brzmi „nie”, zwykły while najczęściej lepiej komunikuje logikę programu.
W projektach .NET nie wybieram tej konstrukcji tylko dlatego, że jest krótka. Sprawdzam jeszcze, czy warunek jest czytelny, czy zmienna sterująca zawsze się zmienia i czy potrzebny jest limit prób. Takie trzy kontrole zwykle wystarczają, aby uniknąć zarówno przypadkowej pętli nieskończonej, jak i kodu trudnego w utrzymaniu.
Pętla do-while jest mała, ale bardzo konkretna. Najlepiej sprawdza się tam, gdzie pierwsze wykonanie jest obowiązkowe, a kolejne zależą od wyniku poprzedniego działania, na przykład przy walidacji wejścia, menu lub ograniczonym mechanizmie ponawiania operacji.
