Variabelen

De data die we in een programma gebruiken bewaren we in een variabele van een bepaald datatype. Een variabele is een plekje in het geheugen dat in je programma zal gereserveerd worden om daarin data te bewaren van het type dat je aan de variabele hebt toegekend.

Een variabele heeft een geheugenadres, namelijk de plek waar de data in het geheugen staat. Maar het zou lastig programmeren zijn indien je steeds dit adres moest gebruiken. Daarom moeten we ook steeds een naam oftewel identifier aan de variabele geven. Op die manier kunnen we eenvoudig de geheugenplek aanduiden en hoeven we niet te werken met een lang hexadecimaal geheugen adres (bv. 0x4234FE13EF1).

Een variabele is een gereserveerd plekje in het geheugen. Jij spreekt dat plekje aan met de identifier, de computer met het geheugenadres.

Tip

De identifier van de variabele moet uiteraard voldoen aan de identifier regels zoals eerder besproken.

Variabelen aanmaken en gebruiken

Om een variabele te maken moeten we deze declareren, door een type en naam te geven. Vanaf dan zal de computer een hoeveelheid geheugen voor je reserveren waar de inhoud van deze variabele in kan bewaard worden. Hiervoor dien je minstens op te geven:

  1. Het datatype (bv. int, double).
  2. Een identifier zodat de variabele uniek kan geïdentificeerd worden volgens de naamgevingsregel van C#.
  3. (optioneel) Een beginwaarde die de variabele krijgt bij het aanmaken ervan.

Een variabele declaratie heeft als syntax:

datatype identifier;

Enkele voorbeelden:

int leeftijd;
string leverAdres;
bool isGehuwd;

Indien je weet wat de beginwaarde moet zijn van de variabele dan mag je de variabele ook reeds deze waarde toekennen bij het aanmaken:

int mijnLeeftijd = 37;
Tip

Je mag ook meerdere variabelen van het zelfde datatype in 1 enkele declaratie aanmaken door deze met komma’s te scheiden:

datatype identifier1, identifier2, identifier3;

Bijvoorbeeld string voornaam, achternaam, adres;

Waarden toekennen aan variabelen

Van zodra je een variabele hebt gedeclareerd kunnen we dus ten allen tijde deze variabele gebruiken om een waarde aan toe te kennen, de bestaande waarde te overschrijven, of de waarde te gebruiken, zoals:

  • Waarde toekennen: Herinner dat de toekenning steeds gebeurt van rechts naar links: het deel rechts van het gelijkheidsteken wordt toegewezen aan het deel links er van, bijvoorbeeld: mijnGetal = 15;
  • Waarde gebruiken: Bijvoorbeeld anderGetal = mijnGetal + 15;
  • Waarde tonen op scherm: Bijvoorbeeld Console.WriteLine(mijnGetal);

Met de toekennings-operator (=) kan je een waarde toekennen aan een variabele. Hierbij kan je zowel een literal toekennen oftewel het resultaat van een expressie .

Je kan natuurlijk ook een waarde uit een variabele uitlezen en toewijzen (kopiëren) aan een andere variabele:

int eenAndereLeeftijd = mijnLeeftijd;

Literals

Literals zijn expliciet neergeschreven waarden in je code. De manier waarop je een literal schrijft in je code zal bepalen wat het datatype van die literal is:

  • Gehele getallen worden standaard als int beschouwd, vb: 125.
  • Kommagetallen (met punt .) worden standaard als double beschouwd, vb: 12.5.

Wil je echter andere getaltypes dan int of double een waarde geven dan moet je dat dus expliciet in de literal aanduiden. Hiervoor plaats je een suffix achter de literalwaarde. Afhankelijk van deze suffix duidt je dan aan om welke datatype het gaat:

  • U of u voor uint, vb: 125U (dus bijvoorbeeld uint aantalSchapen = 27u;)
  • L of l voor long, vb: 125L.
  • UL of ul voor ulong, vb: 125ul.
  • F of f voor float, vb: 12.5f.
  • M of m voor decimal, vb: 12.5M.

