# Visual Basic/Variabelen
## Wat is een variabele?

In de wiskunde of bij het rekenen heb je wel eens een opgave gekregen in de trant van: "x + 3 = 5. Wat is de waarde van x?". Hierbij wordt x wel de variabele genoemd die opgelost moet worden. Het is dus "iets" dat een bepaalde waarde heeft.
Bij programmeertalen is dat ook zo. Een variabele is "iets" dat een waarde kan hebben. die waarde kan van alles zijn, niet alleen getallen, maar ook teksten, objecten, afbeeldingen, eigenlijk alles wat je in een computer tegen komt. Al deze gegevens worden in het geheugen bewaard en de naam van de variabele geeft aan waar precies in het geheugen dat gegeven wordt bewaard.
Stel het geheugen voor als een grote verzameling brievenbussen die allemaal een nummer hebben. Je kunt een brief of een pakje voorzien van zo'n brievenbusnummer en hem laten bezorgen. Daarna kun je in de brievenbus kijken wat er in zit. Zo werken variabelen ook. Ze hebben alleen één bijzonderheid. Een brievenbus kan meerdere stukken post bevatten, maar een variabele kan maar één waarde tegelijkertijd hebben. Als je een nieuwe waarde naar een variabele stuurt, wordt de oude waarde vervangen door de nieuwe waarde.
Een variabele moet worden gedeclareerd met een Dim-instructie. Hierbij bepaalt de programmeur de naam van de variabele en het type gegeven dat opgeslagen kan worden. De compiler bepaalt het adres van de variabele en de lengte ervan in byte. Het is aan te raden om variabelen te declareren aan het begin van een procedure. Zo zie je direct welke variabelen er gebruikt worden en van welk type ze zijn. Variabelen waarvan het gebruik niet beperkt tot één procedure worden aan het begin van het programma gedeclareerd. En dit is wat er achter de schermen gebeurt: als je in een programma een variabele gebruikt, wordt de naam van deze variabele tijdens het compileren vervangen door een adres in het geheugen. In het hele programma wordt dit adres gebruikt op elke plaats waar die variabele wordt genoemd.
Stel, je hebt ondertaand programmafragment:
Tijdens het compileren wordt overal getal vervangen door een adres in het geheugen waar alleen gehele getallen kunnen worden opgeslagen. De eerste instructie (Dim getal As Integer) reserveert een stukje geheugen. De tweede instructie (getal = 5) slaat de waarde 5 op in dat stukje geheugen. De derde instructie (getal = getal + 2) haalt de waarde (5) op uit dat stukje geheugen, telt er 2 bij op en bewaart het resultaat (7) in dat stukje geheugen.
Op deze manier maak je dus gebruik van variabelen in een programma.

## Gegevenstypen

