Wat leer je in dit hoofdstuk?

Na dit hoofdstuk kan je:

de C#-syntax en de rol van keywords uitleggen

geldige identifiers herkennen en variabelen volgens de conventies benoemen

de belangrijkste datatypes kiezen (int, double, bool, char, string, …)

variabelen declareren, initialiseren en literals correct schrijven

expressies en operators gebruiken, inclusief de valkuil van gehele deling

constanten gebruiken en de structuur van solutions en projecten uitleggen

C# als programmeertaal

Net als elke taal bestaat C# uit:

grammatica

de C#-syntax

woordenschat

de gereserveerde keywords

Een programma is een opeenvolging van statements, en elk statement eindigt op een puntkomma (;).

Eén statement = één lijn in je recept, het algoritme.

Een paar harde regels

Aa Hoofdlettergevoelig: Reinhardt en reinhardt zijn niet hetzelfde

; Puntkomma sluit elk statement af

Witruimte (spaties, tabs, enters) wordt genegeerd, behalve tussen " "

// Commentaar mag: // voor één lijn, /* ... */ voor een blok

Je code start altijd in Main

Uitvoering gaat van boven naar onder

Keywords: de woordenschat

C# heeft 80 gereserveerde keywords met een vaste, eenduidige betekenis

int   double   bool   string   if   for   while   class   void   return

Doorheen het boek leren we ze stelselmatig gebruiken.

Tip

C# is een levende taal. Nieuwe woorden komen erbij als contextual keywords (bv. get, set, value, var); de lijst van 80 echte keywords verandert niet.

Step away from the keyboard!

Don’t use goto!

goto is een officieel keyword, maar je ziet het in dit boek nooit.

  • Elk probleem los je op zonder goto
  • Voel je de drang? Don’t. Het is het niet waard.

Waarschuwing

NEVER EVER USE GOTO. Enneuh, ik hou je in ’t oog hoor.

Variabelen, identifiers en naamgeving

Variabelen

Een variabele is een geheugenplekje waarin we tijdelijk data bewaren (bv. gebruikersinput).

het nummer op de deur: het geheugenadres

het naambordje dat jij erop plakt: de identifier

de maat van het kluisje: het datatype

wat erin zit: de waarde, altijd maar één

Variabelen aanmaken

Bij het aanmaken geef je minstens twee zaken mee:

een identifier

de gebruiksvriendelijke naam voor die geheugenplek

een datatype

wat voor soort data erin mag

optioneel: meteen een beginwaarde

int mijnLeeftijd = 37;

Identifier en geheugenadres

Jij spreekt het kluisje aan met de identifier, de computer met het geheugenadres.

Regels voor identifiers

Terug in de gym

Identifiers: mag het of niet?

werknemer

ja

kerst2018

ja

pippo de clown

nee (spaties)

4dPlaats

nee (start cijfer)

_ILOVE2022

ja

Tor+Bjorn

nee (+)

class

nee (keyword)

Naamgeving: de conventies

Duidelijke naam

liever gewicht of leeftijd dan a of meuh

camelCasing bij meerdere woorden

elk volgend woord met een hoofdletter, het eerste woord met een kleine letter

int leeftijdTimDams;
int aantalLeerlingenKlas1EA;

Welk kluisje vind jij morgen nog terug?

Commentaar

//De start van het programma
int getal = 3;
int result = getal * 5;
Console.WriteLine(result); //resultaat: 15

/*
    Dit is blok-commentaar
    over meerdere lijnen
*/

// zet alles tot het einde van de lijn in commentaar

/* */ zet een volledig blok in commentaar

Handig om tijdelijk code “uit te schakelen”

Datatypes

Datatypes in C#

C# is een strongly typed language: je legt van bij de start vast welk soort data een variabele bevat.

Tip

Anders dan in JavaScript kan data hier niet zomaar van vorm veranderen. Dat is soms strenger, maar bespaart je veel gevloek.

Datatypes (vervolg)

In dit boek gebruiken we types voor:

gehele getallen

sbyte, byte, short, ushort, int, uint, long, ulong

kommagetallen

double, float, decimal

tekst

char, string

booleans

bool

Elk datatype is een doosje waar maar één soort data in past.

Gehele getallen

Geheugen Met teken (signed) Enkel positief (unsigned)
8 bits sbyte: -128 tot 127 byte: 0 tot 255
16 bits short: -32 768 tot 32 767 ushort: 0 tot 65 535
32 bits int: ca. -2,1 tot +2,1 miljard uint: 0 tot ca. 4,3 miljard
64 bits long: ca. -9,2 tot +9,2 triljoen ulong: 0 tot ca. 18,4 triljoen

