Zmienne, stałe i komentarze

Program bez pamięci potrafi tylko wypisać z góry ustalony tekst. Zmienne to pudełka, w których program przechowuje dane w trakcie działania — i od nich zaczyna się prawdziwe programowanie. Poznasz też stałe, komentarze i zasięg, czyli zasadę mówiącą, gdzie zmienna w ogóle istnieje.

C# zmienne const zasięg 45 min
CEL LEKCJI

Czego się dziś nauczysz

  • Zadeklarujesz zmienną i przypiszesz jej wartość
  • Wyjaśnisz różnicę między deklaracją, inicjalizacją a przypisaniem
  • Użyjesz var i wskażesz, kiedy nie wolno go użyć
  • Utworzysz stałą i wyjaśnisz, czym różni się od zmiennej
  • Opiszesz zasięg zmiennej i wskażesz, gdzie przestaje ona istnieć
  • Napiszesz komentarz, który wnosi coś do kodu
TEORIA

Czym jest zmienna

Zmienna to nazwane miejsce w pamięci komputera, w którym program przechowuje jakąś wartość. Wartość można odczytywać i zmieniać — stąd nazwa.

Analogia: pudełko z etykietą

Wyobraź sobie regał z pudełkami. Każde ma etykietę (nazwa zmiennej) i coś w środku (wartość). Etykieta mówi też, co wolno w nim trzymać (typ) — w pudełku podpisanym „liczby całkowite” nie schowasz zdania.

Gdy program potrzebuje wartości, mówi „daj mi zawartość pudełka wiek„. Gdy chce ją zmienić — wkłada do tego samego pudełka coś innego, a stara zawartość przepada.

W C# każda zmienna ma typ, który ustala się raz i już się nie zmienia. Poniżej cztery typy, których użyjemy w tej lekcji; wszystkim przyjrzymy się dokładniej w lekcji 06.

TypCo przechowujePrzykład
intliczbę całkowitąint wiek = 17;
doubleliczbę z częścią ułamkowądouble srednia = 4.25;
stringtekststring imie = "Anna";
boolprawdę albo fałszbool czyZdal = true;

Kropka, nie przecinek

W kodzie część ułamkową oddziela się kropką: 4.25. Przecinek ma w C# zupełnie inne znaczenie — rozdziela argumenty. Zapis double x = 4,25; to błąd kompilacji.

Uwaga, bo to bywa mylące: program wypisze tę liczbę jako 4,25, bo przy wyświetlaniu obowiązują polskie ustawienia regionalne. W kodzie piszemy kropkę, na ekranie widzimy przecinek.

TEORIA

Deklaracja, inicjalizacja, przypisanie

Trzy słowa, które często myli się ze sobą, a oznaczają trzy różne rzeczy.

Program.cs
int wiek;              // DEKLARACJA — mówimy: będzie pudełko na liczbę o nazwie wiek
wiek = 17;             // INICJALIZACJA — pierwszy raz coś do niego wkładamy
wiek = 18;             // PRZYPISANIE — wymieniamy zawartość na nową

int rok = 2026;        // deklaracja i inicjalizacja w jednej linii (tak robi się najczęściej)
NazwaCo się dzieje
DeklaracjaPodajemy typ i nazwę. Od tej chwili nazwa jest znana kompilatorowi, ale nie ma jeszcze żadnej wartości.
InicjalizacjaPierwsze nadanie wartości.
PrzypisanieKażda kolejna zmiana wartości. Poprzednia bezpowrotnie znika.

Zmiennej bez wartości nie wolno użyć

To jedna z ważniejszych rzeczy do zapamiętania na początku:

błąd — program się nie skompiluje
int wiek;
Console.WriteLine(wiek);   // CS0165: Użyto niezainicjowanej zmiennej lokalnej „wiek"

Zwróć uwagę: zmienna nie zawiera zera ani żadnej innej wartości domyślnej. Ona po prostu nie ma jeszcze wartości, a kompilator w ogóle nie pozwoli takiego programu zbudować. To dobra wiadomość — w wielu językach taki kod się uruchomi i wypisze przypadkową liczbę.