In een brievenbus kun je allerlei soorten post kwijt: briefkaarten, brieven, pakketjes. In een programmeertaal is dat niet zo. Je hebt verschillende soorten brievenbussen met een bepaalde afmeting en bedoeld voor een bepaald soort post. Zo zijn er variabelen voor gehele getallen, niet-gehele getallen (ook wel drijvende komma getallen genaamd), losse tekens, tekst enz. Dit noemen we gegevenstypen. Ieder gegevenstype neemt een bepaalde hoeveelheid geheugen in beslag en kan bepaalde waardes bevatten. Er bestaan de volgende gegevenstypen binnen Visual Basic:
| Datatype | Beschrijving | Aantal bytes | Bereik |
| Boolean | Logische waarde | Afhankelijk van patform | True of False |
| Byte | geheel getal | 1 byte | 0 t/m 255 (zonder teken) |
| Char | één teken | 2 bytes | 0 t/m 65535 (1 unicode-teken) |
| Date | Datum en tijd | 8 bytes | 0:00:00 1 jan 0001 t/m 11:59:59 PM 31 dec 9999 |
| Decimal | decimaal getal | 16 bytes | 0 t/m 79.228.162.514.264.337.593.543.950.335 zonder cijfers na de komma, 0 t/m 7,9228162514264337593543950335 met 28 cijfers na de komma; kleinste niet-nul getal: +/-0.0000000000000000000000000001 |
| Double | drijvende komma, lang | 8 bytes | -1,79769313486231570E+308 t/m -4,94065645841246544E-324, 0 en 4,94065645841246544E-324 t/m 1,79769313486231570E+308 |
| Integer | geheel getal | 4 bytes | -2.147.483.648 t/m 2.147.483.647 (met teken) |
| Long | geheel getal | 8 bytes | -9.223.372.036.854.775.808 t/m 9.223.372.036.854.775.807 (met teken) |
| Object | Object (pointer) | 4 bytes op 32-bit platform, 8 bytes op 64-bit platform | elk type kan worden bewaard in een Object |
| SByte | geheel getal | 1 byte | -128 t/m 127 (met teken) |
| Short | geheel getal | 2 bytes | -32.768 t/m 32.767 (met teken) |
| Single | drijvende komma, kort | 4 bytes | -3,4028235E+38 t/m -1,401298E-45, 0 en 1,401298E-45 t/m 3,4028235E+38 |
| String | tekst | platform-afhankelijk | 0 tot ca. 2 miljard unicode-tekens |
| UInteger | geheel getal | 4 bytes | 0 t/m 4.294.967.295 (zonder teken) |
| ULong | geheel getal | 8 bytes | 0 t/m 18.446.744.073.709.551.615 (zonder teken) |
| UShort | geheel getal | 2 bytes | 0 t/m 65.535 (zonder teken) |
| User Defined | bepaald door gebruiker | afhankelijk van declaratie | afhankelijk van declaratie |
Bovenstaande gegevenstypen worden verdeeld in twee groepen: valuetypen en referencetypen (naar het Engelse value voor waarde en reference voor referentie). Bij valuetypen bevat de variabele de waarde van die variabele. Bij referencetypen bevat de variabele niet de waarde, maar een verwijzing naar het adres van de waarde. De waarde zelf is ergens anders opgeslagen. Zo'n variabele wordt ook wel pointer genoemd: het verwijst naar iets. Objecten en strings zijn altijd referentietypes. He gebruik van valuetypen is sneller dan dat van referentietypen, vooral omdat de omweg via een pointer niet nodig is.

## Declareren van variabelen

