Typy proste, zakresy i wartości domyślne
Każda zmienna w C# ma typ, a każdy typ ma swoje granice. Ta lekcja pokazuje, ile miejsca zajmują poszczególne typy, jakie liczby się w nich mieszczą i co się dzieje, gdy się nie zmieszczą. Dowiesz się też, dlaczego 0.1 + 0.2 nie daje dokładnie 0.3.
Czego się dziś nauczysz
- Dobierzesz typ do danych, które program ma przechowywać
- Odczytasz zakres typu za pomocą
MinValueiMaxValue - Wyjaśnisz, co się dzieje po przekroczeniu zakresu
- Wskażesz, kiedy użyć
double, a kiedydecimal - Wyjaśnisz, dlaczego liczb zmiennoprzecinkowych nie porównuje się przez
== - Podasz wartość domyślną każdego z poznanych typów
Po co w ogóle typy
Komputer przechowuje wszystko jako ciągi zer i jedynek. Ten sam zestaw bitów może oznaczać liczbę, literę albo kolor piksela — typ mówi, jak te bity odczytać.
Typ decyduje o trzech rzeczach:
Ile miejsca
Zmienna byte zajmuje 1 bajt, int — 4 bajty, double — 8. Więcej miejsca to szerszy zakres, ale i większe zużycie pamięci.
Jakie wartości
W byte zmieści się liczba od 0 do 255 i ani jedna więcej. W bool — tylko prawda albo fałsz.
Co wolno robić
Liczby można dodawać i mnożyć. Tekst można sklejać i mierzyć jego długość. Kompilator pilnuje, żeby nie mylić jednego z drugim.
Dlaczego to dla ciebie dobre
C# sprawdza typy podczas kompilacji. Jeśli spróbujesz odjąć tekst od liczby, dowiesz się o tym natychmiast, w edytorze. W językach bez tej kontroli taki program uruchomi się i zepsuje dopiero u użytkownika — często w najgorszym możliwym momencie.
Typy liczb całkowitych
Liczby bez części ułamkowej: wiek, liczba uczniów, numer indeksu. Jest ich w C# osiem, ale w praktyce używa się głównie dwóch.
| Typ | Rozmiar | Zakres | Kiedy |
|---|---|---|---|
byte | 1 bajt | 0 … 255 | bajty pliku, składowa koloru |
sbyte | 1 bajt | −128 … 127 | rzadko |
short | 2 bajty | −32 768 … 32 767 | rzadko |
ushort | 2 bajty | 0 … 65 535 | rzadko |
int | 4 bajty | −2 147 483 648 … 2 147 483 647 | domyślny wybór |
uint | 4 bajty | 0 … 4 294 967 295 | rzadko |
long | 8 bajtów | około ±9,2 × 1018 | gdy int za mały |
ulong | 8 bajtów | 0 … około 1,8 × 1019 | rzadko |
W praktyce: używaj int
Typy short czy byte oszczędzają pamięć, ale przy dzisiejszych komputerach ta oszczędność jest zwykle bez znaczenia, a kod staje się trudniejszy. Domyślnie bierz int. Sięgnij po long, gdy liczby mogą przekroczyć dwa miliardy — na przykład przy liczeniu milisekund albo bajtów dużego pliku.
Typy bez znaku (uint, ulong) wyglądają kusząco przy wartościach, które nie mogą być ujemne, ale sprawiają kłopoty przy odejmowaniu. Nie używaj ich bez potrzeby.
Przyrostki literałów
Liczba wpisana w kod jest domyślnie typu int. Jeśli chcesz inny typ, dopisujesz literę:
int zwykla = 42; // bez przyrostka = int
long duza = 9000000000L; // L, bo liczba nie mieści się w int
uint bezZnaku = 3000000000U; // U
// Bez L byłby błąd — kompilator próbowałby zmieścić to w int:
// long zle = 9000000000; // CS1021: liczba całkowita jest za duża
Co się dzieje po przekroczeniu zakresu
To zachowanie zaskakuje wiele osób. Liczba nie zgłasza błędu — ona się „przekręca”, jak licznik przebiegu w starym samochodzie.
int maksimum = int.MaxValue; // 2 147 483 647
Console.WriteLine(maksimum);
maksimum = maksimum + 1; // dodajemy jeden...
Console.WriteLine(maksimum); // ...i lądujemy na samym dole zakresu
2147483647
-2147483648
Program się nie zatrzyma, tylko poda złą liczbę
To jeden z podstępniejszych błędów: nic nie wybucha, nie ma czerwonego komunikatu, program po prostu liczy dalej na błędnych danych. Dlatego dobierając typ, warto od razu pomyśleć, jak duże wartości mogą się w nim pojawić.
Można kazać C# pilnować przekroczeń słowem checked — wtedy zamiast przekręcenia dostaniesz wyjątek OverflowException. Do wyjątków wrócimy w bloku 8.
Typy liczb z częścią ułamkową
| Typ | Rozmiar | Dokładność | Przyrostek | Do czego |
|---|---|---|---|---|
float | 4 bajty | około 6–9 cyfr | f | grafika, gry — gdy liczy się pamięć |
double | 8 bajtów | około 15–17 cyfr | brak | obliczenia domyślnie |
decimal | 16 bajtów | 28–29 cyfr | m | pieniądze |
float maly = 3.14f; // f jest konieczne
double zwykly = 3.14; // bez przyrostka = double
decimal cena = 19.99m; // m jest konieczne (od ang. money)
// double srednia = 4.5f; // to zadziała, ale traci sens
// decimal zle = 19.99; // CS0664 — bez m to literał double
Problem, który musisz znać: 0.1 + 0.2
double a = 0.1 + 0.2;
Console.WriteLine(a); // 0,30000000000000004
Console.WriteLine(a == 0.3); // False
decimal b = 0.1m + 0.2m;
Console.WriteLine(b); // 0,3
Console.WriteLine(b == 0.3m); // True
Skąd to się bierze
Typy float i double zapisują liczby w systemie dwójkowym. Ułamek 0,1 w systemie dwójkowym jest nieskończony — dokładnie tak, jak 1/3 w systemie dziesiętnym daje 0,3333… Komputer musi gdzieś uciąć, więc zapisuje wartość bardzo bliską 0,1, ale nie dokładnie równą.
Przy jednym działaniu różnica jest niewidoczna. Przy tysiącu działań na kwotach potrafi urosnąć do złotówek.
Typ decimal liczy w systemie dziesiętnym, więc ułamki dziesiętne zapisuje dokładnie. Jest za to wolniejszy i zajmuje dwa razy więcej miejsca.
Zasada nie do podważenia: pieniądze zawsze w decimal
Ceny, salda, kwoty faktur, wypłaty — wszystko, co ktoś potem policzy i porówna ze stanem konta. Użycie double do pieniędzy to klasyczny błąd, który w prawdziwych systemach kosztował już bardzo dużo.
Do wszystkiego innego — pomiarów, średnich, obliczeń fizycznych i geometrycznych — double jest właściwym wyborem.
Jak porównywać liczby z przecinkiem
Skoro double bywa niedokładny, porównanie przez == jest zawodne. Zamiast tego sprawdzamy, czy liczby są dostatecznie blisko siebie:
double a = 0.1 + 0.2;
double b = 0.3;
// ✗ Zawodne
Console.WriteLine(a == b); // False
// ✓ Porównanie z tolerancją
double tolerancja = 0.000001;
bool saRowne = Math.Abs(a - b) < tolerancja;
Console.WriteLine(saRowne); // True
Math.Abs zwraca wartość bezwzględną, czyli „odległość od zera”. Dzięki temu nie musimy sprawdzać, która liczba jest większa — interesuje nas sama różnica.
Typ znakowy, logiczny i tekstowy
char — pojedynczy znak
char litera = 'A'; // APOSTROFY, nie cudzysłów
char cyfra = '7'; // to znak, nie liczba siedem
char polska = 'ł';
char spacja = ' ';
// Każdy znak ma swój numer w tablicy Unicode
Console.WriteLine((int)litera); // 65
Console.WriteLine((int)polska); // 322
Apostrofy kontra cudzysłów
'A' to znak typu char. "A" to tekst typu string, który akurat ma długość jeden. To dwa różne typy i nie można ich mieszać.
W apostrofach musi być dokładnie jeden znak: 'Ab' to błąd kompilacji.
bool — prawda albo fałsz
bool czyPelnoletni = true;
bool czyZdal = false;
// Najczęściej wartość logiczna powstaje z porównania
int wiek = 20;
bool moznaGlosowac = wiek >= 18; // true
Console.WriteLine(moznaGlosowac); // True
W C# zero to nie fałsz
W językach C i C++ liczba 0 znaczy „fałsz”, a każda inna „prawda”. W C# tak nie jest. Zapis if (liczba) to błąd kompilacji — warunek musi być typu bool, więc trzeba napisać if (liczba != 0).
To celowe utrudnienie: chroni przed klasyczną pomyłką, w której if (x = 5) zamiast if (x == 5) po cichu zmienia wartość zamiast ją sprawdzić.
string — tekst
string imie = "Anna";
string puste = ""; // tekst o długości zero
string nic = null; // brak jakiegokolwiek tekstu — to nie to samo!
Console.WriteLine(imie.Length); // 4
Console.WriteLine(puste.Length); // 0
// Console.WriteLine(nic.Length); // wysypie program — nie ma czego mierzyć
string różni się od pozostałych typów z tej lekcji: nie ma stałego rozmiaru i jest typem referencyjnym. Co to znaczy w praktyce, dokładnie wyjaśnimy w bloku 7. Na razie zapamiętaj jedną konsekwencję: tylko string może przyjąć wartość null.
Wartości domyślne
Każdy typ ma wartość, którą przyjmuje, gdy nikt nie podał innej.
| Typ | Wartość domyślna | Uwaga |
|---|---|---|
int, long, byte, short | 0 | — |
double, float, decimal | 0 | — |
bool | false | — |
char | '\0' | znak pusty, nie spacja |
string | null | brak tekstu, a nie tekst pusty |
Uwaga: to nie dotyczy zmiennych lokalnych
Wartości domyślne dostają pola klas i elementy tablic. Zmienna lokalna w metodzie nie dostaje nic — i kompilator nie pozwoli jej odczytać, dopóki czegoś do niej nie włożysz. Wracaliśmy do tego w lekcji 04; to błąd CS0165.
Jeśli potrzebujesz wartości domyślnej wprost, służy do tego słowo default:
int liczba = default; // 0
bool flaga = default; // false
string tekst = default; // null
Console.WriteLine(liczba); // 0
Console.WriteLine(flaga); // False
Co dokładnie robi każdy użyty element
| Element | Zwraca | Działanie |
|---|---|---|
int.MinValueint.MaxValue | int |
Stałe wbudowane w typ. Podają najmniejszą i największą wartość, jaka się w nim mieści. Ma je każdy typ liczbowy: byte.MaxValue, double.MinValue i tak dalej. |
Math.Abs(x) | ten sam typ co x |
Wartość bezwzględna — usuwa znak minus. Math.Abs(-7) daje 7. Klasa Math jest statyczna, więc nie tworzy się jej obiektu. |
Math.Round(x, n) | double lub decimal |
Zaokrągla x do n miejsc po przecinku. |
sizeof(typ) | int |
Podaje, ile bajtów zajmuje typ prosty. sizeof(int) daje 4. |
(int)znak | int |
Rzutowanie — nawias z nazwą typu przed wartością każe potraktować ją jako inny typ. Dla char daje numer znaku w tablicy Unicode. |
double.IsNaN(x) | bool |
Sprawdza, czy wynik jest „nie-liczbą” (ang. Not a Number) — tak oznaczany jest np. rezultat dzielenia 0,0 przez 0,0. |
x.GetType().Name | string |
Zwraca nazwę typu wartości x. Przydatne, gdy chcesz sprawdzić, co naprawdę wywnioskował kompilator z var. |
Program, który pokazuje granice typów
Console.WriteLine("=== ROZMIARY I ZAKRESY ===");
Console.WriteLine($"byte: {sizeof(byte)} B od {byte.MinValue} do {byte.MaxValue}");
Console.WriteLine($"int: {sizeof(int)} B od {int.MinValue} do {int.MaxValue}");
Console.WriteLine($"long: {sizeof(long)} B od {long.MinValue} do {long.MaxValue}");
Console.WriteLine($"double: {sizeof(double)} B");
Console.WriteLine();
Console.WriteLine("=== PRZEKROCZENIE ZAKRESU ===");
byte licznik = 255;
Console.WriteLine($"licznik = {licznik}");
licznik = (byte)(licznik + 1);
Console.WriteLine($"po dodaniu 1: {licznik}");
Console.WriteLine();
Console.WriteLine("=== DOKLADNOSC ===");
double wynikDouble = 0.1 + 0.2;
decimal wynikDecimal = 0.1m + 0.2m;
Console.WriteLine($"double: {wynikDouble}");
Console.WriteLine($"decimal: {wynikDecimal}");
Console.WriteLine();
Console.WriteLine("=== CO WYWNIOSKOWAL KOMPILATOR ===");
var a = 42;
var b = 42.5;
var c = 42.5m;
var d = '4';
Console.WriteLine($"42 -> {a.GetType().Name}");
Console.WriteLine($"42.5 -> {b.GetType().Name}");
Console.WriteLine($"42.5m -> {c.GetType().Name}");
Console.WriteLine($"'4' -> {d.GetType().Name}");
=== ROZMIARY I ZAKRESY ===
byte: 1 B od 0 do 255
int: 4 B od -2147483648 do 2147483647
long: 8 B od -9223372036854775808 do 9223372036854775807
double: 8 B
=== PRZEKROCZENIE ZAKRESU ===
licznik = 255
po dodaniu 1: 0
=== DOKLADNOSC ===
double: 0,30000000000000004
decimal: 0,3
=== CO WYWNIOSKOWAL KOMPILATOR ===
42 -> Int32
42.5 -> Double
42.5m -> Decimal
'4' -> Char
Omówienie
| Fragment | Dlaczego tak |
|---|---|
licznik = (byte)(licznik + 1); |
Rzutowanie jest tu konieczne. Dodawanie dwóch bajtów daje w C# wynik typu int, a takiego nie da się bez pytania wcisnąć z powrotem do zmiennej byte. Nawias (byte) mówi: „wiem, co robię”. |
Wynik 0 zamiast 256 |
Liczba 256 nie mieści się w bajcie, więc wartość przekręciła się na początek zakresu. Program nie zgłosił żadnego problemu — to właśnie czyni ten błąd niebezpiecznym. |
0,30000000000000004 |
Zapis dwójkowy nie potrafi dokładnie przedstawić ułamka 0,1. Dla decimal, który liczy dziesiętnie, problem nie występuje. |
Int32, Double… |
To prawdziwe nazwy typów w bibliotece .NET. int jest skrótem na System.Int32, double na System.Double. Obu zapisów można używać zamiennie, ale w kodzie C# przyjęło się pisać krótkie. |
sizeof(double) bez zakresu |
Zakres typów zmiennoprzecinkowych podaje się przez rząd wielkości, a nie przez dokładne liczby — ich MinValue to gigantyczna wartość ujemna, nieczytelna na ekranie. |
Na co uważać
1. Dzielenie liczb całkowitych ucina resztę
int suma = 7;
int ile = 2;
double srednia = suma / ile; // ✗ 3, a nie 3,5!
Console.WriteLine(srednia); // 3
double poprawna = (double)suma / ile; // ✓ 3,5
Console.WriteLine(poprawna); // 3,5
To najczęstszy błąd w całym bloku podstaw. Dzielenie int przez int daje int — reszta jest odrzucana, zanim wynik trafi do zmiennej double. Wystarczy zamienić na double jedną ze stron, żeby całe działanie policzyło się dokładnie.
2. Zapomniany przyrostek
| Kod | Problem |
|---|---|
float x = 3.14; | CS0664 — 3.14 to literał double, który nie zmieści się w float. Poprawnie: 3.14f. |
decimal c = 19.99; | CS0664 — potrzebny przyrostek m. |
long x = 9000000000; | CS1021 — bez L kompilator próbuje zmieścić liczbę w int. |
3. Pozostałe pułapki
| Kod | Problem |
|---|---|
char c = "A"; | Cudzysłów zamiast apostrofów — to string, nie char. |
if (liczba) | W C# warunek musi być typu bool. Poprawnie: if (liczba != 0). |
if (a == b) dla double | Kompiluje się, ale bywa zawodne. Porównuj przez Math.Abs(a - b) < tolerancja. |
double cena = 19.99; dla pieniędzy | Działa, ale po wielu operacjach zgubi grosze. Kwoty trzymamy w decimal. |
int wiek = 17.5; | CS0266 — typ całkowity nie przyjmie ułamka. Trzeba rzutować i pogodzić się z utratą części ułamkowej. |
string s = 'A'; | CS0029 — pojedynczy znak nie jest tekstem. Poprawnie "A". |
Zadania
Dla każdej informacji wybierz najodpowiedniejszy typ i uzasadnij wybór: liczba uczniów w klasie, cena produktu w sklepie, ocena z przedmiotu, informacja czy uczeń jest obecny, pierwsza litera nazwiska, liczba mieszkańców Ziemi, numer PESEL.
pokaż rozwiązanie
| Informacja | Typ | Dlaczego |
|---|---|---|
| liczba uczniów w klasie | int | Liczba całkowita, mała. byte też by wystarczył, ale int jest wygodniejszy w działaniach. |
| cena produktu | decimal | To pieniądze. Zawsze decimal. |
| ocena z przedmiotu | int lub double | int dla ocen całkowitych, double jeśli dopuszczamy 4,5. |
| czy uczeń obecny | bool | Dwa możliwe stany. |
| pierwsza litera nazwiska | char | Dokładnie jeden znak. |
| liczba mieszkańców Ziemi | long | Ponad 8 miliardów — int kończy się na 2,1 miliarda. |
| numer PESEL | string | To pułapka. Mimo że składa się z cyfr, PESEL to identyfikator, nie liczba. Nie wykonuje się na nim działań, a wiodące zero zniknęłoby w typie liczbowym. |
Ostatni punkt to reguła warta zapamiętania: jeśli na czymś nie wykonujesz działań matematycznych, to nie jest liczba — nawet gdy składa się z cyfr. Dotyczy to numerów telefonów, kodów pocztowych i numerów kont.
Napisz program, który wypisze rozmiar w bajtach oraz wartość najmniejszą i największą dla typów byte, short, int i long. Sformatuj wynik w kolumny.
pokaż rozwiązanie
Console.WriteLine("Typ Bajty Min Max");
Console.WriteLine(new string('-', 62));
Console.WriteLine($"byte {sizeof(byte),5}{byte.MinValue,24}{byte.MaxValue,22}");
Console.WriteLine($"short {sizeof(short),5}{short.MinValue,24}{short.MaxValue,22}");
Console.WriteLine($"int {sizeof(int),5}{int.MinValue,24}{int.MaxValue,22}");
Console.WriteLine($"long {sizeof(long),5}{long.MinValue,24}{long.MaxValue,22}");
Liczba po przecinku w klamrach to wyrównanie: {sizeof(byte),5} rezerwuje 5 znaków i dosuwa wartość do prawej. Ujemna liczba, na przykład {tekst,-8}, dosuwałaby do lewej.
new string('-', 60) tworzy napis złożony z sześćdziesięciu myślników — wygodniejsze niż przepisywanie ich ręcznie.
Zapisz na kartce, co wypisze każda linia. Dopiero potem uruchom program i porównaj.
Console.WriteLine(7 / 2);
Console.WriteLine(7.0 / 2);
Console.WriteLine(7 / 2.0);
Console.WriteLine((double)7 / 2);
Console.WriteLine(7 % 2);
Console.WriteLine(1 / 3 * 3);
pokaż rozwiązanie
3
3,5
3,5
3,5
1
0
Linia 1 — dwie liczby całkowite, więc dzielenie całkowite: reszta odrzucona.
Linie 2, 3, 4 — wystarczy, że jedna strona jest typu double, a całe działanie liczy się dokładnie. Nieważne która.
Linia 5 — operator % zwraca resztę z dzielenia. 7 podzielone przez 2 to 3 i reszty 1.
Linia 6 — najciekawsza. 1 / 3 daje 0 (dzielenie całkowite), a 0 * 3 to nadal 0. Matematycznie wynik powinien wynosić 1. To pokazuje, że kolejność działań ma znaczenie przy typach całkowitych.
Napisz program, który przechowuje sumę pięciu ocen (liczba całkowita) i oblicza średnią. Wypisz ją z dokładnością do dwóch miejsc po przecinku. Uważaj na dzielenie całkowite.
pokaż rozwiązanie
int ocena1 = 5;
int ocena2 = 4;
int ocena3 = 3;
int ocena4 = 5;
int ocena5 = 4;
int suma = ocena1 + ocena2 + ocena3 + ocena4 + ocena5;
int liczbaOcen = 5;
double srednia = (double)suma / liczbaOcen;
Console.WriteLine($"Suma ocen: {suma}");
Console.WriteLine($"Srednia: {srednia:F2}");
Suma ocen: 21
Srednia: 4,20
Bez rzutowania (double) wynik wyniósłby 4 zamiast 4,2 — suma 21 podzielona całkowicie przez 5 daje 4, a reszta przepada.
Format F2 wymusza dwa miejsca po przecinku, dlatego widzimy 4,20, a nie 4,2.
Napisz program, który pokazuje przekręcenie się wartości dla typu short: wypisz wartość maksymalną, dodaj jeden i wypisz wynik. Następnie wykonaj to samo działanie w bloku checked i opisz, czym się różni zachowanie programu.
pokaż rozwiązanie
short maksimum = short.MaxValue;
Console.WriteLine($"short.MaxValue = {maksimum}");
// Bez kontroli — wartosc sie przekreca
short poDodaniu = (short)(maksimum + 1);
Console.WriteLine($"po dodaniu 1: {poDodaniu}");
// Z kontrola — program zglasza problem
try
{
short zKontrola = checked((short)(maksimum + 1));
Console.WriteLine(zKontrola);
}
catch (OverflowException)
{
Console.WriteLine("checked wykryl przekroczenie zakresu!");
}
short.MaxValue = 32767
po dodaniu 1: -32768
checked wykryl przekroczenie zakresu!
Bez checked program liczy dalej na błędnej wartości i nikt się o tym nie dowiaduje. Z checked zgłaszany jest wyjątek OverflowException, który da się przechwycić i obsłużyć.
Konstrukcja try/catch jest tu użyta zaliczkowo — dokładnie omówimy ją w bloku 8. Na razie wystarczy, że rozumiesz ideę: kod w try jest wykonywany, a jeśli coś pójdzie nie tak, program przeskakuje do catch zamiast się wysypać.
W praktyce checked stosuje się rzadko, bo spowalnia obliczenia. Warto go użyć tam, gdzie błędna liczba miałaby poważne konsekwencje — na przykład w rozliczeniach.
Napisz program, który dodaje wartość 0,01 tysiąc razy — raz w typie double, raz w decimal. Wypisz oba wyniki i porównaj każdy z oczekiwaną wartością 10 za pomocą operatora ==.
pokaż rozwiązanie
double sumaDouble = 0;
decimal sumaDecimal = 0;
for (int i = 0; i < 1000; i++)
{
sumaDouble += 0.01;
sumaDecimal += 0.01m;
}
Console.WriteLine($"double: {sumaDouble}");
Console.WriteLine($"decimal: {sumaDecimal}");
Console.WriteLine();
Console.WriteLine($"double == 10: {sumaDouble == 10}");
Console.WriteLine($"decimal == 10: {sumaDecimal == 10}");
double: 9,999999999999831
decimal: 10,00
double == 10: False
decimal == 10: True
To jest właśnie moment, w którym teoria z tej lekcji staje się namacalna. Tysiąc razy po jednym groszu powinno dać równo 10 złotych — a w typie double zabrakło ułamka grosza.
Wyobraź sobie, że to system kasowy zliczający transakcje przez cały dzień. Po tysiącach operacji różnica przestaje być teoretyczna, a raport kasowy nie zgadza się ze stanem kasy.
Pętli for jeszcze nie omawialiśmy — poznasz ją w bloku 3. Tutaj wystarczy wiedzieć, że powtarza ona instrukcję w środku tysiąc razy.
Co trzeba zapamiętać
- Typ decyduje o rozmiarze, zakresie i dozwolonych operacjach.
- Do liczb całkowitych domyślnie
int;long, gdy wartości przekraczają dwa miliardy. - Do obliczeń
double. Do pieniędzy zawszedecimalz przyrostkiemm. - Po przekroczeniu zakresu wartość przekręca się bez ostrzeżenia — program liczy dalej na złych danych.
doublezapisuje ułamki w systemie dwójkowym, więc0.1 + 0.2nie daje dokładnie0.3.- Liczb zmiennoprzecinkowych nie porównuj przez
==, tylko przezMath.Abs(a - b) < tolerancja. - Dzielenie
intprzezintucina resztę. Rzutuj jedną stronę nadouble. charzapisujemy w apostrofach,stringw cudzysłowie.- W C# zero nie znaczy „fałsz” — warunek musi być typu
bool. - Wartości domyślne dostają pola klas i elementy tablic. Zmienne lokalne nie — te trzeba zainicjalizować samemu.