Znak = to nie znak równości

W matematyce x = 5 stwierdza fakt. W programowaniu to polecenie: „weź wartość z prawej strony i włóż ją do pudełka po lewej”. Czytaj to jako strzałkę w lewo.

Program.cs
int licznik = 5;
licznik = licznik + 1;     // w matematyce bez sensu, w programowaniu: weź 5, dodaj 1, włóż z powrotem
Console.WriteLine(licznik);  // 6
TEORIA

Słowo kluczowe var

Jeśli od razu nadajesz zmiennej wartość, kompilator sam potrafi rozpoznać typ. Zamiast pisać go dwa razy, można użyć var.

Program.cs
var imie = "Anna";       // kompilator widzi tekst  → string
var wiek = 17;           // widzi liczbę całkowitą  → int
var srednia = 4.25;      // widzi liczbę z kropką   → double
var czyZdal = true;      // widzi prawda/fałsz      → bool

var to NIE jest „zmienna dowolnego typu”

To najczęstsze nieporozumienie. var nie znaczy „typ nieokreślony” — znaczy „kompilatorze, ustal typ sam”. Typ zostaje ustalony raz, na etapie kompilacji, i dalej działa dokładnie tak samo jak wpisany ręcznie.

błąd — typ już jest ustalony
var wiek = 17;      // od tej chwili wiek jest typu int
wiek = "osiemnaście";  // CS0029: Nie można niejawnie przekonwertować typu „string" na „int"

Kiedy var nie zadziała

ZapisDlaczego nie
var x;Brak wartości, więc kompilator nie ma z czego odczytać typu.
var x = null;null nie mówi nic o typie.
var jako typ pola klasyDziała tylko dla zmiennych lokalnych, wewnątrz metod.

Kiedy używać, a kiedy nie

Używaj var, gdy typ i tak widać z prawej strony: var lista = new List<string>(); — powtarzanie nazwy typu nic nie wnosi.

Wpisuj typ wprost, gdy z prawej strony go nie widać: int liczba = int.Parse(tekst); czyta się lepiej niż var liczba = ..., bo od razu wiadomo, co dostajemy.

W tym kursie w przykładach dla początkujących będziemy zwykle pisać typ wprost — żeby było widać, z czym pracujemy.

TEORIA

Stałe — wartości, które nie mogą się zmienić

Czasem chcemy mieć pewność, że wartość nigdy się nie zmieni: liczba dni w tygodniu, stawka VAT, maksymalna liczba graczy. Służy do tego słowo const.

Program.cs
const int DniWTygodniu = 7;
const double StawkaVat = 0.23;
const string NazwaSzkoly = "ZSMI Lębork";

Console.WriteLine($"Tydzień ma {DniWTygodniu} dni.");

// DniWTygodniu = 8;   // CS0131: Lewa strona przypisania musi być zmienną
ZasadaWyjaśnienie
Wartość od razuStałą trzeba zainicjalizować w tej samej linii, w której ją deklarujesz. const int x; to błąd.
Wartość znana przy kompilacjiMożna napisać const double Pi = 3.14;, ale nie const DateTime Teraz = DateTime.Now; — czas uruchomienia nie jest znany podczas kompilacji.
Nazwa jak dla klasyStałe nazywamy od wielkiej litery: StawkaVat, a nie stawkaVat. Więcej o tym w następnej lekcji.

Po co w ogóle stałe, skoro można użyć zwykłej zmiennej?

Z dwóch powodów. Po pierwsze kompilator pilnuje, żeby nikt jej przez pomyłkę nie nadpisał. Po drugie, i ważniejsze — nazwa tłumaczy liczbę. Porównaj:

double doZaplaty = cena * 1.23; — skąd się wzięło 1.23?
double doZaplaty = cena * (1 + StawkaVat); — od razu wiadomo.

Liczby wpisane wprost w kod nazywa się „magicznymi”. Gdy stawka VAT się zmieni, w pierwszej wersji trzeba przeszukać cały program; w drugiej — poprawić jedną linię.

TEORIA

Jak wolno nazywać zmienne