Naast getallen zijn er uiteraard ook nog andere datatypes waar we de literals van moeten kunnen schrijven:

Voor bool zijn dit enkel true en false.

Voor char wordt dit aangeduid met een enkele apostrof voor en na de literal. Denk maar aan char laatsteLetter = 'z';.

Voor string wordt dit aangeduid met aanhalingsteken voor en na de literal. Bijvoorbeeld string myPoke = "pikachu".

Tip

Om samen te vatten, even de belangrijkste literal schrijfwijzen op een rijtje:

int getal = 5;
double anderGetal = 5.5;
uint nogAnderGetal = 15u;
float kleinKommaGetal = 158.9f;
char letter = 'k';
bool isDitCool = true;
string zin = "Ja hoor";

De overige types sbyte, short en ushort hebben geen literal aanduiding. Volgende code mag dus toch:

sbyte start = 127;

Dit wordt toegestaan omdat 127 een literal is: de compiler ziet al tijdens het compileren dat die waarde binnen het bereik van een sbyte past en zet ze stilletjes om.

Tip

Let op: dit lukt enkel omdat het om een vaste literal gaat die de compiler op voorhand kan controleren. Zet je dezelfde waarde eerst in een int-variabele, dan weigert de compiler:

int x = 127;
sbyte y = x; //FOUT: een int past niet zomaar in een sbyte

De compiler kan dan immers niet garanderen dat de waarde van x binnen het bereik van een sbyte blijft. Hoe je dat soort omzettingen wél forceert (een cast) zie je verderop.

Bij sbyte start = 127; staat de waarde zwart op wit in de code en kan de compiler ze nakijken. Bij sbyte y = x; moet hij afgaan op het type int, en dat past niet in een sbyte.

Literal toewijzen

Als je in je code expliciet de waarde 4 wilt toekennen aan een variabele dan is het getal 4 in je code een zogenaamde literal.

Voorbeelden van een literal toekennen:

int temperatuurGisteren = 20; //20 is de literal
int temperatuurVandaag = 25; //25 is de literal

Het is belangrijk dat het type van de literal overeenstemt met dat van de variabele waaraan je deze zal toewijzen. Volgende code zal dan ook een compiler-fout genereren. Je probeert een string-literal aan een int-variabele wil toewijzen, en omgekeerd:

string eenTekst;
int eenGetal;
eenTekst = 4;
eenGetal = "4";

Als je bovenstaande probeert te compileren dan krijg je volgende foutboodschappen:

Foutboodschap wanneer je literals toekent van een verkeerd datatype.

Foutboodschap wanneer je literals toekent van een verkeerd datatype.
Hexadecimale en binaire notatie

Je kan ook hexadecimale notatie (starten met 0x of 0X) gebruiken wanneer je bijvoorbeeld met int of byte werkt:

int mijnLeeftijd = 0x0024; //36
byte mijnByteWaarde = 0x00C9; //201

Ook binaire notatie (starten met 0b of 0B) kan:

int mijnLeeftijd = 0b001001000; //72
int andereLeeftijd = 0b0001_0110_0011_0100_0010 //idem, maar met _ als seperator

Deze schrijfwijzen kunnen handig zijn wanneer je met binaire of hexadecimale data wilt werken.

Beginwaarden van variabelen

Het is een goede gewoonte om variabelen steeds ogenblikkelijk een beginwaarde toe te wijzen. C# verplicht je daar zelfs toe voor de variabelen die we nu gebruiken: een lokale variabele (een variabele die je binnen Main of een andere methode declareert) moet een waarde gekregen hebben vóór je ze uitleest. Doe je dat niet, dan weigert de compiler te bouwen met de fout “use of unassigned local variable”:

int getal;
Console.WriteLine(getal); //FOUT: 'getal' is nog niet toegekend

