Konwersje typów
Użytkownik wpisuje z klawiatury tekst, a ty potrzebujesz liczby. Obliczenie daje ułamek, a ty chcesz liczbę całkowitą. Ta lekcja pokazuje, jak zamieniać jeden typ na drugi — i jak nie stracić przy tym danych ani nie wywrócić programu.
Czego się dziś nauczysz
- Wyjaśnisz, kiedy konwersja dzieje się sama, a kiedy trzeba o nią poprosić
- Zapiszesz rzutowanie i wskażesz, jakie dane przy nim tracisz
- Zamienisz tekst na liczbę metodą
ParseiTryParse - Wyjaśnisz, dlaczego
TryParsejest bezpieczniejsze - Zamienisz liczbę na tekst i nadasz jej format
- Wskażesz różnicę między
Parse,TryParsea klasąConvert
Po co w ogóle konwersje
C# pilnuje typów bardzo rygorystycznie. Nie pozwoli włożyć tekstu do zmiennej liczbowej ani wykonać działania na niepasujących typach.
string wiekTekst = "17";
// int rok = 2026 - wiekTekst;
// └── CS0019: nie można odjąć tekstu od liczby
Program musi więc najpierw przekształcić napis "17" w liczbę 17. Taka zamiana jednego typu w drugi to konwersja.
To nie jest to samo, co „zmiana typu zmiennej”
Typu istniejącej zmiennej nie da się zmienić — on jest ustalony raz na zawsze. Konwersja tworzy nową wartość innego typu na podstawie starej. Oryginał zostaje nietknięty.
W C# konwersje dzielą się na dwie grupy: te, które kompilator wykona sam, i te, o które musisz poprosić.
Konwersja niejawna — dzieje się sama
Gdy nowy typ jest „szerszy” od starego i na pewno pomieści każdą wartość, kompilator wykonuje konwersję bez pytania. Nic nie może się zgubić, więc nie ma o czym dyskutować.
int liczba = 42;
long dluga = liczba; // int → long zawsze bezpieczne
double ulamek = liczba; // int → double zawsze bezpieczne
decimal kwota = liczba; // int → decimal zawsze bezpieczne
byte maly = 200;
int wiekszy = maly; // byte → int zawsze bezpieczne
Console.WriteLine($"{dluga} {ulamek} {kwota} {wiekszy}"); // 42 42 42 200
Kierunki, w których konwersja jest automatyczna
byte → short → int → long → float → double
↓ ↓
└────────┴──→ decimal
char → int (i dalej jak wyżej)
| Zasada | Wyjaśnienie |
|---|---|
| Węższy w szerszy — tak | Każda liczba typu int zmieści się w long. Nie ma ryzyka. |
| Całkowity w zmiennoprzecinkowy — tak | int wchodzi do double i decimal automatycznie. |
Zmiennoprzecinkowy w decimal — nie | double ma szerszy zakres niż decimal, więc automatu nie ma. Trzeba rzutować. |
decimal w double — nie | Straciłbyś dokładność, na której właśnie zależało. Trzeba rzutować świadomie. |
Cokolwiek na string — nie | Tekst to zupełnie inna kategoria. Służą do tego metody, nie rzutowanie. |
Bezpieczne nie znaczy dokładne
int → float jest automatyczne, bo każda liczba int mieści się w zakresie float. Ale float ma tylko około 7 cyfr znaczących, więc bardzo duże liczby całkowite tracą precyzję:
int duza = 16777217; po zamianie na float i z powrotem daje 16777216.
Dlatego do liczb całkowitych, które mają zostać dokładne, nie używa się float.
Rzutowanie — gdy coś może się zgubić
Gdy nowy typ jest węższy, kompilator odmawia współpracy. Musisz sam potwierdzić, że wiesz, co robisz — służy do tego rzutowanie: nazwa typu w nawiasie przed wartością.
double cena = 123.87;
// int calkowita = cena; // CS0266 — kompilator odmawia
int calkowita = (int)cena; // ✓ prosimy wprost
Console.WriteLine(calkowita); // 123 — część ułamkowa UCIĘTA, nie zaokrąglona
Rzutowanie ucina, nie zaokrągla
(int)123.87 daje 123, a nie 124. Rzutowanie po prostu odrzuca wszystko po przecinku, niezależnie od tego, jak blisko było do następnej liczby. (int)0.99 daje zero.
Jeśli chcesz zaokrąglić, użyj Math.Round — a dopiero potem rzutuj: (int)Math.Round(123.87) daje 124.
Zawężanie liczb całkowitych
int mala = 200;
byte b1 = (byte)mala; // 200 — mieści się, wszystko dobrze
Console.WriteLine(b1); // 200
int duza = 300;
byte b2 = (byte)duza; // 300 NIE mieści się w bajcie!
Console.WriteLine(b2); // 44 — i nikt nie ostrzega
Skąd 44? Bajt mieści liczby 0–255, więc 300 „przekręca się” o pełny zakres: 300 − 256 = 44. To ten sam mechanizm, który poznałeś w lekcji 06.
Rzutowanie to obietnica, którą składasz kompilatorowi
Pisząc (byte), mówisz: „sprawdziłem, ta wartość się zmieści”. Kompilator ci wierzy i przestaje pilnować. Jeśli obietnica była fałszywa, dostaniesz cichy, błędny wynik — bez żadnego komunikatu.
Dlatego przed rzutowaniem warto sprawdzić zakres albo użyć słowa checked, które zamienia ciche przekręcenie w wyjątek.
Liczba na tekst — zawsze się udaje
To najprostszy kierunek. Każda wartość w C# potrafi opisać się tekstem metodą ToString().
int liczba = 42;
double ulamek = 3.14159;
bool flaga = true;
string t1 = liczba.ToString(); // "42"
string t2 = ulamek.ToString(); // "3,14159"
string t3 = flaga.ToString(); // "True"
// Z formatem
string t4 = ulamek.ToString("F2"); // "3,14"
// Najczęściej i tak używamy interpolacji — ona wywołuje ToString za nas
Console.WriteLine($"{liczba} {ulamek:F2} {flaga}"); // 42 3,14 True
Wartość logiczna zamienia się na "True" lub "False"
Z wielkiej litery i po angielsku — tak zdefiniowano to w bibliotece .NET. Jeśli chcesz pokazać użytkownikowi „tak” i „nie”, musisz to zrobić sam, instrukcją warunkową. Poznasz ją w następnym bloku.
Tekst na liczbę — tu bywa trudno
Ten kierunek jest ryzykowny, bo nie każdy tekst da się zamienić na liczbę. Co ma zrobić program, gdy dostanie "abc" albo pusty napis? C# daje dwie odpowiedzi na to pytanie.
Sposób 1: Parse — przerywa program przy błędzie
string tekst = "123";
int liczba = int.Parse(tekst);
Console.WriteLine(liczba + 1); // 124
// A gdy tekst nie jest liczbą:
string zly = "sto dwadziescia trzy";
// int x = int.Parse(zly); // FormatException — program się wywraca
Sposób 2: TryParse — mówi, czy się udało
string tekst = "123";
bool sukces = int.TryParse(tekst, out int wynik);
Console.WriteLine(sukces); // True
Console.WriteLine(wynik); // 123
// Przy błędnym tekście program działa dalej
bool sukces2 = int.TryParse("abc", out int wynik2);
Console.WriteLine(sukces2); // False
Console.WriteLine(wynik2); // 0 — wartość domyślna, bo konwersja się nie udała
Co robi słowo out
TryParse musi zwrócić dwie informacje naraz: czy się udało oraz jaki jest wynik. Metoda potrafi zwrócić tylko jedną wartość, więc druga jest przekazywana przez parametr oznaczony słowem out.
Zapis out int wynik jednocześnie deklaruje zmienną i przekazuje ją do metody, żeby ta mogła ją wypełnić. Po wywołaniu zmienna wynik jest dostępna w twoim kodzie. Do parametrów out wrócimy dokładniej w bloku o metodach.
Które wybrać
| Metoda | Gdy tekst jest błędny | Kiedy używać |
|---|---|---|
int.Parse(t) |
przerywa program wyjątkiem | Gdy masz pewność, że tekst jest poprawny — np. pochodzi z twojego własnego kodu, nie od użytkownika. |
int.TryParse(t, out x) |
zwraca false, program działa dalej |
Zawsze przy danych od użytkownika, z pliku albo z sieci — czyli wszędzie tam, gdzie błąd jest normalną możliwością. |
Zasada na cały kurs
Cokolwiek wpisuje użytkownik — TryParse. Nie dlatego, że Parse jest złe, tylko dlatego, że użytkownik prędzej czy później wpisze coś nieoczekiwanego, a program nie powinien się od tego wywracać.
Pozostałe typy działają tak samo
double.TryParse("3,14", out double d); // przecinek — polskie ustawienia
decimal.TryParse("19,99", out decimal m);
bool.TryParse("true", out bool b); // działa też "True", "TRUE"
long.TryParse("9000000000", out long l);
Przecinek czy kropka?
double.TryParse patrzy na ustawienia regionalne systemu. Na polskim Windowsie separatorem części ułamkowej jest przecinek, więc "3,14" zadziała, a "3.14" zostanie odrzucone albo — co gorsza — zrozumiane jako 314.
To bywa źródłem trudnych do znalezienia błędów, zwłaszcza przy czytaniu plików utworzonych na innym komputerze. Jak to opanować, pokazujemy w następnej lekcji, przy okazji formatowania.
Klasa Convert
Trzecia droga: klasa Convert z zestawem metod zamieniających dowolny typ na dowolny inny.
| Metoda | Zwraca | Uwagi |
|---|---|---|
Convert.ToInt32(x) | int | Przyjmuje tekst, liczbę, wartość logiczną. Dla null zwraca 0 zamiast błędu. |
Convert.ToDouble(x) | double | — |
Convert.ToDecimal(x) | decimal | — |
Convert.ToBoolean(x) | bool | Dla liczb: 0 to false, każda inna to true. |
Convert.ToString(x) | string | Z drugim argumentem zamienia liczbę na inny system: Convert.ToString(20, 2) daje "10100". |
// Convert zaokrągla, a rzutowanie ucina — to ważna różnica!
double x = 4.7;
Console.WriteLine((int)x); // 4 — ucięcie
Console.WriteLine(Convert.ToInt32(x)); // 5 — zaokrąglenie
// Convert radzi sobie z brakiem wartości
string brak = null;
Console.WriteLine(Convert.ToInt32(brak)); // 0 — zamiast błędu
| Sposób | Przy błędnym tekście | Przy liczbie z ułamkiem |
|---|---|---|
(int) — rzutowanie | nie dotyczy | ucina część ułamkową |
int.Parse | wyjątek | nie dotyczy |
int.TryParse | zwraca false | nie dotyczy |
Convert.ToInt32 | wyjątek | zaokrągla |
Czego używać w praktyce
Do danych od użytkownika — zawsze TryParse.
Do zamiany liczby na liczbę — rzutowanie, ewentualnie Math.Round plus rzutowanie, gdy chcesz zaokrąglić.
Convert przydaje się głównie tam, gdzie wartość może być pusta, oraz do zamiany systemów liczbowych.
Znak a liczba
Typ char to w gruncie rzeczy liczba — numer znaku w tablicy Unicode. Dlatego konwersje między char a int są bardzo proste.
char litera = 'A';
int kod = litera; // char → int, automatycznie: 65
char zKodu = (char)66; // int → char, rzutowanie: 'B'
Console.WriteLine($"{kod} {zKodu}"); // 65 B
// Następna litera alfabetu
char nastepna = (char)(litera + 1); // 'B'
Console.WriteLine(nastepna);
Znak cyfry to nie jest ta cyfra
Znak '7' ma w tablicy Unicode numer 55, a nie 7. To bardzo częste źródło pomyłek.
char cyfra = '7';
Console.WriteLine((int)cyfra); // 55 ✗ numer znaku, nie wartość
// Sposób 1: odejmujemy numer znaku zera
int wartosc1 = cyfra - '0'; // 55 - 48 = 7 ✓
// Sposób 2: gotowa metoda
int wartosc2 = (int)char.GetNumericValue(cyfra); // 7 ✓
Console.WriteLine($"{wartosc1} {wartosc2}"); // 7 7
Sztuczka z odejmowaniem '0' działa, bo cyfry mają w tablicy Unicode kolejne numery: '0' to 48, '1' to 49, i tak dalej aż do '9' = 57. Odjęcie numeru zera daje więc wartość cyfry.
Paragon — wszystkie konwersje naraz
Program dostaje dane w postaci tekstu (tak, jakby przyszły z formularza), zamienia je na liczby, liczy i wypisuje wynik z powrotem jako tekst.
// Dane „z formularza" — zawsze przychodzą jako tekst
string sztukTekst = "3";
string cenaTekst = "24,99";
string rabatTekst = "abc"; // celowo błędny
const decimal StawkaVat = 0.23m;
// Konwersje z zabezpieczeniem
bool okSztuk = int.TryParse(sztukTekst, out int sztuk);
bool okCena = decimal.TryParse(cenaTekst, out decimal cenaJednostkowa);
bool okRabat = decimal.TryParse(rabatTekst, out decimal rabatProcent);
Console.WriteLine($"Sztuki wczytane: {okSztuk} -> {sztuk}");
Console.WriteLine($"Cena wczytana: {okCena} -> {cenaJednostkowa}");
Console.WriteLine($"Rabat wczytany: {okRabat} -> {rabatProcent}");
Console.WriteLine();
// Obliczenia — sztuk to int, cena to decimal; int wchodzi w decimal automatycznie
decimal netto = sztuk * cenaJednostkowa;
decimal vat = netto * StawkaVat;
decimal brutto = netto + vat;
// Ile pełnych sztuk zmieści się w budżecie 50 zl
decimal budzet = 50m;
int zaBudzet = (int)(budzet / cenaJednostkowa); // rzutowanie UCINA — i o to chodzi
Console.WriteLine($"Netto: {netto,8:F2} zl");
Console.WriteLine($"VAT: {vat,8:F2} zl");
Console.WriteLine($"Brutto: {brutto,8:F2} zl");
Console.WriteLine();
Console.WriteLine($"Za {budzet:F2} zl kupisz {zaBudzet} szt.");
Sztuki wczytane: True -> 3
Cena wczytana: True -> 24,99
Rabat wczytany: False -> 0
Netto: 74,97 zl
VAT: 17,24 zl
Brutto: 92,21 zl
Za 50,00 zl kupisz 2 szt.
Omówienie
| Fragment | Dlaczego tak |
|---|---|
Wszystkie dane jako string |
Tak wygląda rzeczywistość: z klawiatury, z pliku i z formularza dane przychodzą jako tekst. Konwersja jest zawsze pierwszym krokiem. |
TryParse zamiast Parse |
Celowo podaliśmy błędny rabat. Program nie wywrócił się — po prostu zapisał, że konwersja się nie udała, a zmienna dostała zero. |
sztuk * cenaJednostkowa |
int pomnożony przez decimal daje decimal — kompilator sam poszerza węższy typ. Rzutowanie nie jest potrzebne. |
(int)(budzet / cenaJednostkowa) |
50 / 24,99 to 2,0008. Rzutowanie ucina do 2 — i tego właśnie chcemy, bo nie kupimy dwóch sztuk i ośmiu tysięcznych. To przykład, w którym ucinanie jest zaletą, a nie pułapką. |
50m |
Przyrostek m jest konieczny — bez niego byłby to double, którego nie da się podzielić przez decimal bez rzutowania. |
{netto,8:F2} |
Dwa formaty naraz: 8 to szerokość kolumny (wyrównanie do prawej), F2 to dwa miejsca po przecinku. Dzięki temu kwoty ładnie się układają jedna pod drugą. |
Na co uważać
| Kod | Problem |
|---|---|
int x = 3.99; |
CS0266 — konwersja zawężająca wymaga rzutowania: (int)3.99. |
int x = (int)3.99; licząc na 4 |
Da 3. Rzutowanie ucina. Do zaokrąglenia użyj (int)Math.Round(3.99). |
int.Parse(Console.ReadLine()) |
Kompiluje się, ale przerwie program, gdy użytkownik wpisze cokolwiek innego niż liczbę. Użyj TryParse. |
double.Parse("3.14") na polskim systemie |
Kropka nie jest tu separatorem ułamka. Albo dane muszą używać przecinka, albo trzeba podać kulturę — o tym w następnej lekcji. |
int w = cyfra; gdy cyfra = '7' |
Da 55, nie 7. Trzeba cyfra - '0'. |
string s = (string)liczba; |
CS0030 — na tekst się nie rzutuje. Użyj liczba.ToString() albo interpolacji. |
byte b = (byte)300; |
Kompiluje się, ale da 44. Rzutowanie nie ostrzega przed przekroczeniem zakresu. |
decimal d = 19.99; |
CS0664 — literał bez przyrostka jest typu double, a double → decimal nie jest automatyczne. Potrzebne 19.99m. |
if (int.TryParse(t, out int x)) { }a potem użycie x na zewnątrz |
Zmienna zadeklarowana w wywołaniu TryParse jest widoczna od tego miejsca do końca bloku — poza blokiem już nie. To ten sam zasięg, który poznałeś w lekcji 04. |
Zadania
Zapisz wynik każdej linii, zanim uruchomisz program.
Console.WriteLine((int)9.99);
Console.WriteLine((int)(-9.99));
Console.WriteLine(Convert.ToInt32(9.99));
Console.WriteLine((int)Math.Round(9.5));
Console.WriteLine((char)(65 + 5));
Console.WriteLine('9' - '0');
Console.WriteLine((byte)260);
pokaż rozwiązanie
9
-9
10
10
F
9
4
Linie 1 i 2 — rzutowanie ucina w stronę zera, więc z −9,99 robi się −9, a nie −10.
Linia 3 — Convert zaokrągla, więc 9,99 daje 10.
Linia 4 — Math.Round(9.5) daje 10.
Linia 5 — 65 to 'A', więc 70 to 'F'.
Linia 7 — 260 nie mieści się w bajcie: 260 − 256 = 4.
Masz trzy napisy: "42", "3,5" i "pies". Spróbuj zamienić każdy z nich na int metodą TryParse i wypisz, czy się udało oraz jaki wyszedł wynik.
pokaż rozwiązanie
string t1 = "42";
string t2 = "3,5";
string t3 = "pies";
bool ok1 = int.TryParse(t1, out int w1);
bool ok2 = int.TryParse(t2, out int w2);
bool ok3 = int.TryParse(t3, out int w3);
Console.WriteLine($"\"{t1}\" -> udalo sie: {ok1,-5} wynik: {w1}");
Console.WriteLine($"\"{t2}\" -> udalo sie: {ok2,-5} wynik: {w2}");
Console.WriteLine($"\"{t3}\" -> udalo sie: {ok3,-5} wynik: {w3}");
"42" -> udalo sie: True wynik: 42
"3,5" -> udalo sie: False wynik: 0
"pies" -> udalo sie: False wynik: 0
Ciekawy jest drugi przypadek. "3,5" to poprawna liczba, ale nie całkowita — a prosiliśmy o int. Konwersja się nie udaje. Ten sam napis przekazany do double.TryParse zadziałałby bez problemu.
\" w tekście to sposób na wstawienie cudzysłowu do napisu. Bez ukośnika kompilator uznałby, że w tym miejscu napis się kończy.
Dla liczb 2,3, 2,5 i 2,7 wypisz obok siebie wynik rzutowania (int), Math.Round, Math.Floor i Math.Ceiling. Ułóż to w czytelną tabelkę.
pokaż rozwiązanie
double a = 2.3, b = 2.5, c = 2.7;
Console.WriteLine("liczba (int) Round Floor Ceiling");
Console.WriteLine("----------------------------------------");
Console.WriteLine($"{a,6}{(int)a,8}{Math.Round(a),8}{Math.Floor(a),8}{Math.Ceiling(a),10}");
Console.WriteLine($"{b,6}{(int)b,8}{Math.Round(b),8}{Math.Floor(b),8}{Math.Ceiling(b),10}");
Console.WriteLine($"{c,6}{(int)c,8}{Math.Round(c),8}{Math.Floor(c),8}{Math.Ceiling(c),10}");
liczba (int) Round Floor Ceiling
----------------------------------------
2,3 2 2 2 3
2,5 2 2 2 3
2,7 2 3 2 3
Najciekawszy jest wiersz środkowy. Math.Round(2.5) daje 2, a nie 3! To nie błąd — .NET domyślnie stosuje zaokrąglanie bankierskie: przy dokładnej połówce wynik idzie do najbliższej liczby parzystej. Dzięki temu przy wielu zaokrągleniach błędy nie kumulują się w jedną stronę.
Gdy potrzebujesz szkolnego zaokrąglania „połowa zawsze w górę”, podaj to wprost: Math.Round(2.5, MidpointRounding.AwayFromZero) da 3.
To jedna z tych rzeczy, które potrafią zaskoczyć na egzaminie — warto o niej pamiętać.
Dane przychodzą jako tekst: kwota tygodniowa "37,50" i liczba tygodni "8". Oblicz łączną kwotę oraz ile pełnych gier po 149,99 zł da się za nią kupić. Użyj TryParse i odpowiednich typów.
pokaż rozwiązanie
string kwotaTekst = "37,50";
string tygodnieTekst = "8";
const decimal CenaGry = 149.99m;
decimal.TryParse(kwotaTekst, out decimal naTydzien);
int.TryParse(tygodnieTekst, out int tygodnie);
decimal lacznie = naTydzien * tygodnie;
int ileGier = (int)(lacznie / CenaGry);
decimal zostanie = lacznie - ileGier * CenaGry;
Console.WriteLine($"Na tydzien: {naTydzien:F2} zl");
Console.WriteLine($"Tygodni: {tygodnie}");
Console.WriteLine($"Lacznie: {lacznie:F2} zl");
Console.WriteLine($"Gier: {ileGier}");
Console.WriteLine($"Zostanie: {zostanie:F2} zl");
Na tydzien: 37,50 zl
Tygodni: 8
Lacznie: 300,00 zl
Gier: 2
Zostanie: 0,02 zl
Kwoty trzymamy w decimal, bo to pieniądze. Liczbę tygodni w int, bo to sztuki.
lacznie / CenaGry daje 2,0001…, a rzutowanie ucina do 2 — dokładnie tego chcemy, bo za resztę nie kupimy trzeciej gry.
Zwróć uwagę, że ileGier * CenaGry miesza int z decimal — i działa bez rzutowania, bo int poszerza się automatycznie.
Mając napis "48317", oblicz sumę jego cyfr. Nie używaj pętli — sięgaj po kolejne znaki przez indeks i zamieniaj je na wartości liczbowe.
pokaż rozwiązanie
string tekst = "48317";
int c1 = tekst[0] - '0';
int c2 = tekst[1] - '0';
int c3 = tekst[2] - '0';
int c4 = tekst[3] - '0';
int c5 = tekst[4] - '0';
int suma = c1 + c2 + c3 + c4 + c5;
Console.WriteLine($"Cyfry: {c1} {c2} {c3} {c4} {c5}");
Console.WriteLine($"Suma: {suma}");
Cyfry: 4 8 3 1 7
Suma: 23
tekst[0] zwraca pojedynczy znak typu char, a nie napis. Odejmowanie '0' zamienia go na wartość liczbową.
Gdybyś napisał int.Parse(tekst[0]), kompilator zaprotestowałby — Parse przyjmuje napis, nie znak. Zadziałałoby dopiero int.Parse(tekst[0].ToString()), ale wersja z odejmowaniem jest krótsza i szybsza.
Po lekcji o pętlach wrócisz do tego zadania i napiszesz wersję działającą dla napisu o dowolnej długości.
Program ma policzyć średnią cenę trzech produktów i pokazać ją w groszach. Nie działa poprawnie — znajdź i popraw cztery usterki.
string c1 = "12,50", c2 = "8,99", c3 = "abc";
decimal cena1 = decimal.Parse(c1);
decimal cena2 = decimal.Parse(c2);
decimal cena3 = decimal.Parse(c3);
decimal srednia = cena1 + cena2 + cena3 / 3;
int grosze = srednia * 100;
Console.WriteLine("Srednia w groszach: " + grosze);
pokaż rozwiązanie
string c1 = "12,50", c2 = "8,99", c3 = "abc";
// 1. TryParse zamiast Parse — trzeci napis nie jest liczbą
decimal.TryParse(c1, out decimal cena1);
decimal.TryParse(c2, out decimal cena2);
decimal.TryParse(c3, out decimal cena3); // false, cena3 = 0
// 2. nawias — dzielenie miało dotyczyć całej sumy
decimal srednia = (cena1 + cena2 + cena3) / 3;
// 3. rzutowanie — decimal nie wejdzie do int bez pytania
int grosze = (int)(srednia * 100);
// 4. interpolacja zamiast sklejania plusem
Console.WriteLine($"Srednia w groszach: {grosze}");
Srednia w groszach: 716
Błąd 1 — decimal.Parse("abc") przerywa program wyjątkiem FormatException. Przy danych, które mogą być błędne, zawsze TryParse.
Błąd 2 — brak nawiasu. Dzielenie wykonałoby się tylko na cena3, a nie na sumie. Kod się kompiluje i wypisuje bzdurę.
Błąd 3 — CS0266, jedyny błąd zatrzymujący kompilację. decimal nie zamieni się w int automatycznie.
Błąd 4 — sklejanie plusem działa, ale interpolacja jest czytelniejsza i odporniejsza na pomyłki.
Wynik: (12,50 + 8,99 + 0) / 3 = 7,1633…, po pomnożeniu przez 100 i ucięciu — 716 groszy.
Co trzeba zapamiętać
- Konwersja niejawna dzieje się sama, gdy nic nie może się zgubić:
int → long → double. - Rzutowanie
(typ)wartoscto twoja obietnica, że wiesz, co robisz. Kompilator przestaje pilnować. - Rzutowanie
(int)ucina część ułamkową.Convert.ToInt32zaokrągla. - Zawężanie liczb całkowitych poza zakres daje cichy, błędny wynik — bez ostrzeżenia.
- Na tekst zamieniamy metodą
ToString()albo interpolacją. Rzutowanie nastringnie istnieje. Parseprzerywa program przy błędnym tekście,TryParsezwracafalsei działa dalej.- Dane od użytkownika zawsze przez
TryParse. - Słowo
outpozwala metodzie zwrócić drugą wartość obok tej głównej. - Znak cyfry to nie jej wartość:
'7'ma numer 55. Wartość liczbową dajecyfra - '0'. - Separator ułamka zależy od ustawień regionalnych — na polskim systemie to przecinek.