To są zasady techniczne — kompilator ich pilnuje. O tym, jak nazywać, żeby było czytelnie, jest cała następna lekcja.

Program.cs
// Poprawne nazwy
int wiekUcznia = 17;
string imie2 = "Anna";
double _tymczasowa = 1.5;

// Niepoprawne — każda z tych linii to błąd kompilacji
// int 2wiek = 17;          nazwa nie może zaczynać się od cyfry
// string imie ucznia;      nazwa nie może zawierać spacji
// double cena-netto;       nazwa nie może zawierać myślnika
// int class = 5;           class to słowo kluczowe języka
ZasadaSzczegóły
Litery, cyfry, podkreślenieTylko te znaki. Bez spacji, myślników i znaków działań.
Nie zaczyna się od cyfryliczba1 tak, 1liczba nie.
Nie może być słowem kluczowymclass, int, for i pozostałe słowa zarezerwowane przez język są zajęte.
Wielkość liter ma znaczeniewiek, Wiek i WIEK to trzy różne zmienne. To najczęstsze źródło błędu CS0103.

Polskie znaki: wolno, ale nie rób tego

C# dopuszcza znaki narodowe w nazwach, więc double wartość = 5; się skompiluje. Mimo to w tym kursie nazw z ogonkami nie używamy, i nie powinieneś ich używać w swoim kodzie.

Powody są praktyczne: nazwy z polskimi znakami psują się przy kopiowaniu między systemami o różnym kodowaniu, utrudniają pracę w zespole i sprawiają kłopot przy wyszukiwaniu w kodzie. Piszemy więc wartosc, sredniaOcen, liczbaUczniow — a polskie znaki zostawiamy dla tekstów wyświetlanych użytkownikowi i dla komentarzy.

TEORIA

Komentarze

Komentarz to tekst, który kompilator całkowicie pomija. Jest wyłącznie dla ludzi — dla współpracowników i dla ciebie za pół roku.

Program.cs
// Komentarz jednoliniowy — od dwóch ukośników do końca linii

int cena = 100;   // można też dopisać na końcu linii z kodem

/* Komentarz wieloliniowy.
   Ciągnie się aż do znaku zamykającego,
   więc mieści się w nim dowolnie długi tekst. */

/// <summary>
/// Komentarz dokumentacyjny — trzy ukośniki.
/// Visual Studio pokaże ten opis w podpowiedzi,
/// gdy ktoś najedzie myszą na nazwę metody.
/// </summary>

Skrót, który oszczędza czas

Zaznacz kilka linii i naciśnij Ctrl + K, potem Ctrl + C — Visual Studio zamieni je w komentarz. Ctrl + K, Ctrl + U cofa tę operację. Bardzo przydatne przy szukaniu błędu: wyłączasz fragment kodu, nie kasując go.

Dobry komentarz wyjaśnia DLACZEGO, nie CO

Program.cs
// ✗ Zbędny — kod mówi dokładnie to samo
int wiek = 17;   // przypisanie 17 do zmiennej wiek

// ✓ Wnosi coś, czego z kodu nie widać
int wiek = 17;   // wiek minimalny do kursu na kat. AM

// ✓ Ostrzeżenie dla następnej osoby
// UWAGA: kolejność ma znaczenie — walidacja musi być przed zapisem

// ✓ Notatka na przyszłość
// TODO: dodać sprawdzanie, czy plik istnieje

Jeśli czujesz, że fragment kodu koniecznie wymaga opisu, bo inaczej nikt go nie zrozumie — często lepszym rozwiązaniem jest zmiana nazw zmiennych albo podzielenie kodu na mniejsze części, niż dopisywanie komentarza.

TEORIA

Zasięg — gdzie zmienna istnieje

Zmienna nie istnieje w całym programie. Żyje tylko wewnątrz bloku, w którym została zadeklarowana — czyli między klamrami { }, w których ją utworzono.

Program.cs
int liczba = 10;              // istnieje od tej linii do końca programu

if (liczba > 5)
{
    string komunikat = "Duża liczba";   // istnieje tylko w tym bloku
    Console.WriteLine(komunikat);        // ✓ jesteśmy w środku
    Console.WriteLine(liczba);           // ✓ blok zewnętrzny też jest widoczny
}