Een u vooraan = unsigned: ushort, uint en ulong zijn de positieve versies van de gewone types

byte is de uitzondering: die is al positief, dus heet de versie met teken sbyte (s = signed)

Tip

Dubbel zoveel bits verdubbelt het bereik niet, het kwadrateert het: 256 waarden bij een byte, 65 536 bij een short. Bij twijfel kies je gewoon int.

Kies je kluisje

Elk volgend type neemt dubbel zoveel geheugen in.

Signed of unsigned

Bij elk signed type, hier een short, gaat het eerste bitje naar het teken.

Moet ik dit allemaal kennen?

“Wow, moet ik al die datatypes vanbuiten kennen? Ik was al blij dat ik tekst op het scherm kon tonen.”

Nee. Onthoud de belangrijkste, en door veel te programmeren ontdek je vanzelf welk type waar past. Laat je niet afschrikken door de ellenlange tabellen: we gebruiken er maar een handvol.

Een trein met 256 assen

In Zwitserland mag een trein niet exact

256

assen hebben. Waarom?

De asteller

255 assen: spoor bezet

As 256: teller op 0, spoor vrij

Opgelost met een regel in het reglement, niet met een groter datatype.

Kommagetallen

Type Geheugen Sterkte
float 32 bits kleinst
double 64 bits grootste bereik
decimal 128 bits hoogste precisie (28-29 cijfers)

decimal vooral voor financiële en wetenschappelijke code

Precisie = aantal beduidende cijfers (2.2345 heeft precisie 5)

Tip

Bij twijfel kies je voor kommagetallen double.

Bereik, precisie of geheugen

Elk type wint op precies één van de drie criteria. Het rode balkje toont welk.

Bool, char en string

bool: het eenvoudigste type, enkel true of false (neemt 1 byte in)

onmisbaar bij beslissingen (if) vanaf een later hoofdstuk

char: één enkel karakter (zie volgende hoofdstuk)

string: een stuk tekst (een reeks van chars)

Waarschuwing

Weet je dat een variabele maar twee waarden kan hebben? Gebruik dan een bool, geen int. Scheelt geheugen en is duidelijker.

4 KB naar de maan

De boordcomputer van Apollo 11 had

4 KB

werkgeheugen.

Je smartphone: miljoenen keren meer.

Met de hand geweven

Koperdraad door het ringetje: 1. Errond: 0.

Bugs eruit halen kon niet meer. Dus: veeeeeelvuldig testen.

Variabelen

Variabelen declareren

Declareren = type + identifier opgeven

int leeftijd;
string leverAdres;
bool isGehuwd;

Optioneel meteen een beginwaarde toekennen:

int mijnLeeftijd = 37;

Toekenning gaat van rechts naar links: het deel rechts van = gaat naar links.

Tip

Meerdere variabelen van hetzelfde type mogen op één lijn: string voornaam, achternaam, adres;

Literals

Een literal is een waarde die je letterlijk neerschrijft. De schrijfwijze bepaalt het type:

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

Gehele getallen zijn standaard int, kommagetallen standaard double

Suffixen: u (uint), L (long), f (float), m (decimal)

Geef altijd een beginwaarde

Een lokale variabele (binnen Main) moet een waarde hebben voor je ze uitleest:

int getal;
Console.WriteLine(getal); //FOUT: use of unassigned local variable

Stagiair Steven

Steven laat zijn code door A.I. schrijven. Lengte en breedte zijn allebei 5 meter:

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

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

Belangrijk

Dit compileert niet eens. Het = 5 hoort enkel bij breedte, de laatste van het rijtje. lengte blijft zonder waarde: use of unassigned local variable. Wil je allebei 5, schrijf dan int lengte = 5, breedte = 5;

Waarden overschrijven

Een nieuwe waarde wist de oude onherroepelijk:

int temperatuurGisteren = 20;
temperatuurGisteren = 25; //20 is weg

Op de tweede lijn staat geen type: je kent een nieuwe waarde toe, je declareert niet opnieuw.

Belangrijk

Declareer een variabele maar één keer. double kdRating = 2.1; gevolgd door double kdRating = 3.4; geeft already defined in this scope.

Eerst kopiëren, dan overschrijven

Heb je de oude waarde nog nodig, zet ze dan eerst in een tweede variabele.

Puzzel: wissel twee variabelen om

Je hebt twee variabelen. Hoe wissel je hun waarden om?

