Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Nu we de elementaire zaken van C# en Visual Studio kennen is het tijd om onze programma's wat interessanter te maken. De ontwikkelde programma's tot nog toe waren steevast lineair van opbouw, ze werden lijn per lijn uitgevoerd zonder de mogelijkheid om de flow van het programma aan te passen. Het programma doorliep de lijnen braaf na elkaar en wanneer deze aan het einde kwam sloot het programma zich af.
Onze programma's waren met andere woorden niet meer dan een eenvoudige oplijstingen van opdrachten. Je kan het vergelijken met een lijst die je vertelt over hoe je een brood moet kopen: 1. Neem geld uit spaarpot 2. Wandel naar de bakker om de hoek 3. Vraag om een brood 4. Krijg het brood 5. Betaal het geld aan de bakker 6. Keer huiswaarts 7. Smullen maar
Alhoewel dit algoritme redelijk duidelijk en goed zal werken, zal de realiteit echter zelden zo goed zijn. Een beter algoritme (dat foutgevoeliger is én interactieve voor de eindgebruiker) zal afhankelijk van de omstandigheden (bakker gesloten, geen geld meer, etc.) mogelijke andere stappen ondernemen. Het programma zal beslissingen maken.
De locatie waar je een variabele aanmaakt bepaald de scope, oftewel de zichtbaarheid, van de variabele. Eenvoudig gezegd zullen steeds de omliggende accolades de scope van de variabele bevatten. Indien je de variabele dus buiten die accolades nodig hebt dan heb je een probleem: de variabele is enkel bereikbaar binnen de accolades vanaf het punt in de code waarin het werd aangemaakt.
Zeker wanneer je begint met if
, loops, methoden, etc. zal de scope belangrijk zijn: deze code-constructies gebruiken steeds accolades om codeblocks aan te tonen. Een variabele die je dus binnen een if-blok aanmaakt zal enkel binnen dit blok bestaan, niet erbuiten.
Wil je dus getal ook nog buiten de if
gebruiken zal je je code moeten herschrijven zodat getal
VOOR de if
wordt aangemaakt:
De scope van variabelen is soms wat verwarrend maar wel een onderdeel dat je deze hele cursus zal zien terugkomen.
Hopelijk kan volgende kennisclip je helpen: Kennisclip "Scope van variabelen.
Zolang je in de scope van een variabele bent kan je geen nieuwe variabele met dezelfde naam aanmaken:
Volgende code is dus niet toegestaan:
Je krijgt de error: A local variable named 'getal' cannot be declared in this scope because it would give a different meaning to 'getal', which is already used in a 'parent or current' scope to denote something else
Enkel de tweede variabele een andere naam geven is toegestaan in het voorgaande geval.
Dit is wel geldig, daar de scope van de eerste variabele afgesloten wordt door de accolades:
Delen van dit hoofdstuk komen uit Visual C# 2012 - De basis (Sander Gerz)
Dit is nog zo'n onderschat hoofdstuk. Enums zijn wat raar in het begin, maar van zodra je er mee weg bent zal je niet meer zonder kunnen!
Stel dat je een programma moet schrijven dat afhankelijk van de dag van de week iets anders moet doen. In een wereld zonder enums (enumeraties) zou je dit kunnen schrijven op 2 zeer foutgevoelige manieren: 1. Met een int
die een getal van 1 tot en met 7 kan bevatten 2. Met een string
die de naam van de dag bevat
De waarde van de dag staat in een variabele int dagKeuze
. We bewaren er 1 in voor Maandag, 2 voor dinsdag, enzovoort.
Deze oplossing heeft 2 grote nadelen:
Wat als we per ongeluk dagKeuze
een niet geldige waarde geven, zoals 9, 2000, -4, etc. ?
De code is niet erg leesbaar. dagKeuze==2
? Was dat nu dinsdag of woensdag (want misschien was maandag 0 i.p.v. 1).
De waarde van de dag bewaren we nu in een variabele string dagKeuze
. We bewaren de dagen als "maandag"
, "dinsdag"
, etc.
De code wordt nu wel leesbaarder dan met 1, maar toch is ook hier 1 groot nadeel:
De code is veel foutgevoeliger voor typfouten. Wanneer je "Maandag"
i.p.v. "maandag"
bewaard dan zal de if al niet werken. Iedere schrijffout of variant zal falen.
Enumeraties (enum) zijn een C# syntax die bovenstaand probleem oplost en het beste van beide samenvoegt: leesbaardere code en visual studio kan je helpen met minder foutgevoelige foute schrijven.
Het keyword enum
geeft aan dat we een nieuw type maken dat maar enkele mogelijke waarden kan hebben. Nadat we dit nieuwe type hebben gedefiniëerd kunnen we variabele van dit nieuwe type aanmaken. De variabele die we dan later maken zal van dit type zijn en enkel de opgegeven waarden mogen bevatten. Ook zal IntelliSense van Visual Studio je de mogelijke waarden helpen invullen.
In C# zitten al veel Enum-types ingebouwd. Denk maar aan ConsoleColor
: wanneer je de kleur van het lettertype van de console wilt veranderen gebruiken we een enum-type. Er werd reeds gedefinieerd wat de toegelaten waarden zijn, bijvoorbeeld: Console.ForegroundColor = ConsoleColor.Red;
Zelf een enum
type maken gebeurt in 2 stappen: 1. Het type en de mogelijke waarden definiëren 2. Variabele(n) van het nieuwe type aanmaken en gebruiken in je code
We maken eerst een enum type aan. In je console-applicaties moet dit binnen class Program
gebeuren, maar niét binnen de (main
) methoden:
Vanaf nu kan je variabelen van het type Weekdagen
aanmaken.
Merk op dat er geen puntkomma achteraan komt.
Locatie enum definitie
Let er op dat je je enum
op de juiste locatie in je code schrijft:
Dit is fout:
We kunnen nu variabelen van het type Weekdagen
aanmaken. Bijvoorbeeld:
En vervolgens kunnen we waarden aan deze variabelen toewijzen als volgt
Kortom: we hebben variabelen zoals we gewoon zijn, het enige verschil is dat we nu beperkt zijn in de waarden die we kunnen toewijzen. Deze kunnen enkel de waarden zijn die in het type gedefiniëerd werden. De code is nu ook een pak leesbaarder geworden.
Ook de beslissingsstructuren worden leesbaarder:
of een switch:
Intern worden de enum-variabelen als ints bewaard. In het geval van de Weekdagen
zal maandag de waarde 0 krijgen, dinsdag 1, etc.
Volgende conversies met behulp van casting zijn dan ook perfect toegelaten:
Wil je dus bijvoorbeeld 1 dag bijtellen dan kan je schrijven:
Standaard worden de waarden dus genummerd intern beginnende bij 0, enz. Je kan dit ook manueel veranderen door bij het maken van de enum
expliciet aan te geven wat de interne waarde moet zijn, als volgt:
De dagen zullen nu vanaf 1 genummerd worden, dus WeekDagen.Woensdag
zal de waarde 3 hebben.
We kunnen ook nog meer informatie meegeven, bijvoorbeeld:
In dit geval zullen Maandag tot Vrijdag intern als 1 tot en met 5 bewaard worden, Zaterdag als 50, en Zondag als 60.
Je kan perfect leven zonder enum
. Vele programmeurs voor je hebben dit bewezen. Echter, van zodra ze enum
ontdekten (en begrepen) zijn nog maar weinig programmeurs ervan af gestapt.
De eerste kennismaking met enumeraties is wat bevreemdend: je kan plots je eigen datatypes aanmaken?! Van zodra je ze in de vingers hebt zal je ontdekken dat je veel leesbaardere code kunt schrijven én dat Visual Studio je kan helpen met het opsporen van bugs.
Wanneer gebruik je enum
? Telkens je een variabele (of meerdere) nodig hebt waarvan je perfect op voorhand weet welke handvol mogelijke waarde ze mogen hebben. Ze worden bijvoorbeeld vaak gebruikt in finite state machines. Bij game development willen we bijhouden in welke staat het programma zich bevindt: intro
, startmenu
, ingame
, gameover
, optionsscreen
, etc. Dit is een typisch enum
verhaal. We definiëren hiervoor het volgende type:
En vervolgens kunnen we dan met een eenvoudige switch in ons hoofdprogramma snel de relevante code uitvoeren:
Om beslissingen te kunnen nemen in C# hebben we een nieuw soort operators nodig. Operators waarmee we kunnen testen of iets waar of niet waar is. Dit doen we met de zogenaamde relationele operators. En guess what, je kent die al van uit het lager! Enkel de "gelijk aan" ziet er iets anders uit dan we gewoon zijn:
De logische EN, OF en NIET-operatoren die je kent van de booleaanse algebra kan je ook gebruiken in C#:
Je kan de niet-operator voor een expressie zetten om het resultaat hiervan om te draaien. Bijvoorbeeld:
Een booleaanse expressie is een stuk C# code dat een bool
als resultaat zal geven.
De logische operators van hierboven zijn operators die een bool
teruggeven. Ze zijn zogenaamde test-operators: ze testen of iets waar is of niet. "Is b kleiner dan c?" schrijf je dan als de booleaanse expressie: b<c
Test maar eens wat er op je scherm komt als je in code schrijft: Console.WriteLine(45<=55);
.
Zoals verwacht zal er true
op het scherm verschijnen.
Wat zal de uitkomst zijn van volgende expressies? (protip: het zal steeds true
of false
zijn, niets anders)
3>2
4!=4
4<5 && 4<3
"a"=="a" || 4>=3
(3==3 && 2<1) || 5!=4
!(4<=3)
true || false
!true && false
Voorgaande oefeningen komen uit een vorige kennistoets examen. Het is voornaam dat je dit soort expressies vlot kunt oplossen!
conditionele boodschappen
Deze opgave bouwt verder op H3-BMI-berekenaar. Meerbepaald moet je de gebruiker niet alleen zijn of haar BMI tonen, maar moet je ook een gekleurde boodschap tonen die laat weten of de BMI goed zit of niet.
Voor een BMI lager dan 18,5 toon je de boodschap "ondergewicht" in rode tekst. Voor een BMI die hoger ligt dan 18,5 maar lager dan 25, toon je de boodschap "normaal gewicht" in groene tekst. Voor een hogere BMI, maar lager dan 30, toon je in gele tekst "overgewicht". Voor een hogere BMI, maar lager dan 40, toon je "zwaarlijvig" in rode tekst. Voor een hogere BMI toon je "ernstige obesitas" in magenta.
Via if
en else
(en dus ook else if
) kan je gevallen onderscheiden. Gebruik ConsoleColor.Red
, ConsoleColor.Green
, ConsoleColor.Yellow
en ConsoleColor.Magenta
.
console applicatie
De tekst zou in het groen moeten verschijnen maar Gitbook staat dit niet meteen toe.
conditionele berekeningen
Maak een programma dat aan de gebruiker vraagt hoeveel paar schoenen hij wenst te kopen. Ieder paar schoenen kost normaal 20 euro. Indien de gebruiker 10 paar of meer koopt, kost elk paar maar 10 euro. Toon aan de gebruiker de totale prijs.
Breid in een tweede stap je programma uit zodat gevraagd wordt vanaf welk aantal schoenen de prijs daalt naar 10 euro.
Hou variabelen bij voor de prijs, de gereduceerde prijs en het aantal paar dat nodig is om korting te krijgen. De eerste twee variabelen maak je const
.
console applicatie
(Na de uitbreiding)
conditionele berekeningen
De wet van Ohm houdt in dat een elektrische stroom (voorgesteld als I
) gelijk is aan een spanningsverschil (U
) gedeeld door een weerstand (R
), dus I = U / R.
Vraag aan de gebruiker wat hij wenst te berekenen: Spanning, Weerstand of Stroomsterkte. Vraag vervolgens de twee andere waarden (als dus de gebruiker "Spanning" kiest vraag je aan de gebruiker de stroomsterkte en de weerstand) en bereken m.b.v. de wet van Ohm de gewenste waarde en toon aan de gebruiker.
Denk eraan dat de gegeven formule wiskundig gedefinieerd is. In C♯ zal je rekening moeten houden met het feit dat deze drie maten uitgedrukt kunnen worden in kommagetallen.
Je mag hier gewoon strings gebruiken om na te gaan welke maat de gebruiker heeft ingetypt. Je mag veronderstellen dat de getallen uitgedrukt zijn in de gewoonlijke eenheden (volt, ampère, ohm) zodat je ze gewoon kan invullen in de formule.
console applicatie
conditionele berekeningen
geneste condities
De gebruiker voert een jaartal in en jouw programma toont of het wel of geen schrikkeljaar is. Een schrikkeljaar is deelbaar door 4, behalve als het ook deelbaar is door 100, tenzij het wél deelbaar is door 400.
gebruik de modulo-operator (%
) om deelbaarheid door 4 na te gaan
gebruik een constructie met geneste if
s (en else
s) om alle gevallen af te handelen
console applicatie
conditionele berekeningen
werken met switch
Deze oefening bouwt voort op H2-weerstandberekenaar-deel1. Vraag nu aan de gebruiker om de ringkleuren van de eerste 3 ringen in te voeren als tekst (bv groen
). Toon vervolgens de de waarde van deze weerstand.
Je zal elke kleur moeten omzetten in een getal en dan je eerdere oplossing hergebruiken. Omzetten doe je door de ingevoerde tekst te vergelijken met een vaste string en naargelang het resultaat variabelen voor ring 1, 2 en 3 in te vullen. Los deze oefening op met switch
!
console applicatie
Voel je je vandaag extra leergierig? Maak dan een extra enum
, ResistorColors
en zet de ingegeven tekst om naar waarden binnen deze enum
vooraleer je de berekening uitvoert.
conditionele berekeningen
werken met switch
werken met enumeraties
Je mag veronderstellen dat de huidige leeftijd onder het theoretische maximum ligt.
Gebruik een enum
, met als naam Sexes
en als waarden Male
en Female
om de geslachten voor te stellen.
Het programma zou in dit geval misschien iets simpeler zijn zonder, maar dan gebruik je dit een eerste keer.
Je kan vermijden dat de voorspelde leeftijd te hoog gaat door je .Next
-call aan te passen, zodat de hoogst mogelijke waarde diegene is waarbij je de maximale leeftijd voor het gegeven geslacht bereikt.
console applicatie
Dit is een complexere oefening dan de vorige! Pak het stapje voor stapje aan en gebruik indien nodig de debugger.
werken met enumeraties
conversie van enums van en naar getallen
werken met switch
Deze opgave bouwt verder op H1-ruimte. Eerst vraag je de gebruiker om zijn of haar gewicht in te voeren. Daarna geef je een lijst van de planeten in ons zonnestelsel (Pluto inbegrepen, ook al is dat officieel geen planeet). Iedere planeet wordt voorafgegaan door een nummer. Dan selecteert de gebruiker het nummer van een van deze planeten en ten slotte toont het programma hoe veel de persoon weegt op de planeet in kwestie.
Je hebt hier verschillende zaken nodig:
conversie naar een double
om een gewicht in te lezen
een enum
om de planeten voor te stellen
conversie van de planeten naar getallen om de gebruiker een nummer voor elke planeet te tonen
conversie in de omgekeerde richting om de keuze van de gebruiker te verstaan
een switch
om de juiste vermenigvuldigingsfactor te bepalen
console applicatie
In dit deel zullen we bekijken hoe we ons programma dynamischer kunnen maken met behulp van het if-statement.
De if
is een van de elementairste constructies in een programmeertaal. De syntax is als volgt:
Enkel indien de booleaanse expressie waar is, en dus true
als resultaat heeft, zal de code binnen de accolades van het if-blok uitgevoerd worden. Indien de expressie niet waar is (false
) dan wordt het blok overgeslagen en gaat het programma verder met de code eronder.
Een voorbeeld:
De uitvoer van dit programma zal zijn:
Indien number
groter of gelijk aan 5 was dan zou er enkel B
op het scherm zijn verschenen. De lijn Console.WriteLine("B")
zal sowieso uitgevoerd worden zoals je ook kan zien aan de volgende flowchart:
Het is aangeraden om steeds na de if-expressie met accolades te werken. Dit zorgt ervoor dat alle code tussen het block (de accolades) zal uitgevoerd worden indien de booleanse expressie waar was. Gebruik je geen accolades dan zal enkel de eerste lijn na de if
uitgevoerd worden bij true
.
Een voorbeeld:
De booleaanse expressie die je tussen de if
haakjes plaats moet een stuk code zijn dat altijd een bool
als resultaat teruggeeft.
We verwachten dat je if
altijd met een block gebruikt, omdat dat leesbaarder is. De versie zonder block zien we als een stijlfout!
Er zijn enkele veelgemaakte fouten waar je op moet letten:
De types in je booleanse expressie moeten steeds vergelijkbaar zijn. Volgende code is dus fout: if( "4" > 3)
daar we hier een string
met een int
vergelijken.
Accolades vergeten plaatsen om een codeblock aan te duiden, maar je code toch zodanig outlinen (met tabs) dat het lijkt of je een heel codeblock hebt. Het gevolg zal zijn dat enkel de eerste lijn na de if
zal uitgevoerd worden indien true
. Gebruiken we de if
met block van daarnet maar zonder accolades dan zal de laatste lijn altijd uitgevoerd worden ongeacht de if
:
Merk ook op dat je code anders uitlijnen géén invloed heeft op de uitvoer (wat bijvoorbeeld wel zo is bij de programmeertaal Python).
Dit zal ervoor zorgen dat er eigenlijk geen codeblock bij de if
hoort en je dus een nietszeggende if
hebt geschreven. De code na het puntkomma zal uitgevoerd worden ongeacht de if
:
Met de relationele operatoren (==
, !=
, <
, >
, <=
en >=
) kunnen we complexere expressies schrijven die als uitkomst waar (true
) of niet waar (false
) geven.
Een voorbeeld:
Uitvoer van bovenstaande code zal zijn:
We kunnen ook meerdere expressies combineren zodat we complexere uitdrukkingen kunnen maken. Hierbij kan je gebruik maken van de logische operatoren (&&
, ||
, !
) .
Een voorbeeld:
Uitvoer van dit programma zal zijn:
Met if
/else
kunnen we niet enkel zeggen welke code moet uitgevoerd worden als de conditie waar is maar ook welke specifieke code indien de conditie niet waar (false
) is. Volgend voorbeeld geeft een typisch gebruik van een if
/else
structuur om 2 waarden met elkaar te vergelijken:
Kan je zelf een flowchart van bovenstaande code tekenen? Try it!
Met een if
/else if
constructie kunnen we meerdere criteria opgeven die waar/niet waar moeten zijn voor een bepaald stukje code kan uitgevoerd worden. Sowieso begint men steeds met een if
. Als men vervolgens een else if
plaats dan zal de code van deze else if
uitgevoerd worden enkel en alleen als de eerste expressie (van de if
) niet waar was en de expressie van deze else if
wel waar is.
Een voorbeeld:
Merk op dat else if
niet meer is dan een verkorte schrijfwijze voor nesting van een if
in een else
-block.
We kunnen met behulp van nesting ook complexere programma flows maken. Hierbij gebruiken we de accolades om het blok code aan te duiden dat bij een if
/else if
/else
hoort. Binnen dit blok kunnen nu echter opnieuw if
/else if
/else
structuren worden aangemaakt.
Volgende voorbeeld toont dit aan (bekijk wat er gebeurt als je emergencyValve aan closed
gelijkstelt):
Vul de oefening aan uit het vorige hoofdstuk (zie ). Voor het orakel je vertelt hoe lang je te leven hebt zal eerst vragen naar je geslacht, dat je ingeeft als v
of m
. Dan vraagt ze je leeftijd. Mannen leven maximum tot hun 120 jaar. Vrouwen tot 150 jaar. Het orakel moet rekening houden met je huidige leeftijd, dus het mag niet zeggen dan een man nog 110 jaar te leven heeft als hij al 50 is, want dan zou hij ouder worden dan 120.
C#-syntax | Betekenis |
| groter dan |
| kleiner dan |
| gelijk aan |
| niet gelijk aan |
| kleiner dan of gelijk aan |
| groter dan of gelijk aan |
C#-syntax | Betekenis |
| en-operator |
| of-operator |
| niet-operator |
Een switch
statement is een program-flow element om een veelvoorkomende constructie van if
/if else
...else
elementen eenvoudiger te tonen. Vaak komt het voor dat we bijvoorbeeld aan de gebruiker vragen om een keuze te maken (bijvoorbeeld een getal van 1 tot 10, waarbij ieder getal een ander menu-item uitvoert van het programma), zoals:
Met een switch
kan dit eenvoudiger. De syntax van een switch
is een beetje specialer dan de andere programma flow-elementen (if
, while
, etc.), namelijk als volgt:
value
is de waarde of variabele (beide mogen) die wordt gebruikt als test in de switch. Iedere case begint met het case
keyword gevolgd door de waarde die value moet hebben om in deze case te springen. Na het dubbelpunt volgt vervolgens de code die moet uitgevoerd worden in deze case
. De case
zelf mag eender welke code bevatten (methoden, nieuwe program flow elementen, etc.), maar moet zeker afgesloten worden met het break
keyword.
Tijdens de uitvoer zal het programma value
vergelijken met iedere case constant van boven naar onder. Wanneer een gelijkheid wordt gevonden dan wordt die case uitgevoerd. Indien geen case wordt gevonden die gelijk is aan value dan zal de code binnen de default
-case uitgevoerd worden (de else
achteraan indien alle vorige if else
-tests negatief waren).
Het menu van zonet kunnen we nu herschrijven naar een switch
:
De case waarden moeten literals zijn. Dit zijn waarden die je letterlijk uitschrijft, d.w.z. die je niet voorstelt als variabele (1
, "1"
, 1.0
, 1.d
, '1'
, etc.)
Soms wil je dat dezelfde code uitgevoerd wordt bij 2 of meer cases. Je kan ook zogenaamde fallthrough cases beschrijven wat er als volgt uit ziet:
In dit geval zullen zowel de waarden 2
en 3
resulteren in de zin "Laden of opslaan gekozen" op het scherm.