// Console.WriteLine(komunikat);   // ✗ CS0103: nazwa nie istnieje w tym kontekście

Zasada jednym zdaniem

Z wnętrza bloku widzisz wszystko na zewnątrz, ale z zewnątrz nie widzisz niczego, co powstało w środku. Gdy program wychodzi z bloku, zadeklarowane w nim zmienne przestają istnieć.

Wygląda to na ograniczenie, ale jest ułatwieniem: dzięki temu tę samą nazwę można spokojnie użyć w różnych miejscach programu, a zmienne pomocnicze nie zaśmiecają reszty kodu.

PRZYKŁAD Z OMÓWIENIEM

Kalkulator zakupów

Program liczy wartość zamówienia: cenę netto, podatek i kwotę do zapłaty po rabacie. Wszystko, co poznaliśmy w tej lekcji, w jednym miejscu.

Program.cs
// Stałe — wartości ustalone raz dla całego programu
const double StawkaVat = 0.23;      // 23%
const double ProgRabatu = 500.0;    // od tej kwoty przysługuje rabat
const double Rabat = 0.10;          // 10%

// Dane zamówienia
string nazwaProduktu = "Klawiatura mechaniczna";
int sztuk = 3;
double cenaNetto = 249.99;

// Obliczenia
double wartoscNetto = sztuk * cenaNetto;
double podatek = wartoscNetto * StawkaVat;
double wartoscBrutto = wartoscNetto + podatek;

// Rabat naliczamy tylko powyżej progu
double doZaplaty = wartoscBrutto;

if (wartoscBrutto > ProgRabatu)
{
    double kwotaRabatu = wartoscBrutto * Rabat;   // istnieje tylko w tym bloku
    doZaplaty = wartoscBrutto - kwotaRabatu;
    Console.WriteLine($"Przyznano rabat: {kwotaRabatu:F2} zl");
}

Console.WriteLine($"Produkt:       {nazwaProduktu}");
Console.WriteLine($"Sztuk:         {sztuk}");
Console.WriteLine($"Wartosc netto: {wartoscNetto:F2} zl");
Console.WriteLine($"VAT:           {podatek:F2} zl");
Console.WriteLine($"Brutto:        {wartoscBrutto:F2} zl");
Console.WriteLine($"DO ZAPLATY:    {doZaplaty:F2} zl");
wynik w konsoli
Przyznano rabat: 92,25 zl
Produkt:       Klawiatura mechaniczna
Sztuk:         3
Wartosc netto: 749,97 zl
VAT:           172,49 zl
Brutto:        922,46 zl
DO ZAPLATY:    830,22 zl

Omówienie

FragmentDlaczego tak
const double StawkaVat = 0.23; Wartość, która nie ma prawa zmienić się w trakcie działania. Nazwa tłumaczy, czym jest liczba 0,23 — bez niej w kodzie pojawiłaby się „magiczna” liczba.
double doZaplaty = wartoscBrutto; Zmienną deklarujemy przed instrukcją if, bo ma być widoczna także po niej. Gdyby powstała w środku bloku, ostatnia linia programu by się nie skompilowała.
double kwotaRabatu = ... Ta z kolei celowo istnieje tylko w bloku — poza nim jest niepotrzebna. Tak działa zasięg i tak należy z niego korzystać.
{kwotaRabatu:F2} Zapis po dwukropku to format. F2 oznacza „liczba stałoprzecinkowa z dwoma miejscami po przecinku”. Bez tego zobaczylibyśmy 92,2460000000001.
Wynik z przecinkiem W kodzie napisaliśmy 249.99 z kropką, a program wypisał 249,99 z przecinkiem. To nie błąd — przy wyświetlaniu obowiązują ustawienia regionalne systemu.

Do pieniędzy nie używa się typu double

Ten przykład jest uproszczony dla czytelności. W prawdziwym programie kwoty przechowuje się w typie decimal, bo double potrafi po wielu działaniach zgubić grosz. Dlaczego tak się dzieje, pokażemy w lekcji 06.