int a = 3;
int b = 5;
// gewenst: a wordt 5, b wordt 3

Belangrijk

a = b; b = a; werkt niet: na a = b is de oude waarde van a al weg.

Puzzel: de oplossing

Bewaar de oude waarde eerst in een hulpvariabele:

int hulp = a; // bewaar 3
a = b;        // a wordt 5
b = hulp;     // b wordt 3

Gangnam Style en de viewteller

YouTube telde views in een int, en dat gaat tot

2 147 483 647

Genoeg voor elke video, toch?

“We never thought a video would be watched in numbers greater than a 32-bit integer (=2,147,483,647 views), but that was before we met PSY.”

De teller werd vervangen door een 64 bits long.

Expressies en operators

Operators en operanden

Een expressie is een reeks bewerkingen die uitkomt op één resultaat met een type. 3 + 2 geeft 5 (type int).

Volgorde van berekeningen, net als in de wiskunde:

  1. Haakjes
  2. *, /, %
  3. +, -
3 + 5 * 2     // 13
(3 + 5) * 2   // 16

Een expressie ontleed

In 3 + 2 zijn 3 en 2 de operanden en is + de operator.

Een echte berekening

Hoeveel zou je wegen op Mars?

double gewichtOpAarde = 80.3; //kg
double gAarde = 9.81;
double gMars = 3.711;
double gewichtOpMars = (gewichtOpAarde / gAarde) * gMars;
Console.WriteLine($"Je weegt op Mars {gewichtOpMars} kg");
Je weegt op Mars 30,376483180428128 kg

Literals, variabelen en operators samen, met haakjes om de volgorde af te dwingen.

Modulo: de rest na deling

De %-operator geeft de gehele rest van een deling:

int rest = 7 % 2;   // 1  (7 = 3*2 + 1)
int rest2 = 10 % 5; // 0

Tip

% 2 is dé manier om te testen of een getal even is: is de rest 0, dan is het even.

Waar komt de rest vandaan?

De linkse operand staat links van de streep, de rechtse rechts. Wat onderaan overblijft, geeft % terug.

Verkorte notaties

getal++;    // getal = getal + 1
getal--;    // getal = getal - 1
getal += 3; // getal = getal + 3
getal *= 7; // getal = getal * 7

Compacter om te lezen, niet sneller. getal++ zie je overal (zeker in lussen), dus je moet het vlot kunnen lezen.

Voor of achter de variabele?

int getal = 1;
int som = getal++;  // som wordt 1, getal wordt 2
int som2 = ++som;   // som2 wordt 2, som wordt 2

Belangrijk

  • som++ (achteraan): geef eerst de waarde terug, dan verhogen
  • ++som (vooraan): eerst verhogen, dan de nieuwe waarde teruggeven

getal++ of ++getal

Links geeft getal eerst zijn waarde af, rechts verhoogt het eerst.

Opletten geblazen

Zet je helm op. Als je de volgende sectie goed begrijpt, heb je een grote stap gezet.

Variabelen zijn het hart van programmeren. Expressies zijn het bloedvatensysteem dat ze combineert tot iets nieuws.

Expressiedatatypes

Het type van een expressie

De types die je in een expressie gebruikt, bepalen het type van het resultaat.

int result = 3 + 4;       // int + int = int, ok
int fout = 3.1 / 45.2;    // FOUT: double past niet in int

int + int geeft een int. Een double kan je niet zomaar aan een int toewijzen.

De val: gehele deling

int getal1 = 9;
int getal2 = 2;
int result = getal1 / getal2;
Console.WriteLine(result);
4

Waarschuwing

Op het scherm verschijnt 4, niet 4.5.

int / int geeft altijd een int

C# kapt alles na de komma af (truncatie), het rondt niet af. Ook 4.9 wordt zo 4.

De beurs van Vancouver

Januari 1982: een nieuwe beursindex op

1000

3000 keer per dag herberekend, en telkens afgekapt. Waar staat hij bijna twee jaar later?

524,811

afgekapt

1098,892

juist berekend

Datatypes mengen

Meng je een int met een double, dan kiest C# het grootste type (hier double):

double result = 3 / 5.6;  // ok
int    fout   = 3 / 5.6;  // FOUT: double past niet in int

Wil je 9 / 2 als 4.5, zet dan minstens één operand op double:

double getal2 = 2.0; //slim he
double result = 9 / getal2; // 4.5

Krijg jij de helft van mijn salaris?

Ik verdien 10 000 euro per maand (I wish) en geef je de helft:

double helft = 10000.0 * (1 / 2);

