Lekce 4 - Typový systém podruhé: Datové typy ve VB.NET
V předešlém cvičení, Řešené úlohy k 3. lekci VB.NET, jsme si procvičili nabyté zkušenosti z předchozích lekcí.
Dnešní Visual Basic .NET tutoriál bude hodně teoretický, ale o to více bude praktický ten příští. Na konci si vytvoříme pár jednoduchých ukázek.
VB.NET rozeznává dva druhy datových typů, hodnotové a referenční.
Hodnotové datové typy
Proměnné hodnotového datového typu si dokážeme jednoduše představit. Může se jednat např. o číslo nebo znak. V paměti je jednoduše uložena přímo hodnota a my k této hodnotě můžeme z programu přímo přistupovat. Slovo přímo jsem tolikrát nepoužil jen náhodou. V této sekci tutoriálů se budeme věnovat výhradně těmto proměnným.
Celočíselné datové typy
Podívejme se nyní na tabulku všech vestavěných celočíselných
datových typů v .NET, všimněte si typu Integer
, který již
známe z minula.
Data type | Range | Size | .NET type |
---|---|---|---|
SByte | -128 až 127 | 8 bitů | System.SByte |
Byte | 0 až 255 | 8 bitů | System.Byte |
Short | -32 768 až 32 767 | 16 bitů | System.Int16 |
UShort | 0 až 65 535 | 16 bitů | System.UInt16 |
Integer | -2 147 483 648 až 2 147 483 647 | 32 bitů | System.Int32 |
UInteger | 0 až 4 294 967 295 | 32 bitů | System.UInt32 |
Long | -9 223 372 036 854 775 808 až 9 223 372 036 854 775 807 | 64 bitů | System.Int64 |
ULong | 0 až 18 446 744 073 709 551 615 | 64 bitů | System.UInt64 |
Poznámka: všechna ta šílená čísla z tabulky si pamatovat nemusíte, téměř vždy vám pomůže ve Visual Studiu nástroj IntelliSense, který když budete psát ten datový typ a počkáte ukáže nad ním bublinu:
![Intellisense ve Visual Studio - Základní konstrukce jazyka Visual Basic (VB.NET)](images/3588/vbnet_tutorial/visual_studio_intellisense.png)
Případně v dokumentaci dodávané k Visual studiu to najdete podrobněji. Do dokumentace se dostanete, když napíšete konkrétní datový typ, označíte jej a stisknete F1.
Asi vás napadá otázka, proč máme tolik možných typů pro uložení
čísla. Odpověď je prostá, záleží na jeho velikosti. Čím větší
číslo, tím více spotřebuje paměti. Pro věk uživatele tedy zvolíme
Byte
, protože se jistě nedožije více, než 255
let. Představte si databázi milionu uživatelů nějakého systému, když
zvolíme místo Byte
Integer
, bude zabírat 4x více
místa. Naopak když budeme mít funkci k výpočtu faktoriálu, stěží nám
bude stačit rozsah Integer
u a použijeme Long
.
Všimněte si, že některé typy začínají na U
. Jsou
téměř stejné, jako jejich dvojníci bez U
, jen neumožňují
záporné hodnoty a tím pádem na kladnou část mohou uložit 2x vyšší
hodnotu. Těmto typům se říká unsigned, klasickým signed.
.NET typ je název dané struktury v .NET knihovnách. My používáme tzv. aliasy, aby byla práce jednodušší, ve skutečnosti si VB.NET kód:
Dim a As Integer = 10
přebere jako:
Dim a As System.Int32 = 10
My budeme samozřejmě používat aliasy, od toho tam jsou
Nad výběrem datového typu nemusíte moc přemýšlet a většinou se
používá jednoduše Integer
. Typ řešte pouze v případě,
když jsou proměnné v nějakém poli (obecně kolekci) a je jich tedy více,
potom se vyplatí zabývat se paměťovými nároky. Tabulky sem dávám spíše
pro úplnost. Mezi typy samozřejmě funguje již zmíněná implicitní
konverze, tedy můžeme přímo přiřadit Integer
do proměnné
typu Long
a podobně, aniž bychom něco konvertovali.
Desetinná čísla
U desetinných čísel je situace poněkud jednodušší, máme na výběr
pouze dva datové typy. Samozřejmě se liší opět v rozsahu hodnoty, dále
však ještě v přesnosti (vlastně počtu des. míst). Double
má
již dle názvu dvojnásobnou přesnost oproti Single
.
Datový typ | Rozsah | Přesnost | .NET typ |
---|---|---|---|
Single | +-1.5 * 10−45 až +-3.4 * 1038 | 7 čísel | System.Single |
Double | +-5.0 * 10−324 až +-1.7 * 10308 | 15-16 čísel | System.Double |
Pozor, vzhledem k tomu, že desetinná čísla jsou v počítači uložena ve dvojkové soustavě, dochází k určité ztrátě přesnosti. Odchylka je sice téměř zanedbatelná, nicméně když budete programovat např. finanční systém, nepoužívejte tyto typy dat. typy pro uchování peněz, mohlo by dojít k malým odchylkám.
Když do Single
chceme dosadit přímo ve zdrojovém kódu,
musíme použít sufix F
, u double sufix R
(u double
ho můžeme vypustit, jelikož je výchozí desetinný typ):
Dim a As Single = 3.14F Dim b As Double = 2.72R
Jako desetinný separátor používáme ve zdrojovém kódu vždy tečku, nehledě na to, jaké máme ve Windows regionální nastavení.
Další vestavěné datové typy
Podívejme se na další datové typy, které nám .NET nabízí:
Datový typ | Rozsah | Velikost/Přesnost | .NET typ |
---|---|---|---|
Char | U+0000 až U+ffff | 16 bitů | System.Char |
Decimal | +-1.0 * 10−28 až +-7.9 * 1028 | 28-29 čísel | System.Decimal |
Boolean | True nebo False | 8 bitů | System.Boolean |
Char
Char
nám reprezentuje jeden znak, na rozdíl od
String
u, který reprezentoval celý řetězec charů. Znaky v
VB.NET píšeme do uvozovek:
Dim c As Char = "A"
Char
patří v podstatě do celočíselných proměnných
(obsahuje číselný kód znaku), ale přišlo mi logičtější uvést ho zde.
Char
nám vrací např. metoda Console.ReadKey()
.
Decimal
Typ Decimal
řeší problém ukládání desetinných čísel v
binární podobě, ukládá totiž číslo vnitřně podobně, jako text.
Používá se tedy pro uchování peněžních hodnot. Ke všem dalším
matematickým operacím s des. čísly použijeme Single
nebo
Double
. K zápisu Decimal
hodnoty opět používáme
sufix D
:
Dim d As Decimal = 3.14159265358979323846D
Boolean
Boolean
nabývá dvou hodnot: True
(pravda) a
False
(nepravda). Budeme ho používat zejména tehdy, až se
dostaneme k podmínkám. Do proměnné typu Boolean
lze uložit jak
přímo hodnotu True
/False
, tak i logický výraz.
Zkusme si jednoduchý příklad:
{VBNET_CONSOLE}
Dim b As Boolean = False
Dim vyraz As Boolean = (15 > 5)
Console.WriteLine(b)
Console.WriteLine(vyraz)
Console.ReadKey()
{/VBNET_CONSOLE}
Výstup programu:
Konzolová aplikace
False
True
Výrazy píšeme do závorek. Vidíme, že výraz nabývá hodnoty
True
(pravda), protože 15
je opravdu větší než
5
. Od výrazů je to jen krok k podmínkám, na ně se podíváme
příště.
Referenční datové typy
K referenčním typům se dostaneme až u objektově orientovaného
programování, kde si také vysvětlíme zásadní rozdíly. Zatím budeme
pracovat jen s tak jednoduchými typy, že rozdíl nepoznáme. Spokojíme se s
tím, že referenční typy jsou složitější, než ty hodnotové. Jeden
takový typ již známe, je jím String
. Možná vás napadá, že
String
nemá nijak omezenou délku, je to tím, že s
referenčními typy se v paměti pracuje jinak.
String
má na sobě řadu opravdu užitečných metod. Některé
si teď probereme a vyzkoušíme:
String
StartsWith()
,
EndsWith()
a Contains()
Můžeme se jednoduše zeptat, zda řetězec začíná, končí nebo zda
obsahuje určitý podřetězec (substring). Podřetězcem myslíme část
původního řetězce. Všechny tyto metody budou jako parametr brát
samozřejmě podřetězec a vracet hodnoty typu Boolean
(True
/False
). Zatím na výstup neumíme reagovat, ale
pojďme si ho alespoň vypsat:
{VBNET_CONSOLE}
Dim s As String = "Krokonosohroch"
Console.WriteLine(s.StartsWith("krok"))
Console.WriteLine(s.EndsWith("hroch"))
Console.WriteLine(s.Contains("nos"))
Console.WriteLine(s.Contains("roh"))
Console.ReadKey()
{/VBNET_CONSOLE}
Výstup programu:
Konzolová aplikace
False
True
True
False
Vidíme, že vše funguje podle očekávání. První výraz samozřejmě neprošel díky tomu, že řetězec ve skutečnosti začíná velkým písmenem.
ToUpper()
a ToLower()
Rozlišování velkých a malých písmen může být někdy na obtíž.
Mnohdy se budeme potřebovat zeptat na přítomnost podřetězce tak, aby
nezáleželo na velikosti písmen. Situaci můžeme vyřešit pomocí metod
ToUpper()
a ToLower()
, které vrací řetězec ve
velkých a v malých písmenech. Uveďme si reálnější příklad než je
Krokonosohroch. Budeme mít v proměnné řádek konfiguračního souboru,
který psal uživatel. Jelikož se na vstupy od uživatelů nelze spolehnout,
musíme se snažit eliminovat možné chyby, zde např. s velkými písmeny.
{VBNET_CONSOLE}
Dim konfig As String = "Fullscreen shaDows autosave"
konfig = konfig.ToLower()
Console.WriteLine("Poběží hra ve fullscreenu?")
Console.WriteLine(konfig.Contains("fullscreen"))
Console.WriteLine("Budou zapnuté stíny?")
Console.WriteLine(konfig.Contains("shadows"))
Console.WriteLine("Přeje si hráč vypnout zvuk?")
Console.WriteLine(konfig.Contains("nosound"))
Console.WriteLine("Přeje si hráč hru automaticky ukládat?")
Console.WriteLine(konfig.Contains("autosave"))
Console.ReadKey()
{/VBNET_CONSOLE}
Výstup programu:
Konzolová aplikace
Poběží hra ve fullscreenu?
True
Budou zapnuté stíny?
True
Přeje si hráč vypnout zvuk?
False
Přeje si hráč hru automaticky ukládat?
True
Vidíme, že jsme schopni zjistit přítomnost jednotlivých slov v řetězci tak, že si nejprve řetězec převedeme celý na malá písmena (nebo na velká) a potom kontrolujeme přítomnost slova jen malými (nebo velkými) písmeny. Takhle by mimochodem mohlo opravdu vypadat jednoduché zpracování nějakého konfiguračního skriptu.
Trim()
, TrimStart()
a TrimEnd()
Problémem ve vstupech od uživatele může být i diakritika, ale VB.NET naštěstí pracuje plně v UTF8, nestane se nám tedy, že by se diakritika nějak zkomolila. Další nástrahou mohou být mezery a obecně všechny tzv. bílé znaky, které nejsou vidět, ale mohou nám uškodit. Obecně může být dobré trimovat všechny vstupy od uživatele, můžeme trimovat buď celý řetězec nebo jen bílé znaky před ním a za ním. Prozradím, že při parsovacích funkcích VB.NET trimuje zadaný řetězec automaticky, než s ním začne pracovat. Zkuste si v následující aplikaci před číslo a za číslo zadat několik mezer:
{VBNET_CONSOLE}
Console.WriteLine("Zadejte číslo:")
Dim s As String = Console.ReadLine()
Console.WriteLine("Zadal jste text: " & s)
Console.WriteLine("Text po funkci trim: " & s.Trim())
Dim a As Integer = CInt(s)
Console.WriteLine("Převedl jsem zadaný text na číslo parsováním, zadal jste: " & a)
Console.ReadKey()
{/VBNET_CONSOLE}
Replace()
Asi nejdůležitější metodou na String
u je nahrazení
určité jeho části jiným textem. Jako parametry zadáme dva podřetězce,
jeden co chceme nahrazovat a druhý ten, kterým to chceme nahradit. Metoda
vrátí nový String
, ve kterém proběhlo nahrazení. Když daný
podřetězec metoda nenajde, vrátí původní řetězec. Zkusme si to:
{VBNET_CONSOLE}
Dim s As String = "C# je nejlepší!"
s = s.Replace("C#", "VB.NET")
Console.Write(s)
Console.ReadKey()
{/VBNET_CONSOLE}
Výstup programu:
Konzolová aplikace
VB.NET je nejlepší!
Format()
Format()
je velmi užitečná metoda, která nám umožňuje
vkládat do samotného textového řetězce zástupné značky. Ty jsou
reprezentovány jako číslo ve složených závorkách, prvním číslem je
0
. Jako další parametry metody následují v tomto pořadí
proměnné, které se mají do textu místo značek vložit. Všimněte si, že
se metoda nevolá na konkrétní proměnné (přesněji instanci, viz další
díly), ale přímo na typu String
.
{VBNET_CONSOLE}
Dim a As Integer = 10
Dim b As Integer = 20
Dim c As Integer = a + b
Dim s As String = String.Format("Když sečteme {0} a {1}, dostaneme {2}", a, b, c)
Console.WriteLine(s)
Console.ReadKey()
{/VBNET_CONSOLE}
Výstup programu:
Konzolová aplikace
Když sečteme 10 a 20, dostaneme 30
Konzole sama umí přijímat text v takovémto formátu, můžeme tedy napsat:
{VBNET_CONSOLE}
Dim a As Integer = 10
Dim b As Integer = 20
Dim c As Integer = a + b
Console.WriteLine("Když sečteme {0} a {1}, dostaneme {2}", a, b, c)
Console.ReadKey()
{/VBNET_CONSOLE}
Toto je velmi užitečná a přehledná cesta, jak sestavovat řetězce, a
určitě se ji vyplatí mnohdy použít místo běžné konkatenace pomocí
operátoru &
, pokud nebazírujeme na vysoké rychlosti.
PadLeft()
a
PadRight()
Jako poslední si zmíníme metody, které nám k textu naopak mezery
přidají K čemu to je
dobré? Představte si, že máme 100 proměnných a budeme je chtít seřadit
do tabulky. Text upravíme pomocí metody
PadRight()
s parametrem
šířky sloupce, tedy např. 20 znaků. Pokud bude mít text jen 12 znaků,
vypíše se před něj 8 mezer, aby měl velikost 20. Obdobně metoda
PadLeft()
by vypsala 8 mezer za něj. Jelikož nemáme znalosti k
vytvoření takové tabulky, budeme si metody jen pamatovat a vyzkoušíme si je
jindy, až budeme programovat kalendář.
Vlastnost Length
Poslední, ale nejdůležitější vlastnost (pozor, ne metoda) je
Length
, tedy délka. Vrací celé číslo, které představuje
počet znaků v řetězci. Za vlastnosti nepíšeme závorky, protože nemají
parametry.
{VBNET_CONSOLE}
Console.WriteLine("Zadejte vaše jméno")
Dim jmeno As String = Console.ReadLine()
Dim delkaJmena As Integer = jmeno.Length
Console.WriteLine("Délka vašeho jména je: " & delkaJmena)
Console.ReadKey()
{/VBNET_CONSOLE}
Je toho ještě spoustu k vysvětlování a jsou další datové typy, které jsme neprobrali.
V následujícím cvičení, Řešené úlohy k 4. lekci VB.NET, si procvičíme nabyté zkušenosti z předchozích lekcí.