CZĘSTE BŁĘDY

Na co uważać

KodProblem
int wiek;
Console.WriteLine(wiek);
CS0165 — użycie zmiennej bez wartości. Zmienna lokalna nie ma wartości domyślnej; kompilator nie pozwoli jej odczytać.
int Wiek = 17;
Console.WriteLine(wiek);
CS0103 — inna wielkość litery na początku. Dla kompilatora to dwie różne nazwy.
double x = 4,25; Przecinek zamiast kropki. W kodzie część ułamkową oddziela kropka.
int wiek = "17"; CS0029 — po prawej jest tekst, po lewej pudełko na liczbę. Cudzysłów robi z liczby napis.
int liczba = 5;
int liczba = 8;
CS0128 — zmienna o tej nazwie już istnieje. Za drugim razem nie podajemy typu: samo liczba = 8;.
const int X; Stała musi dostać wartość w linii deklaracji.
var x; Nie ma z czego odczytać typu. var wymaga wartości od razu.

Pułapka: zmienna zadeklarowana w bloku

To bardzo częsty błąd przy pierwszych programach z instrukcją if:

błąd i poprawka
// ✗ ŹLE
if (punkty > 50)
{
    string ocena = "zdany";
}
Console.WriteLine(ocena);      // CS0103 — poza blokiem ocena nie istnieje

// ✓ DOBRZE — deklaracja przed blokiem
string ocena = "niezdany";
if (punkty > 50)
{
    ocena = "zdany";           // tu tylko zmieniamy wartość
}
Console.WriteLine(ocena);      // działa
ZADANIA

Zadania

ZAD 1Metryczka★☆☆

Zadeklaruj cztery zmienne: imię (tekst), wiek (liczba całkowita), średnia ocen (liczba z ułamkiem) i informację, czy jesteś pełnoletni (prawda/fałsz). Wypisz je w czytelnej formie.

pokaż rozwiązanie
string imie = "Anna";
int wiek = 17;
double sredniaOcen = 4.35;
bool czyPelnoletnia = false;

Console.WriteLine($"Imie:          {imie}");
Console.WriteLine($"Wiek:          {wiek}");
Console.WriteLine($"Srednia ocen:  {sredniaOcen}");
Console.WriteLine($"Pelnoletnia:   {czyPelnoletnia}");

Zmienna typu bool wypisze się jako True albo False, z wielkiej litery i po angielsku — tak działa metoda zamieniająca wartość logiczną na tekst. Jak to zmienić, poznasz przy instrukcjach warunkowych.

ZAD 2Zamiana zawartości★★☆

Masz dwie zmienne: int a = 5; i int b = 9;. Zamień ich wartości miejscami tak, aby na końcu a miało 9, a b miało 5. Wypisz wartości przed i po zamianie.

pokaż rozwiązanie
int a = 5;
int b = 9;

Console.WriteLine($"Przed: a = {a}, b = {b}");

int tymczasowa = a;   // odkładamy wartość a na bok
a = b;                // do a wkładamy wartość b
b = tymczasowa;       // do b wkładamy odłożoną wartość

Console.WriteLine($"Po:    a = {a}, b = {b}");

Trzecia zmienna jest konieczna. Gdybyś napisał od razu a = b;, pierwotna wartość a zostałaby nadpisana i przepadła bezpowrotnie — nie byłoby już czego włożyć do b.

To klasyczne zadanie na rozmowach o pracę. Warto rozumieć, dlaczego kolejność ma tu znaczenie.

ZAD 3Usuń magiczne liczby★★☆

Poniższy program działa, ale jest nieczytelny. Zamień liczby wpisane wprost na nazwane stałe i dodaj komentarze tam, gdzie naprawdę są potrzebne.

do poprawienia
double p = 249.0;
double w = p * 0.23;
double c = p + w;
double k = c * 0.9;
Console.WriteLine(k);
pokaż rozwiązanie
const double StawkaVat = 0.23;
const double MnoznikPoRabacie = 0.9;   // rabat 10% = zapłata 90% ceny