Hoeveel krijg je? 0.0 euro. MUHAHAHA.

1 / 2 is een gehele deling en geeft 0. Pas dit aan:

double helft = 10000.0 * (1.0 / 2); // 5000.0

Constanten

Met const maak je een variabele onveranderlijk:

const double G_AARDE = 9.81;
G_AARDE = 10.48; //ERROR, al bij het compileren

Conventie: een const in ALLCAPS met liggende streepjes

Vermijd losse magic numbers: geef ze een duidelijke naam

Voor in het labo: 1 solution, meerdere projecten

Solutions en projecten

Visual Studio organiseert je code in een hiërarchie:

een solution is een map met één of meer projecten

een project bundelt codebestanden tot één uitvoerbaar geheel

Daarom raden we aan om “Place solution and project in the same directory” niet aan te vinken.

Solution > project.

Waarschuwing

Een .sln-bestand bevat geen code. Wil je je werk delen, geef dan de hele folderstructuur mee.

Conclusie

C# = syntax (grammatica) + keywords (woordenschat); statements eindigen op ;

Een variabele = identifier + datatype; geef ze altijd meteen een beginwaarde

Kies je datatype bewust: int en double als veilige standaard

Expressies volgen de wiskundige volgorde, maar let op int / int: dat kapt af

const maakt waarden onveranderlijk; solutions bundelen projecten

Tip

Volgende halte: alles over tekst: char, string en hun trucjes.

Meer weten

Kennisclips

Oefeningen H2 · Quizlet flashcards

Zie verder

Hoe doen andere programmeertalen hetzelfde? En een korte zoek-de-fout, om zo kritisch mogelijk naar code te leren kijken.

Zie verder: zoek de fout

Onderstaande C#-code wil de helft van een prijs berekenen, maar toont altijd 0. Wat loopt er mis?

int prijs = 5;
double helft = prijs * (1 / 2);
Console.WriteLine(helft);

Opmerking

1 / 2 is een deling van twee gehele getallen, en die geeft opnieuw een geheel getal: 0, niet 0.5. De vermenigvuldiging wordt dan 5 * 0, dus 0. Dat helft een double is, helpt niet: de fout zit al in de int-deling die ervoor gebeurt. Maak minstens één kant een kommagetal, bijvoorbeeld prijs * (1.0 / 2).

Zie verder: andere talen

Dezelfde concepten uit dit hoofdstuk, maar dan in andere talen. Je hoeft die talen niet te kennen: het gaat om het herkennen van het patroon, ook al ziet de syntax er anders uit.

Belangrijk

Steeds vaker laat je een A.I. een eerste versie schrijven en moet je die daarna lezen, beoordelen en bijsturen. Zo’n A.I. spuwt even vlot Python, JavaScript of C++ uit als C#.

Zie verder: types in Python

In Python geef je nooit een type op. Diezelfde variabele mag later zelfs een ander soort data bevatten:

x = 5        # x is een geheel getal
x = "hallo"  # nu tekst, Python klaagt niet

In C# blijft een int een int: regel twee zou hier een compilatiefout geven.

Handig om te weten: zo’n stukje Python kan je nu al grotendeels lezen, ook al schrijf je het zelf nog niet.

Zie verder: getaltypes elders

Die hele waaier integer-types deelt C# met C en C++: ook daar kies je tussen short, int, long, … omdat geheugen telt.

JavaScript doet het omgekeerde: één enkel getaltype number, altijd een 64-bit kommagetal.

let leeftijd = 25;   // intern een kommagetal
let prijs = 19.99;   // exact hetzelfde type

Handig, maar het verklaart waarom JS onnauwkeurig wordt bij heel grote gehele getallen.

Zie verder: bestaat bool overal?

Niet vanzelfsprekend. De oude C-standaard had geen booleantype: men gebruikte een int, met 0 als false en al de rest als true.

int klaar = 0;        /* false */
if (klaar) { /* ... */ }   /* draait niet */

C# (net als Java en Python) maakt van true en false echte, aparte waarden, zodat je geen getal per ongeluk als conditie gebruikt.

Zie verder: const in Python

Python kent geen echt const-keyword. Een naam in ALLCAPS is er enkel een afspraak, geen regel die de taal afdwingt.

G_AARDE = 9.81   # afspraak: niet wijzigen
G_AARDE = 10.48  # Python staat dit gewoon toe

In C# vangt de compiler die tweede regel meteen op: de taal dwingt de belofte af.

Samenvattende poster

Een handige samenvattende poster (Opgelet: gemaakt m.b.v. ChatGPT Image Gen 2).