Rozpoczynajmy czym prędzej następny temat z dziedziny "CSharpa" jakim będą typy danych w języku C#. C# znowu postępuje bardziej oryginalnie od innych języków i trzeba się wypowiedzieć na temat typów danych od samego początku. Przystępujemy zatem do kolejnej drogi po wiedzę :)!
Tweet |
TYPY DANYCH W JĘZYKU C# DZIELĄ SIĘ NA RÓŻNE KATEGORIE
Typ danych sam w sobie to informacja na temat rodzaju przechowywanej wartości oraz przedziału dopuszczalnych wartości. C# jest kolejnym przedstawicielem silnej typizacji i u niego nie ma miejsca na "mieszaniny" wartości z typami. Krótko pisząc, jeżeli deklarujemy że chcemy przechowywać liczbę całkowitą, to próba "zrobienia na złość" kompilatorowi (poprzez wstawienie np. łańcucha znaków) odbije się nam czkawką i zgłosi błąd.
Język może się pochwalić sporą gamą rodzajów typów, w niektórych przypadkach po kilka sztuk na jeden rodzaj, podobnie jak w C i C++. Przedstawię Wam ich dużą część (jeśli nie wszystkie), przy czym prośba jest. Nie zapamiętujcie ich wszystkich, przynajmniej na początku swojej drogi poznawania języka. W miarę nabywania doświadczenia w tym kierunku, ta część wiedzy sama już "wpadnie" do głowy. A jeżeli nie, to zawsze możecie wrócić tu ponownie czy zajrzeć do oficjalnej dokumentacji, jeżeli dany problem programistyczny będzie wymagać specyficznego typu danych.
Jeszcze jedna uwaga na koniec. Język będzie Wam "patrzeć na ręce" w kwestii pilnowania się typów i zakresów. Kompilator nie dopuści do kompilacji programu, jeśli podacie wartość niezgodną z typem bądź przekraczającą jego zakres, którą można przewidzieć przed uruchomieniem (chyba, że zasygnalizujecie rzutowaniem typu, że jesteście świadom konsekwencji).
Starczy tego monologu ;). Oto typy danych w języku C# jakie możecie spotkać w cudzych kodach źródłowych. To jest zestawienie powierzchowne, więcej informacji będziecie mogli znaleźć w artykułach przyszłościowych.
CAŁKOWITOLICZBOWE
Typ całkowitoliczbowy polega na przechowywaniu wartości w charakterze liczby całkowitej. Standardowym przedstawicielem liczb całkowitych był, jest i będzie "int", jednak występuje znacznie więcej typów całkowitoliczbowych. Oto tabela ze wszystkimi odmianami:
NAZWA | MINIMALNY ZAKRES | MAKSYMALNY ZAKRES | PRZYKŁAD |
sbyte | -27 | 27 - 1 | -109 |
byte | 0 | 28 - 1 | 25 |
short | -215 | 215 - 1 | -17500 |
ushort | 0 | 216 - 1 | 32500 |
int | -231 | 231 - 1 | 1000000 |
uint | 0 | 232 - 1 | 48U |
long | -263 | 263 - 1 | 1870L |
ulong | 0 | 264 - 1 | 567000UL |
Charakterystyczne typy danych w języku C# są te, które występują "bez znaku" (ang. unsigned). Są to: "ushort", "uint" oraz "ulong" (z bajtem postąpiono na odwrót i występuje "sbyte", czyli "ze znakiem"). Charakteryzują się one podwójnie większym zakresem liczb dodatnich kosztem zakresu dla liczb ujemnych (minimalną wartością jest zero). Na przykład w języku Java już takich nie znajdziecie!
Domyślnie, każda liczba jest traktowana jak "int" (o ile mieści się w zakresie). W sytuacji, kiedy chcemy wymusić stałą wartość na wersję "bez znaku", dodajemy na końcu literę 'u' lub 'U'. Dla "long", stosujemy literę 'l' lub 'L', choć ze względu na czytelność dużo lepiej pisać wielką literą. Dla "ulong", korzystamy z kombinacji dwóch liter "UL" (kombinacje dowolne co do wielkości liter).
ZMIENNOPRZECINKOWE
Zmiennoprzecinkowy typ danych to możliwość przechowania liczby z ułamkiem, pisząc jak najbardziej zwięźle. Takie liczby jak 154.6 czy 80.01 są przykładami wymagania typu zmiennoprzecinkowego. C# i w tym przypadku posiada coś "exclusive", jednak w o wiele mniejszym spektrum. Przyjrzyjcie się tabelce:
NAZWA | MINIMALNY ZAKRES | MAKSYMALNY ZAKRES | PRECYZJA | PRZYKŁAD |
float | ±3.4*10-38 | 3.4*1038 | 7 cyfr | -35.89f |
double | ±1.79*10-308 | 1.79*10308 | 15-16 cyfr | 106.78d |
decimal | ±1.0*10-28 | 7.9*1028 | 28-29 cyfr | 45.678313m |
Parę słów więcej o "decimal", którym C# może się pochwalić na wyłączność. Powinno się z niego korzystać gdy w grę wchodzi liczba miejsc po przecinku, a nie wielkość. Użycie na wagę złota znajduje się na przykład w bankowości gdzie główną rolę odgrywają finanse i nawet grosze mają ogromne znaczenie.
Domyślnym typem dla zmiennoprzecinkowych jest "double". Aby wymusić konkretny typ, korzystamy ponownie z sufiksów o następujących postaciach:
- litera 'f' lub 'F' dla typu "float",
- litera 'd' lub 'D' dla typu "double",
- litera 'm' lub 'M' dla typu "decimal".
ZNAKOWY
Znakowy typ danych to reprezentacja znaków z klawiatury jako danych i C# dysponuje tylko jednym takim (jest jeszcze łańcuch znaków, ale ja go traktuję jak typ obiektowy - zobaczcie niżej dlaczego). Jest nim "char", ten sam znany z innych języków zanim pojawił się "CSharp". Tutaj także jego możliwości zostały poszerzone o wsparcie kodowania znanego pod hasłem "Unicode". Jest to kodowanie znaków z myślą o użyciu międzynarodowym. Znak japoński na ten przykład nie zmieściłby się w jednym bajcie, stąd "char" w języku C# jest "uzbrojony" w DWA bajty! Efekt? Nie musimy się martwić, że w programie ujrzymy "krzaki" (wybrakowane albo niespodziewane znaki) zamiast znaków diakrytycznych.
Patrząc na "char", istotna jest tylko jedna zasada do opanowania. Wstawiamy JEDEN znak i wewnątrz APOSTROFÓW! Dotyczy to nawet wstawiania sekwencji sterującej, która składa się z dwóch znaków!
char c = 'ą';
LOGICZNY
Logiczny typ danych to stary dobry "boolean". Obowiązuje tu jednak krótsza forma tego słowa, "bool", stając się jedną z różnic pomiędzy C# a Javą. Typ zdolny przyjmować dwie wartości: prawdę lub fałsz ("true" lub "false" pisane małymi literami!):
bool b = true;
Pamiętajcie dodatkowo, że niedopuszczalne jest utożsamianie liczby całkowitej z wartością logiczną w instrukcji warunkowej. To nie jest język C!
if(0)
{
}
WYLICZENIOWY
Kryptonim "enum". Typ wyliczeniowy to składowanie zbioru wartości w jednym "worku". Dzięki przechowywaniu stałych, poprawia się w ten sposób czytelność i bezpieczeństwo kodu (więcej informacji zostawiono w odrębnym artykule):
enum Directions
{
NORTH, SOUTH, EAST, WEST
}
STRUKTURALNY
Tym razem mowa o słowie kluczowym "struct". Typy danych w języku C# to także typ strukturalny, który jest budowany podobnie jak klasa, tylko z jedną ważną różnicą: charakteryzuje się przekazywaniem przez kopię. Jak przy całej reszcie - szczegóły w osobnym artykule:
struct Point
{
public int X {get; set;}
public int Y {get; set;}
}
REFERENCYJNE
Referencyjne typy danych w języku C# odnoszą się do przechowywania obiektów, a w rzeczywistości referencji do tych obiektów przy pomocy wskaźnika. Dwa najbardziej rozpoznawalne typy to...
INSTANCJA KLASY
Czyli każdy obiekt powstały dzięki skorzystaniu z klasy, wbudowanej bądź zdefiniowanej własnoręcznie. Korzystając z operatora przypisania, alokujemy pamięć dla obiektu, wywołujemy jego konstruktor i przechowujemy w istocie adres, za pomocą którego możemy uzyskiwać dostęp do obiektu za pomocą operatora kropki. Obiektowość to bardzo szeroki temat, więc wszystkie szczegóły zostały wyjaśnione w osobnych materiałach:
[typ klasy] instance = new [typ klasy]();
ŁAŃCUCH ZNAKÓW
Zdziwieni, co? Logika każe myśleć, że powinno to mieć swoje miejsce w znakowych. Otóż nie! Z dwóch powodów. Po pierwsze, "string" to jest alias od "System.String", a to jest proszę Państwa klasa (w rozumieniu paradygmatu obiektowego). Po drugie, wynika to z prawdziwej natury typu łańcuchowego. Najważniejszym wnioskiem do wyciągnięcia od niej jest to, iż obiekt łańcucha jest w rzeczywistości niemodyfikowalny. Choć może to przeczyć możliwości podstawienia nowego łańcucha do istniejącego obiektu, to jednak "za kotarą" odbywa się wtedy "przepinanie" wskaźnika do nowego łańcucha, porzucając referencję do starego. Macie prawo tego nie wiedzieć, dlatego więcej informacji zostawiam w odrębnym artykule, w którym tłumaczę dlaczego nie powinno się NIGDY PRZENIGDY przypisywać nowego łańcucha do obiektu "string", a już posiada on jakąś referencję (a także co zrobić w takiej sytuacji).
Co się tyczy składni, to trzymamy się słowa "string" (najlepiej korzystać z wersji pisanej małą literą), a po znaku przypisania podajemy dowolny łańcuch (możliwości nie kończą się na literach) w cudzysłowach. One nie są "wszczepiane" do tekstu, to są jedynie oznaczenia dla kompilatora, żeby wiedział od którego momentu do którego, należy interpretować kod jako łańcuch znaków:
string s = "To mój łańcuch znaków.";
Typy danych w języku C# dzielą się na wiele rodzajów, a każdy z nich charakteryzuje się posiadaniem innej wartości, zakresem oraz sposobem przechowywania.
To wszystko, jak na początek. Niech Was nie przeraża skomplikowana gdzieniegdzie terminologia. Nauczyłem się już tak pisać, choć wiem że to może nie być właściwe podejście dla początkujących :). Z biegiem czasu jak poświęcicie się nauce "CSharpa", wszystko będzie stawało się coraz łatwiejsze. Uwierzcie osobie (lekko) doświadczonej.