Je hebt hierboven al gezien dat een variabele wordt gedeclareerd met het sleutelwoord Dim. Hiermee worden zogenaamde lokale variabelen gedeclareerd: variabelen die alleen in een beperkt stuk programma worden gebruikt. Als een variabele een groter bereik moet hebben, bijvoorbeeld een klasse of module of zelfs het hele programma gebruik je in plaats van Dim één van de sleutelwoorden Public of Private. Daar wordt later op teruggekomen.
Het Dim-statement heeft de volgende vorm:
Dim en As zijn vaste sleutelwoorden. variabele is de naam van een variabele. datatype geeft het soort variabele aan, b.v. Integer of String.
Er bestaat ook een uitbreiding van het Dim-statement waarmee je de variabele voorziet van een initiële waarde. Dit Dim-statement heeft de volgende vorm:
Hierbij moet de initiële waarde van hetzelfde type zijn als datatype, bijvoorbeeld:
Zoals je ziet moet je een string in je programma tussen dubbele aanhalingstekens zetten ("). Zo weet de compiler waar de string begint en eindigt.
Je bent verplicht iedere gebruikte variabele te declareren. Deze verplichting kun je omzeilen door de optie Explicit de waarde Off te geven. Maar daardoor loop je wel de kans dat je programma niet goed werkt als je je vertikt bij het typen van de naam van een variabele. De compiler beschouwt de twee namen niet als de naam van dezelfde variabele (zoals bedoeld), maar als de namen van twee verschillende variabelen, waardoor je programma niet goed werkt.
Je kunt ook meerdere variabelen tegelijk declareren en wel als volgt:
Dit is compacter dan drie afzonderlijke Dim-opdrachten.
Een andere mogelijkheid om meerdere variabelen te declareren is:
Maar deze mogelijkheid wordt afgeraden. Declareer in één Dim-instructie alleen variabelen van hetzelfde type. Dit is veel duidelijker.

## Type-aanduidingen

De compiler doet bepaalde aannamens als je getallen opneemt in je programma. Zo wordt aangenomen dat een geheel getal (b.v. 53) een Integer is en een gebroken getal (b.v. 12.53) een Double. Dat levert een foutmelding op in de volgende situatie:
De compiler zal aangegeven dat 12.45 een Double is en geconverteerd moet worden naar een Decimal. Deze foutmelding kun je voorkomen door 12.45 te vervangen door 12.45D. De D achter het getal geeft aan dat het een Decimal betreft. Visual Basic kent de volgende type-aanduidingen:
| Type/aanduiding | Beschrijving | Voorbeeld |
| C | Converteer naar Char | Dim teken As String = "A"c |
| D of @ | Converteer naar Decimal | Dim getal As Decimal =12.45D |
| R of # | Converteer naar Double | Dim getal As Double = 123.456R |
| I of % | Converteer naar Integer | Dim getal As Integer = 100I |
| L of & | Converteer naar Long | Dim getal As Long = 12345L |
| S | Converteer naar Short | Dim getal As Short = 12S |
| F of ! | Converteer naar Single | Dim getal As Single = 12.34F |
Zoals je ziet zijn er soms twee mogelijkheden om het type aan te duiden. De tweede mogelijkheid is nog een erfenis van een grijs verleden, toen die tekens gebruikt werden. In de jaren '70 werd een integer bijvoorbeeld als volgt gedeclareerd:
Het teken achter de naam van de variabele gaf dan het type aan. Deze manier van declareren mag nu niet meer gebruikt worden.

## Eisen aan de naamgeving

Allereerst geen eis, maar een aanbeveling. Voor de naamgeving van variabelen wordt meestal gebruikgemaakt van camel casing. Dit houdt in dat de naam bestaat uit kleine letters, maar dat woorden binnen de naam beginnen met een hoofdletter, bijvoorbeeld:
Bij de namen van procedures wordt gebruik van pascal casing. Dit is hetzelfde als camel casing, maar de eerste letter is geen kleine letter maar een hoofdletter. Zo krijg je namen als:
Aan de eerste letter kun je dus zien of het een variabele of een procedure betreft.
Let op: Visual Basic maakt geen onderscheid tussen hoofdletters en kleine letters. Daarom wijzen de volgende namen naar dezelfde variabele:
Namen van variabelen moeten voldoen aan de volgende eisen:
* de naam mag alleen bestaan uit letters, cijfers en onderstrepingstekens (_)
* de naam moet beginnen met een letter of een onderstrepingsteken
* als de naam begint met een onderstrepingsteken, moet er nog minimaal één letter of cijfer volgen
* de lengte van een naam bedraagt maximaal 1023 tekens
* de naam moet uniek zijn in het geldigheidsgebied (de scope van de variabele)
Als je een variabele declareert in een methode, subroutine of functie (een zgn. lokale variabele) is de scope van de variabele de betreffende methode, subroutine of functie. Het is ook mogelijk om een variabele globaal te declareren (je gebruikt dan het sleutelwoord Global in plaats van Dim), waarbij de scope het gehele programma is.
Als je een globale variabele hebt gedecleerd en je declareert in een methode, subroutine of functie een variabele met dezelfde naam, zal binnen die methode, subroutine of functie alleen de lokale variabele gebruikt worden en daarbuiten de globale variabele.
Let op: de maximale lengte van een naam heeft ook betrekking op samengestelde namen zoals tbxInvoer.Text. Zo'n samengestelde naam kan theoretisch bestaan uit tientallen namen gescheiden door punten. Ook zo'n samengestelde naam mag dus maximaal 1023 tekens lang zijn. Daarbij komt dat lange namen kunnen leiden tot tikfouten en het invoeren en lezen van een programma bemoeilijken. Zorg er daarom voor dat de naam van een variabele zo kort mogelijk is, maar wel duidelijk. Als richtlijn kan bijvoorbeeld een maximum van 30 tekens worden aangehouden.
Over het gebruik van hoofdletters binnen namen is in de inleiding al gesproken. Kort gezegd: de naam van een variabele begint met een kleine letter en ieder woord binnen de naam begint met een hoofdletter, b.v.: tbxInvoer.

## De nauwkeurigheid van getallen

Getallen hebben een bepaalde nauwkeurigheid, omdat de computer maar een beperkte ruimte heeft om getallen op te slaan.
Gehele getallen hebben geen cijfers achter de komma en zijn daardoor altijd volkomen nauwkeurig.
Getallen van het type Single hebben een nauwkeurigheid van ongeveer 7 cijfers. Als je bijvoorbeeld in een programma zou schrijven:
zou getal de waarde 0.3333333 bevatten. Maar als je schrijft:
dan zal getal de waarde 33333.34 bevatten.
Getallen van het type Double hebben een grotere nauwkeurigheid, namelijk 15 cijfers.
Het type Decimal is bijzonder. Een variabele van het type Decimal bestaat uit twee delen:
* een getal zonder komma
* het aantal posities dat de komma naar links of rechts verschoven moet worden
Hierdoor is het mogelijk om met heel grote (of kleine) getallen te werken met een grote nauwkeurigheid. Het nadeel is dat het werken met Decimals relatief langzaam gaat.

## Dim, Public, Private en Static

Hierboven is Dim gebruikt om een variabele te declareren. Een variabele kun je echter niet overal in een programma gebruiken. Iedere variabele heeft een bepaald bereik ofwel scope.
Een programma bestaat meestal uit een aantal onderdelen, procedures of subroutines genoemd, die vanuit het hoofdprogramma of andere procedures/subroutines worden aangeroepen. Als een variabele aan het begin van een subroutine wordt gedeclareerd, is de scope van die variabele die betreffende subroutine. Bekijk het volgende voorbeeld: een console applicatie):
De uitvoer van dit programma is:
De variabele getal is gedeclareerd binnen de subroutine DoeIets en bestaat daarom alleen binnen deze deze subroutine (tussen Sub DoeIets en End Sub. Binnen de subroutine Main bestaat de variabele getal dus niet en kan dus ook niet gebruikt worden. De scope van variabele getal is dus de subroutine DoeIets.
Steeds als de subroutine start worden alle gedeclateerde variabelen aangemaakt en als de subroutine klaar is, worden de variabelen weer verwijderd. Dus er wordt steeds weer begonnen met een schone lei. Dit is te voorkomen met het sleutelwoord Static. Een variabele die gedeclareerd is met het sleutelwoord Static blijft bestaan als de subroutine klaar is en zal niet opnieuw worden aangemaakt als de subroutine weer wordt aangeroepen.
Wijzig het bovenstaande programma maar als volgt (vervang Dim door Static):
De uitvoer van dit programma is:
Zoals je ziet is de uitvoer nu anders. Ondanks het feit dat er staat
waardoor de variabele bij aanmaak de waarde 0 krijgt, zal bij een tweede aanroep van de subroutine de waarde niet meer op 0 worden gezet, omdat de variabele nog steeds bestaat. Daarom zal bij de tweede aanroep de oude waarde (1) met 1 verhoogd worden, waardoor de tweede uitvoer 2 is.
Een Static variabele kan bijvoorbeeld gebruikt worden om een teller te declareren die bijhoudt hoe vaak een subroutine is aangeroepen. Ook wordt een Static variabele gebruikt om een waarde te onthouden voor een volgend gebruik.
Het is ook mogelijk om op deze manier bij te houden of een subroutine voor de eerste keer wordt uitgevoerd. Dit gebeurt als volgt:
Zoals je ziet, zal bij de eerste keer dat deze subroutine wordt aangeroepen de waarde van status 0 zijn en worden de opdrachten na If uitgevoerd. Daarna verandert de inhoud van status in 1.
Alle volgende keren dat deze subroutine wordt uitgevoerd, zullen de opdrachten na Else worden uitgevoerd, omdat de waarde van status nu 1 is.
Het gebruik van Private komt bij variabelen nauwelijks of niet voor. Private zorgt ervoor dat de scope van de variabele beperkt is tot de betreffende subroutine, maar dat gebeurt bij Dim ook al. Private wordt wel gebruikt bij het declareren van onder andere subroutines, maar dit wordt op aan andere plaats behandeld.
Public geeft aan dat een variabele bekend is in hele programma. Deze variabele worden meestal buiten alle subroutines gedeclareerd, dus in bovenstaand voorbeeld direct na de opdracht Module Module1.
Wat is nu het nut van deze verschillende declaraties? Het getuigt van vakmanschap als de scope van een variabele zo klein mogelijk is. Dit voorkomt fouten in het programma en maakt het mogelijk om in meerdere subroutines variabelen met dezelfde naam te gebruiken, terwijl hun functie gescheiden blijft.

## Constanten

De structuur van een constante-declarie is:
Const naam [ As type [ = initiële waarde ]
Een constante is eigenlijk een variabele waarvan de waarde niet kan veranderen. Dat houdt in dat de compiler de tweede instructie hieronder als foutief markeert:
Zoals je ziet, wordt de naam van een constante in hoofdletters geschreven. Dit is niet verplicht, maar zo zie je snel het verschil tussen een variabele en een constante. Visual Basic kent ook een aantal constanten zoals vbCrLf, vbTab, enz. Deze veel gebruikte constanten hoef je dus niet zelf te declareren.
Misschien vraag je je af waarom een constante gebruikt wordt in plaats van een variabele, want ze worden allebei gebruikt om een waarde te onthouden.
Zoals hierboven aangegeven, kan een constante niet gewijzigd worden. Dit voorkomt programmeerfouten. Een tweede voordeel is, dat het programma robuuster wordt door het gebruik van constanten. Stel, je hebt een programma dat veel met BTW-percentages werkt. Nu kun je overal in het programma de waarde 19 gebruiken, zoals in
Maar als het BTW-percentage verandert van 19 naar 21, moet je het hele programma doorlopen om te kijken waar dit percentage wordt gebruikt. Je kunt nu menen dat je in één keer alle "19" kunt vervangen door "21", maar wie zegt dat in je programma niet de waarde "19" toevallig voor iets anders wordt gebruikt? Daarom is het goed om een constante te gebruiken. Als het BTW-percentage verandert, hoef je alleen maar de constante aan te passen en het hele programma is weer up-to-date.
De declaratie van constanten kent twee expliciete vormen:
De eerste vorm gebruik je voor een lokale constante, bijvoorbeeld in een subroutine. Zo'n constante kan alleen binnen die subroutine gebruikt worden.
De tweede vorm gebruik je voor een globale constante, die gebruikt kan worden in het hele programma.

## Een voorbeeld met variabelen en constanten

Het volgende programma vraagt naar de straal van een cirkel en geeft vervolgens de straal, de diameter en de oppervlakte van de cirkel.
Omdat er geen foutcontrole plaatsvindt, moet de gebruiker van het programma er op letten dat alleen een geldig getal wordt opgegeven.
Je ziet hierboven tweemaal CSng staan. Hiermee wordt een waarde omgezet naar een single.
Als je het programma uitvoert en als straal de waarde 1,5 opgeeft, dan zal de uitvoer zijn:
Let weer op het verschil: in het programma wordt de decimale punt gebruikt en de gebruiker gebruikt de decimale komma, terwijl de uitvoer ook de decimale komma gebruikt.

## Gereserveerde woorden

Je bent volledig vrij in het kiezen van de namen van variabelen. Maar er is één uitzondering. Een naam mag niet gelijk zijn aan een gereserveerd woord. Deze gereserveerde woorden zijn woorden die binnen Visual Basic een speciale betekenis hebben. Als je zo'n gereserveerd woord gebruikt als de naam van een variabele, weet de compiler niet meer wat de bedoeling is. Bepaalde andere woorden zijn niet verboden, maar kunnen leiden tot onduidelijkheid en worden daarom afgeraden.
Onderstaande woorden zijn zogenaamde gereserveerde woorden en zijn onderdeel van de Basic-taal. Daarnaast bevat de lijst woorden die niet gereserveerd zijn, maar waarvan het gebruik tot grote onduidelijkheid leidt. Deze woorden zijn cursief. Vetgedrukte sleutelwoorden zijn afkomstig uit vroegere Basic-versies. Ze worden niet meer gebruikt, maar zijn nog steeds gereserveerd.
AddHandler
AdressOf
Aggregate
Alias
And
AndAlso
Ansi
As
Assembly
Async
Auto
Await
Binary
Boolean
ByRef
Byte
ByVal
Call
Case
Catch
CBool
CByte
CChar
CDate
CDbl
CDec
Char
CInt
Class
CLng
CObj
Compare
Const
Continue
CSByte
CShort
CSng
CStr
CType
CUInt
CULng
CUShort
Custom
Date
Decimal
Declare
Default
Delegate
Dim
DirectCast
Distinct
Do
Double
Each
Else
ElseIf
End
EndIf
Enum
Equals
Erase
Error
Event
Exit
Explicit
False
Finally
For
Friend
From
Function
Get
GetType
GetXMLNamespace
Global
GoSub
GoTo
Group
Handles
If
Implements
Imports
In
Inherits
Integer
Interface
Into
Is
IsFalse
IsNot
IsTrue
Iterator
Join
Key
Let
Lib
Like
Long
Loop
Me
Mid
Mod
Module
MustInherit
MustOverride
MyBase
MyClass
Namespace
Narrowing
New
Next
Not
Nothing
NotInheritable
NotOverridable
Object
Of
Off
On
Operator
Option
Optional
Or
OrderBy
OrElse
Out
Overloads
Overridable
Overrides
ParamArray
Partial
Preserve
Private
Property
Protected
Public
RaiseEvent
ReadOnly
ReDim
REM
RemoveHandler
Resume
Return
SByte
Select
Set
Shadows
Shared
Short
Single
Skip
Static
Step
Stop
Strict
String
Structure
Sub
SyncLock
Take
Then
Text
Throw
To
True
Try
TryCast
TypeOf
UInteger
ULong
Unicode
Until
UShort
Using
Variant
Wend
When
Where
While
Widening
With
WithEvents
WriteOnly
Xor
Yield
#Const
#Else
#ElseIf
#End
#ExternalSource
#If
#Region

## De scope van variabelen

Iedere variabelen heeft een bepaald bereik. Als een variabele in een procedure is gedeclareerd, is die variabele ook alleen binnen die procedure bekend. Als je in een andere procedure die variabele gebruikt, krijg je een foutmelding dat de variabele onbekend is (niet gedeclareerd). Je kunt ook variabelen op module-niveau declareren. Dit doe je door de DIM-opdracht direct na de regel met Module te plaatsen. Zo'n variabele is dan bekend in de gehele module, dus ook binnen alle procedures binnen die module.
Variabelen die binnen een procedure gedeclareerd zijn, noemen we lokale variabelen. Ze zijn alleen geldig binnen de betreffende procedure. Variabelen die direct na Module zijn gedeclareerd, noemen we globale variabelen. Ze zijn geldig in de hele module.
Een voorbeeld om dit te verduidelijken:
var1 is op module-niveau gedefinieerd en is dus bekend in de hele module, dus in sub1, funct1 en funct2. var2 is een lokale variabele binnen sub1 en is dus bekend in sub1 en funct1 (omdat funct1 onderdeel is van sub1), maar niet in funct2. var3 is een lokale variabele binnen funct1 en is alleen bekend binnen funct1, maar niet in de rest van sub1. var4 is een lokale variabele binnen funct2 en is alleen bekend binnen funct2.
Naast Dim kunnen variabelen ook gedeclareerd worden met Private en Public. Dit gebeurt meestal binnen klassen (die komen later aan de orde). Private is te vergelijken met Dim: de scope is dan beperkt. Bij variabelen die Public gedeclareerd zijn, is de scope het hele programma. Dus zelfs als je programma uit meerdere modulen bestaat en in één module een variabele als Public gedeclareerd is, is die variabele bekend bij alle modulen.

## De scope van procedures

Ook procedures hebben een scope. In bovenstaand voorbeeld is funct1 allen bekend binnen sub1. Maar het is ook mogelijk om een procedure globaal te declareren:
Subroutine sub2 is als Public gedeclareerd en kan nu ook buiten sub1 worden aangeroepen. Zo bevat de klasse Math veel subroutines die als Public zijn gedeclareerd, zodat alle programma's er gebruik van kunnen maken.