In sommige oudere programmeertalen krijg je in dat geval een volledig willekeurige beginwaarde, met vreemde bugs tot gevolg. C# beschermt je daartegen. Geef je variabelen dus altijd meteen een waarde, al was het maar om je literals te oefenen.

Tip

Verderop in dit boek leer je instantievariabelen kennen (variabelen die bij een object horen, zie het hoofdstuk over klassen). Die krijgen, in tegenstelling tot lokale variabelen, wél automatisch een standaard beginwaarde afhankelijk van het datatype:

  • Voor getallen is dat steeds de nulwaarde (dus 0 bij int, 0.0 bij double, enz.).
  • Bij variabelen van het type bool is dat false.
  • Bij char is dat de literal \0 (in het volgende hoofdstuk leggen we die vreemde backslash uit).
  • En bij tekst is dat de lege string-literal "" (maar je mag ook String.Empty gebruiken).

Een lokale variabele blijft leeg tot jij er zelf een waarde in stopt. Een instantievariabele krijgt meteen de standaardwaarde van haar type.

Stagiair Steven

Stagiair Steven is weer lui geweest. Hij moet de lengte en breedte van een kamer bijhouden, allebei voorlopig 5 meter en heeft volgende code gekregen van de A.I.:

int lengte, breedte = 5;
Console.WriteLine(lengte);
Console.WriteLine(breedte);

“Eén regel voor twee variabelen, allebei 5. Lekker compact”, denkt hij.

Wat toont deze code echt? Zal deze code werken?

Deze code compileert niet eens: lengte krijgt hier helemaal geen waarde, en Console.WriteLine(lengte) geeft de fout “use of unassigned local variable ‘lengte’”.

Bij int lengte, breedte = 5; declareer je twee variabelen op één regel, maar het = 5 hoort enkel bij breedte, de laatste van het rijtje. Wil je allebei 5, dan moet je dat ook allebei apart zeggen: int lengte = 5, breedte = 5;.

Steven las de komma als “en dus ook”, en de A.I. liet hem in die veronderstelling.

Nieuwe waarden overschrijven oude waarden

Wanneer je een reeds gedeclareerde variabele een nieuwe waarde toekent dan zal de oude waarde in die variabele onherroepelijk verloren zijn. Probeer dus altijd goed op te letten of je de oude waarde nog nodig hebt of niet. Wil je de oude waarde ook nog bewaren dan zal je een nieuwe, extra variabele moeten aanmaken en daarin de nieuwe waarde moeten bewaren:

int temperatuurGisteren = 20;
temperatuurGisteren = 25;

In dit voorbeeld zal er voor gezorgd worden dat de oude waarde van temperatuurGisteren (20) overschreven zal worden met 25.

Volgende code toont hoe je bijvoorbeeld eerst de vorige waarde kunt bewaren en dan overschrijven:

int temperatuurGisteren = 20;
//Doe van alles
//...
//Vervolgens: vorige temperatuur in eergisteren bewaren
int temperatuurEerGisteren = temperatuurGisteren; 
//temperatuur nu overschrijven
temperatuurGisteren = 25; 

We hebben aan het einde van het programma zowel de temperatuur van eergisteren (20), als die van gisteren (25).

Links verdwijnt de 20 op het moment dat je 25 toekent. Rechts staat de 20 eerst in een tweede variabele en blijft ze dus bewaard.

Belangrijk

Een veel gemaakte fout is variabelen meer dan één keer declareren. Dit mag niet! Van zodra je een variabele declareert is deze bruikbaar in de scope (zie hoofdstuk 5) tot het einde. Binnen de scope van die variabele kan je geen nieuwe variabele aanmaken met dezelfde naam (zelfs niet wanneer het type anders is).

Volgende code zal dus een fout geven:

double kdRating = 2.1;
//even later...
double kdRating = 3.4; 

De foutboodschap vertelt duidelijk wat het probleem is: A local variable or function named ‘kdRating’ is already defined in this scope.

Lijn 3 moet dus worden:

kdRating = 3.4;