Składnia i system typów C#
Średniki, klamry, stos vs sterta i parsowanie. Pierwszy krok w C# z interaktywnym quizem i mini-zadaniem na koniec.
C# pochodzi z rodziny języków, w których kompilator pilnuje ci typów zanim w ogóle uruchomisz program. Dzięki temu wiele błędów łapie się przy kompilacji, a nie w nocy na produkcji. Zanim jednak coś napiszesz, musisz znać reguły gry.
1. Podstawowa składnia (zasady gry) #
C# jest:
- silnie typowany - każda zmienna ma określony typ i tego typu nie da się zignorować
- wrażliwy na wielkość liter (case sensitive) -
Zmiennaizmiennato dwie różne rzeczy
Najważniejsze zasady składniowe #
- Średniki (
;) - każda instrukcja kończy się średnikiem. Jak kropka na końcu zdania. - Nawiasy klamrowe (
{ }) - określają “zasięg” (scope) kodu. Zamykają w sobie klasy, metody, pętle, bloki warunkowe. - Komentarze:
//- komentarz w jednej linii/* ... */- komentarz wielolinijkowy/// <summary> ... </summary>- komentarz dokumentacyjny (Visual Studio i Rider potem podpowiadają je w tooltipach)
Nowoczesny C# (top-level statements) #
W starszych wersjach C# do wypisania jednej linii w konsoli potrzebowałeś klasy Program, metody Main, importów. Od .NET 6+ plik startowy może wyglądać tak:
Console.WriteLine("Witaj świecie C#!");
Kompilator sam owinie ten kod w niewidoczną metodę Main. Wygodne na początku - mniej szumu wokół tego, co chcesz pokazać.
2. Popularne typy danych #
Zanim utworzysz zmienną, musisz powiedzieć kompilatorowi, jakiego rodzaju dane będzie przechowywać.
| Typ | Co trzyma | Przykład |
|---|---|---|
int | liczby całkowite | 10, -5 |
long | duże liczby całkowite | 9_000_000_000L |
double | liczby zmiennoprzecinkowe (ułamki) | 3.14 |
decimal | ułamki precyzyjne (finanse!) | 19.99m |
bool | wartości logiczne | true / false |
char | pojedynczy znak (apostrofy!) | 'A' |
string | tekst (cudzysłowy!) | "Witaj" |
Dlaczego decimal do pieniędzy, a nie double? #
double przechowuje liczby binarnie i niektóre ułamki dziesiętne (np. 0.1) reprezentuje niedokładnie. Po setce dodawań możesz dostać 9.99999999998 zamiast 10. W matematyce nieistotne, w księgowości - katastrofa. decimal jest wolniejszy, ale dziesiętnie dokładny.
Słowo kluczowe var #
Zamiast jawnie pisać typ, możesz pozwolić by C# wywnioskował go z prawej strony przypisania:
int age = 25; // jawna deklaracja
var name = "Jan"; // kompilator wie, że to string
var pi = 3.14; // double
Uwaga: var to nadal silne typowanie - typ jest ustalony przy kompilacji, tylko nie musisz go wypisywać. To nie jest dynamic typing jak w Pythonie.
Typy nullable (?) #
Domyślnie zmienne typów wartościowych nie mogą być null. Jeśli chcesz móc je tak ustawić, dodajesz ?:
int age = null; // BŁĄD kompilacji
int? age = null; // OK - age może mieć wartość albo być null
3. System typów: wartościowe vs referencyjne #
To najważniejsza koncepcja w tym rozdziale. Typy w C# dzielą się na dwie rodziny zachowujące się zupełnie inaczej w pamięci.
Typy wartościowe (value types) #
- Gdzie żyją: na stosie (Stack) - szybka, uporządkowana pamięć
- Jak działają: przechowują bezpośrednio swoją wartość. Przypisanie do innej zmiennej tworzy niezależną kopię.
- Kto należy:
int,double,bool,char,decimal, struktury (struct), wyliczenia (enum)
int a = 10;
int b = a; // b dostaje KOPIĘ wartości a
b = 20; // zmieniamy b
// a nadal wynosi 10
Typy referencyjne (reference types) #
- Gdzie żyją: dane na stercie (Heap), a na stosie trzymany jest tylko adres wskazujący na to miejsce
- Jak działają: zmienna trzyma adres do wartości, nie samą wartość. Przypisanie kopiuje adres - obie zmienne wskazują na to samo miejsce w pamięci.
- Kto należy:
string, tablice, klasy (class), delegaty,object
int[] arrayA = { 1, 2, 3 };
int[] arrayB = arrayA; // kopiowany jest ADRES, nie zawartość
arrayB[0] = 99;
// arrayA[0] też wynosi 99 - to to samo miejsce w pamięci
Wyjątek: string #
string jest referencyjny, ale zachowuje się jakby był wartościowy, ponieważ jest niemutowalny (immutable). Każda zmiana tekstu tworzy nowy obiekt w pamięci - oryginalny string nie zostanie podmieniony “pod nogami” innej zmiennej.
string a = "Witaj";
string b = a;
b = "Cześć"; // powstał NOWY string, a nadal pokazuje "Witaj"
4. Konwersje typów (rzutowanie) #
Czasem trzeba zamienić jeden typ na inny - np. tekst od użytkownika na liczbę.
Konwersja niejawna (bezpieczna) #
C# robi ją sam, gdy nie ma ryzyka utraty danych. Mała liczba całkowita wpasuje się w większy worek na liczby z ułamkiem:
int smallNumber = 100;
double bigNumber = smallNumber; // C# ogarnie to automatycznie
Konwersja jawna (rzutowanie / casting) #
Gdy istnieje ryzyko utraty danych (obcięcie po przecinku, przekroczenie zakresu), musisz to zrobić siłą używając nawiasów (typ):
double pi = 3.14;
int approximation = (int)pi; // wynik: 3 (część po przecinku ucięta!)
Parsowanie tekstu na liczbę #
Console.ReadLine() zawsze zwraca string. Musisz go przerobić na liczbę. Masz dwie drogi:
Parse - działa, ale wywala wyjątek (FormatException) jeśli tekst nie jest liczbą:
string ageInput = "30";
int age = int.Parse(ageInput); // OK
string trash = "trzydzieści";
int parsed = int.Parse(trash); // EXPLODES! program się wykrzaczy
TryParse - bezpieczna wersja. Zwraca bool (czy się udało) i zapisuje wynik przez parametr out:
string ageInput = Console.ReadLine();
if (int.TryParse(ageInput, out int age))
{
Console.WriteLine($"Twój wiek to {age}");
}
else
{
Console.WriteLine("To nie jest liczba!");
}
Reguła: gdy dane przychodzą z zewnątrz (użytkownik, plik, sieć) → zawsze TryParse. Gdy parsujesz coś, co na pewno jest liczbą (np. hardkodowany string w teście) → Parse jest OK.
Podsumowanie tematu #
W tej części złapałeś:
- Składnię - średniki, klamry, komentarze, top-level statements
- Typy danych - kiedy
int, kiedydecimal, czym jestvar, jak działa? - Stos vs sterta - najważniejsze rozróżnienie: kopia wartości vs współdzielony adres
- Konwersje - bezpieczne (niejawne), wymuszone (cast), i
ParsevsTryParse
Teraz sprawdź się w quizie poniżej, a potem zmierz się z mini-zadaniem - oba otworzą się w osobnym oknie.
Podobne wpisy
LINQ w C# - lambdy, Where, Select i leniwa ewaluacja
Wyrażenia lambda, operator zapytań LINQ, łączenie metod w łańcuchy oraz pułapka leniwej ewaluacji - jak filtrować, sortować i przekształcać kolekcje jednym, czytelnym łańcuchem wywołań. Czwarta część kursu C#.
Generyki i kolekcje w C# - List, Dictionary, ograniczenia typów
Dlaczego powstały generyki, jak działają List i Dictionary od podszewki oraz jak pisać własne bezpieczne kontenery z ograniczeniami where. Trzecia część kursu C#.
Programowanie obiektowe w C# - klasy, dziedziczenie, polimorfizm
Klasy i obiekty, hermetyzacja przez właściwości, dziedziczenie z virtual/override, polimorfizm w praktyce i interfejsy jako kontrakty. Druga część kursu C#.
🔗 Linkują tu