Konstanter
En konstant er en variabel, som tildeles en værdi ved erklæring, og som efterfølgende ikke kan rettes igen.
Information til undervisere
- Kursisterne skal udover at forstå begrebet “konstanter” også forstå enums i C# (relaterede konstanter)
- De bør løse opgaven
Simple konstanter
Erklæring af en enkelt konstant sker ligesom erklæring af en almindelig variabel med tilføjelse af const-kodeordet, samt en tildeling:
const int antalMåneder = 12;
const int juleDag = 24;
const int juleMåned = 12;
const double moms = 0.25;
const string farve = "Rød";
Herefter kan konstanterne benyttes, som var det almindelige variabler, men kan blot ikke tildeles en ny værdi:
const int juleDag = 24;
const int juleMåned = 12;
DateTime jul2019 = new DateTime(2019, juleMåned, juleDag);
const double moms = 0.25;
double prisFørMoms = 200;
double prisEfterMoms = 200 * (1 + moms);
moms = 0.15; // FEJL – kan ikke kompilere
Indbyggede simple konstanter
Du vil uden tvivl falde over konstanter, som Microsoft stiller til rådighed. Det klassiske eksempel er konstanten for Pi, som kan findes under System.Math:
double radius = 7;
// radius opløftet i anden x PI
double areal = System.Math.Pow(radius, 2) * System.Math.PI;
Når du ser en konstant i Visual Studio, har de et specielt ikon:
Settings
Nogle gange er konstanter ikke noget man ønsker at sætte i kode men i stedet i en konfigurationsfil eller environment variabel - se evt Konfigurationsfiler eller environment variabler.
Relaterede konstanter
En anden type konstant er en decideret typedefinition, som gør det muligt at gruppere relaterede konstanter. Det gør koden langt mere læsbar, samt nem at både skrive og vedligeholde.
Forestil dig, at du skal skrive kode, der repræsenterer en person med navn, alder og køn:
Bemærk, at køn er en int og dermed i princippet kan have værdier fra -2.1 milliard til +2.1 milliard. Vi vedtager dog, at værdien 0 repræsenterer en mand, og værdien 1 en kvinde. Det er helt ok og fuldt lovligt, men vi skal sørge for, at vi tydeligt dokumenterer hvad 0 og 1 betyder for dem, der skriver og læser koden. Det kan naturligvis gøres i koden som kommentarer, men det bliver hurtigt svært at styre.
Derfor har du mulighed for at definere relaterede konstanter i en typedefinition en gang for alle, og så lade kompileren og Visual Studio (Code) hjælpe med at benytte konstanterne.
Denne type hedder en enum (forkortet fra enumeration) og er en af de typer, du kan definere i C# (enum, class, struct, interface, poster og dele-gate). Når du definerer en enum, skaber du en skabelon for, hvordan instanser skal se ud, og en enum består udelukkende af konstanter med navne og værdier:
Hvis du skal definere en enum, der indeholder konstanter til kønnet på en person, kan den eksempelvis skrives således:
Du behøver dog ikke angive typen (int er default):Og hvis du ikke angiver et nummer, vil kompileren nummerere konstanterne fra 0:
Det mest normale er, at definering af typer placeres i en fil for selv og typisk med samme navn:
Denne type kunne således placeres i en fil kaldet personkøn.cs.
Brug af enum
Når du har defineret en enumeration, kan den benyttes på samme måde som en int eller en anden type – så koden fra tidligere:
kan nu erstattes med det langt mere logiske og læsbare:Det er ligeledes langt nemmere at skrive i Visual Studio (Code), fordi den godt ved, at der er tale om en relateret konstant:
Typekonvertering
Hvis du ønsker at tildele en enum-variabel en værdi fra et nummer (eksempelvis et nummer fra en database eller fil), skal du foretage en typekonvertering:
// hvis nummeret er et heltal
int nr1 = 1;
PersonKøn køn1 = (PersonKøn)nr1;
// hvis nummeret er en streng er det lidt mere komplekst
string nr2 = "1";
PersonKøn køn2 = (PersonKøn)Enum.Parse(typeof(PersonKøn), nr2);
Så du kan godt komme fra tal til enum og retur igen.
Overvejelser om brugen af enums
Enums er understøttet af et heltalstalstype, oftest int
, repræsenterer hver enum
-medlem en talværdi, hvilket gør enum
-typer til et kraftfuldt værktøj for at skabe klar og læsbar kode. Dog, denne forbindelse til heltalstyper fører også til særlige overvejelser, når det kommer til at arbejde med enum
-værdier.
Som standard er hvert enum
-medlem i C# baseret på int
-typen og starter fra 0, medmindre andet er specificeret. For eksempel:
Her får Rød
automatisk værdien 0, Grøn
værdien 1, og så videre. Det er denne underliggende integer-repræsentation, der gør det muligt at behandle enum
-værdier som tal.
Da enum
-værdier i bund og grund er integers, er det teknisk muligt at caste en hvilken som helst integer til en given enum
-type. Dette kan dog føre til ugyldige enum
-værdier, hvis det tal, der castes, ikke svarer til et defineret enum
-medlem:
For at håndtere sådanne tilfælde, er det vigtigt at validere enum
-værdier, før de bruges:
bool erGyldigFarve = Enum.IsDefined(typeof(Farve), f);
if (!erGyldigFarve)
{
// Håndter den ugyldige værdi passende
}
Validering af enum
-værdier er essentiel for at sikre, at din kode forbliver fejltolerant og nem at forstå. Ugyldige enum
-værdier kan føre til fejl og forvirrende resultater, især når de bruges i beslutningsprocesser eller komplekse beregninger. Korrekt validering forhindrer disse problemer og bidrager til mere robust og pålidelig kode.
Indbyggede relaterede konstanter
Microsoft har en del forskellige enums i frameworket, som du kan benytte, som du vil. Her er et par eksempler, men der er mange flere:
// ugedag
System.DayOfWeek dag = DayOfWeek.Saturday;
// farve til konsol
System.ConsoleColor farve = ConsoleColor.Cyan;
// drev type
System.IO.DriveType t = System.IO.DriveType.Network;
Brug af flag i enums
Enums kan også bruges til at repræsentere flag, hvor flere værdier kan kombineres. Dette er nyttigt, når du har en række indstillinger, der kan være aktive eller inaktive samtidig. For at gøre dette skal du bruge Flags
-attributten og definere værdierne som potenser af 2 (1, 2, 4, 8, osv.) - altså en binær repræsentation.
Her er et eksempel. Antag, at du arbejder med en applikation, der repræsenterer ting i forskellige farver, og du vil kunne vælge en eller flere farver på samme tid.
I dette eksempel repræsenterer hver farve en potens af 2, hvilket gør det muligt at kombinere farverne ved at tilføje deres værdier. For eksempel, hvis du vil repræsentere en ting, der er rød:
Eller en der er både rød og blå - det kan du gøre det ved at kombinere disse to farver med bitwise OR-operatoren (|
):
For at tjekke, om en bestemt farve er inkluderet i en kombination, kan du bruge bitwise AND-operatoren (&
):
På samme måde kan du tilføje eller fjerne farver fra en kombination ved at bruge bitwise OR- og XOR-operatoren:
Bemærk iøvrigt at Flags
-attributten ikke er nødvendig for at bruge flags. Det er blot en hjælp til at gøre det mere læsbart og forståeligt for andre, der læser din kode - og så giver ToString-metoden en pæn repræsentation af værdierne.
Brugen af flags i enums giver dig mulighed for at arbejde med kombinationer af værdier på en effektiv og letlæselig måde, hvilket er nyttigt i mange scenarier, hvor du har brug for at repræsentere flere indstillinger eller tilstande samtidig.
Info
Jeg bliver ofte spurgt hvorfor det er nødvendigt at lære det binære/hexadecimale talsystem. Dette er et godt eksempel på, hvorfor det er vigtigt. Hvis du ikke forstår, hvordan binære tal fungerer, vil det være meget svært at forstå, hvordan flags i enums fungerer.
Kombinationen af rød og blå:
For at tjekke om en farve er inkluderet i en kombination, bruger du bitwise AND-operatoren:
For at tilføje en farve til en kombination, bruger du bitwise OR-operatoren:
For at fjerne en farve fra en kombination, bruger du bitwise XOR-operatoren:
Det er faktisk ret simpelt, når du først forstår det binære talsystem.
Opgaver
- Prøv selv at lege med simple konstanter i en tom konsol applikation
- Se N122 Brug af enums