double cenaNetto = 249.0;
double podatek = cenaNetto * StawkaVat;
double cenaBrutto = cenaNetto + podatek;
double doZaplaty = cenaBrutto * MnoznikPoRabacie;

Console.WriteLine($"Do zaplaty: {doZaplaty:F2} zl");

Ta sama arytmetyka, ale teraz kod tłumaczy się sam. Nazwy p, w, c, k nie mówiły nic — po tygodniu ich autor też by już nie wiedział, co znaczą.

Komentarz jest tylko jeden i jest w miejscu, w którym naprawdę pomaga: wyjaśnia, dlaczego rabat 10% zapisujemy jako mnożnik 0,9. Reszta linii komentarza nie potrzebuje.

ZAD 4Przewidz wynik★★☆

Nie uruchamiając programu, zapisz na kartce, co wypisze. Dopiero potem sprawdź w Visual Studio.

co wypisze?
int x = 10;
int y = x;

x = 20;

Console.WriteLine(x);
Console.WriteLine(y);
pokaż rozwiązanie
20
10

Instrukcja int y = x; skopiowała wartość, a nie połączyła zmiennych. Powstały dwa niezależne pudełka: jedno z liczbą 10, drugie też z liczbą 10. Późniejsza zmiana x nie ma już żadnego wpływu na y.

Zapamiętaj ten wynik. W bloku o programowaniu obiektowym zobaczysz, że dla obiektów ta sama instrukcja zachowuje się zupełnie inaczej — i będzie to jedno z ważniejszych zaskoczeń w całym kursie.

ZAD 5Znajdź pięć błędów★★★

W poniższym kodzie jest pięć błędów. Znajdź je wszystkie, nazwij i popraw.

do poprawienia
const double Pi;
int 2liczba = 5;
double cena = 19,99;
string Imie = "Ala";
Console.WriteLine(imie);
int suma;
Console.WriteLine(suma);
pokaż rozwiązanie
const double Pi = 3.14159;   // 1. stała musi dostać wartość od razu
int liczba2 = 5;             // 2. nazwa nie może zaczynać się od cyfry
double cena = 19.99;         // 3. kropka, nie przecinek
string imie = "Ala";         // 4. mała litera — spójnie z użyciem niżej
Console.WriteLine(imie);
int suma = 0;                // 5. zmienna musi mieć wartość przed odczytem
Console.WriteLine(suma);

1. const double Pi; — stałą trzeba zainicjalizować w linii deklaracji.

2. 2liczba — nazwa nie może zaczynać się od cyfry. liczba2 jest poprawne.

3. 19,99 — przecinek jest w C# separatorem argumentów, nie części ułamkowej.

4. Zadeklarowano Imie z wielkiej litery, a odczytano imie z małej — dla kompilatora to dwie różne nazwy, stąd CS0103. Zgodnie z konwencją zmienne lokalne piszemy od małej litery, więc poprawiamy deklarację.

5. int suma; bez wartości, a niżej odczyt — CS0165.

PODSUMOWANIE

Co trzeba zapamiętać

  • Zmienna to nazwane miejsce w pamięci. Ma typ, który ustala się raz i już się nie zmienia.
  • Deklaracja tworzy zmienną, inicjalizacja nadaje pierwszą wartość, przypisanie ją zmienia.
  • Zmiennej lokalnej bez wartości nie wolno odczytać — to błąd kompilacji CS0165, a nie zero.
  • Znak = to nie równość, tylko polecenie „włóż wartość z prawej do pudełka z lewej”.
  • var każe kompilatorowi odczytać typ z wartości. Typ i tak jest ustalany raz i na stałe.
  • const tworzy wartość niezmienną — i, co ważniejsze, nadaje liczbie zrozumiałą nazwę.
  • Wielkość liter ma znaczenie: wiek i Wiek to dwie różne zmienne.
  • Część ułamkową w kodzie zapisujemy kropką, choć na ekranie zobaczymy przecinek.
  • Zmienna żyje tylko w bloku, w którym powstała. Potrzebujesz jej po bloku — zadeklaruj ją przed nim.
  • Komentarz ma wyjaśniać dlaczego, a nie powtarzać to, co i tak widać w kodzie.