298
Poul Klausen C# 1 Introduktion til programmering og sproget C# Download free books at

,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

  • Upload
    lediep

  • View
    236

  • Download
    6

Embed Size (px)

Citation preview

Page 1: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Poul Klausen

C# 1Introduktion til programmering og sproget C#

Download free books at

Page 2: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

2

Poul Klausen

C# 1 Introduktion til programmering og programmeringssproget C#

Page 3: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

3

C# 1: Introduktion til programmering og programmeringssproget C#© 2012 Poul Klausen & bookboon.com (Ventus Publishing ApS)ISBN 978-87-403-0236-3

Page 4: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

Click on the ad to read more

C# 1: Introduktion til programmering og programmeringssproget C#

4

Indhold

Indhold

Forord 11

Del 1 Introduktion til C# 14

1 Indledning 15 Exam01 Hello World 15

2 Grundlæggende programarkitektur 20 Exam02 Print en bog 20

3 Variabler 23 Exam03 Summen af to tal 25 Exam04 Operatorer 26

4 Konsolprogrammer 29 Exam05 Omkreds og areal af en cirkel 29 Exam06 Vareberegning 31 Exam07 Dato og klokkeslæt 33 Exam08 Argumenter på kommandolinjen 34

SÆT LYD PÅ FREMTIDENWidex udvikler højteknologiske høreapparater til gavn for de 500 millioner mennesker verden over, der har nedsat hørelse.

Mere end fem årtiers intensiv forskning og udvikling har gjort os til en af verdens førende høreapparatproducenter, og vi udvikler digital teknologi af en kvalitet, kun få kan måle sig med.

Som videnbaseret virksomhed betragter vi medarbejderne som vores vigtigste kapital. Vi kan godt lide at gøre tingene selv og sætter en ære i at være selvforsynende inden for de fl este om-råder. Det skaber et spændende, tværfagligt arbejdsmiljø med plads til initiativ og rig mulighed for personlig og faglig udvikling.

Vil du være med til at sætte lyd på fremtiden? Følg med i vores jobopslag på www.widex.dk/job eller skriv til [email protected]

www.widex.com

Page 5: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

Click on the ad to read more

C# 1: Introduktion til programmering og programmeringssproget C#

5

Indhold

5 Programkontrol 36 if 37 Exam09 Sorter to tal 37 if-else 40 Exam10 En anden grads ligning 41 while 44 Exam11 Summen af de positive tal mindre end 100 44 for 47 Exam12 Sum af positive heltal 48 do 49 switch 50 Exam13 Ugedag 50 Exam14 Tværsum 51 Exam15 Det største og det mindste tal 55

6 Strenge 58 Exam16 Klassen String 59 Exam17 Palindrom 61

7 Arrays 65 Exam18 To arrays af typen int 65

Dedicated Analytical Solutionswww.foss.dk/careers

Protein 13.2%

Moisture 8.4%

Starch 67%

FOSS is known throughout the world for efficient analytical solutions that help to improve both food quality and safety in the global food market. We are playing an increasingly important role in ensuring optimal use of valuable natural resources, and have throughout the years created ground-breaking innovations. And there’s more to come. At FOSS you will find professional challenges, training and development in a work environment that offers good work/ life balance. Join us and make a difference.

80% of the grain traded in the world is analysed on a FOSS solution

Page 6: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

Click on the ad to read more

C# 1: Introduktion til programmering og programmeringssproget C#

6

Indhold

Exam19 Array af strenge 67 Exam20 Yatzy 67 Exam21 Craps 69

Del 2 Objektorienteret programmering 73

8 Klasser 76 Exam22 Mønter 76

9 Design af klasser 84 Exam23 Terninger 85

10 Metoder 92 Metoders navne 92 Exam24 Funktionsoverstyring 92 Metoders returværdier 94 Properties 95 Exam25 Et Punkt 95 Parametre 97 Exam26 Metoders parametre 102

11 Arv 103

HD – vejen tilen karrierei erhvervslivet

Læs mereAarhus: hd.au.dkHerning: auhe.au.dk/hd

LÆS HD I ØKONOMI OG LEDELSE

HD er en anerkendt diplom- uddannelse, som giver dig mulighed for at specialisere dig inden for det erhvervsøkonomiske fagområde ved siden af dit job.

Page 7: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

Click on the ad to read more

C# 1: Introduktion til programmering og programmeringssproget C#

7

Indhold

Exam31 Punkter 103 Exam27 Personer 105

12 Klassen Object 113

13 Abstrakte klasser 117 Exam32 Abstrakte punkter 117 Exam29 Lån 119

14 Interfaces 127 Exam33 Punkter igen 127 Exam30 Penge 128

15 Statiske medlemmer 138 Exam34 StringBuilder 139

16 Mere om arrays 143 Exam35 Flerdimensionale arrays 145

17 Typer 149

18 Enum 158

19 Struct 160

������������� ����������������������������������������������� �� ���������������������������

������ ������ ������������������������������ ����������������������!���"���������������

�����#$%����&'())%�*+����������,����������-

.��������������������������������� ��

���������� ���������������� ������������� ���������������������������� �����������

The Wakethe only emission we want to leave behind

Page 8: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

Click on the ad to read more

C# 1: Introduktion til programmering og programmeringssproget C#

8

Indhold

20 Generiske typer 165 Generiske metoder 165 Exam38 Sortering af et array 166 Parametriserede typer 171 Exam40 Klassen Set 173

21 Exception handling 181 SystemException 187

22 Kommentarer 189

23 Extension metoder 195

Del 3 Collection klasser 198

24 List<T> 200 Exam45 List af strenge 201 Exam68 Indtast varesalg 202

25 Stack<T> og Queue<T> 207 Exam46 Stak af heltal 207 Exam69 StackSort 208 Kø 211

We are a global specialist in energy management represented in more than 100 countries. We provide technology and integrated solutions to optimise energy usage across multiple market segments. We are more than 130,000 colleagues worldwide and 1.000 of us are situated in Denmark.

We invest in our employees, in the environment and in the future. Each year 5% of our revenue is allocated for research and development activities. In Schneider Electric you have many career paths to choose from – also internationally.

Would you like take on the challenge of transforming the way people and organisations use energy?

Do you know Schneider Electric?

Meet us at: www.schneider-electric.dk/job

Page 9: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

Click on the ad to read more

C# 1: Introduktion til programmering og programmeringssproget C#

9

Indhold

26 LinkedList<T> 212 Exam48 LinkedList af navne 214

27 Dictionary<K,V> og SortedDictionary<K,V> 216 Exam49 Tabel over stillingsbetegnelser 217 Exam50 Brugerdefineret nøgle 219 Exam51 Et ordnet dictionary 221 Exam52 Sammenlignelige nøgler 221 Exam70 Stikordsliste 223

Del 4 IO 229

28 Tekstfiler 230 Exam51 Skriv og læs tekst 230 Exam54 Skriv en kommasepareret file 233 Exam55 Læs en kommasepareret file 236

29 Binære filer 238 Exam56 Print 100 tal til en fil 238 Exam57 Læs en binær file 239 Exam58 Seek 241

Vil du også stå på ski i fremtiden?

Verden har brug for nye løsninger, og Topsøe har de katalysatorer og teknologier, der kan løse centrale udfordringer på den globale agenda: verdens energi- og miljøudfordringer.

Vi har fart på. Vores løsninger skal fortsat udvikles, udbredes og implementeres på det globale marked. Derfor vil vi gerne have endnu flere kolleger, som vil være med til at skabe værdi og fremdrift.

Du får mulighed for fordybelse, kundekontakt og rejseaktivitet. Og adgang til en verden af viden.

Vi arbejder i en fri og uformel atmosfære. Vi er stolte af at tage ansvar og bidrage til et bedre miljø.

Vil du være med?

WWW.TOPSOE.COM/JOBS

Need for speed?

Page 10: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

Click on the ad to read more

C# 1: Introduktion til programmering og programmeringssproget C#

10

Indhold

30 Info om biblioteker og filer 243 Exam59 FileInfo 243 Exam60 DirectroryInfo 243

31 Objekt serialisering 245 Datatypes 245 Exam61 Binær serialisering 247 Exam62 Binær deserialisering 251 Exam63 XML serialisering 253 Exam64 SOAP serialisering 255 Exam65 Serialsering af en collection 257

32 Brugerdefineret serialisering 260

Del 5 Afsluttende eksempler 266 Lotto 266 Expression 278

IFRS 2012, Standarder og fortolk-ningsbidrag – på dansk fås nu både som trykt bog samt som e-bog til smartphone, tablet og pc.

Introduktionspris: e-bog og trykt bog kr. 1545,-

E-bog inkl. opdateringer i 2012

Læs mere og køb e-bogen sammen med den trykte bog her: shop.magnus.dk

REGNSKABIFRS 2012 – nu også som e-bog

– Nuogså som

e-bog

Page 11: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

11

Forord

ForordDenne bog er den første i en serie af bøger om udvikling af programmer til .NET platformen. Programmeringssproget er C#, og selv om bøgerne dermed har fokus på sproget C# og den valgte platform, så spiller programmering i almindelighed en stor rolle, og bøgerne har således også fokus på begreber som algoritmer, design og programkvalitet. Jeg har tilstræbt, at de enkelte bøger skal kunne læses uafhængige af hinanden, men den aktuelle bog eller tilsvarende stof må dog anses som en forudsætning for de efterfølgende, og det gælder i nogen udstrækning også C# 2.

Bøgerne henvender sig til alle, som ønsker at beskæftige sig med programmering i relation til .NET platformen, men bl.a. på grund af eksempelvalget er bøgerne primært tænkt som enten undervisnings- eller supplerende materiale på en videregående uddannelse. Bøgerne er ikke rettet mod nogen bestemt uddannelse, og det behøver ikke direkte at være en it uddannelse, men det kan også være andre uddannelser, hvor der indgår kurser i programmering. Endelig vil bøgerne kunne anvendes af professionelle softwareudviklere enten som inspiration eller som opslagsværk vedr. konkrete teknologier.

Bøgerne har et praktisk sigte, således at det primære mål er at vise, hvordan man gør. Der er naturligvis også mere teoretiske forklaringer, men jeg har bevist forsøgt at minimere det teoretiske stof, således at man hurtigt når frem til, hvad man skal skrive. Det meste af stoffet præsenteres gennem et stort antal eksempler og de forklaringer, som knytter sig hertil, og bøgerne er i stor udstrækning underinddelt svarende til disse eksempler. Alle eksemplerne har et intetsigende navn, som er navnet på det projekt, som de er oprettet under af udviklingsværktøjet, men i bogen har hvert eksempel en undertitel i form af et ord eller sætning, som kort fortæller, hvad eksemplet viser, forklarer eller omhandler. Der er referencer til disse undertitler i indholdsfortegnelsen.

Alle eksempler er udviklet ved hjælp af Visual Studio, men værktøjet er alene behandlet i den udstrækning, der er nødvendig for selv at kunne skrive programmer ved hjælp af Visual Studio. Selv om bøgerne godt kan læses med udbytte, hvis man anvender et andet udviklingsværktøj, så bygger bøgerne dog på, at man har Visual Studio til rådighed. Alle bøgernes eksempler ligger som færdige Visual Studio projekter til download fra forlagets hjemmeside. Projekterne hørende til en konkret bog downloades samlet som en zip fil.

Den aktuelle bog er, som det fremgår af titlen, en introduktion til programmeringen og sproget C#. Bogen kræver ikke særlige forudsætninger af læseren og henvender sig til alle, som har lyst eller behov for at lære om programmering. Det er således ikke en forudsætning, at læseren har kendskab til programmering, men kun at læseren interesserer sig for programmering og gerne har Visual Studio installeret på sin computer. Alle bogens eksempler er skrevet ved hjælp af Visual Studio 11 beta.

Page 12: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

12

Forord

Målet med bogen er sproget og programmering generelt og i det hele taget at behandle det basale, og hvad der er nødvendig viden, for selv at kunne skrive programmer. Derfor er alle eksempler simple konsolprogrammer. Når man skal give en introduktion til programmering kan man vælge

- udelukkende at se på konsolprogrammer, for på den måde at holde fokus på det grundlæggende stof vedr. programmering og sproget

- hurtigt at indføre det nødvendige til at kunne skrive programmer med en grafisk brugergrænseflade og dermed hurtigt at nå frem til at kunne skrive mere interessante og virkelighedsnære programmer

Jeg har valgt den første måde, fordi det andet har en tendens til at skjule det basale og næsten drukne alt det grundlæggende stof i de utroligt mange begreber og detaljer, der knytter sig til udvikling af et program med en grafisk brugergrænseflade. Det er simpelthen min erfaring, at det er den rigtige vej, og hvad der skal til for at skrive Windows programmer har derfor fået sin egen bog. Prisen er, at eksemplerne i denne bog virker lidt kedelige - alt afhængig af øjnene der ser. Man skal nu en gang starte et sted, og jeg vil meget anbefale, at man har det grundlæggende på plads, inden man tager fat på de mere avancerede emner. Det skal dog tilføjes, at man sagtens kan arbejde med stoffet i C# 3 efter at have læst denne bogs del 1 og 2.

Bogen er inddelt i 5 dele:

- Den første del er en kort introduktion til programmering og C#. Målet er at indføre alle de grundlæggende begreber uden at tage alle detaljer med. Sagt lidt anderledes er det målet, at man efter del 1 skulle være i stand til selv at kunne skrive simple konsolprogrammer.

- Del 2 omhandler objekt orienteret programmering, der dækker over den måde, som man programmerer i dag og de begreber, som knytter sig hertil. Stoffet i del 2 må anses som basisviden, der skal være på plads, for man er i stand til at kunne udvikle færdige applikationer i praksis.

- Del 3 omhandler collection klasser, der er en del af alle moderne sprog. Bogen har kun i begrænset udstrækning fokus på de enkelte klassers implementering og herunder fordele og ulemper, men fokus ligger i stedet på, hvordan klasserne anvendes. For en mere detaljeret gennemgang af klassernes karakteristiske egenskaber henvises til C# 7.

- Bogens fjerde del omhandler filer. Filer spiller ikke den samme rolle i praksis programmering som tidligere, men alligevel er der situationer, hvor det er nødvendigt at kunne arbejde med filer. Bogen har primært fokus på behandling af tekstfiler og objektserialisering. Har et program behov for at behandle større eksterne datamængder, vil det i praksis altid være i form af databaser, og her henvises til C# 4.

Page 13: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

13

Forord

- Endelig afsluttes bogen med del 5, som egent blot er to lidt større eksempler. Del 5 belyser således ikke nyt stof, og af hensyn fortsat læsning i andre bøger kan man udmærket springe denne del over. Målet er imidlertid at vise de mange begreber, som er omtalt i bogen, i en lidt større sammenhæng og samtidig også vise lidt om, hvordan man arbejde med programudvikling i et lidt større perspektiv og i forbindelse med problemstillinger, som er mere komplekse, end tilfældet er med boges øvrige eksempler.

Poul Klausen

Page 14: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

14

Introduktion til C#

Del 1 Introduktion til C#Et computerprogram er en familie af kommandoer, som udføres i en bestemt rækkefølge, og som tilsammen løser en konkret opgave. Et program skrives som et tekstdokument, der indeholder alle de nødvendige kommandoer. Dette dokument kaldes programkoden, kildekoden eller source koden. De enkelte kommandoer skal skrives på en meget præcis måde, for at computeren kan forstå dem, og det er her, at programmeringssprog kommer ind i billedet. Et programmeringssprog fastsætter præcise regler for, hvordan kommandoer skal skrives. Der findes mange programmeringssprog, og selv om de er forskellige med hver deres fordele og ulemper, er lighederne større end forskellene, og har man først lært sig et sprog, er det let at lære det næste. I det følgende anvendes overalt programmeringssproget C#, der er et udbredt sprog inden for Microsoft verdenen.

Som nævnt ovenfor skrives et program som et tekstdokument (i praksis flere eller mange) og er dermed blot et dokument med kommandoer. Kommandoer kaldes også for sætninger. Disse kommandoer eller sætninger, som jo blot er tekst, kan maskinen ikke umiddelbart udføre, men de skal først oversættes til et internt format, som computeren forstår. Denne proces kaldes oversættelse eller kompilering og udføres af et program, der kan omforme sætninger skrevet i et bestemt programmeringssprog til computerens interne kommandoer. Programmet kaldes sædvanligvis for en compiler. Under oversættelsen kontrolleres programmet for fejl, og er der fejl, får man en fejlmeddelelse, og fejlen må herefter rettes, inden programmet oversættes på ny. Det er ikke alle fejl, som findes under oversættelsen, men kun syntaksfejl, der dækker over de fejl, hvor en sætning ikke er skrevet i overensstemmelse med programmeringssprogets regler. Et oversat program kan således sagtens indeholde fejl, f.eks. en forkert beregning.

For at skrive et program skal man naturligvis lære det programmeringssprog, der er valgt, men desuden skal man lære, hvordan løsningen af en opgave kan formuleres ved hjælp af sprogets sætninger. Det er det sidste, der er det sværeste, og der er sjældent en entydig løsning. En løsning af et problem ved hjælp af et program kaldes også for en algoritme. Programmering er derfor i stor udstrækning et spørgsmål om at skrive algoritmer, noget som jeg vil vende tilbage til flere gange.

Når man skal skrive programmet, har man behov for et værktøj, der kan anvendes til indtastning af programkoden, og i princippet kunne man nøjes med Notesblok og så compileren, men i praksis vil man altid anvende et særligt udviklingsværktøj, da det gør arbejdet langt lettere. I det følgende vil jeg overalt anvende Visual Studio, som er Microsofts generelle udviklingsværktøj til en lang række forskellige opgaver og herunder at skrive programkode i C#. Det er en integreret programpakke, som indeholder alle de værktøjer, der er nødvendige til udvikling af en række forskellige programtyper.

Page 15: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

15

Indledning

1 IndledningC# er et objektorienteret programmeringssprog. Det fundamentale arkitekturelement i et program er en class eller klasse, og set fra programmørens synsvinkel består et C# program af en familie af klasser, der i forening definerer alle programmets egenskaber og funktionalitet. At skrive et program består således i at definere - designe - og skrive koden til programmets klasser. Intet kan i C# eksisterer uden for en klasse. Et program vil desuden altid anvende andre klasser, som ikke er skrevet af programmøren, men klasser der kommer fra .NET frameworket, og dermed er til programmørens rådighed som færdige komponenter.

Én af programmets klasser har en særlig rolle som programmets ”entry point”, og det sted hvor programmet starter, og denne klasse skal skrives med en særlig navngivning, men det er næsten også det eneste formelle krav, der stilles til arkitekturen af et C# program. Målet med dette kapitel er med et meget simpelt eksempel at vise, hvordan man skriver et program ved hjælp af Visual Studio.

Exam01 Hello World

Et godt sted at starte med et nyt programmeringssprog er det klassiske Hello World program, der blot printer en tekst skærmen. Dette program er efterhånden en obligatorisk del af enhver fremstilling af et programmeringssprog. Programmet kan skrives på følgende måde:

using System;

namespace Exam01{class Program{static void Main(string[] args){Console.WriteLine(“Hello World”);

}}

}

Kører man programmet, er resultatet:

Dvs. at programmet kører i et kommandovindue (en prompt), hvor det printer teksten Hello World på skærmen. Programmet laver altså ikke meget, men det er et fuldt færdigt program.

Page 16: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

Click on the ad to read more

C# 1: Introduktion til programmering og programmeringssproget C#

16

Indledning

Fremgangsmåde

Åben Visual Studio og i menuen vælger du File | New | Project

Page 17: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

17

Indledning

Her skal du:

- være sikker på at du har valgt sproget C#

- at du har markeret projekttypen Console Application

- at du har valgt det bibliotek, hvor programmets filer skal oprettes (her er det F:\Home\Prog01)

- at du har indtastet programmets navn (ovenfor er det Exam01)

Når du herefter klikker OK, vil Visual Studio oprette et skelet til et program:

using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;

namespace Exam01{class Program{static void Main(string[] args){}

}}

Faktisk er det et fuldt færdigt program, som kan køre på maskinen - det lavet blot ingenting.

Du skal dernæst skrive programmets kode, som vist i indledningen til eksemplet. I dette tilfælde skal du kun skrive en enkelt linje - en enkelt sætning:

static void Main(string[] args){Console.WriteLine(”Hello World”);

}

Herefter er programmet færdigt og kan afprøves. Fra menuen vælger du

Debug | Start Without Debugging

Forklaring

Bemærk først, at C# er case-sensitive, således at der overalt skelnes mellem store og små bogstaver.

Page 18: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

18

Indledning

Ethvert C# program består af mindst én klasse, der her hedder Program (navnet er valgt af Visual Studio). En klasse består af variabler og metoder. I dette tilfælde har klassen kun én metode, der hedder Main(), og som er den metode der kaldes, når programmet starter. En metode består af sætninger, der kan opfattes som kommandoer, som udfører et eller andet på maskinen. At en metode kaldes betyder, at dens sætninger udføres. Bemærk, at man foran metoden Main() skal skrive ordet static. Forklaringen på det følger senere. I dette tilfælde indeholder Main() kun en enkelt sætning, der skriver en tekst på skærmen. WriteLine() er faktisk en metode i klassen Console, som bl.a. repræsenterer skærmen. Når programmet kører, sker der ikke andet, end at WriteLine-sætningen i Main() udføres, som så printer en tekst på skærmen.

Bemærk, i C# skal hver sætning afsluttes med semikolon - ovenfor er der et semikolon efter WriteLine-sætningen. Det fortæller oversætteren, hvor en sætning slutter.

I C# grupperes klasser i såkaldte namespaces. System er et namespace, der indeholder mange klasser og herunder klassen Console. En klasses fulde navn består af det namespace, som klassen er grupperet under, samt klassenavnet, f.eks. System.Console. Når man i et program med using definerer et namespace, kan klasser i dette namespace refereres ved klassenavnet alene. Således kan man skrive

Console.WriteLine(”Hello World”);

i stedet for det fulde navn

System.Console.WriteLine(”Hello World”);

Visual Studio indsætter automatisk 5 using sætninger i koden og dermed referencer til 5 namespaces. I dette tilfælde er det kun System, der er nødvendig, og man må gerne slette de 4 andre (det har jeg gjort i den færdige version vist i starten af eksemplet). I princippet er der ikke nogen særlig grund til at slette unødvendige using sætninger, da de ikke har nogen betydning for det færdige program, så den eneste begrundelse for at slette dem er, at man muligvis på den måde gør koden mere læsbar.

Bemærkning

Visual Studio vil automatisk placere programmet i sit eget namespace, der her hedder Exam01. Hvis man skrev programmet ved anvendelse af en almindelig teksteditor, var det ikke nødvendigt at medtage dette namespace. Faktisk kan programmet skrives simplere end ovenstående. Nedenstående version af programmet er skrevet i Notesblok og gemt som en fil med navnet Hello.cs:

class Program{

static void Main(){System.Console.WriteLine(”Hello World”);

}}

Page 19: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

Click on the ad to read more

C# 1: Introduktion til programmering og programmeringssproget C#

19

Indledning

Hvis man herefter åbner en .NET prompt, kan programmet oversættes med kommandoen

csc Hello.cs

hvorefter der dannes en exe-file, som kan afprøves. Alle programeksempler i denne bog er imidlertid skrevet i Visual Studio, da gevinsten ved lidt større programmer er betydelig - ja faktisk er det det eneste fornuftige værktøj til udvikling af .NET programmer.

Tænker du også på fremtidens vand?

Så bliv en del af Nordens mest kompetente medarbejderstab specialiseret i vand.

Service | Value | Respo

nsib

ility

Vil du med på holdet?

Tjek vores jobside for ledige

stillinger og upload dit CV på

www.kruger.dk/da/job

Foto

: K

rüg

er

Sta

fett

en

rrn

ddn

dddn

dn

dddu

ndd

un

t o

t o

to

t ooo

t ooo

t o ot o

to

t ooo ooot ooo

t o

t o

too

t o

tm

CCm

Cm

Cm

CCm

Cm

Cm

CCm

CCm

Cm

Cm

CCm

CCCCCCCm

CCm

Cm

Cm

Cm

Cm

Cm

Cm

Cm

Cm

CCCmmmmmmmmmmmmmmmmm

hririiri

hri

hri

hri

hri

hririirii

hri

hriiiii

hri

hri

hri

hriiiirrr

hrr

hr

hr

hr

hrrrrrrrrrrrrrrrrrrr

hr

hrrrr

hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhst

ist

ist

ist

ist

ist

ist

ist

ist

ist

ist

ist

ist

ist

ist

ist

ist

ist

ist

ist

ist

ist

ist

ist

ist

ist

itisti

sti

sti

sti

sti

sti

stititistiiii

sti

sti

stii

sti

sti

sti

sti

sti

stiii

stii

stitistii

stii

sti

sstststststtsssssssssssn

sn

ssssssssn

sn

sa

ns

nssss

nss

ns

nss

an

sa

nss

nssss

an

sn

ssssa

ns

ns

an

sa

ns

an

ssn

ssa

nss

an

sa

ns

an

sa

nss

an

sa

ns

an

sa

ns

an

ssa

na

na

na

na

nnnnnna

na

na

nnnnna

nnnnnnnnna

nnnna

nna

na

nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnna

nnnnnnnnaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa

or

or

or

or

or

or

orr

or

or

orr

or

orrr

or

or

or

or

or

orr

orr

orr

or

orr

or

or

orr

oooooob

ooob

ob

oob

oob

ooobbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb

ggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggg

Page 20: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

20

Grundlæggende programarkitektur

2 Grundlæggende programarkitektur

Ovenstående eksempel viser i princippet den overordnede arkitektur for et C# program, nemlig en klasse, som har en Main() metode som start sted. Eksemplet var dog meget simpelt, da programmet kun bestod af en enkelt sætning i Main(). I dette afsnit vil jeg skrive et program, hvor der er flere sætninger, men også flere metoder. I det følgende eksempel er der ikke nogen særlig begrundelse for at opdele koden i metoder - kun at vise hvordan en metode skrives og kaldes i C# - men i andre sammenhænge er metoder ikke bare nyttige, de er også nødvendige, og derfor vil jeg helt fra starten inddrage metoder i eksemplerne.

Exam02 Print en bog

Målet er at skrive et program, der på skærmen kan printe oplysninger om en bog:

Fremgangsmåde

Åben Visual Studio og opret på samme måde som i Exam01 et Console Application projekt. Denne gang har jeg kaldt projektet Exam02, men ellers er alle indstillinger som ovenfor.

Visual Studio opretter igen et skelet til et program, og den færdige programkode er vist herunder:

using System;

namespace Exam02{class Program{static void Main(string[] args){Title();More();

}

private static void Title(){Console.WriteLine(”Pro C# 2010 and the .NET 4 Platform”);Console.WriteLine(”Andrew Troelsen”);

Page 21: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

21

Grundlæggende programarkitektur

Console.WriteLine(”ISBN: 978-1-4302-2549-2”);Console.WriteLine(”Apress”);

}

private static void More(){Console.WriteLine(”Fifth edition”);Console.WriteLine(”Published 2010”);Console.WriteLine(”1712 pages”);

}}

}

Programmet kan herefter oversættes og køre, og resultatet er et konsolvindue som vist ovenfor.

Forklaring

I princippet gør programmet det samme som Exam01: Det skriver tekst på skærmen, blot skrives der denne gang flere linjer. Desuden er print sætningerne placeret i metoder, der kaldes fra Main().

En metode har - foreløbig - formen:

private static void MetodeNavn(){// sætninger

}

F.eks. består metoden Title() af fire sætninger, der alle skriver en tekst. En metode har et navn, f.eks. Title(), og det er parenteserne, der fortæller, at det er en metode. En metode kaldes - udføres - ved at skrive dens navn. Når programmet starter, udføres Main(), og den har to sætninger, der hver kalder en metode.

De to metoder er simple og består alene af sætninger, som printer en tekst på skærmen, men begge metoder har flere sætninger.

Bemærkning

Det er naturligvis ikke noget særligt interessant program, da det hver gang printer oplysninger om den samme bog. Programmet udfører ikke nogen databehandling, men det kommer i de næste eksempler.

Bemærkning

Når man opretter et projekt i Visual Studio, oprettes der flere biblioteker og filer:

Page 22: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

22

Grundlæggende programarkitektur

Projektet oprettes i et bibliotek, som her hedder Exam02, og herunder er et underbibliotek med samme navn, og det er det bibliotek, som indeholder projektets filer. Der er mange filer, men for et simpelt konsolprogram er der i virkeligheden kun to, som rigtig er interessante for programmøren. Resten er af hensyn til Visual Studio. Filen Program.cs (se ovenfor) indeholder programmets source kode, og dermed de sætninger, som programmøren har indtastet. Sagt anderledes, så er det den fil, man arbejder med i Visual Studio.

Åbner man biblioteket bin og herunder igen biblioteket Debug finder man følgende filer:

Her er den øverste det oversatte program, som hedder Exam02.exe (bemærk, at stifinderen som default ikke viser efternavnet exe, og at file nr. 2 i virkeligheden hedder Exam02.exe.config). Hvis man ønsker det, kan man tage filen Exam02.exe og kopiere det et andet sted hen (på den samme maskine eller en anden maskine), og programmet kan så køre ved at åbne det i en prompt på samme måde som ethvert andet program.

Page 23: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

Click on the ad to read more

C# 1: Introduktion til programmering og programmeringssproget C#

23

Variabler

3 VariablerProgrammer skal behandle data, og de har hertil brug for en måde, hvorpå de kan gemme eller opbevare data. Hertil anvendes variabler, der er størrelser, som kan have eller gemme en værdi. En variabel er karakteriseret ved

- et navn

- en type

- operatorer

Variabler skal have et navn, så man kan referere til dem i programmet. C# er i lighed med andre moderne programmeringssprog relativt fleksibel mht. navngivning af variabler, men følgende skal (bør) overholdes:

- navnet på en variabel skal starte med et bogstav - de danske bogstaver æ, ø, å, Æ, Ø, Å bør ikke anvendes

- navnet på en variabel bør altid starte med et lille bogstav

- herefter må følge et vilkårligt antal tegn bestående af bogstaver og cifre

- et navn må aldrig indeholde mellemrum

Jeg udvikler og udviklesPrevas startede i 1985 og er i dag hovedleverandør og udviklingspartner til førende virksomhederindenfor Life Science, telecom, automotive, forsvar, energi og fremstillingsindustrien. Vi er mereend 500 ingeniører som brænder for at finde effektive løsninger for vores kunder. ”Innovation for Growth” er vores mantra.Hos Prevas møder du kompetente og spændende mennesker hver dag. Det kan være dine nyekollegaer eller det kan være vores kunders medarbejdere. Hos os får du mulighed for at arbejdemed nye teknologier i mange forskellige brancher for spændende virksomheder.Som medarbejder hos Prevas kommer du derfor altid til at udvikles - så længe du selv vil.

iNNovATioN For groWTHwww.prevas.com

Page 24: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

24

Variabler

Hvis man overholder disse simple regler, har man aldrig problemer med navne på variabler, men en del andre tegn er faktisk tilladte.

Variabler har en type, der angiver, hvilke værdier, der kan gemmes i dem, samt hvor meget en variabel fylder i maskinens hukommelse. Typen bestemmer samtidig hvilke operationer, der kan udføres på en variabel, dvs. hvad man kan gøre med den.

Variabler skal oprettes eller erklæres inden de kan anvendes. Det sker ved en sætning af formen:

type navn = værdi;

Dvs. man skriver typen først, dernæst variablens navn og endelig tildeles den en værdi, f.eks.

int tal = 23;

Her er der erklæret en variabel, der hedder tal, og som har typen int og værdien 23. Variabler skal altid initialiseres, ellers får man en oversættelsesfejl.

Når variabler skal erklæres, er det fordi, at oversætteren skal allokere plads i maskinens hukommelse, samt at når navnet optræder et sted i koden, skal oversætteren kende navnets betydning for at kunne kontrollere, om variablen er anvendt i en korrekt sammenhæng. Er det ikke tilfældet, vil oversætteren komme med en fejlmeddelelse. Programmet kan først afprøves, når det er oversat uden fejl.

C# har følgende indbyggede eller simple datatyper:

Type Beskrivelse Literaler (værdier)

bool Boolean true, false

char 16 bit unicode karakter ‘A’, ‘\x0041’, ‘\u0041’

sbyte 8 bit signed heltal

byte 8 bit unsigned heltal

short 16 bit signed heltal

ushort 16 bit unsigned heltal

int 32 bit signed heltal

uint 32 bit unsigned heltal Suffix: U

long 64 bit signed heltal Suffix: L/l

ulong 64 bit unsigned heltal Suffix: U/u eller L/l

float 32 bit flydende tal Suffix: F/f

double 64 bit flydende tal Suffix: D/d

decimal 96 bit decimal tal Suffix: M/m

string Karakter streng (tekst) “C:\\test.txt”, @”C:\test.txt”

Page 25: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

25

Variabler

Her angiver første kolonne typenavnet, anden kolonne hvor meget en variabel af den pågældende type fylder i maskinens hukommelse, samt hvilke værdier den kan indeholde. Den sidste kolonne angiver, hvordan man erklærer (definerer) konstante (literaler) af den pågældende type.

Den sidste type string er lidt anderledes end de øvrige og er en såkaldt reference type, der forklares senere. Hvad angår string-literaler kan man med tegnet @ angive om escape-tegn skal fortolkes eller ej. Escape-tegn er tegn i en streng, der har en særlig betydning, og de starter altid med \ efterfulgt at et tegn. F.eks. betyder \n linjeskift.

Exam03 Summen af to tal

Herunder er vist et program, der beregner summen af to tal og printer resultatet:

using System;

namespace Exam03

{

class Program

{

static void Main(string[] args)

{

int num1 = 17;

int num2 = 23;

int sum = num1 + num2;

Console.WriteLine(“The sum of “+ num1 + “ and “ + num2 + “ er “ + sum);

}

}

}

Fremgangsmåde

På samme måde som i de to første eksempler oprettes et Console Application projekt i Visual Studio, og koden indtastes som vist ovenfor.

Der er altså tale om et program, som i form af en beregning udfører en databehandling, og det er dermed ikke blot et program, som printer tekst på skærmen.

Page 26: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

Click on the ad to read more

C# 1: Introduktion til programmering og programmeringssproget C#

26

Variabler

Forklaring

Først erklæres to variabler num1 og num2, der initialiseres med hhv. 17 og 23. I dette tilfælde er typen int, der betyder at de to variabler kan indeholde heltal. Det er lokale variabler, da de er oprettet i Main(), og de er kun kendte inden for metoden Main(). Dernæst beregnes summen, der gemmes i variablen sum. Bemærk, at den værdi, der gemmes i sum, er resultatet af et udtryk. WriteLine() printer resultatet. I dette tilfælde opbygges en streng ud fra flere led eller elementer. Bemærk, at de enkelte elementer adskilles af +, der her betyder string-concatenering, samt at der automatisk sker typekonvertering af heltal til en streng.

Exam04 Operatorer

C# har en række operatorer, der kan virke på variabler. I ovenstående program er anvendt operatoren +. Bemærk, at betydningen af operatoren er afhængig af typen af de variabler eller konstanter, som operatoren virker på. I det første tilfælde, hvor begge operander er heltal, er betydningen addition, og i det andet tilfælde (i WriteLine-sætningen) er betydningen string-concatenering. En operators betydning, og også i hvilke sammenhænge den giver mening og er lovlig, er således afhængig af datatypen. Bemærk at, i ovenstående program anvendes også operatoren =, der kaldes for tildelingsoperatoren, og som anvendes til at tildele en variabel en værdi.

Dine fordele ved forsikring hosPantaenius

DEN

10083 w

ww

.hqh

h.de

04/2

012

Østerbro 11 · 7800 SkiveTel. +45-9751 3388 · [email protected]

www.pantaenius.dk

Hjælp ved uheld

Du har behov for bugsering til nærmeste værft?Pantaenius overtager omkostningerne dog begrænset op til DKK 37.500,00!

Kontakt osHar du spørgsmål til dine forsikringer?Du kan ringe +45-9751 33 88 eller skrive til os på e-mail [email protected]

Inspektionsomkostninger

Du har haft en grundstødning og vil have bunden inspiceret?Pantaenius dækker inspektionen uden selvrisiko!

Ingen selvrisiko

Indbrud, transportskade, brand, lynnedslag eller totalskade?Ved disse skadesårsager er der ingen selvrisiko hos Pantaenius!

Page 27: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

27

Variabler

C# har følgende operatorer ordnet efter prioritet, og med faldende prioritet nedefter:

() . [] function(...) new typeof sizeof checked unchecked

+ - ! ~ ++ -- (unary operatorer)

* / %

+ -

<< >>

< > <= >= is as

== !=

&

^

|

&&

||

?:

= *= /= %= += -= <<= >>= &= ^= |=

De enkelte operatorer forklares efterhånden som de anvendes. Prioriteten har betydning i udtryk, hvor der indgår flere operatorer. Hovedreglen er, at man først evaluerer operatorer med højeste prioritet, og i tilfældet hvor der er flere operatorer med samme prioritet evalueres fra venstre. Har man f.eks. udtrykket

a + b * c

beregnes først b * c, da * har højere prioritet end +. Hvis man i stedet skriver

(a + b) * c

beregnes først a + b, da parenteser har højere prioritet end *. I langt de fleste tilfælde er anvendelsen af operatorer uden de store vanskeligheder, men enkelte kræver lidt forklaring. Bemærk specielt tildelingsoperatorerne, f.eks. +=. F.eks. betyder følgende

int a = 11;a += 2;

at variablen a får værdien 13. Det er således blot en kort skrivemåde for følgende:

int a = 11;a = a + 2;

En anden operator man skal være speciel opmærksom på er ++, der tæller en variabel op med 1. F.eks. betyder

Page 28: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

28

Variabler

int n = 7;++n;

at variablen n får værdien 8. ++ må skrives på begge sider af variablen, og ovenstående kan også skrives på følgende måde:

int n = 7;n++;

Betydningen er i dette tilfælde det samme. Hvis den sidste sætning imidlertid indgår i et udtryk, har det betydning, på hvilken side man skriver operatoren. Reglen er, at hvis operatoren står først (til venstre), tælles variablen op, hvorefter udtrykkets værdi beregnes, og står operatoren sidst, beregnes først udtrykkets værdi, hvorefter variablen tælles op. Resultatet af følgende sætninger

int n = 7;int a = 0;a = ++n;

er således at n får værdien 8 og a får værdien 8 (n tælles op med 1 og resultatet tildeles a), mens resultatet af følgende

int n = 7;int a = 0;a = n++;

er at n får værdien 8 og a værdien 7 (a får værdien af n og derefter tælles n op med 1).

Operatoren -- virker på sammen måde, blot tæller den værdien af en variabel ned med 1. Kører man f.eks. følgende program:

namespace Exam04{class Program{static void Main(string[] args){int n = 7;Console.WriteLine(n++);Console.WriteLine(++n);Console.WriteLine(n--);Console.WriteLine(--n);

}}

}

får man resultatet:

Page 29: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

Click on the ad to read more

C# 1: Introduktion til programmering og programmeringssproget C#

29

Konsolprogrammer

4 KonsolprogrammerSom nævnt i forordet behandler denne bog alene konsolprogrammer. Det er programmer, der udføres fra en kommandolinje, som skriver resultatet på en tekstskærm, og hvor brugeren kan indtaste data til en prompt. I dette afsnit vil jeg se på, hvordan brugeren kan indtaste data til programmet, og hvordan man kan formatere programmets resultat.

Exam05 Omkreds og areal af en cirkel

Som et eksempel vil jeg vise et program, hvor brugeren skal indtaste radius for en cirkel, og hvor programmet beregner og skriver cirklens omkreds og areal. Herunder er vist et eksempel på en kørsel af programmet:

Get “Bookboon’s Free Media Advice” Email [email protected]

See the light! The sooner you realize we are right, the sooner your life will get better!

A bit over the top? Yes we know!

We are just that sure that we can make your media activities more effective.

Page 30: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

30

Konsolprogrammer

Fremgangsmåde

Koden kan skrives på følgende måde (hvor jeg ikke har medtaget programmets using sætninger og programmets namespace):

static void Main(string[] args)

{

Console.Write(“Enter radius: “);

string text = Console.ReadLine();

double r = Convert.ToDouble(text);

double p = r * 2 * Math.PI;

double a = r * r * Math.PI;

Console.WriteLine(

“Perimeter and area of a circle with radius {0:F4}: {1:F4}, {2:F4}”, r, p, a);

}

Forklaring

Programmet har i princippet samme opbygning som det første eksempel og består alene af en Main() metode. Programmer skriver en hjælpetekst, hvorefter brugeren skal indtast et tal (radius):

string text = Console.ReadLine();

Bemærk, at hjælpeteksten skrives med metoden Write(). Forskellen mellem denne metode og WriteLine() er, at Write() ikke afsluttes med et linjeskift. ReadLine() er en metode i klassen Console, der opsamler brugerens indtastninger, indtil der tastes Enter, hvorefter indtastningerne returneres som en streng - en variabel af typen string. Bemærk, at ReadLine() altid returnerer en streng, og det er herefter programmets opgave evt. at konvertere indtastningen til en anden type. I dette tilfælde skal indtastningen konverteres til en double, der sker med sætningen:

double r = Convert.ToDouble(text);

Convert er en klasse i namespacet System, der definerer en familie af konverteringsfunktioner. Bemærk, at disse - her ToDouble() - kræver, at brugeren rent faktisk har indtastet et lovligt tal. Er det ikke tilfældet, stopper programmet med en såkaldt exception, der er en fejlhåndtering. Dernæst beregnes omkreds og areal:

double p = r * 2 * Math.PI;double a = r * r * Math.PI;

Page 31: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

31

Konsolprogrammer

Her er Math.PI en konstant i klassen Math, som er en klasse i System namespacet. Til sidst skrives resultatet med WriteLine(), men denne gang har funktionen flere argumenter. Det første argument er en såkaldt formatstreng og efterfølges af tre variabler. Variablernes værdier indsættes i formatstrengen bestemt af såkaldte pladsholdere. F.eks. er {0:F4} en pladsholder, der angiver at her skal den første variabel efter formatstrengen indsættes, dvs. værdien af r. Den næste pladsholder hedder {1:F4}. Den angiver, at her skal variablen p indsættes - variabel nr. 2 efter formatstrengen. F4 betyder, at værdien indsættes som et decimaltal (F) med 4 pladser efter decimalpunktet. På samme måde angiver {2:F4} at der skal indsættes en værdi formateret som et decimaltal med 4 cifre. Det er i dette tilfælde variablen a.

Bemærkning

Der er følgende muligheder for at formatere en pladsholder:

C Valuta (afhænger af lokalindstillingen)

D Heltal

E Exponentiel form (float, double)

F Fast decimalpunkt (float, double)

G Generelt (F eller E)

N Numerisk med tusindtalsseperation

X Hexadecimalt

Exam06 Vareberegning

Det næste eksempel udfører en beregning. Brugeren skal indtaste enhedspris og antal enheder for en vare. Herefter beregner programmet totalprisen ekskl. moms, momsen, totalprisen inkl. moms og skriver resultatet på skærmen.

Køre man programmet, kunne resultatet være følgende:

Page 32: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

Click on the ad to read more

C# 1: Introduktion til programmering og programmeringssproget C#

32

Konsolprogrammer

Fremgangsmåde

Udgangspunktet er igen et Console Application projekt:

static void Main(string[] args)

{

Console.Write(“Enter the unit price: “);

string text = Console.ReadLine();

double price = Convert.ToDouble(text);

Console.Write(“Enter the number of units: “);

text = Console.ReadLine();

int quantity = Convert.ToInt32(text);

double amount = price * quantity;

double vat = amount * 0.25;

double total = amount + vat;

Console.WriteLine(“{0, -15} {1, 10:F}”, “Unit price”, price);

Console.WriteLine(“{0, -15} {1, 10:D}”, “Number of units”, quantity);

Console.WriteLine(“{0, -15} {1, 10:F}”, “Total excl. VAT”, amount);

Console.WriteLine(“{0, -15} {1, 10:F}”, “VAT”, vat);

Console.WriteLine(“{0, -15} {1, 10:F}”, “Total incl. VAT”, total);

}

Mangler du dygtige callcenter medarbejdere?Lad Assistance finde din nye medarbejderVi sætter en ære i at indhente viden om din virksomhed, jeres kultur og værdier, strategi, mission og vision. Herigennem danner vi os et præcist indtryk af jeres foretrukne profil. I rekrutteringsprocessen lægger vi vægt på følgende forhold:

• Grundig behovsafdækning – for et optimalt match• Jobprofil og stillingsopslag• Rådgivning i forhold til valg af annonceringsmedie• Screening af relevante ansøgere (test, analyse og problemløsning)

Kontakt os for et uforpligtende møde på telefon 33 55 00 90

Page 33: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

33

Konsolprogrammer

Forklaring

Programmet virker i princippet som det forrige program, blot skal man denne gang indtaste to værdier. Desuden er pladsholderne mere komplekse. Hvis man f.eks. ser på sætningen:

Console.WriteLine(“{0, -15} {1, 10:F}”, “Unit price”, price);

er der to pladsholdere. {0, -15} er den første, og her indsættes teksten ”Unit price”. -15 betyder, at feltet er 15 tegn bredt, og da tallet er negativt, skal værdien venstrestilles. Bemærk, at der ikke er noget formattegn, og det er da datatypen på elementet, der bestemmer formateringens typeangivelse. Den næste pladsholder {1, 10:F} betyder, at det næste element skal formateres højrestillet i et felt på 10 tegn og som et decimaltal. Da antallet af decimaler ikke er angivet anvendes default værdien, der er 2.

Exam07 Dato og klokkeslæt

Dette program printer, hvor mange klokken er:

Programmet skal primært vise formateringen af resultatet, men det skal desuden vise anvendelse af typen DateTime.

Fremgangsmåde

Koden kan skrives som vist nedenfor, hvor der denne gang er to metoder, som kaldes fra Main():

static void Main(string[] args){DateTime dt = DateTime.Now;Time1(dt);Time2(dt);

}

static void Time1(DateTime t){Console.WriteLine(“{0:D2} {1:D2} {2:D2} {3:D3}”, t.Hour, t.Minute, t.Second, t.Millisecond);

}

static void Time2(DateTime t){Console.WriteLine(t.ToLongDateString());Console.WriteLine(t.ToLongTimeString());

}

Page 34: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

34

Konsolprogrammer

Bemærk, at jeg ikke har vist hele koden, men blot metoderne.

Forklaring

I Main() aflæses maskinen uret, hvis værdi gemmes i en variabel:

DateTime dt = DateTime.Now;

DateTime er en klasse, som indeholder en række metoder til dato og klokkeslæt. Now er en egenskab (en property), som altid indeholder værdien af maskinuret. Denne værdi gemmes i en variabel, som hedder dt, og som har typen DateTime. Dernæst kaldes en metode Time1(), hvor variablen dt sendes med som parameter. Det betyder, at den er kendt og kan anvendes i metoden Time1(). Metoden printer tidspunktet i form af timer, minutter, sekunder og millisekunder, hvert led adskilt af mellemrum. Du skal bemærke pladsholderne. F.eks. betyder {0:d2} at den første variabel skal formateres i et felt som et heltal, og at feltet skal være på to tegn, således at der indsættes et foranstillet 0, hvis der kun er et ciffer. Du skal også bemærke, hvordan man refererer til værdierne. t er en variabel, hvis type er DateTime, som er en klasse. Klassen definerer en række egenskaber, f.eks. t.Hour for timer, og man refererer til de enkelte egenskaber med variablens navn efterfulgt af et punktum og egenskabens navn.

Klassen DateTime giver andre muligheder. Metoden Time2() skriver den aktuelle dato og klokkeslettet, men her anvendes metoder fra DateTime klassen, som formaterer resultatet som en streng.

Bemærkning

DateTime er en klasse (faktisk en struct), og som du kan se, er der tale om en del nye ting som f.eks. properties mv. Alt det bliver behandlet detaljeret senere. Det samme gælder parametre, som også er anvendt i dette eksempel, og uden at gå i detaljer med betydningen kan du tænke på en parameter som en variabel, der angiver den værdi, som en metode skal virke på. I eksemplerne her skal metoderne bruge værdien af variablen dt, men den findes kun i Main() og er dermed ikke kendt i de to andre metoder. Det er nødvendigt med en mekanisme, som kan overføre dt, når metoderne kaldes, og det er præcis hvad, parametre anvendes til.

Exam08 Argumenter på kommandolinjen

Når man opretter et program ved hjælp af Visual Studio, har Main() metoden en parameter, som jeg ikke har anvendt indtil nu. Den anvendes til på kommandolinjen at overføre argumenter til et program. Dvs. hvis man har et program med navnet Exam08.exe, kan man udføre programmet fra kommandolinjen ved at skrive

Exam08 a b c

Page 35: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

35

Konsolprogrammer

hvor a, b og c er argumenter til programmet og er vilkårlige strenge adskilt af mindst et mellemrum. Der er ingen begrænsninger i antallet af argumenter, og et argument behøver ikke at være et enkelt tegn som herover, men må være en vilkårlig streng. Hvis programmet ikke gør noget, bliver evt. argumenter ignoreret, og det er således op til programmet at behandle disse argumenter.

Som eksempel er vist et program, hvor brugeren skal overføre to heltal som argumenter på kommandolinjen, og programmet skal så printe tallenes kvotient og modulus. Resultatet kunne f.eks. være følgende:

Fremgangsmåde

Programmet skrives på samme måde som de øvrige eksempler, og koden for Main() metoden er følgende:

static void Main(string[] args){long t1 = Convert.ToInt64(args[0]);long t2 = Convert.ToInt64(args[1]);Console.WriteLine(“Quotient of {0} and {1} is {2}”, t1, t2, t1 / t2);Console.WriteLine(“Modulus of {0} and {1} is {2}”, t1, t2, t1 % t2);

}

Forklaring

Main() metoden har en parameter, som er et array (arrays behandles nedenfor), og som repræsenterer evt. argumenter på kommandolinjen. Da argumenter fra kommandolinjen altid er strenge, skal de konverteres til heltal (her typen long) inden resultatet kan beregnes. Beregningerne består i at beregne tallenes kvotient og tallenes modulus. Bemærk specielt operatoren %, der er modulus operatoren (rest ved division).

Bemærk, at hvis man kører programmet og ikke angiver to argumenter, eller hvis der er et af argumenterne, der ikke er et heltal, så vil programmet gå ned med en fejlmeddelelse. Hvis man derimod angiver mere end to argumenter, bliver de sidste blot ignoreret.

Page 36: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

Click on the ad to read more

C# 1: Introduktion til programmering og programmeringssproget C#

36

Programkontrol

5 ProgramkontrolOvenstående eksempler er alle sekventielle, således at sætningerne udføres i den rækkefølge de er skrevet. I praksis har alle programmer brug for at gøre udførelsen af sætninger afhængig af en betingelse, der sker ved anvendelse af kontrolsætninger. C# har grundlæggende følgende sætninger til programkontrol

• if• while• do• for• switch

Kontrolsætningerne illustreres bedst gennem eksempler i form af simple metoder, hvilket er emnet for dette afsnit.

Kontrolsætningerne anvendes som sætninger i metoder på samme måde som f.eks. WriteLine, men en kontrolsætning gør udførelsen af én eller flere andre sætninger afhængig af en betingelse. Man har derfor brug for at kunne referere til flere sætninger som et hele, hvilket sker ved hjælp af en blok, som blot er et antal sætninger i parentes:

Page 37: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

37

Programkontrol

{sætning1;sætning2;....

}

F.eks. er sætningerne i en metode en blok, men som det vil fremgå af det følgende, kan man have blokke inden i blokke. Det har du faktisk allerede set eksempler på, da en klasse også er en form for blok, som i stedet for sætninger indeholder metoder.

Kontrolsætninger er nødvendige for at man kan skrive programmer, som udfører noget interessant. Først med kontrolsætninger til rådighed kan man begynde at arbejde med algoritmer og dermed skriver programmer, som løser et konkret problem. Det følgende vil derfor også i nogen udstrækning have fokus på algoritmer.

if

En if-sætning har formen:

if (betingelse) blok

og betydningen er, at hvis betingelse er sand, så udføres blokken (blokkens sætninger). Ellers sker der ingenting. En betingelse er et udtryk, hvis værdi er en bool og dermed et udtryk, som er sand eller falsk. Hvis der kun er en enkelt sætning, der skal kontrolleres af en betingelse, må man undlade parenteserne og blot skrive:

if (betingelse) sætning;

Exam09 Sorter to tal

Opgaven er at skrive et program, hvor brugeren kan indtaste to heltal. Programmet skal herefter printe de to tal i stigende orden. Et eksempel på en kørsel af programmet kunne være:

Fremgangsmåde

Opgaven kan nedbrydes i to delopgaver:

- indtast to hele tal - print de to tal i stigende orden

Page 38: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

38

Programkontrol

For at løse det første problem skal man udføre den samme operation (indtast et heltal) to gang, og det kan derfor betale sig at skrive denne operation som en metode:

static int Enter(){Console.Write(“Enter an integer: “);string text = Console.ReadLine();return Convert.ToInt32(text);

}

Bemærk, at metoden har en type, men det forklares nedenfor.

For at printe resultatet skal man finde det mindste tal, og det er her at if sætningen kommer på banen. Jeg vil anvende den strategi, at hvis det første tal er større end det sidste, så vil jeg bytte om på de to tal, og på én eller anden måde skal jeg derfor i C# kunne afgøre (teste), om det første tal er større end det andet. Det er præcis hvad en if sætning anvendes til.

Man kan definere en metode til print af resultatet på følgende måde:

static void Sort1(int a, int b){hvis a > b så{gem a i en hjælpevariabel ta = bb = t

}Console.WriteLine(“{0} {1}”, a, b);

}

Strengt taget er det ikke en metode, men det er løsningsmetode formuleret ved hjælp af et uformelt sprog - det er en algoritme. Opgaven består derfor i at skrive denne algoritme i C#:

static void Sort1(int a, int b){if (a > b){int t = a;a = b;b = t;

}Console.WriteLine(“{0} {1}”, a, b);

}

Herefter kan selve programmet skrives på følgende måde:

static void Main(string[] args){

Page 39: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

Click on the ad to read more

C# 1: Introduktion til programmering og programmeringssproget C#

39

Programkontrol

int a = Enter();int b = Enter();Sort1(a, b);

}

Forklaring

Metoden Stort1() har en betingelsen i form af en if sætning, som tester om værdien af a er større end værdien af b, og er det tilfældet, udføres den næste blok, som bytter om på de to tal. Da blokken kun udføres, hvis værdien af a er større end værdien af b, vil værdien af a altid være mindre end værdien af b efter at blokken er udført. Resultatet er, at de to tal printes i stigende orden.

Du skal bemærke, hvordan man skriver en betingelse i en if sætning, og at det er et udtryk, hvis værdi enten er sand eller falsk. Det er et udtryk, hvis type er bool. Bemærk også, at udtrykket skal stå i parentes.

Du skal også bemærke metoden Enter(), som er en metode med en returværdi. Returværdier behandles senere i afsnittet om metoder, men indtil da kan du tænke på en returværdi som en værdi, der knyttes til metodens navn med en return sætning. På den måde kan man få værdien overført til det sted, hvor metoden kaldes f.eks. ved at skrive:

int a = Enter();

Det betyder, at den værdi som knyttes til metodens navn med return gemmes i variablen a.

Hvor mange skal tage en beslutning, før man kan føre

en beslutning ud i livet?

Slip for komplekse kommandoveje. Hos NNIT løser vi de store it-opgaver i små teams, der ikke skal spørge om lov til at tage

en beslutning. Se ledige job på nnit.dk/job

RE

TH

INK

PIP

EL

INE

Hvor mange skal tage en beslutning, før man kan føre

en beslutning ud i livet?

Slip for komplekse kommandoveje. Hos NNIT løser vi de store it-opgaver i små teams, der ikke skal spørge om lov til at tage

en beslutning. Se ledige job på nnit.dk/job

RE

TH

INK

PIP

EL

INE

Hvor mange skal tage en beslutning, før man kan føre

en beslutning ud i livet?

Slip for komplekse kommandoveje. Hos NNIT løser vi de store it-opgaver i små teams, der ikke skal spørge om lov til at tage

en beslutning. Se ledige job på nnit.dk/job

RE

TH

INK

PIP

EL

INE

Hvor mange skal tage en beslutning, før man kan føre

en beslutning ud i livet?

Slip for komplekse kommandoveje. Hos NNIT løser vi de store it-opgaver i små teams, der ikke skal spørge om lov til at tage

en beslutning. Se ledige job på nnit.dk/job

RE

TH

INK

PIP

EL

INE

Page 40: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

40

Programkontrol

Bemærkning

En metodes sætninger er en algoritme eller en løsningsmetode. Den største udfordring i at skrive programmer er at lære at skrive algoritmer, bl.a. fordi et givet problem ofte kan løses på flere måder. Ovenfor har jeg vist en algoritme til at bytte om på to tal, og ofte kan det være en god idé at starte med at skrive algoritmen i et uformelt sprog, da man på den måde frigør løsningen fra programmeringssprogets mange detaljer og dermed kan have fokus på selve problemet, og hvordan det løses. Har man først formuleret algoritmen i et uformelt sprog, er det typisk en let opgave at omsætte algoritmen til det konkrete programmeringssprog, som her er C#. Bemærk specielt algoritmen til at bytte om på to tal. Det er en simpel algoritme, men den er faktisk vigtig, og det er en algoritme, som du vil møde mange gange.

if-else

En if sætning kan kombineres med en else del:

if (betingelse)blok_1

elseblok_2

hvor både blok_1 og blok_ 2 må være simple sætninger. Betydningen er, at blok_1 udføres, hvis betingelse er sand, og hvis ikke så udføres blok_2. Som eksempel kunne ovenstående sort metode, der printer to tal i stigende orden, skrives på følgende måde:

static void Sort2(int a, int b){if (a < b)Console.WriteLine(“{0} {1}”, a, b);

elseConsole.WriteLine(“{0} {1}”, b, a);

}

Bemærk i øvrigt, at metoden også må skrives på følgende måde, hvor den eneste forskel er, at det hele er skrevet på en enkelt linje:

static void Sort2(int a, int b){if (a < b) Console.WriteLine(“{0} {1}”, a, b); else Console.WriteLine(“{0} {1}”, b, a);

}

og som endnu et eksempel kunne den skrives som:

static void Sort2(int a, int b){if (a < b)

Page 41: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

41

Programkontrol

{Console.WriteLine(“{0} {1}”, a, b);

}else{Console.WriteLine(“{0} {1}”, b, a);

}}

Set fra maskinen er de tre versioner lige gode, og valget er alene et spørgsmål om, hvad man synes er mest læsbar.

Exam10 En anden grads ligning

Jeg vil vise et program, som kan løse en anden grads ligning, og dermed et program, som løser en klassisk opgave fra skolens matematikundervisning. En anden grads ligning er af formen:

Løsningsformlen er:

Givet diskriminanten :

Opgaven er således at skrive et program, hvor brugeren skal indtaste ligningens koefficienter (dvs. a, b og c). Programmet skal herefter bestemme ligningens løsninger ved hjælp af ovenstående formel og printe resultatet på skærmen.

Et eksempel på en kørsel af programmet kunne være følgende:

Page 42: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

42

Programkontrol

Fremgangsmåde

Selve løsningen af ligningen kan uformelt beskrives på følgende måde:

beregn diskriminanten dhvis d < 0 så der er ingen løsningerellers hvis d > 0 så der er to løsningerellers der er én løsning

Umiddelbart er der ikke meget løsning i det, men det nedbryder opgaven i tre delproblemer, som hver er simplere end det oprindelige problem. Denne form for problemnedbrydning er et princip, som går igen i løsningen af mange opgaver og er et vigtigt skridt frem mod en færdig løsning. Hver af de tre delproblemer er relativt simple, og det færdige program, kan skrives på følgende måde:class Program{static void Main(string[] args){double a = Enter(“Enter a”);double b = Enter(“Enter b”);double c = Enter(“Enter c”);Solve(a, b, c);

}

static double Enter(string text){Console.Write(text + “: “);string line = Console.ReadLine();return Convert.ToDouble(line);

}

static void Solve(double a, double b, double c){double d = b * b - 4 * a * c;Console.WriteLine(“The equation {0:F4}x^2 + {1:F4}x + {2:F4} = 0”, a, b, c);if (d < 0) Result();else if (d > 0) Result(a, b, d);else Result(a, b);

}

static void Result(){Console.WriteLine(“has no solution”);

}

static void Result(double a, double b){Console.WriteLine(“has the solution {0:F4}”, -b / (2 * a));

}

static void Result(double a, double b, double d){double y = Math.Sqrt(d);Console.WriteLine(“has the solutions {0:F4} and {1:F4}”,(-b - y) / (2 * a), (-b + y) / (2 * a));

}}

Page 43: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

Click on the ad to read more

C# 1: Introduktion til programmering og programmeringssproget C#

43

Programkontrol

Forklaring

Bemærk først metoden Enter(), som i det væsentlige er den samme som i det forrige eksempel. Der er to forskelle. Hjælpeteksten, som fortæller brugeren, hvad der skal indtastes, sendes denne gang med som en parameter. Den anden forskel er, at metoden denne gang konverterer indtastningen til en double, og metoden skal derfor også returnere en double - metodens type er double.

Metoden Solve() løser ligningen, og den udfører tre ting:

- beregner diskriminanten - printer selve ligningen - implementerer ovenstående algoritme, som deler løsningen op i de tre delproblemer, og her

skal du primært bemærke, hvordan if-else sætningerne skrives

De tre metoder til print af resultatet kræver ikke megen forklaring, men bemærk dog i den sidste, hvordan man bestemmer kvadratroden af et tal. Det sker med metoden Sqrt(), som er en metode i klassen Math.

Bemærkning

I metoden Solve() indgår der if-else sætninger:

if (d < 0) Result();else if (d > 0) Result(a, b, d);else Result(a, b);

Page 44: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

44

Programkontrol

og da hver betingelse kun kontrollerer en enkelt sætning, har jeg udnyttet, at det ikke er nødvendigt at placere sætningen i en blok. Det er noget, man kan diskutere, og mange vil foretrække at skrive koden på følgende måde, da de synes, at det giver en mere læsbar kode:

if (d < 0){Result();

}else if (d > 0){Result(a, b, d);

}else{Result(a, b);

}

Set fra det færdige program og maskinen er det uden betydning, og de to koder oversættes til det samme og den ene er således hverken mere eller mindre effektiv end den anden. Valget er programmørens og er alene et spørgsmål om læsbarhed, og man skal ganske enkelt vælge den version, som man synes er mest læsbar. Jeg synes, at den første version er den mest læsbare, men det er der langt fra alle der er enige i.

Det med at et program skal være læsbar er faktisk vigtigere end som så, og her skal man tænke på, at programmer ofte skal vedligeholdes af andre end den, der oprindelig har skrevet programmet, og for at det skal være muligt, skal det være let både at læse og forstå programmet.

while

Man har ofte brug for at kunne udføre en sætning eller en blok flere gange indtil en betingelse indtræffer. Hertil kan man anvende en while sætning, der har følgende form:

while (betingelse)blok

Betydningen er, at blokken og dens sætninger udføres så længe betingelsen efter while er sand. Herefter fortsætter programmet med næste sætning efter while konstruktionen.

På samme måde som ved if gælder, at hvis blokken kun indeholder en enkelt sætning, må man undlade parenteserne og blot skrive sætningen.

Exam11 Summen af de positive tal mindre end 100

Som eksempel er herunder vist et program, som bestemmer summen af alle positive heltal mindre end eller lig med 100, dvs. summen 100...321 ++++ .

Page 45: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

45

Programkontrol

Fremgangsmåde

Programmet kan skrives på følgende måde:

class Program{const int N = 100;

static void Main(string[] args){long s = 0;int n = 1;while (n <= N){s += n;++n;

}Console.WriteLine(s);

}}

Forklaring

Bemærk først, at der i starten af programmet er defineret en konstant, som er det største tal, der skal indgå i summen:

const int N = 100;

Det er ikke nødvendigt, men det gør det let at ændre programmet, hvis det f.eks. i stedet skal bestemme summen af tallene fra 1 til 1000.

Bemærk algoritmen. Først defineres en variabel s til resultatet. Dernæst defineres en variabel n til det tal, der skal adderes til summen, og som initialiseres til 1, der er det første tal. Så gentager man den efterfølgende blok, så længe at n er mindre end eller lig med 100 (konstanten N). I blokken sker der to ting: Værdien af variablen n adderes til s, og n tælles op med 1. Bemærk, at den sidste sætning bevirker, at n bliver 1 større for hver gentagelse, og dermed at betingelsen efter while før eller siden bliver falsk.

Bemærkning

I starten kan det være svært at gennemskue en algoritme som ovenstående og se at den gør det rigtige, og her kan det være en god idet at gennemføre en skrivebordtest, hvor man manuelt prøver at holde styr på, hvad der sker med variablerne. Antag f.eks. at N = 10. Dvs. at programmet skal bestemme summen

. Når algoritmen udføres, sker der følgende, hvor den første kolonne viser, hvad der sker med variablen s, mens den anden kolonne viser, hvad der sker variablen n:

Page 46: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

Click on the ad to read more

C# 1: Introduktion til programmering og programmeringssproget C#

46

Programkontrol

s n

0 1 De to variabler efter de er initialiseret (oprettet)

1 2 Variablerne efter 1. udførelsen af while sætningen

3 3 Variablerne efter 2. udførelsen af while sætningen

6 4 Variablerne efter 3. udførelsen af while sætningen

10 5 Variablerne efter 4. udførelsen af while sætningen

15 6 Variablerne efter 5. udførelsen af while sætningen

21 7 Variablerne efter 6. udførelsen af while sætningen

28 8 Variablerne efter 7. udførelsen af while sætningen

36 9 Variablerne efter 8. udførelsen af while sætningen

45 10 Variablerne efter 9. udførelsen af while sætningen

55 11 Variablerne efter 10. udførelsen af while sætningen

Dvs. at løkken stopper, når n bliver 11, og på det tidspunkt har variablen s værdien 55.

Er det et stort program med mange variabler og iterationer med mange gentagelser, er ovenstående naturligvis ikke en farbar vej, men i simplere tilfælde kan det være en god måde til at overbevise sig om, at en algoritme virker - og til at finde fejl.

SÆT LYD PÅ FREMTIDENWidex udvikler højteknologiske høreapparater til gavn for de 500 millioner mennesker verden over, der har nedsat hørelse.

Mere end fem årtiers intensiv forskning og udvikling har gjort os til en af verdens førende høreapparatproducenter, og vi udvikler digital teknologi af en kvalitet, kun få kan måle sig med.

Som videnbaseret virksomhed betragter vi medarbejderne som vores vigtigste kapital. Vi kan godt lide at gøre tingene selv og sætter en ære i at være selvforsynende inden for de fl este om-råder. Det skaber et spændende, tværfagligt arbejdsmiljø med plads til initiativ og rig mulighed for personlig og faglig udvikling.

Vil du være med til at sætte lyd på fremtiden? Følg med i vores jobopslag på www.widex.dk/job eller skriv til [email protected]

www.widex.com

Page 47: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

47

Programkontrol

Visual Studio giver i én eller anden udstrækning de sammen muligheder ved hjælp af debuggeren, men det viser jeg senere.

Bemærkning

while sætningen kaldes også for en løkke, en iteration eller en gentagelse. Hvis blokken kun indeholder en enkelt sætning, må man som nævnt undlade parenteserne. F.eks. kan ovenstående program skrives på følgende måde:

static void Main(string[] args){long s = 0;int n = 1;while (n <= N) s += n++;Console.WriteLine(s);

}

Bemærk, at det her er vigtigt, at ++ står efter n, da n først skal tælles op med 1 efter at beregningen er udført. Igen er det op til den enkelte og læsbarheden, om man vil undlade parenteserne eller ej.

Bemærkning

Opgaven er at bestemme summen at en talrække N++++ ...321 , og ovenfor er det løst ved hjælp af en løkke. Set i relation til programmering er det måske den mest oplagte løsning, men der er andre muligheder, da summen er et eksempel på en differencerække, og i matematikken har man en formel til beregning af denne sum. Jeg nævner det blot for at pege på, at et give problem ofte kan løses på flere måder, og det er ikke altid, at den mest oplagte løsning er den bedste.

for

for sætningen består af tre dele adskilt af semikolon: Initialisering, betingelse og udtryk:

for (initialisering; betingelse; udtryk)blok;

Hver af de tre dele i for sætningen kan faktisk være tom. Når sætningen udføres, sker der følgende:

1. udfør initialiseringsdelen (hvis der er én)2. test om betingelsen er sand (hvis betingelsen er tom regnes den for sand)3. hvis betingelsen er sand udføres den efterfølgende blok4. ellers afbrydes for sætningen5. udfør udtryksdelen6. fortsæt med 2

Bemærk dermed, at initialiseringsdelen kun udføres én gang.

Page 48: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

48

Programkontrol

Exam12 Sum af positive heltal

Dette eksempel er samme opgave som ovenfor, blot løses opgaven denne gang ved hjælp af en for sætning.

Fremgangsmåde

Med en for sætning, kan programmet skrives på følgende måde, hvor konstanten N er som ovenfor:

static void Main(string[] args){long s = 0;for (int i = 1; i <= N; ++i) s += i;Console.WriteLine(s);

}

Bemærk, at koden ligner det forrige eksempel.

Forklaring

for sætningen har typisk en tæller - her variablen i - som tæller antallet af gentagelser. For hver gentagelse udføres sætningen

s += i;

Bemærk, at tælleren i tælles op med 1 efter hvert gennemløb, og at gentagelsen fortsætter indtil i når en øvre grænse

Bemærkning

for sætningen er meget fleksibel. Initialiseringsdelen anvendes sædvanligvis til at initialisere variabler, og det er tilladt at have flere initialiseringer, når de adskilles af komma:

for (a = 2, b= 3, c = 5; ...

Når der som ovenfor erklæres en variabel i initialiseringsdelen, er denne lokal til for sætningen og er ikke eksisterende udenfor for sætningen og den tilhørende blok. Man kan godt erklære flere variabler i initialiseringsdelen:

for (int i = 0, j = 1; ...

men de skal da have samme type. Hvad angår betingelsen er der ikke andre krav, end at det skal være en lovlig betingelse. Dvs. at der kan indgå boolske operatorer, funktionskald mv. Udtryksdelen anvendes typisk til at kontrollere en styrende variabel i betingelsen, men generelt kan her stå hvad som helst der er et udtryk og f.eks. også et funktionskald. Udtryksdelen kan have flere udtryk, hvis de adskilles af komma, f.eks.

for (...; ...; ++i, j += 7)

Page 49: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

Click on the ad to read more

C# 1: Introduktion til programmering og programmeringssproget C#

49

Programkontrol

I ovenstående tilfælde er der ingen fordel ved at anvende for i stedet for while, og set fra programmet har det sjældent den store betydning, hvilken løkkekonstruktion man anvender. Valget er sædvanligvis bestemt af opgavens natur, hvor den ene struktur kan være mere hensigtsmæssig den anden. for sætningen er dog den mest fleksible og den hyppigst anvendte.

do

Der findes en anden variant af while, som kaldes en do løkke og har formen:

do{sætning;...

}while (betingelse);

Betydningen er, at sætningerne i blokken udføres, og herefter testes betingelsen. Er den sand, gentages blokken, og det fortsætter indtil betingelsen bliver falsk. Sammenlignet med while sætningen er forskellen, at do altid vil udføre blokken mindst én gang, da betingelsen først testes efter at blokken er udført. do sætningen anvendes ikke så ofte som de andre løkker.

switch

while, for og do er kontrolstrukturer til løkker, mens if er en kontrolstruktur til forgrening eller selektion.

Dedicated Analytical Solutionswww.foss.dk/careers

Protein 13.2%

Moisture 8.4%

Starch 67%

FOSS is known throughout the world for efficient analytical solutions that help to improve both food quality and safety in the global food market. We are playing an increasingly important role in ensuring optimal use of valuable natural resources, and have throughout the years created ground-breaking innovations. And there’s more to come. At FOSS you will find professional challenges, training and development in a work environment that offers good work/ life balance. Join us and make a difference.

80% of the grain traded in the world is analysed on a FOSS solution

Page 50: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

50

Programkontrol

I langt de fleste tilfælde anvendes if til forgreninger, men der er et alternativ, som hedder switch. Den forklares bedst med et eksempel.

Exam13 Ugedag

Opgaven er at skrive et program, hvor brugeren skal indtaste et heltal. Hvis tallet er 1, 2, 3, 4, eller 5 skal programmet printe navnet på den tilsvarende ugedag, er tallet 6 eller 7 skal programmet printe teksten Weekend, og ellers skal programmet printe en fejlmeddelelse. Herunder er vist et eksempel på en kørsel af programmet:

Fremgangsmåde

Programmet kan skrives på følgende måde, hvor man i Main() skal indtaste nummeret for dagens nummer i ugen:

static void Main(string[] args){Console.Write(“Enter the day number in week: “);string text = Console.ReadLine();switch (Convert.ToInt32(text)){case 1:Console.WriteLine(“Monday”);break;

case 2:Console.WriteLine(“Tuesday”);break;

case 3:Console.WriteLine(“Wednesday”);break;

case 4:Console.WriteLine(“Thursday”);break;

case 5:Console.WriteLine(“Friday”);break;

case 6:case 7:Console.WriteLine(“Weekend”);break;

default:Console.WriteLine(“Illegal day...”);break;

}}

Page 51: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

51

Programkontrol

Forklaring

Efter ordet switch er et udtryk:

switch(Convert.ToInt32(text))

Konstruktionen har desuden et antal case indgange, hvor der efter case står en konstant efterfulgt af kolon. Konstanten skal have samme type som udtrykket:

case 1:

Når sætningen udføres, evalueres udtrykket, og kontrollen overføres til den case indgang, der er identisk med værdien af udtrykket. Herefter udføres sætninger, indtil man møder en break sætning eller switch sætningen er slut. Hvis der ikke findes en case indgang, der svarer til værdien af udtrykket, er der to muligheder. Har switch sætningen en default indgang, overføres kontrollen hertil. Ellers overspringes hele switch sætningen. Bemærk, at en switch ikke behøver at have en default-indgang. Hvis der ovenfor indtastes 6 eller 7, vil programmet i begge tilfælde printe

Weekend

Hvis man f.eks. taster 6, vil programmet fortsætte med sætningen efter case 7, da der ikke er nogen break efter indgangen for 6.

switch sætningen er en form for multiforgrening, og den kan undertiden være en fornuftig løsning, men anvendes dog ikke så ofte som de øvrige kontrolsætninger.

Exam14 Tværsum

Som afslutning på kapitlet om kontrolstrukturer vil jeg vise yderligere to eksempler, som anvender flere af ovenstående kontrolsætninger.

Det første program bestemmer tværsummen af et tal, som brugeren indtaster. Indtaster brugeren f.eks. 123456, er tværsummen 3:

1 + 2 + 3 + 4 + 5 + 6 = 212 + 1 = 3

Programmet skal vise, hvordan man kan have to while sætninger inden i hinanden, men er også et eksempel på en algoritme som måske umiddelbart ikke er så let at gennemskue.

Fremgangsmåde

Løsning af opgaven kan nedbrydes i tre delproblemer:

Page 52: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

Click on the ad to read more

C# 1: Introduktion til programmering og programmeringssproget C#

52

Programkontrol

- Indtast tallet - Bestem tværsummen - Print resultatet

Her et løsning af det første og sidste problem noget, som jeg har set på tidligere, og som er simple problemer, og opgaven er derfor reduceret til at bestemme tværsummen af et tal. Den opgave kan beskrives på følgende måde:

- bestem summen af tallets cifre - gentag det indtil summen er mindre end 10

Lidt mere formelt kan den formuleres som en algoritme på følgende måde:

sålænge tal > 9 gentag{sum = sum af tallets cifretal = sum

}tal er nu tværsummen

Problemet kan således løses med en løkke, dog er det ikke helt klart, hvordan man bestemmer summen af cifrene i et tal. Det kan man gøre med en anden løkke:

HD – vejen tilen karrierei erhvervslivet

Læs mereAarhus: hd.au.dkHerning: auhe.au.dk/hd

LÆS HD I ØKONOMI OG LEDELSE

HD er en anerkendt diplom- uddannelse, som giver dig mulighed for at specialisere dig inden for det erhvervsøkonomiske fagområde ved siden af dit job.

Page 53: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

53

Programkontrol

sålænge tal > 0 gentag{adder tal % 10 til sumdivider tal med 10

}

hvor den første operation i løkken adderer det sidste ciffer i tallet til summen, mens den anden operation smider det sidste ciffer væk.

Med disse overvejelser på plads kan man skrive en metode som bestemmer og returnerer tværsummen af et tal:

static uint DigitSum(ulong n){while (n > 9){ulong s = 0;while (n > 0){s += n % 10;n /= 10;

}n = s;

}return (uint)n;

}

Selve programmet kan nu skrives som, hvor metoden Enter() er som tidligere:

static void Main(string[] args){ulong number = Enter();Console.WriteLine(“The reduced sum of digits in {0} is {1}”,number, DigitSum(number));

}

Kører man programmet, kunne resultatet være følgende:

Forklaring

Den inderste while sætning bestemmer summen af tallets cifre. Bemærk operatoren %, der er modulus operatoren. F.eks. betyder

Page 54: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

Click on the ad to read more

C# 1: Introduktion til programmering og programmeringssproget C#

54

Programkontrol

number % 10

rest ved division med 10, som er det bageste ciffer i number. Bemærk også resultatet af

number /= 10;

hvor division med 10 (heltalsdivision) “smider” det sidste ciffer væk. Den yderste løkke gentages så længe at ciffersummen er større end 9 - det er på mere end et ciffer.

Bemærk også datatyperne. Parameteren til metoden DigitSum() har typen ulong. Jeg har valgt en long for at kunne arbejde med store tal og her igen en ulong, da tallet ikke må være negativt. På samme måde returnerer metoden en uint, som er et ikke negativt heltal. Unsigned typer anvendes ikke så ofte, og jeg har primært anvendt dem her for at vise, hvordan de bruges. n er en ulong, og metoden returnerer en uint. I return sætningen er der således behov for at lægge et stort tal (en ulong) over i et mindre (en uint). Det kan man ikke umiddelbart gøre uden at fortælle oversætteren, at man mener det alvorligt. Det gør man med et type cast:

return (uint)n;

hvor man fortæller compileren, at den skal konvertere n til en uint.

������������� ����������������������������������������������� �� ���������������������������

������ ������ ������������������������������ ����������������������!���"���������������

�����#$%����&'())%�*+����������,����������-

.��������������������������������� ��

���������� ���������������� ������������� ���������������������������� �����������

The Wakethe only emission we want to leave behind

Page 55: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

55

Programkontrol

Exam15 Det største og det mindste tal

Dette eksempel er et program, der anvender kontrolstrukturerne while og if. if er i øvrigt den hyppigst anvendte af kontrolsætningerne, og i praksis kan man ikke tænke sig et program, der ikke anvender if. I programmet skal man indtaste et vilkårligt antal tal, og metoden printer herefter

- antallet af indtastede tal - summen af indtastede tal - det mindste af de indtastede tal - det største af de indtastede tal - gennemsnittet af de indtastede tal

Et eksempel på en kørsel af programmet kunne være:

Fremgangsmåde

Programmet kan skrives på følgende måde:

namespace Exam15{class Program{static void Main(string[] args){double sum = 0;int count = 0;double min = double.MaxValue;double max = double.MinValue;double number;while ((number = Enter()) != 0){sum += number;++count;if (min > number) min = number;if (max < number) max = number;

}

Page 56: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

56

Programkontrol

Print(count, sum, min, max);}

static double Enter(){Console.Write(“Enter a number (enter 0 to stop): “);string line = Console.ReadLine();return Convert.ToDouble(line);

}

static void Print(int count, double sum, double min, double max){if (count > 0){Console.WriteLine(“Number of entered numbers: {0, 10:D}”, count);Console.WriteLine(“The sum of the numbers: {0, 10:F}”, sum);Console.WriteLine(“The smallest number: {0, 10:F}”, min);Console.WriteLine(“The highest number: {0, 10:F}”, max);Console.WriteLine(“Average: {0, 10:F}”, sum / count);

}elseConsole.WriteLine(“There are no numbers entered...”);

}}

}

Forklaring

Metoden starter med at erklære og initialisere nogle variabler. Typen double har to konstanter MaxValue og MinValue, der er hhv. det største og det mindste forekommende tal af typen double. Bemærk at det betyder, at variablen min initialiseres med en værdi, der med sikkerhed er for stor, mens max initialiseres med værdi, der med sikkerhed er for lille. Dernæst følger en while løkke. Her skal du især bemærke betingelsen:

while ((number = Enter()) != 0)

Enter() er den samme indtastningsmetode, som jeg tidligere har set på. Den returnerer en double, som gemmes i variablen number. Værdien af tildelingen er værdien af variablen number efter at metoden Enter() er udført, og det er denne værdi, der sammenlignes med 0. Bemærk, at det er nødvendigt med parenteser om tildelingen, da sammenligningsoperatoren != har højere prioritet end tildelingen. Resultatet er, at while løkken gentages indtil brugeren taster 0.

Inde i while løkken sker der følgende:

- det indtastede tal adderes til summen - tælleren count tælles op med 1 - hvis det indtastede tal er et nyt mindste tal (mindre end det, som før var det mindste) ændres

variablen min

Page 57: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

Click on the ad to read more

C# 1: Introduktion til programmering og programmeringssproget C#

57

Programkontrol

- hvis det indtastede tal er et nyt største tal (større end det, som før var det største) ændres variablen max

Efter at løkken er afsluttet, printes resultatet i metoden Print(). Her testes, om count er større end 0 for at sikre, at man ikke kommer til at dividere med 0.

We are a global specialist in energy management represented in more than 100 countries. We provide technology and integrated solutions to optimise energy usage across multiple market segments. We are more than 130,000 colleagues worldwide and 1.000 of us are situated in Denmark.

We invest in our employees, in the environment and in the future. Each year 5% of our revenue is allocated for research and development activities. In Schneider Electric you have many career paths to choose from – also internationally.

Would you like take on the challenge of transforming the way people and organisations use energy?

Do you know Schneider Electric?

Meet us at: www.schneider-electric.dk/job

Page 58: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

58

Strenge

6 StrengeEn string er en type, der repræsenterer tekst, og det er et alias for klassen System.String. string er i modsætning til de andre typer, der er behandlet indtil nu, en referencetype, men det forklares i detaljer i et senere kapitel. I C# består en streng af Unicode tegn, dvs. tegn af typen char. Strenge er en vigtige i praktisk programmering, og man kan faktisk ikke forestille sig et program, hvor man ikke anvender strenge. En streng literale angives som en sekvens af tegn i dobbelt anførselstegn, f.eks.

string navn = “Volmer”;

Ofte har man brug for at angive specielle tegn i en string. Det gør man i form af escape sekvenser, f.eks.

string navn = “\”Volmer\””;

hvis man ønsker at angive teksten ”Volmer” inkl. anførselstegn. Der findes følgende escape sekvenser:

Escape-sekvens Karakter Unicode kode

\’ Enkelt anførselstegn 0x0027

\” Dobbelt anførselstegn 0x0022

\\ Backslash 0x005C

\0 Nul 0x0000

\a Alert 0x0007

\b Backspace 0x0008

\f Formfeed 0x000C

\n New line 0x000A

\r Carriage return 0x000D

\t Vandret tabulator 0x0009

\v Lodret tabulator 0x000B

Variabler af typen string volder generelt ikke de store problemer, da de - selv om der er tale om en referencetype - i stor udstrækning anvendes som variabler af de simple typer. Man bør dog være opmærksom på erklæringer af formen:

string str1 = null;string str2 = “”;

hvor den første er en null reference, altså en string der ikke refererer til noget, mens den anden refererer til den tomme streng - en streng uden tegn.

Page 59: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

59

Strenge

Hvis man har et string objekt som f.eks.

string text = “Volmer”;

kan man referere til de enkelte tegn med et 0-baseret indeks. Hvis man f.eks. skriver

char ch = text[3];

vil variablen ch have værdien ’m’.

Exam16 Klassen String

string klassen har en række metoder, der er nyttige i forbindelse med behandling af strenge. Det følgende program viser eksempler på nogle af disse metoder:

static void Main(string[] args)

{

string text = “ABCDEFGHIJKLMNOPQRSTUVWXYZ”;Console.WriteLine(text.ToLower());

Console.WriteLine(text);

Console.WriteLine(text[3]);

Console.WriteLine(text.Length);

Console.WriteLine(text.Substring(3, 7));

Console.WriteLine(text.Substring(12));

Console.WriteLine(text.IndexOf(“KLMN”));

Console.WriteLine(text.IndexOf(“KMLN”));

Console.WriteLine(text.Substring(3, 7).CompareTo(“DEFGHIJ”));

Console.WriteLine(

String.Compare(text, 9, “1234567891234jklmnopq56789”, 13, 8, true));

string text1 = “Peter”;

string text2 = “Anders”;

Console.WriteLine(String.Compare(text1, text2));

Console.WriteLine(String.Compare(text2, text1));

}

Page 60: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

Click on the ad to read more

C# 1: Introduktion til programmering og programmeringssproget C#

60

Strenge

Forklaring

Først initialiseres en variabel text. Metoden text.ToLower() returnerer en streng, hvor alle bogstaver i text er konverteret til små bogstaver. Length er en egenskab, der returnerer antallet af tegn i en streng. Substring() er en metode, der returnerer en delstreng. F.eks. returnerer text.Substring(3, 7) en delstreng på 7 tegn fra plads 3 og frem, dvs. ”DEFGHIJ”. Hvis man kun angiver et argument til Substring() returneres en delstreng startende fra den plads og til slutningen af strengen. IndexOf() er en metode, der returnerer startpositionen for den første forekomst af en delstreng. F.eks. returnerer text.Indexof(”KLMN”) værdien 10. Hvis delstrengen ikke findes, returneres -1. CompareTo() er en metode, der alfabetisk sammenligner to strenge. Hvis man f.eks. skriver

text.CompareTo(“xyz”)

returneres værdien 0, hvis de to strenge er ens, -1 hvis text er mindre end ”xyz” og ellers 1. Der findes også en statisk version til sammenligning af strenge. F.eks. vil String.Compare(text1, text2) returnere 1, da text1 er større end text2.

Der er andre metoder til behandling af strenge, men de metoder, der er vist i dette eksempel, er de vigtigste.

Vil du også stå på ski i fremtiden?

Verden har brug for nye løsninger, og Topsøe har de katalysatorer og teknologier, der kan løse centrale udfordringer på den globale agenda: verdens energi- og miljøudfordringer.

Vi har fart på. Vores løsninger skal fortsat udvikles, udbredes og implementeres på det globale marked. Derfor vil vi gerne have endnu flere kolleger, som vil være med til at skabe værdi og fremdrift.

Du får mulighed for fordybelse, kundekontakt og rejseaktivitet. Og adgang til en verden af viden.

Vi arbejder i en fri og uformel atmosfære. Vi er stolte af at tage ansvar og bidrage til et bedre miljø.

Vil du være med?

WWW.TOPSOE.COM/JOBS

Need for speed?

Page 61: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

61

Strenge

Exam17 Palindrom

Som endnu et eksempel på et program, der behandler strenge, er følgende et program, der tester om en streng er et palindrom. Et palindrom er en sætning, der staves ens forfra og bagfra, dog sådan at mellemrum og specialtegn ignoreres, og at der ikke skelnes mellem store og små bogstaver. Eksempler på palindromer er

- Otto - En af dem der red med fane - Madam, I’m Adam - Selmas lakserøde garagedøre skal samles

Programmet skal virke på den måde, at brugeren indtaster en sætning, hvorefter programmet printer, om det er et palindrom. Kører man programmet, kunne resultatet være følgende:

Eksemplet skal dels vise mere om tegn og strenge, men skal desuden vise flere anvendelser af kontrolsætninger og betingelser.

Fremgangsmåde

Programmet kan beskrives (nedbrydes) på følgende måde:

1. indtast en streng2. test om det er et palindrom3. print resultatet4. gentag ovenstående indtil brugeren blot taster Enter

Indtastning er en simpel opgave, som jeg allerede har set på flere gange. Print af resultatet kræver heller ikke meget, og lidt mere formelt kan løsningen formuleres på følgende måde:

gentag indtast en linje sålænge linjen ikke er tom{hvis linje er et palindrom så

Page 62: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

62

Strenge

print linje er et palindromellersprint linje er ikke et palindrom

}

Her er den største udfordring at teste om den indtastede linje er et palindrom:

i = 0j = indeks på det sidste tegnsålænge i < j gentag{hvis både i og j refererer til et tegn der skal igonoreres så{tæl i 1 fremtæl j 1 tilbage

}ellers hvis i refererer til et tegn der skal ignoreres såtæl i 1 frem

ellers hvis j refererer til et tegn der skal ignoreres såtæl j 1 tilbage

ellers hvis det i’te tegn er forskellig fra det j’te tegn sådet er ikke et palidrom

ellers{tæl i 1 fremtæl j 1 tilbage

}}det er et palindrom

Denne algoritme kan skrives i C# på følgende måde:

static bool IsPalindrom(string text){for (int i = 0, j = text.Length - 1; i < j; ){if (!CharOk(text[i]) && !CharOk(text[j])){++i;--j;

}else if (!CharOk(text[i]))++i;

else if (!CharOk(text[j]))--j;

else if (text[i] != text[j])return false;

else{++i;--j;

}}return true;

}

Page 63: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

Click on the ad to read more

C# 1: Introduktion til programmering og programmeringssproget C#

63

Strenge

static bool CharOk(char ch){return (ch >= ’a’ && ch <= ’z’) || (ch >= ’0’ && ch <= ’9’) || ch == ’æ’ ||ch == ‘ø’ || ch == ‘å’;

}

Herefter kan man skrive Main() metoden:

static void Main(){while (true){string line = Enter();if (IsPalindrom(line.ToLower())) Console.WriteLine(line + “ er et palindrom”); else Console.WriteLine(line + “ er ikke et palindrom”);

}}

Tilbage er der indtastningsfunktionen:

static string Enter(){Console.Write(“? “);string text = Console.ReadLine();if (text.Length == 0) Environment.Exit(0);return text;

}

IFRS 2012, Standarder og fortolk-ningsbidrag – på dansk fås nu både som trykt bog samt som e-bog til smartphone, tablet og pc.

Introduktionspris: e-bog og trykt bog kr. 1545,-

E-bog inkl. opdateringer i 2012

Læs mere og køb e-bogen sammen med den trykte bog her: shop.magnus.dk

REGNSKABIFRS 2012 – nu også som e-bog

– Nuogså som

e-bog

Page 64: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

64

Strenge

Forklaring

Bemærk først betingelsen i while løkken i Main(). Den er altid sand, og det er dermed en uendelig løkke. Det betyder, at løkken og dermed programmet må stoppe på en anden måde. Det sker i indtastningsmetoden. Hvis brugeren blot taster enter og dermed ikke indtaster noget, udføres sætningen:

Environment.Exit(0);

der stopper programmet. Man kan diskutere, om det er måden at gøre det på, og det er da også primært medtaget her for at vise, at det er muligt.

Kontrollen udføres af metoden IsPalindrom(). Idéen er at have et indeks til både start og slut af strengen. Tegnene sammenlignes parvis. Der anvendes en hjælpemetode CharOk() der tester, om det er et tegn, der skal medregnes.

I forbindelse med betingelser er der tre vigtige operatorer, der som argumenter har én eller to betingelser:

- && har to argumenter af typen bool og er en matematisk konjunktion. Dvs. at den er sand, hvis begge dens argumenter er sande.

- || har to argumenter af typen bool og er en matematisk disjunktion. Dvs. at den er sand, hvis blot et af dens argumenter er sande.

- ! har et argument af typen bool og er en matematisk negation. Dvs. at den har den modsatte sandhedsværdi af argumentet.

Metoden CharOk() skal teste om dens parameter er et tegn, som skal tælles med: Om det er et bogstav eller et ciffer. Tegnene er ordnet i naturlig rækkefølge, men de tre danske bogstaver ligger for sig selv, hvilket komplicerer kontrollen en smule. Du skal bemærke, hvordan det sammensatte udtryk er bygget op med operatorerne && og ||. && har højere prioritet end ||, så strengt taget kan parenteserne undlades, men de øger læsbarheden. Kontrollen kan i tekst udtrykkes noget i retning af:

hvis (ch er mindst a og ch er højst z) eller (ch er mindst 0 og ch er højst 9) ellerch er æ eller ch er ø eller ch er å så ...

I Metoden IsPalindrom() anvendes ! operatoren til at teste den modsatte værdi af CharOk(), f.eks.

hvis not CharOk(text[i]) så ...

Bemærk, at når metoden IsPalindrom() kaldes i Main() metoden, så konverteres teksten (den streng der er indtastet) først til små bogstaver med metoden ToLower(). Det er derfor, det er tilstrækkelig at teste for små bogstaver i metoden CharOk().

Page 65: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

65

Arrays

7 ArraysEt array er et antal objekter af en bestemt type, der kan refereres med et fælles navn, og de enkelte objekter refereres med dette navn og et indeks. Det første element har altid indeks 0, og man kan således have følgende billede af et array med 10 objekter

0 1 2 3 4 5 6 7 8 9

hvor hver kasse har plads til et objekt af den pågældende type. I C# kan man oprette et array med plads til 10 int objekter på følgende måde:

int[] number = new int[10];

Det er parenteserne [] som fortæller, at number er et array. Bemærk, hvordan et array oprettes med new. Det er nødvendigt og fortæller bl.a. at et array er en referencetype. Hvis man f.eks. vil placere tal i de første fire pladser, kunne det ske på følgende måde:

number[0] = 2;number[1] = 3;number[2] = 5;number[3] = 7;

Følgende er også en lovlig sætning:

int sum = number[1] + number[3];

og variablen sum vil få værdien 10. Et konkret element som f.eks. number[2] kan ganske enkelt anvendes alle steder, hvor man kan anvende en int variabel.

Exam18 To arrays af typen int

Som et eksempel opretter nedenstående program to arrays til objekter af typen int og printer disse på skærmen:

static void Main(string[] args){int[] v1 = new int[10];int[] v2 = { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29 };for (int i = 0; i < v1.Length; ++i) v1[i] = i + 1;Print(v1);Print(v2);

}

Page 66: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

Click on the ad to read more

C# 1: Introduktion til programmering og programmeringssproget C#

66

Arrays

static void Print(int[] t){for (int i = 0; i < t.Length; ++i) Console.Write(”{0} ”, t[i]);Console.WriteLine();

}

Kører man programmet, får man resultatet:

Forklaring

Du skal bl.a. bemærke hvordan arrayet v2 defineres ud fra en liste af tal. Det betyder blot, at compileren kan oprette arrayet og direkte initialisere det med listens elementer. Bemærk også, hvordan arrayet v1 initialiseres i en for løkke. Bemærk her specielt, hvordan man med Length kan referere til antallet af elementer. Bemærk endelig, hvordan man kan overføre et array som parameter til en metode, og specielt hvordan man i metoden Print() angiver parameteren.

Page 67: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

67

Arrays

Exam19 Array af strenge

I ovenstående eksempel er typen int, men typen af et array kan generelt være hvad som helst. Herunder er vist et program, der opretter et array med 5 objekter af typen string:

static void Main(string[] args){string[] names = new string[5];names[0] = “Svend”;names[1] = “Knud”;names[2] = “Valdemar”;Console.WriteLine(“---------------------------”);for (int i = 0; i < names.Length; ++i) Console.WriteLine(names[i]);Console.WriteLine(“---------------------------”);

}

Når typen er en referencetype (her typen string) indeholder et array referencer. Dvs. at hver kasse indeholder en reference til en string. Bemærk, at det kun er de tre første der initialiseres. De to sidste er ikke initialiserede og har værdien null, svarende til at string er en referencetype. Udføres metoden, får man resultatet:

Bemærk de to blanke linjer der svarer til print af null. Det er et spørgsmål om, at WriteLine() metoden er lavet, så den blot printer en tom linje, hvis elementet er null.

Exam20 Yatzy

Der skal skrives et program, der skal simulere, at man kaster 5 terninger indtil de alle viser de samme øjne - indtil man får yatzy.

Fremgangsmåde

Programmet kan skrives på følgende måde:

class Program{static Random rand = new Random();

static void Main(string[] args){int[] cup = new int[5];

Page 68: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

68

Arrays

int count = 0;do{Cast(cup);Show(cup);++count;

}while (!Equals(cup));Console.WriteLine(“You’ve got yatzy after {0} attempts”, count);

}

static void Cast(int[] cup){for (int i = 0; i < cup.Length; ++i) cup[i] = rand.Next(1, 7);

}

static void Show(int[] cup){Console.Write(“[“);for (int i = 0; i < cup.Length; ++i) Console.Write(“ {0}”, cup[i]);Console.WriteLine(“ ]”);

}

static bool Equals(int[] cup){for (int i = 1; i < cup.Length; ++i) if (cup[i] != cup[0]) return false;return true;

}}

Forklaring

For at kunne simulere dette spil er der behov for en tilfældighedsgenerator. .NET har en class Random til det formål, og programmet starter derfor med at oprette en tilfældighedsgenerator med navnet rand. Bemærk, at den er oprettet uden for alle metoder. Det betyder, at der er adgang til den overalt i programmet, og dermed at alle metoder kender den.

Programmet skal simulere et raflebæger med 5 terninger. Hertil er i Main() defineret et array med 5 int elementer. Der er også defineret en variabel count, som skal anvendes til at tælle, hvor mange gange man skal slå med bægeret, indtil man får yatzy.

Ud over Main() er der tre metoder. Den første simulerer, at man slår med bægeret. Her skal du især bemærke, hvordan tilfældighedsgeneratoren anvendes: rand.Next(1, 7) betyder, at man får et tilfældigt tal, som er større end eller lig med 1 og mindre end 7 og dermed et tilfældigt af et af tallene 1, 2, 3, 4, 5 og 6. Metoden Show() gør ikke andet, end at den printer indholdet af bægeret på skærmen.

Metoden Equals() skal teste om de 5 terninger i bægeret er ens. Her skal du bemærke to ting, nemlig algoritmen og returværdien. Hvad angår det sidste er metoders returværdi noget der behandles i et

Page 69: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

Click on the ad to read more

C# 1: Introduktion til programmering og programmeringssproget C#

69

Arrays

senere afsnit, men en metode, som har en værdi, kan f.eks. anvendes i en betingelse, som det her sker i Main() metoden. Bemærk også, hvordan metodens værdi tildeles med en return sætning. Vedr. algoritmen så består den i at sammenligne alle terninger fra plads 1 og frem med den første terning - terningen på plads 0. Finder man én, der afviger fra den første, er alle terninger ikke ens, og metoden returnerer false. Kommer man derimod gennem hele for løkken, er alle terninger ens, og metoden returnerer true.

Exam21 Craps

Der skal skrives et program, der simulerer et simpelt terningespil, der kaldes craps:

En spiller kaster to terninger, hvorefter summen af øjnene noteres. Hvis summen er 7 eller 11, har spilleren vundet. Hvis summen er 2, 3 eller 12 har spilleren tabt (huset har vundet). Hvis summen derimod er 4, 5, 6, 8, 9 eller 10, noteres summen som spillerens point. Spilleren fortsætter herefter med at kaste terningerne, indtil summen af øjerne enten er spillerens point eller indtil summen er 7. Er summen spillerens point, har denne vundet. Er summen 7, har spilleren tabt, og huset har vundet.

Programmet skal virke på den måde, at brugeren først skal indtaste hvor mange spil, man ønsker at spille. Herefter simulere programmet det ønskede antal spil, og til sidste printer det, hvor mange gange spilleren har vundet, og hvor mange gange huset har vundet.

Tænker du også på fremtidens vand?

Så bliv en del af Nordens mest kompetente medarbejderstab specialiseret i vand.

Service | Value | Respo

nsib

ility

Vil du med på holdet?

Tjek vores jobside for ledige

stillinger og upload dit CV på

www.kruger.dk/da/job

Foto

: K

rüg

er

Sta

fett

en

rrn

ddn

dddn

dn

dddu

ndd

un

t o

t o

to

t ooo

t ooo

t o ot o

to

t ooo ooot ooo

t o

t o

too

t o

tm

CCm

Cm

Cm

CCm

Cm

Cm

CCm

CCm

Cm

Cm

CCm

CCCCCCCm

CCm

Cm

Cm

Cm

Cm

Cm

Cm

Cm

Cm

CCCmmmmmmmmmmmmmmmmm

hririiri

hri

hri

hri

hri

hririirii

hri

hriiiii

hri

hri

hri

hriiiirrr

hrr

hr

hr

hr

hrrrrrrrrrrrrrrrrrrr

hr

hrrrr

hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhst

ist

ist

ist

ist

ist

ist

ist

ist

ist

ist

ist

ist

ist

ist

ist

ist

ist

ist

ist

ist

ist

ist

ist

ist

ist

itisti

sti

sti

sti

sti

sti

stititistiiii

sti

sti

stii

sti

sti

sti

sti

sti

stiii

stii

stitistii

stii

sti

sstststststtsssssssssssn

sn

ssssssssn

sn

sa

ns

nssss

nss

ns

nss

an

sa

nss

nssss

an

sn

ssssa

ns

ns

an

sa

ns

an

ssn

ssa

nss

an

sa

ns

an

sa

nss

an

sa

ns

an

sa

ns

an

ssa

na

na

na

na

nnnnnna

na

na

nnnnna

nnnnnnnnna

nnnna

nna

na

nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnna

nnnnnnnnaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa

or

or

or

or

or

or

orr

or

or

orr

or

orrr

or

or

or

or

or

orr

orr

orr

or

orr

or

or

orr

oooooob

ooob

ob

oob

oob

ooobbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb

ggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggg

Page 70: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

70

Arrays

Fremgangsmåde

Denne gang er løsningen ikke helt simpel, og der er flere løsningsmuligheder. Jeg vil forsøge mig med en form for nedbrydning af opgaven i mindre dele, og Main() metoden kan skrives på følgende måde:

Main(){count = antallet af spilgentag count gange{Spilhvis spiller har vundet så adder 1 til variablen vundetprint hvem der har vundet

}print resultatet

}

Af denne skitse af Main() metoden er det tydeligt, at det centrale er Spil(), som er en metode, der simulerer et enkelt spil, og dermed en metode som skal implementere reglerne for craps. Algoritmen kan skrives på følgende måde:

Spil(){bg er et bæger med to terningerslå med bg og noter summen af terningernes øjne som pointhvis point er 7 eller point er 11 så spilleren har vundetellers hvis point er 2 eller point er 3 eller point er 12 så huset har vundetellers{slå med bg og noter summen af øjnene som sumsålænge sum er forskellig fra point og sum er forskellig fra 7 gentag{slå med bg og noter summen af øjnene som sum

}}hvis sum er lig med point så spiller har vundet elllers huset har vundet

}

Algoritmen for Spil() består grundlæggende af simple operationer, måske lige bortset fra det at slå med bægeret, der kan beskrives på følgende måde:

1. Kast terningerne

2. Print indholdet af bægeret

3. Bestem summen af terningernes øjne

Page 71: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

71

Arrays

Med alt det på plads er der i det væsentlige kun tilbage at oversætte ovenstående algoritmer til C#, og jeg vil starte med det sidste og dermed at simulere, at man slår med bægeret:

static int Throw(int[] cup){Cast(cup);Show(cup);return Sum(cup);

}

static void Cast(int[] cup){for (int i = 0; i < cup.Length; ++i) cup[i] = rand.Next(1, 7);

}

static void Show(int[] cup){Console.Write(”[”);for (int i = 0; i < cup.Length; ++i) Console.Write(” {0}”, cup[i]);Console.WriteLine(” ]”);

}

static int Sum(int[] cup){int sum = 0;for (int i = 0; i < cup.Length; ++i) sum += cup[i];return sum;

}

hvor rand er en tilfældighedsgenerator. Som vist ovenfor består det af tre operationer:

1. Kast terningerne implementeret af metoden Cast()2. Vis indholdet af bægeret implementeret af metoden Show()3. Bestem summen af terningernes øjne og returner værdien implementeret af metoden Sum()

Bemærk, at de tre metoder er relativ simple og alle er skrevet, så de er uafhængige af antallet af terninger i bægeret.

Med metoden Throw() til rådighed kan man skrive algoritmen for Play() i C#:

static bool Play(){int[] cup = new int[2];int point = Throw(cup);if (point == 7 || point == 11) return true;if (point == 2 || point == 3 || point == 12) return false;int sum = Throw(cup);while (sum != point && sum != 7) sum = Throw(cup);return sum == point;

}

Page 72: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

72

Arrays

Bemærk, at metoden i det væsentlige er en direkte afskrift af ovenstående algoritme.

Tilbage er der Main() metoden:

static void Main(){int count = Enter();int won = 0;for (int i = 0; i < count; ++i)if (Play()){Console.WriteLine(”Player has won...”);++won;

}elseConsole.WriteLine(”The house has won...”);

Result(count, won);}

static int Enter(){Console.Write(”Enter the numbers of games: ”);string text = Console.ReadLine();return Convert.ToInt32(text);

}

Forklaring

Jeg vil ikke systematisk gennemgå hele koden, men nøjes med at pege på ting, som du speciel skal være opmærksom på. Programmet indeholder i øvrigt ikke noget nyt i forhold til, hvad der er vist i tidligere eksempler.

Bemærk således, at flere af metoderne har returværdier. Bemærk f.eks. metoden Enter(), der returnerer en int. Bemærk hvordan metodens returværdi i Main() gemmes i variablen count.

Metoden Play() udfører et spil. Den opretter et bæger som et array med to terninger (en terning er igen repræsenteret som en int). Man kaster terningerne første gang og noterer, hvad terningerne viser (variablen point). Dernæst testes om spilleren har vundet, eller om huset har vundet. Har spilleren vundet, returnerer metoden true, og har huset vundet returnerer metoden false. Hvis spillet ikke er afgjort efter første kast, kastes terningerne igen, og det gentages, indtil spillet er afgjort.

Bemærk også metoderne Cast() og Show() der er direkte kopier af de tilsvarende metoder fra det forrige program.

Bemærkning

Ovenstående version af spillet er lidt simplificeret, og der findes flere regler knyttet til spillet. Hvis man spiller spillet, som beskrevet ovenfor, har spiller og huset næsten den samme sandsynlighed for at vinde med en lille overvægt til huset - og det skulle der jo også gerne være, hvis huset ikke skal gå fallit.

Page 73: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

Click on the ad to read more

C# 1: Introduktion til programmering og programmeringssproget C#

73

Objektorienteret programmering

Del 2 Objektorienteret programmering

Programmer skal behandle data, og data skal repræsenteres og opbevares, hvilket sker i variabler. Et sprog som C# har en række indbyggede typer til variabler, men ofte har man behov for at kunne definere sine egne datatyper, der bedre afspejler den opgave, som programmet skal løse. Det er her, klassebegrebet kommer ind. En klasse er noget, der definerer et begreb eller en ting inden for programmets problemområde, og der kan siges meget om, hvad der er klasser, og hvad der ikke er, men grundliggende er en klasse en type. Det er lidt mere end blot en type, idet en klasse dels definerer, hvordan data skal repræsenteres, men også hvad man kan med data af den pågældende type. En klasse definerer således både, hvordan typen skal repræsenteres, og hvilke operationer man kan udføre på variabler af den pågældende type.

Når man opretter variabler, hvis type er en klasse, taler man om objekter, således at en variabel af en klassetype kaldes et objekt, men egentlig er der ikke den store forskel på en variabel og et objekt, og der er et godt stykke af vejen ingen begrundelse for at skelne mellem de to ting. Men graver man lidt længere ned, er der dog en begrundelse, der har at gøre med, hvordan variabler og objekter allokeres i maskinens hukommelse.

Jeg udvikler og udviklesPrevas startede i 1985 og er i dag hovedleverandør og udviklingspartner til førende virksomhederindenfor Life Science, telecom, automotive, forsvar, energi og fremstillingsindustrien. Vi er mereend 500 ingeniører som brænder for at finde effektive løsninger for vores kunder. ”Innovation for Growth” er vores mantra.Hos Prevas møder du kompetente og spændende mennesker hver dag. Det kan være dine nyekollegaer eller det kan være vores kunders medarbejdere. Hos os får du mulighed for at arbejdemed nye teknologier i mange forskellige brancher for spændende virksomheder.Som medarbejder hos Prevas kommer du derfor altid til at udvikles - så længe du selv vil.

iNNovATioN For groWTHwww.prevas.com

Page 74: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

74

Objektorienteret programmering

Variabler som f.eks. int, double, bool, char osv. kaldes variabler af simple typer. Til et kørende program er der allokeret en såkaldt stak, der er et hukommelsesområde, som programmet anvender til bl.a. variabler. Stakken er særdeles effektiv, således at det er meget hurtigt for programmet løbende at oprette og fjerne variabler efter behov. Det kaldes en stak, forbi man kan tænke på stakken som en datastruktur illustreret på følgende måde:

Når programmet opretter en ny variabel, sker det øverst på stakken - der hvor pilen peger, og skal en variabel fjernes, er det den, der ligger øverst på stakken. Variabler af simple datatyper har den egenskab, at de altid fylder det samme. F.eks. fylder en int det samme, uanset hvilken værdi den har. Derfor kan den slags variabler gemmes direkte på stakken, da compileren ved, hvor meget de fylder. Hvis man således f.eks. skriver

int a = 23;

så bliver der på stakken oprettet en variabel af typen int og med den plads, som en int kræver, og værdien gemmes der. Variabler, som på den måde gemmes direkte på stakken, kaldes værdityper, og de simple eller indbyggede typer - på nær string - er alle værdityper.

Anderledes er det med variabler af referencetyper som f.eks. variabler, som er en class type. De skal oprettes eksplicit med new. Hvis man f.eks. har en class med navnet Coin (se nedenfor), og man ønsker at oprette et sådant objekt, skal man skrive

Coin c = new Coin();

Det ligner, hvordan man opretter en simpel variabel. Variablen hedder c. Når new udføres, sker der det, at der på den såkaldte heap oprettes et objekt på grundlag af typen Coin. Man kan tænke på heapen som en memory pool, hvorfra man kan allokere hukommelse efter behov. På stakken oprettes der som sædvanlig en variabel med typen Coin, men det, der gemmes på stakken, er ikke værdien af Coin objektet, men i stedet en reference til objektet på heapen. Alle referencer fylder det samme uanset type, og de kan derfor gemmes på stakken. Det er derfor man kalder det for en referencetype. Hvor præcis et objekt oprettes på heapen er bestemt af en såkaldt heap manager, der er et program, der hele tiden kører og administrerer heapen. Det er også heap manageren, som automatisk fjerner et objekt, når der ikke længere er behov for det.

Page 75: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

Click on the ad to read more

C# 1: Introduktion til programmering og programmeringssproget C#

75

Objektorienteret programmering

Af ovenstående grunde er det klart, at variabler af værdityper er mere effektive end objekter af referencetyper. Det betyder på ingen måde, at objekter af referencetyper er ineffektive, og i de fleste tilfælde er det slet ikke en forskel, som man behøver at forholde sig til, men omvendt er der også situationer, hvor forskellen betyder noget. Det er således vigtige at vide, at der er stor forskel på, hvordan værdityper og referencetyper håndteres af systemet, og at det i visse sammenhænge har stor betydning for, hvordan programmet vil opføre sig, men der skal nok komme mange eksempler som tydeliggør forskellen. Foreløbig er det nok at vide, at dataelementer kan grupperes i to slags afhængig af deres datatype, således at data af værdityper allokeres på stakken og sædvanligvis kaldes variabler, mens data af referencetyper allokeres på heapen og kaldes objekter - selv om der ikke er fuldstændig konsistens mht. de to navne.

Dine fordele ved forsikring hosPantaenius

DEN

10083 w

ww

.hqh

h.de

04/2

012

Østerbro 11 · 7800 SkiveTel. +45-9751 3388 · [email protected]

www.pantaenius.dk

Hjælp ved uheld

Du har behov for bugsering til nærmeste værft?Pantaenius overtager omkostningerne dog begrænset op til DKK 37.500,00!

Kontakt osHar du spørgsmål til dine forsikringer?Du kan ringe +45-9751 33 88 eller skrive til os på e-mail [email protected]

Inspektionsomkostninger

Du har haft en grundstødning og vil have bunden inspiceret?Pantaenius dækker inspektionen uden selvrisiko!

Ingen selvrisiko

Indbrud, transportskade, brand, lynnedslag eller totalskade?Ved disse skadesårsager er der ingen selvrisiko hos Pantaenius!

Page 76: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

76

Klasser

8 KlasserEfter denne lidt tekniske forklaring er det tiden at tage fat på klasser i C#.

Exam22 Mønter

Der skal skrive et program, der skal simulere, at man kaster to mønter. Programmet skal kaste mønterne indtil de begge viser krone (Head). Køres programmet, kunne resultatet være følgende:

Fremgangsmåde

Der er behov for en type, som kan repræsentere en mønt. I dette tilfælde kan møntens værdi være head (krone) eller tail (plat), og den skal stille følgende services til rådighed:

- man skal kunne kaste mønten (simulerer at den får en tilfældig værdi) - man skal kunne aflæse møntens værdi (se hvad mønten viser)

Typen kaldes Coin og kan illustreres på følgende måde:

Coin

value: char

Value: charThrow()

Koden kan skrives på følgende måde:

class Program{static void Main(string[] args){Coin c1 = new Coin();

Page 77: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

77

Klasser

Coin c2 = new Coin();do{c1.Throw();c2.Throw();Console.WriteLine(c1.Value + “ “ + c2.Value);

}while (c1.Value != ‘H’ || c2.Value != ‘H’);

}}

public class Coin{private static Random rand = new Random();private char value;

public Coin(){Throw();

}

public char Value{get { return value; }

}

public void Throw(){value = (rand.Next(2) == 0) ? ‘H’ : ‘T’;

}

public override string ToString(){return “” + value;

}}

Forklaring

Man skal repræsentere et begreb, der her er en mønt, og det kan man gøre med en class (en klasse), som her hedder Coin. Bemærk først, at klassen Coin ikke har nogen Main() metode, samt at metoderne ikke er erklæret static. Klassen er et begreb - en type - der kan anvendes i et program.

I C# kan en class indeholde fire elementer:

- medlemsvariabler (eller instance variable)

- konstruktører

- properties

- metoder

Page 78: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

Click on the ad to read more

C# 1: Introduktion til programmering og programmeringssproget C#

78

Klasser

og alle fire elementer forekommer i ovenstående klasse. Klassen har to variabler:

private static Random rand = new Random();private char value;

Den første hedder rand og har typen Random. Den er erklæret static og er lidt speciel, så den forklares om lidt. Den anden hedder value og har typen char. Det er den medlemsvariabel, der skal repræsentere mønten. Bemærk, at begge variabler er erklæret private. Det betyder, at der kun er adgang til disse variabler fra klassens egne metoder - de kan ikke direkte refereres fra andre klasser, der anvender klassen Coin.

Klassen har en metode, der hedder Throw(). Når metoden udføres, simulerer den, at mønten kastes og dermed får en ny værdi:

value = (rand.Next(2) == 0) ? ‘H’ : ‘T’;

Metoden tildeler variablen value en ny tilfældig værdi. Hertil anvendes ?-operatoren. Det er en operator, som har formen

betingelse ? udtryk1 : udtryk2;

og betydningen er, at hvis betingelse er sand, er værdien udtryk1 og ellers er værdien udtryk2.

Get “Bookboon’s Free Media Advice” Email [email protected]

See the light! The sooner you realize we are right, the sooner your life will get better!

A bit over the top? Yes we know!

We are just that sure that we can make your media activities more effective.

Page 79: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

79

Klasser

Random er en klasse i System namespacet, og den har en metode Next(), der returnerer et tilfældigt ikke negativt heltal. Hvis man angiver en parameter som Next(n), får man en tilfældig værdi mellem 0 og n-1 begge inkl. Derfor har

rand.Next(2)

en tilfældig værdi, der er 0 eller 1, og svarende hertil tildeles medlemsvariablen value et tilfældigt af tegnene H og T.

Medlemsvariablen value er private og kan derfor kun anvendes intern i klassen. Det program, der skal anvende Coin klassen skal imidlertid gerne kunne få at vide, hvilken værdi en mønt har, dvs. aflæse variablen value. Hertil anvendes en property:

public char Value{get { return value; }

}

En property har samme type og samme navn som en medlemsvariabel - blot skrives navnet med stort. Bemærk, at en property ikke syntaktisk er en metode (der er ingen parenteser efter navnet). En property har en get del, der returnerer værdien af den aktuelle medlemsvariabel.

Når der oprettes et objekt af klassen Coin, oprettes også en instance variabel value. Mønten kan kun have to lovlige værdier (H og T), og da møntens værdi er værdien af variablen value, vil mønten have en ulovlig værdi indtil den kastes. Det er uheldigt, fordi mønter i virkelighedens verden altid vil have en lovlig værdi, men også fordi at et program, der anvender Coin klassen ville kunne fejle. Dette problem løses med en konstruktør. Syntaktisk er det en metode, der ikke har nogen type, og som har samme navn som klassen:

public Coin(){Throw();

}

En konstruktør er en metode, der automatisk bliver udført, når der oprettes et objekt af klassen, og den anvendes typisk til at initialisere instance variabler. I dette tilfælde kaster konstruktøren mønten og sikrer dermed, at en mønt har en lovlig værdi straks den er oprettet. Bemærk i øvrigt, at den eneste måde hvorpå en mønt kan ændre værdi er ved at kaste den. Det er sikret igennem at medlemsvariablen value er private.

Når man har klassen, kan man oprette objekter, hvis type er Coin. Det sker med new operatoren, f.eks.

Coin c1 = new Coin();

Page 80: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

80

Klasser

Det opretter et objekt med navnet c1 hvis type er Coin. Når new operatoren udføres, oprettes klassens ikke-statiske medlemsvariabler, hvorefter klassens konstruktør automatisk bliver udført. De statiske medlemsvariabler oprettes på en anden måde, og sådan at de kun oprettes én gang. Dvs. at statiske medlemsvariabler deles mellem alle objekter af klassen. I dette tilfælde er medlemsvariablen rand statisk, og alle objekter af klassen Coin vil derfor anvende den samme rand variabel. Det er vigtigt, for ellers ville alle Coin objekter initialisere deres egen tilfældighedsgenerator (der initialiseres ved aflæsning af maskinuret), og resultatet ville være, at to objekter oprettet på samme sted i programmet altid ville have de samme værdier.

I Main() oprettes to objekter, som hedder c1 og c2. Efter at de er oprettet går programmet ind i en do løkke, der kaster mønterne, og viser dem på skærmen. Løkken kører indtil begge mønter viser værdien H. Bemærk, hvordan man kaster en mønt:

c1.Throw();

c1 er et objekt, og Throw() er en metode i den klasse, der definerer objektet. Man får udført metoden på det aktuelle objekt ved hjælp af dot operatoren. Bemærk også, hvordan man refererer til møntens værdi:

c1.Value

Her anvender man klassens property, der jo returnerer møntens værdi. Bemærk at i dette tilfælde har klassen Coin en property, der er readonly. Klasser kan også have properties, der er readwrite, som vil fremgå af andre eksempler.

Klassen har endnu en metode, som hedder ToString(), og som i øvrigt ikke anvendes i dette eksempel. Klasser bør generelt have en ToString() metode, som returnerer en string, der er en tekst repræsentation af et konkret objekt. Det betyder bl.a., at et objekt kan printes med metoden System.WriteLine(). Bemærk, at metoden er defineret som override. Det skal med, og betydningen forklares senere.

Bemærkning

En klasse har en såkaldt type visibility, der er enten public eller internal. Klassen Coin har public-visibility. Det betyder at alle kan oprette objekter af denne type. Visibility kan også angives internal:

internal class Coin

En sådan klasse kan kun instantieres fra klasser i samme assembly (dll eller exe) som klassen selv. Hvis man ikke angiver visibility for en klasse er default internal. Klassens medlemmer har også en visibility, der er én af følgende:

- public - private

Page 81: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

Click on the ad to read more

C# 1: Introduktion til programmering og programmeringssproget C#

81

Klasser

- internal - protected - protected internal

Foreløbigt omtales kun de tre første. public betyder, at et medlem kan refereres fra metoder i andre klasser, mens private betyder, at et medlem kun kan refereres fra klassens egne metoder. internal betyder, at et medlem kan refereres fra alle metoder i samme assembly. Medlemmers visibility kan ikke tilsidesætte type visibility. Hvis f.eks. en klasse har internal visibility, kan man ikke referere en public metode fra en anden assembly.

Både variabler og metoder kan tildeles visibility, men sædvanligvis defineres instance variabler private (eller protected). Det er et princip, der ofte kaldes for dataindkapsling og som sikrer, at det er den, der skriver klassen, der bestemmer hvilken adgang omverdenen skal have til klassens instance variabler. Der er kun adgang til instance variablerne gennem klassens metoder og properties og dermed gennem de services, som klassen stiller til rådighed. Hvis man f.eks. ser på klassen Coin ovenfor, kan variablen value kun ændres af metoden Throw(), og man kan derfor være sikker på, at en Coin altid har en lovlig værdi. Hvis value var public ville en bruger f.eks. kunne skrive

Coin c = new Coin();c.value = ‘X’;

Mangler du dygtige callcenter medarbejdere?Lad Assistance finde din nye medarbejderVi sætter en ære i at indhente viden om din virksomhed, jeres kultur og værdier, strategi, mission og vision. Herigennem danner vi os et præcist indtryk af jeres foretrukne profil. I rekrutteringsprocessen lægger vi vægt på følgende forhold:

• Grundig behovsafdækning – for et optimalt match• Jobprofil og stillingsopslag• Rådgivning i forhold til valg af annonceringsmedie• Screening af relevante ansøgere (test, analyse og problemløsning)

Kontakt os for et uforpligtende møde på telefon 33 55 00 90

Page 82: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

82

Klasser

Det ville dels betyde, at objektet nu har ulovlig værdi, men hvad værre er, kan en sådan fejl være meget vanskelig at finde. En anden begrundelse for altid at erklære en instance variabel private er, at variablen på den måde bliver en intern egenskab i klassen, som brugere af klassen i princippet ikke har kendskab til. I klassen Coin har variablen value typen char. Hvis man af én eller anden grund ønsker at ændre denne type til en string:

public class Coin{private string value;

kan man gøre det, uden at det har betydning for de programmer, der anvender klassen. Der er ingen der direkte refererer til variablen value.

Konklusionen er, at det i OOP er et princip altid at definere instance variabler private (eller protected).

Bemærkning

Når man opretter et objekt af en klasse, oprettes klassen instance variabler, hvorefter klassens konstruktør udføres. Hvis en klasse ingen konstruktør har, bliver der automatisk oprettet en default konstruktør, der er en konstruktør uden parametre og som ingenting laver. En konstruktør er karakteriseret ved, at det er en metode, der har samme navn som klassen, og som ikke har nogen type. En konstruktør er en metode, men den kan ikke kaldes eksplicit og udføres kun, når der instantieres et objekt. Klassen Coin har en konstruktør, der er en default konstruktør, men en klasse kan udmærket have flere konstruktører, da der gælder de almindelige regler for overstyring af metoder.

Coin er en referencetype, og nedenstående sætninger opretter to objekter:

Coin c1 = new Coin();Coin c2 = new Coin();

De lægges som nævnt ikke på stakken, men oprettes på heapen. c1 og c2 er sædvanlige variabler på stakken, men de indeholder ikke objekterne, men i stedet referencer til objekterne på heapen. Det er sjældent man som programmør behøver at tænke over det, men i enkelte situationer er det vigtigt at kende forskellen mellem et objekt allokeret på stakken og på heapen. Figuren herunder kan illustrere, hvordan det ser ud i maskinens hukommelse med de to variabler på stakken som refererer til objekter på heapen:

Page 83: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

83

Klasser

Coin objekt

value

Coin objekt

value

c1

c2

Hvis man f.eks. i programmet skriver

c1 = c2;

betyder det, at der ikke længere er nogen reference til det objekt som c1 før refererede til, men der er til gengæld to referencer til det objekt som c2 refererer til.

Coin objekt

value

Coin objekt

value

c1

c2

Hvis man herefter skriver

c1.Throw();c2.Throw();

betyder det, at man kaster den samme mønt to gange, idet begge referencer refererer til det samme objekt.

Når der ikke længere er nogen referencer til et objekt, betyder det også, at objektet automatisk nedlægges af heap manageren, og den hukommelse, som objektet har anvendt, bliver frigivet.

Page 84: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

Click on the ad to read more

C# 1: Introduktion til programmering og programmeringssproget C#

84

Design af klasser

9 Design af klasserEn klasse er en type, men der er også et design begreb. Klassen definerer objekter i form af instance variabler, hvordan objekter oprettes, og hvilket memory der allokeres til objekter. Objekter har på et givet tidspunkt en værdi i form af instance variablernes indhold, og et objekts værdi omtales sædvanligvis som dets tilstand. Klassen definerer også i form af dens metoder, hvad man kan gøre med objektet, og dermed hvordan man kan aflæse og modificere objekters tilstand.

Ethvert C# program består af en familie af klasser, der i fællesskab definerer, hvordan programmet skal virke, og et kørende program består af et antal objekter instantieret på baggrund af programmets klasser, objekter der samarbejder om at udføre det, som programmet nu skal. Arbejdet med at skrive et program består således i at skrive de klasser, som programmet skal bestå af. Hvilke klasser det er, er til gengæld ikke særlig entydigt, og det samme program kan typisk skrives på mange måder bygget op af klasser, der er helt forskellige. Arbejdet med at fastlægge hvilke klasser et program skal bestå af, og hvordan disse klasser skal se ud mht. variabler og metoder kaldes design. I princippet kan man sige, at hvis et program løser opgaven korrekt, kan det være uden betydning, hvilke klasser det består af, men uhensigtsmæssige klasser betyder

- at det bliver svært at forstå programmet og dermed at finde og rette fejl - at det fremover bliver svært at vedligeholde og modificere programmet

Page 85: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

85

Design af klasser

- at det bliver svært at genbruge programmets klasser i andre sammenhænge - at programmet kan blive ineffektivt og få en dårlig performance

Derfor er design og valg af klasser et yderst centralt emne i forbindelse med programmering, og man taler i den sammenhæng om programkvalitet (eller mangel på samme). En klasse er mere end blot en type, men det er en definition eller beskrivelse af et begreb inden for programmets problemområde. Når man skal definere, hvilke klasser et program skal bestå af, skal man således i stor udstrækning have fokus på klasser som værktøj til at definere væsentlige begreber mere end på klasser som en type i et programmeringssprog.

Et objekt er karakteriseret ved fire ting:

- en entydig identifikation, der identificerer et bestemt objekt i forhold til alle andre - en tilstand, der er objektets øjeblikkelige værdi - en adfærd, der fortæller hvad man kan gøre med objektet - en livscyklus fra objektet oprettes til det igen nedlægges

Et objekt oprettes på grundlag af en klasse, og tildeles på det tidspunkt en reference, der identificerer objektet. Klassens instance variabler fastlægger, hvilke variabler der skal oprettes til objektet, og værdien af disse variabler er objektets tilstand. Klassens metoder definerer, hvad man kan med objektet og dermed objektets adfærd. Det sidste punkt vedr. objekters livscyklus er knyttet til begrebet virkefelt, som forklares senere.

Exam23 Terninger

Opgaven er at skrive et program, der simulerer, at man kaster 5 terninger, indtil de alle er ens. Til sidst skal programmet printe, hvor mange gange terningerne er kastet - et eksempel som jeg i øvrigt har set på tidligere (Exam20), men på det tidspunkt havde jeg ikke klassebegrebet til rådighed.

Fremgangsmåde

Første opgave er at finde (beslutte sig for) programmets klasser, og som udgangspunkt er der behov for en klasse, som kan repræsentere en terning, hvor en terning er karakteriseret ved et antal øjne, og så skal det være muligt at kaste terningen samt få at vide, hvad den viser.

En anden oplagt klasse er et bæger med 5 terninger, og her skal det være muligt at slå med bægeret samt få at vide, hvad terningerne viser.

Endelig vil jeg skrive en klasse, som kan repræsentere selve spillet. Dvs. en klasse som har et bæger og en metode, som udfører spillet.

Page 86: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

86

Design af klasser

Det svarer til følgende design:

Dice

eyes: int

Eyes: intThrow()

Cup

Coint: intDice[]Toss()

Game

Yatzy()Play()

Program

Main()

1 1

5

Bemærk at designet på en måde er vilkårligt forstået sådan, at jeg ikke har fulgt bestemte retningslinjer, men valget af klasser er foretaget af udvikleren, og der kunne være andre løsninger, som kunne være lige så gode. Design er i høj grad en aktivitet, som bygger på erfaring og ved at se og forholde sig til, hvad andre har gjort, og det er sjældent muligt præcis at afgøre, hvad der er det bedste design, men et design kan være mere eller mindre hensigtsmæssigt.

Det skal dog tilføjes, at der findes metoder og teknikker, som kan hjælpe udviklerne med at finde frem til et programs klasser. Det er blot emner som falder uden for denne bogs rammer, men for større projekter er den slags systemudviklingsmetoder ikke blot nyttige, men også nødvendige.

Hvis jeg skal forsøge en begrundelse for ovenstående design, så er opgaven at skrive et program, som kan simulere et simpelt terningspil. Det begreb, som jeg først får øje på, er en terning, som noget af det, som det hele drejer sig om. Derfor en klasse Dice, der kan repræsentere en terning. I spillet skal man kunne kaste 5 terninger og inspireret af, hvordan man f.eks. spiller yatzy, er det naturligt også at tænke på et bæger, som man kan slå med. Derfor en klasse Cup. Endelige skal spillets regler og logikken til at spille være et sted, og det er ikke egenskaber ved et bæger, da man i virkelighedens verden ikke producerer bægere til bestemte spil - et bæger er generel og kan anvendes til mange former for spil. Selve spillet er derfor repræsenteret af en klasse Game.

Page 87: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

Click on the ad to read more

C# 1: Introduktion til programmering og programmeringssproget C#

87

Design af klasser

Med dette design på plads er det relativt simpelt at skrive de enkelte klasser. Klassen til en terning kan skrives på følgende måde:

public class Dice{private static Random rand = new Random();private int eyes;

public Dice(){Throw();

}

public void Throw(){eyes = rand.Next(1, 7);

}

public int Eyes{get { return eyes; }

}

public override string ToString(){return “” + eyes;

}}

Hvor mange skal tage en beslutning, før man kan føre

en beslutning ud i livet?

Slip for komplekse kommandoveje. Hos NNIT løser vi de store it-opgaver i små teams, der ikke skal spørge om lov til at tage

en beslutning. Se ledige job på nnit.dk/job

RE

TH

INK

PIP

EL

INE

Hvor mange skal tage en beslutning, før man kan føre

en beslutning ud i livet?

Slip for komplekse kommandoveje. Hos NNIT løser vi de store it-opgaver i små teams, der ikke skal spørge om lov til at tage

en beslutning. Se ledige job på nnit.dk/job

RE

TH

INK

PIP

EL

INE

Hvor mange skal tage en beslutning, før man kan føre

en beslutning ud i livet?

Slip for komplekse kommandoveje. Hos NNIT løser vi de store it-opgaver i små teams, der ikke skal spørge om lov til at tage

en beslutning. Se ledige job på nnit.dk/job

RE

TH

INK

PIP

EL

INE

Hvor mange skal tage en beslutning, før man kan føre

en beslutning ud i livet?

Slip for komplekse kommandoveje. Hos NNIT løser vi de store it-opgaver i små teams, der ikke skal spørge om lov til at tage

en beslutning. Se ledige job på nnit.dk/job

RE

TH

INK

PIP

EL

INE

Page 88: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

88

Design af klasser

Så er der klassen til et bæger, som bedst kan karakteriseres som en indkapsling af et array med Dice objekter:

public class Cup{private Dice[] dice;

public Cup(int n){dice = new Dice[n];for (int i = 0; i < n; ++i) dice[i] = new Dice();

}

public int Count{get { return dice.Length; }

}

public Dice this[int i]{get { return dice[i]; }

}

public virtual void Toss(){for (int i = 0; i < dice.Length; ++i) dice[i].Throw();

}

public override string ToString(){string text = “”;for (int i = 0; i < dice.Length; ++i){if (i > 0) text += “ “;text += dice[i].Eyes;

}return text;

}}

Klassen til selve spillet er meget simpelt og er i princippet et spørgsmål om, at koden fra Exam20 er flyttet ud i sin egen klasse:

public class Game{private Cup cup;

public Game(int n){cup = new Cup(n);

}

public void Play(){int count = 0;

Page 89: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

89

Design af klasser

do{cup.Toss();++count;Console.WriteLine(cup);

}while (!Yatzy());Console.WriteLine(“You’ve got yatzy after {0} attempts”, count);

}

private bool Yatzy(){for (int i = 1; i < cup.Count; ++i)if (cup[i].Eyes != cup[0].Eyes) return false;

return true;}

}

Til sidst er der Main() metoden:

class Program{static void Main(string[] args){Game game = new Game(5);game.Play();

}}

Forklaring

Hvis man sammenligner klassen Dice med klassen Coin vil man bemærke, at de i princippet er ens, og der er ikke meget at forklare udover at datarepræsentation denne gang er en int.

Klassen Cup repræsenterer et raflebæger, der implementeres som en klasse med en container til terninger - Dice objekter. Containeren er et array:

private Dice []dice;

men for at gøre bægeret mere fleksibel og give mulighed for at det kan anvendes i andre sammenhænge (hvor det ikke nødvendigvis skal indeholde 5 terninger) overføres antallet af terninger som har en parameter til konstruktøren. Dice er en referencetype, og når man opretter et array af referencetyper, får man et array, som indeholder referencer, men ikke objekter af den pågældende type. De skal oprettes eksplicit:

for (int i = 0; i < n; ++i) dice[i] = new Dice();

Da klassen har en konstruktør med en parameter, har den ingen default konstruktør. Der betyder, at man ikke kan oprette et bæger på følgende måde:

Cup cup = new Cup(); // ikke muligt

Page 90: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

Click on the ad to read more

C# 1: Introduktion til programmering og programmeringssproget C#

90

Design af klasser

Klassen har en readonly property, der returnerer antallet af terninger i bægeret. Den er nødvendig for brugere af klassen, da man ellers ikke kan få at vide, hvor mange terninger bægeret indeholder.

Desuden er der en readonly property, der returnerer den i’te Dice:

public Dice this[int i]{get { return dice[i]; }

}

Det er en noget speciel syntaks, hvor der anvendes this som navn, og som jeg ikke vil komme nærmere ind på her, men det betyder, at man i et program kan skrive følgende:

Cup cup = new Cup(5);Dice d = cup[1];

og referere til de enkelte terninger via et indeks - altså som om cup var et array. Brugeren kan altså anvende klassen som var det et array, men brugeren kan ikke se (eller behøver ikke at have viden om), om den interne repræsentation i klassen er et array eller noget andet. I dette tilfælde er der tale om readonly property. At den er readonly betyder, at en bruger f.eks. ikke kan skrive:

cup[1] = new Dice(); // ulovligt

Page 91: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

91

Design af klasser

Brugeren kan altså ikke putte en anden terning i bægeret, men da det, operatoren returnerer, er en reference kan brugeren godt gøre noget med de terninger, der er i bægeret, f.eks.

Dice d = cup[1];d.Throw();

Metoden Toss() er simpel og består blot af en loop, der løber over alle terninger og kaster dem.

Med klassen Cup færdig er klassen Game simpel, og dens konstruktør opretter på grundlag af en parameter et bæger med det antal terninger, som man ønsker at spille med. Selve spillet udføres af metoden Play().

Bemærk her specielt metoden Yatzy(), der tester om alle terninger er ens. Det er en private metode, da den kun skal anvendes i klassen Game.

Bemærkning

Klassen Dice har en property, som fortæller hvad terningen viser:

public int Eyes{get { return eyes; }

}

Rent teknisk betyder det, at der automatisk oprettes følgende metode:

public int get_Eyes(){return eyes;

}

En property er dermed dybest set det samme som en metode blot med en anden syntaks. Målet med en property er, at brugeren anvender en property, som det var en variabel, men stadig med den sikkerhed, at det er programmøren af klassen som bestemmer, hvad der er muligt. Herover er det altså programmøren af klassen Dice, der har bestemt at brugeren må aflæse en ternings øjne, men ikke ændre værdien.

Page 92: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

92

Metoder

10 MetoderDette afsnit uddyber forhold vedr. klassers metoder, og det drejer sig primært om fire ting:

- metoders navne - metoders returværdi - metoders properties - metoders parametre

og her er det om metoders parametre, hvor der er mest at sige.

Metoders navne

Vedr. navne er der ikke meget at sige udover, at der gælder det samme som for navne til variabler. Dog har man i C# den konvention, at navnet på en metode altid starter med et stort bogstav. En metode identificeres af dens navn og dens parametre. En klasse kan således godt have flere metoder, der hedder det samme, når blot de har forskellige parametre enten mht. antal eller typer.

Exam24 Funktionsoverstyring

Dette eksempel viser et program og en klasse med tre metoder, der samme navn.

Fremgangsmåde

Klassen Program har følgende metoder, der alle har det samme navn:

static int Max(int a, int b){return a < b ? b : a;

}

static double Max(double a, double b){return a < b ? b : a;

}

static int Max(int a, int b, int c){return Max(Max(a, b), Max(b, c));

}

Forklaring

Compileren kan adskille de to første, da de to parametre har forskellig type, og den kan også adskille den sidste, da den har tre parametre.

Page 93: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

Click on the ad to read more

C# 1: Introduktion til programmering og programmeringssproget C#

93

Metoder

Bemærk, hvordan ? operatoren er anvendt. Bemærk også, hvordan den sidste metode faktisk kalder den første.

Du skal bemærke, at metoder ikke adskilles på returtypen, men kun på parametrene.

Det at en metode ikke identificeres af navnet alene, men også af dens parametre, kaldes undertiden for funktionsoverstyring. Bemærk i øvrigt, at det ikke er noget, der er speciel for metoder, men også gælder for operatorer. Hvis man f.eks. skriver

c = a + b;

betyder det også noget forskelligt afhængig af, hvilke typer variablerne a og b har - om typen f.eks. er int eller string.

Bemærkning

I dette eksempel har jeg anvendt spørgsmålsoperatoren. Jeg har tidligere omtalt denne operator, men da det er en operator, som nogle føler er svær at forstå, skal den have en ekstra bemærkning her. I et program kan man f.eks. skrive noget i retning af følgende:

if (a < b)m = a;

elsem = b;

SÆT LYD PÅ FREMTIDENWidex udvikler højteknologiske høreapparater til gavn for de 500 millioner mennesker verden over, der har nedsat hørelse.

Mere end fem årtiers intensiv forskning og udvikling har gjort os til en af verdens førende høreapparatproducenter, og vi udvikler digital teknologi af en kvalitet, kun få kan måle sig med.

Som videnbaseret virksomhed betragter vi medarbejderne som vores vigtigste kapital. Vi kan godt lide at gøre tingene selv og sætter en ære i at være selvforsynende inden for de fl este om-råder. Det skaber et spændende, tværfagligt arbejdsmiljø med plads til initiativ og rig mulighed for personlig og faglig udvikling.

Vil du være med til at sætte lyd på fremtiden? Følg med i vores jobopslag på www.widex.dk/job eller skriv til [email protected]

www.widex.com

Page 94: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

94

Metoder

der tildeler variablen m den mindste af variablerne a og b. Dvs. at hvis betingelsen a < b er sand, får m værdien af a og ellers værdien af b. Det kan man også skrive ved hjælp af spørgsmålsoperatoren

m = a < b ? a : b;

og betydningen er præcis det samme. Spørgsmålsoperatoren starter med en betingelse, og hvis den er sand er værdien af udtrykket værdien af udtrykket (variablen) efter spørgsmålstegnet, og ellers er det værdien af udtrykket efter kolon. I dette eksempel vil

return a < b ? b : a;

således returnere det største af variablerne a og b. Man kan se spørgsmålsoperatoren som et alternativ til if, men det er naturligvis den forskel, at det er en operator og dermed kan indgå i udtryk som i ovenstående return sætning. Som nævnt er der nogen der synes, at operatoren er sværd at læse, men med øvelse er den ligeså naturlig, som alle andre operatorer.

Metoders returværdier

Metoderne i det forrige eksempel har alle en returtype, som enten er int eller double. Når en metode har en returtype, så har den en værdi, efter at den er udført. Metoden kan derfor indgå i et udtryk på samme måde som en variabel. F.eks. kan man skrive følgende:

double x = Max(3.14, 1.41);

der betyder, at returværdien af metoden Max() gemmes i variablen x. Når en metode har en returtype, skal den afsluttes med en return sætning, som bestemmer returværdien - ofte som resultatet af et udtryk. Der er ikke så meget at sige vedr. metoders returtyper, bortset fra at returtypen kan være hvad som helst - også referencetyper - samt at en metode kun kan have én returværdi. Som eksempel er herunder vist en simpel indtastningsmetode, der returnerer en string:

static string Indtast(string text)

{

Console.Write(text + “: “);

return Console.ReadLine();

}

Som en sidste bemærkning vedr. returtyper skal da også nævnes void, som ikke er en type, men blot en betegnelse for at en metode ikke har en returværdi. Selv om en metode er void, kan den godt have en tom return sætning, som så ikke giver metoden en værdi, men alene afbryder metoden.

Page 95: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

95

Metoder

Properties

En property er som nævnt tidligere egentlig bare en metode med en anden syntaks, og i princippet kan en property udføre hvad som helst. Tanken med en property er dog, at den skal aflæse (returnere) værdien af en instance variabel og evt. ændre dens værdi. Desuden anvender man den konvention, at navnet på en property er variablens navn skrevet med stort.

Exam25 Et Punkt

Dette eksempel viser en simpel klasse, som repræsenterer et punkt i et koordinatsystem.

Fremgangsmåde

class Point{private int x;private int y;

public Point(int x, int y){this.x = x;this.y = y;

}

public int X{get { return x; }set { x = value; }

}

public int Y{get { return y; }set { y = value; }

}

public override string ToString(){return string.Format(“({0},{1})”, x, y);

}}

Forklaring

Koordinaterne er private, og for at man kan få adgang til dem udefra, må klassen definere get properties. Hvis det også skal være muligt at ændre et objekts koordinater, skal klassen også definere set properties, f.eks.

set { x = value; }

Page 96: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

Click on the ad to read more

C# 1: Introduktion til programmering og programmeringssproget C#

96

Metoder

Betydning er, at man kan ændre værdien af variablen x, men syntaksen er lidt speciel, svarende til at den værdi der skal tildeles x er repræsenteret af det reserverede ord value. Resultatet er, at det i et program er muligt at skrive følgende:

Point p = new Point(2, 3);p.X = 5;

hvor x-koordinaten får en anden værdi.

Når en klasse som ovenfor tilbyder både get og set properties, og set properties ikke gør andet end at tildele værdien af value, så er der ingen forskel til blot at definere begge variabler som public. Det anbefales alligevel at overholde at definere variabler private og så skrive de nødvendige properties, da det som nævnt betyder, at det er programmøren, der lukker op for beskyttelsen. Ofte vil der dog også være knyttet begrænsninger til set properties. Hvis man f.eks. antager at x-koordinaten i ovenstående eksempel altid skal ligge mellem 0 og 1023, kunne man evt. skrive set metoden på følgende måde:

set { if (value >= 0 && value <= 1023) x = value; }

Som en sidste kommentar til ovenstående klasse, skal man bemærke konstruktøren. Klassen har to instance variabler, der hedder hhv. x og y, og konstruktøren har to parametre, som også hedder x og y. Det giver inde i konstruktøren et navnesammenfaldsproblem, da der et to ting (instance variablen og parameteren) der hedder det samme. Problemet løse med ordet this, hvor this.x betyder instance variablen, mens x (uden noget) betyder parameteren.

Dedicated Analytical Solutionswww.foss.dk/careers

Protein 13.2%

Moisture 8.4%

Starch 67%

FOSS is known throughout the world for efficient analytical solutions that help to improve both food quality and safety in the global food market. We are playing an increasingly important role in ensuring optimal use of valuable natural resources, and have throughout the years created ground-breaking innovations. And there’s more to come. At FOSS you will find professional challenges, training and development in a work environment that offers good work/ life balance. Join us and make a difference.

80% of the grain traded in the world is analysed on a FOSS solution

Page 97: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

97

Metoder

Parametre

En metodes parametre kan have en vilkårlig type, men der er flere former for parameteroverførsel. Når man definerer en metode, angiver man, hvilke parametre metoden skal have, og disse parametre kaldes de formelle parametre og angiver de værdier, som metoden skal virke på. Når man kalder metoden, skal man angive de værdier (parametre), der skal overføres til metoden, og de kaldes for de aktuelle parametre.

Værdioverførsel

Generelt er der tale om en såkaldt værdioverførsel, f.eks.

static int Max(int a, int b){return a < b ? b : a;

}

Når denne metode kaldes, skal der overføres to aktuelle parametre. Helt præcis sker der det, at der på stakken oprettes en såkaldt aktiveringsblok, som grundlæggende indeholder fire ting:

- returadressen, så systemet ved hvor programmet skal fortsætte, efter at metoden er termineret - en kopi af hver aktuel parameter - en plads til returværdien svarende til metodens type - metodens lokale variabler, hvis den har lokale variabler

Man kan skitsere det på følgende måde:

3

7

7

retur-adresse

int Max(int a, int b) { ... }

{ .... Max(3, 7); ....}

aktiveringsblok

metode

program

Når programmet kalder metoden Max() oprettes en aktiveringsblok på stakken, og returadressen og de aktuelle parametre kopieres hertil. Herefter får metoden kontrollen og starter sit arbejde. Dvs. at metoden hele tiden arbejder på de kopier (a og b), der ligger på stakken, og det betyder også, at hvis metoden ændrer disse værdier, ændres der på stakken, og disse ændringer har derfor ingen effekt i programmet. Når metoden udfører sin return sætning, kopieres returværdien til aktiveringsblokken, hvorefter metoden terminerer og kontrollen gives tilbage til programmet, som så fortsætter sit arbejde. Umiddelbart efter at programmet har fået kontrollen tilbage, kan den aflæse returværdien fra aktiveringsblokken, som herefter nedlægges. Bemærk at det også betyder, at hvis metoden opretter lokale variabler (hvilket ikke er tilfældet i dette eksempel) er de også væk.

Page 98: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

98

Metoder

Betragt som et andet eksempel følgende metode:

public void Swap(int a, int b){int t = a;a = b;b = t;

}

Når den udføres, bytter den om på værdierne af de to parametre a og b. Afprøver man metoden Swap(), vil man se, at de aktuelle parametre ikke er byttet om:

static void Test2(){int t1 = 2;int t2 = 3;Swap(t1, t2);Console.WriteLine(“{0} {1}”, t1, t2);

}

Hvis man ser på, hvad Swap() laver på stakken, vil den nok bytte om på a og b

23

a

b

t

232

a

b

t

332

a

b

t

322

a

b

t

t=a a=b b=t

men da det sker på stakken i aktiveringsblokken, vil de to variabler t1 og t2 være uændrede efter at Swap() er udført.

Man skal imidlertid være opmærksom på, hvad det betyder for reference typer, da resultatet her kan være anderledes end forventet. Betragt som eksempel klassen Point og følgende metode, som har en Point som parameter:

static void Mul(Point p, int t){p.X *= t;p.Y *= t;

}

Hvis man udfører følgende sætninger:

Point p = new Point(2, 3);Mul(p, 2);Console.WriteLine(p);

Page 99: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

Click on the ad to read more

C# 1: Introduktion til programmering og programmeringssproget C#

99

Metoder

får man resultatet

(4,6)

og dermed at metoden Mul() har ændret Point objektet. Umiddelbart stemmer det ikke med at parameteren overføres ved en værdioverførsel. Metoden Mul() har to parametre, og her er typen af den første parameter Point og dermed en klasse. Den aktuelle parameter er dermed en reference, og det der lægges på stakken er denne reference, hvilket betyder at Mul() metoden refererer til samme objekt som programmet. Resultatet er, at det er dette objekt der ændres.

Hvis man ændrer Mul() metoden til følgende

public void Mul(Point p, int t){p = new Point(p.X, p.Y);p.X *= t;p.Y *= t;

}

vil metoden oprette et nyt Point objekt, og referencen på stakken vil referere til dette objekt. Når Mul() terminerer, nedlægges aktiveringsblokken, og referencen til det nye objekt er væk, og dermed også den ændring som Mul() udfører. Resultatet er, at det objekt som programmet refererer til, er uændret, og programmet vil skrive

HD – vejen tilen karrierei erhvervslivet

Læs mereAarhus: hd.au.dkHerning: auhe.au.dk/hd

LÆS HD I ØKONOMI OG LEDELSE

HD er en anerkendt diplom- uddannelse, som giver dig mulighed for at specialisere dig inden for det erhvervsøkonomiske fagområde ved siden af dit job.

Page 100: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

100

Metoder

(2,3)

Der er altså grund til at være opmærksom på, hvad der sker, hvis man overføre referencer som parametre ved en almindelig værdioverførsel.

Reference parametre

Under .NET kan man også anvende egentlige reference parametre. F.eks. kan man ændre metoden Swap() til følgende:

public void Swap(ref int a, ref int b){int t = a;a = b;b = t;

}

Hvis man dernæst ændre metoden Test2(), så de aktuelle parametre er referencer:

static void Test3(){int t1 = 2;int t2 = 3;Swap(ref t1, ref t2);Console.WriteLine(“{0} {1}”, t1, t2);

}

er det referencer til de aktuelle parametre, der lægges på stakken, og Swap() vil derfor bytte om på værdierne af variablerne t1 og t2. Dvs. at de ændringer, som Swap() udfører, bliver på de objekter, som referencerne på stakken refererer til.

Reference parametre anvendes i stedet for værdi parametre, når de ændringer en metode gør på sine parametre skal være gældende i den kaldende kode.

Bemærk, at man kan kombinere værdiparametre og referenceparametre, således at en metode kan have parametre til både reference- og værdi overførsel.

out parametre

I .NET er der også en mulighed for at anvende out parametre, som er parametre der ikke nødvendigvis er initialiseret inden en metode kaldes, og som i stedet tildeles en værdi i metoden. Følgende metode opretter to Point objekter, som tildeles referencer, der er overført som out parametre til metode:

static void Points2(int x1, int y1, int x2, int y2, out Point p1, out Point p2){

Page 101: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

101

Metoder

p1 = new Point(x1, y1);p2 = new Point(x2, y2);

}

Hvis metoden udføres på følgende måde:

static void Test4(){Point p1;Point p2;Points2(2, 5, 7, 3, out p1, out p2);Console.WriteLine(p1);Console.WriteLine(p2);

}

vil p1 og p2 referere til de objekter, der er oprettet i metoden Points2(). Bemærk, at p1 og p2 ikke er initialiseret i programmet, hvilket ikke er nødvendigt, da de anvendes som aktuelle out parametre. En metode kan kun have én returværdi, og out parametre løser et problem, nemlig hvor det er ønskeligt, at en metode skal returnere flere værdier. F.eks. skal metoden Points2() returnerer to værdier, hvilket ikke er muligt, og problemet kan så løses ved at give metoden to out parametre.

Default parametre

Det er også muligt at angive default værdier for parametre. Nedenstående metode har tre parametre:

static double Calculate(double price, int units = 1, double discount = 5){return price * units * (100 - discount) / 100;

}

Metoden beregner prisen på en vare excl. rabat. Antallet af enheder er som default sat til 1, og rabatprocenten er som default 5 procent. Det betyder, at metoden kan kaldes uden at angive værdier for disse parametre:

static void Test5(){Console.WriteLine(Calculate(20));Console.WriteLine(Calculate(20, 5));Console.WriteLine(Calculate(20, 10));

}

og undlader man det, anvendes default værdierne. I princippet kan alle parametre have en default værdi, men de parametre, som har en default værdi, skal stå sidst.

Page 102: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

102

Metoder

Variabelt antal parametre

Som en sidste bemærkning vedr. parametre vil jeg vise, hvordan det er muligt at lade en metode have et variabelt antal parametre. Følgende metode har et array af typen string som parameter, og metoden returnerer en streng bestående af alle strenge i arrayet adskilt af mellemrum:

static string Concat(params string[] text){if (text.Length == 0) return “”;string temp = text[0];for (int i = 1; i < text.Length; ++i) temp += “ “ + text[i];return temp;

}

Det vigtige er ordet params, som betyder, at man kan angive et variabelt antal aktuelle parametre. F.eks. kan metoden kaldes på følgende måde:

static void Test6(){Console.WriteLine(Concat(“One”, “Two”, “Three”));Console.WriteLine(Concat(“One”));Console.WriteLine(Concat());Console.WriteLine(Concat(“One”, “Two”, “Three”, “Four”, “Five”));

}

Exam26 Metoders parametre

Alle ovenstående testmetoder vedr. metoders parametre er samlet i eksempel Exam26, og udfører man eksemplet er resultatet følgende:

Page 103: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

103

Arv

11 ArvEn klasse skal som nævnt flere gange repræsentere en ting i programmets problemområde, og under designet beslutter man, hvilke egenskaber en klasse skal have. Når en klasse først er færdig, testet og taget i brug skal man være forsigtig med at åbne den igen og foretage ændringer, da der er en betydelig risiko for, at ændringer kan få utilsigtede konsekvenser for de programmer, der anvender klassen. Men uanset hvor omhyggelig man er under designet, kan man komme ud for, at det siden er nødvendigt at udvide en klasse med nye egenskaber, og det er her arv kommer ind i billedet som en teknik til at udvide en klasse uden at ændre i den eksisterende klasse. En anden side af arv skal tilgodese den situation, hvor man har to klasser, som ligner hinanden, men også har forskelle. Her kan man undertiden placere det som de har fælles i en basisklasse, som de andre så arver.

Exam31 Punkter

Dette eksempel skal alene vise syntaksen, men er ikke et eksempel på, hvor arv anvendes i praksis.

Følgende klasse definerer et punkt i et koordinatsystem:

public class Point{private int x;private int y;

public Point(int x, int y){this.x = x;this.y = y;

}

public int X{get { return x; }set { x = value; }

}

public int Y{get { return y; }set { y = value; }

}

public override string ToString(){return string.Format(“({0}, {1})”, x, y);

}}

Page 104: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

Click on the ad to read more

C# 1: Introduktion til programmering og programmeringssproget C#

104

Arv

Klassen er simpel og kræver ikke nogen videre forklaring. Jeg vil nu skrive en klasse som arver Point, og man kan tænke på det som en klasse, der udvider klassen Point med nye egenskaber - i dette tilfælde blot en enkelt metode:

public class NewPoint : Point{public NewPoint(int x, int y) : base(x, y){}public void Add(Point p){X += p.X;Y += p.Y;

}}

Syntaksen for arv er:

public class NewPoint : Point

der betyder, at NewPoint arver eller udvider Point. Resultatet er, at et NewPoint objekt har de public egenskaber (properties og metoder) som NewPoint definerer, samt de public egenskaber som Point klassen definerer. Meningen er, at skal en klasse have nye egenskaber, så skal man arve frem for at modificere den eksisterende klasse. På den måde undgår man at ændre i klasser som allerede er lavet, og som man ved virker.

������������� ����������������������������������������������� �� ���������������������������

������ ������ ������������������������������ ����������������������!���"���������������

�����#$%����&'())%�*+����������,����������-

.��������������������������������� ��

���������� ���������������� ������������� ���������������������������� �����������

The Wakethe only emission we want to leave behind

Page 105: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

105

Arv

Når man opretter et NewPoint objekt, skal der overføres værdier til den klasse, der arves fra, hvilket sker med base efter konstruktøren. Faktisk svarer det til, at konstruktøren i Point klassen udføres.

Herunder er vist et program, som anvender NewPoint klassen:

static void Main(string[] args){NewPoint p1 = new NewPoint(2, 3);NewPoint p2 = new NewPoint(1, 4);p1.Add(p2); // metode defineret i NewPointp1.X = p1.X * 3; // property defineret i PointConsole.WriteLine(p1); // ToString() metoden fra Point

}

Exam27 Personer

Som eksempel vil jeg starte med en klasse, der repræsenterer en person ved et fornavn og et efternavn:

public class Person{private string firstName;private string lastName;

public Person(string firstName, string lastName){this.firstName = firstName;this.lastName = lastName;

}

public string FirstName{get { return firstName; }

}

public string LastName{get { return lastName; }

}

public override string ToString(){return firstName + “ “ + lastName;

}}

Klassen er meget simpel og kræver ikke mange kommentarer.

Page 106: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

106

Arv

Jeg vil dernæst definere en klasse, som repræsenterer en ansat (i en virksomhed), når en ansat er en person med yderligere to egenskaber i form af en stillingsbetegnelse og en månedsløn. Klassen Employee kan skrives på flere måder, og man kan bl.a. tænke på den som en udvidelse af klassen Person med to nye egenskaber. Løsningen er ikke bare at udvide Person klassen, da man kan tænke sig denne klasse anvendt i sammenhænge, hvor begreber som stillingsbetegnelse og månedsløn ikke giver mening. I stedet kan man skrive en klasse, som arver Person:

public class Employee : Person{private string position;private int monthly;

public Employee(string firstName, string lastName, string position, int monthly): base(firstName, lastName)

{this.position = position;this.monthly = monthly;

}

public string Position{get { return position; }

}

public int Monthly{get { return monthly; }

}

public override string ToString(){return base.ToString() + “\n” + position;

}}

Bemærk først at der efter klassens navn Employee står

: Person

Det er det, der fortæller, at Employee arver Person. Når Employee arver Person betyder det, at en Employee får (arver) alle de egenskaber som Person har samt udvider med nye egenskaber. I dette tilfælde udvider en Employee en Person med to nye instance variabler og tilhørende properties. Klassen Employee har en konstruktør, der initialiserer de to nye instance variabler position og monthly, men den skal desuden initialisere instance variablerne firstName og lastName i basisklassen. Det kræver, at konstruktøren i Person bliver kaldt, men da en konstruktør ikke kan kaldes direkte, er det nødvendigt med en syntaks, der udfører konstruktøren i basisklassen. Det sker på følgende med:

: base(firstName, lastName)

Page 107: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

Click on the ad to read more

C# 1: Introduktion til programmering og programmeringssproget C#

107

Arv

Her betyder kolon og base() efter metodeprototypen, at konstruktøren i Person udføres med firstName og lastName som aktuelle parametre. Helt konkret sker der det, når man opretter et Employee objekt, at konstruktøren i Person udføres, hvorefter at konstruktøren i Employee udføres. Da en Employee specielt er en Person, kan man sige, at Person skal oprettes først, inden Employee kan oprettes. Et Employee objekt kan herefter referere til de to properties FistName og LastName. Et Employee objekt kan referere til FirstName, da det er en public property i Person og da Employee arver Person. Employee objekter kan referere til alle public medlemmer i både Person og Employee. private medlemmer kan stadig kun refereres inde fra den klasse, hvor de er defineret. F.eks. kan variablen firstName i Person ikke refereres fra metoder i Employee.

Jeg vil dernæst definere en klasse, som repræsenterer en direktør. En direktør er jo blot en særlig slags Employee, og klassen kan derfor defineres som en klasse, der arver Employee:

public class Director : Employee{public Director(string firstName, string lastName, int monthly): base(firstName, lastName, “Director”, monthly)

{}

}

Klassen er meget simpel og består alene af en konstruktør, som overfører parametre til konstruktøren i Employee klassen. Alle de andre services som en Director behøver, kommer (arves) fra Employee og Person.

We are a global specialist in energy management represented in more than 100 countries. We provide technology and integrated solutions to optimise energy usage across multiple market segments. We are more than 130,000 colleagues worldwide and 1.000 of us are situated in Denmark.

We invest in our employees, in the environment and in the future. Each year 5% of our revenue is allocated for research and development activities. In Schneider Electric you have many career paths to choose from – also internationally.

Would you like take on the challenge of transforming the way people and organisations use energy?

Do you know Schneider Electric?

Meet us at: www.schneider-electric.dk/job

Page 108: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

108

Arv

På helt samme måde kan man definere en klasse, som repræsenterer en bogholder:

public class Bookkeeper : Employee{public Bookkeeper(string firstName, string lastName, int monthly): base(firstName, lastName, “Bookkeeper”, monthly)

{}

}

Betragt nu følgende metode:

static void Print(Employee e){Console.WriteLine(e);Console.WriteLine(“Monthly: {0}”, e.Monthly);Console.WriteLine(“{0}, {1}”, e.LastName, e.FirstName);

}

Den første sætning printer resultatet af ToString() i Employee. Den næste er der ikke så meget mystisk i, men bemærk den sidste, som anvender to properties, der begge er defineret i Person. Parameteren e har typen Employee, og kan dermed specielt anvende, hvad der er defineret public i Person.

Betragt også følgende metode, der opretter to objekter af hhv. typerne Director og Bookkeeper:

static void Test1(){Director d = new Director(“Olga”, “Jensen”, 8000);Bookkeeper b = new Bookkeeper(“Karlo”, “Hansen”, 5000);Print(d);Print(b);

}

Du skal især bemærke, at metoden kalder Print() med de to objekter d og b som aktuelle parametre. Det giver god mening, for d har typen Director, der specielt er en Employee.

Ovenfor er der defineret fire klasser, der hænger sammen i et hierarki, som man kan illustrere på følgende måde:

Page 109: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

109

Arv

Person

Ansat

BogholderDirektoer

Når en klasse arver en anden klasse, kalder man den der arves fra for basisklassen, og den der arver for en afledt klasse. F.eks. er Person basisklasse for Employee, mens Employee er afledt af Person. Undertiden kalder man i stedet Person for superklassen, mens Employee kaldes en subklasse. Man siger også, at Person er en generalisering af Employee, samt at Employee er en specialisering af Person. Denne sprogbrug afspejles bedre i forholdet mellem Employee, Director og Bookkeeper, hvor Employee er en generalisering af Director og Bookkeeper og Director og Bookkeeper er specialiseringer af Employee. Undertiden taler man også om, at den klasse der arver er en udvidelse af basisklassen svarende til at Employee udvider Person med nye egenskaber.

Jeg vil skrive endnu en klasse, som skal repræsentere en konsulent, når det er en Employee, hvis løn er beregnet som en fast månedsløn samt en provision af salget:

public class Consultant : Employee{private double commission;private double sale;

public Consultant(string firstName, string lastName, int monthly,double commission) : base(firstName, lastName, “Consultant”, monthly)

{this.commission = commission;

}

public double Commission{get { return commission; }

}

public double Sale{get { return sale; }set { sale = value; }

}

public override int Monthly{get { return monthly + (int)(sale * commission / 100); }

}}

Page 110: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

Click on the ad to read more

C# 1: Introduktion til programmering og programmeringssproget C#

110

Arv

Bemærk først, at en Consultant udvider klassen Employee med to nye variabler. Den ene initialiseres i konstruktøren, mens den anden får en værdi ved hjælp af en property. Det er der ikke så meget at sige til. Hvis man derimod ser på propertyen Monthly, skal man bemærke to ting, nemlig ordet override, samt at den refererer til variablen monthly i basisklassen Employee - hvilket ikke er muligt, da den er private. Problemet løses ved at ændre Employee og i stedet definere variablen som protected:

public class Employee : Person{protected int monthly;

Hvis et medlem i en klasse er protected, kan det refereres fra afledte klasser, som var det public, mens det fra objekter af klassen ser ud som private. protected er således en mellemting mellem private og public, der giver mulighed for at afledte klasser kan referere til medlemmer i basisklassen, samtidig med at basisklassen bevarer beskyttelsen i forhold til andre klasser. Sagt anderledes, så kan variablen monthly refereres fra subklasser af Employee, men ikke fra klasser der ikke arver Employee. En klasse bør dog ikke gøre alle sine variabler protected, men kun de variabler som man må forvente, at afledte klasser har behov for at referere til, da man jo åbner op for beskyttelsen i forhold til afledte klasser.

I dette tilfælde er protected alene medtaget for at forklare begrebet, for problemet kunne være løst på en anden måde:

Vil du også stå på ski i fremtiden?

Verden har brug for nye løsninger, og Topsøe har de katalysatorer og teknologier, der kan løse centrale udfordringer på den globale agenda: verdens energi- og miljøudfordringer.

Vi har fart på. Vores løsninger skal fortsat udvikles, udbredes og implementeres på det globale marked. Derfor vil vi gerne have endnu flere kolleger, som vil være med til at skabe værdi og fremdrift.

Du får mulighed for fordybelse, kundekontakt og rejseaktivitet. Og adgang til en verden af viden.

Vi arbejder i en fri og uformel atmosfære. Vi er stolte af at tage ansvar og bidrage til et bedre miljø.

Vil du være med?

WWW.TOPSOE.COM/JOBS

Need for speed?

Page 111: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

111

Arv

public override int Monthly

{

get { return base.Monthly + (int)(sale * commission / 100); }

}

hvor man med base referere til den property, der er defineret i basisklassen.

Der findes nu en definition af propertyen Monthly i både Employee og Consultant, og meningen er, at den i Consultant skal overstyre den i Employee - give den en anden betydning. For at det er muligt, skal man i Employee klassen åbne op for det ved at erklære propertyen virtual:

public virtual int Monthly

{

get { return monthly; }

}

Når det er tilfældet kan en afledt klasse - her Consultant - vælge at overstyre propertyen ved at angive ordet override. Hvis man ikke gør det, får man en advarsel om, at den skjuler basisklassen version.

Det var klassen Consultant, og herunder er vist en metode, der anvender klassen:

static void Test2()

{

Consultant c = new Consultant(“Gudrun”, “Madsen”, 2000, 10);

c.Sale = 30000;

Print(c);

}

Hvis man kører metoden, får man resultatet:

der ikke er helt oplagt. Bemærk, at den property, der er udført for månedsløn, er Consultant klassens, det selv om parameteren til Print() metoden har typen Employee. Dvs. at systemet ”husker” typen af det aktuelle objekt, selv om objektet i Print() er kendt som en Employee. Det er en yderst vigtig egenskab, som kaldes polymorfi.

Page 112: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

112

Arv

Når man skriver en klasse, har man ingen garanti for, at der ikke senere er én som arver klassen og udvider den med nye egenskaber - og det er jo præcis også tanken med arv. Der kan imidlertid være situationer, hvor man ikke ønsker denne mulighed, og man kan da erklære klassen sealed, som betyder, at den ikke kan arves. Hvis man f.eks. ikke ønsker, at det skal være muligt at arve klassen Director, kan man definere det på følgende måde:

public sealed class Director : Employee{public Director(string firstName, string lastName, int monthly): base(firstName, lastName, “Director”, monthly)

{}

}

Bemærkning

Arv er ikke et specielt svært begreb - i det mindste ikke, når man har set det nogle gange - men der alligevel nogle ting man skal være opmærksom på:

- En klasse - som f.eks. Employee - kan have én eller flere afledte klasser, men en klasse kan kun arve én klasse.

- Polymorfi - det at runtime systemet husker den konkrete type af et objekt (den type som står efter new, når objektet oprettes) er én af de allervigtigstes begreber inden for objektorienteret programmering.

Desuden er der nogle navne knyttet til arv, hvis betydning, det er vigtig at have styr på:

- base - protected - virtual - override

Page 113: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

113

Klassen Object

12 Klassen ObjectJeg har efterhånden set på en del klasser som f.eks. Coin, Dice, Cup mv. og disse klasser har ikke anvendt arv - tilsyneladende, men faktisk har de indirekte arvet en klasse som hedder Object. Hvis man ikke skriver noget, så vil enhver klasse automatisk arve denne klasse, og dermed vil alle klasser uden undtagelse direkte eller indirekte arve Object. Det gælder faktisk mere end det, for enhver type uanset om det er en værditype eller referencetype arver Object.

C# definerer et alias object for klassen System.Object, som er et reserveret ord, helt på samme måde som string er et alias for klassen System.String.

Klassen Object indeholder ikke meget, og dens primære formål er at være en fælles basisklasse for alle typer. Klassen definerer nogle få metoder, som jeg vil omtale herunder. Først vil jeg nævnte ToString(), som returnerer værdien af et objekt som en streng. Betragt følgende klasse:

class ZipCode{private string code;private string name;

public ZipCode(string code, string name){this.code = code;this.name = name;

}

public string Code{get { return code; }

}

public string Name{get { return name; }

}}

Da der ikke er angivet andet, arver den klassen Object. Betragt følgende metode:

static void Test1(){ZipCode z = new ZipCode(“7800”, “Skive”);Console.WriteLine(z);

}

Page 114: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

Click on the ad to read more

C# 1: Introduktion til programmering og programmeringssproget C#

114

Klassen Object

hvor der oprettes et objekt af typen ZipCode, og dette objekt printes på skærmen. Bemærk, at når objektet printes med WriteLine(), så er det resultatet af objektets ToString() metode, der printes. I dette tilfælde er der ikke nogen ToString() metode i klassen ZipCode, men programmet kan oversættes og køre, og resultatet er følgende:

Den ToString() metode, der udføres, kommer fra klassen Object, og den printer det fulde navn for objektets type, der er klassens namespace og klassens navn. Man kan dermed slå fast, at alle objekter uden undtagelse har en ToString() metode, men det er den, der skriver objektets klasse, som har ansvaret for at overstyre metoden, så den returnerer et meningsfyldt resultat. Da en klasse altid arver Object, er det årsagen til jeg har skrevet override i alle de klasser, der har defineret en ToString() metode - ToString() er en virtual metode i klassen Object.

Object definerer også en metode som hedder Equals(), og som har et Object som parameter. Det er en metode, som returnerer true, hvis det aktuelle objekt og parameteren er ens. Hvis man udfører følgende metode

IFRS 2012, Standarder og fortolk-ningsbidrag – på dansk fås nu både som trykt bog samt som e-bog til smartphone, tablet og pc.

Introduktionspris: e-bog og trykt bog kr. 1545,-

E-bog inkl. opdateringer i 2012

Læs mere og køb e-bogen sammen med den trykte bog her: shop.magnus.dk

REGNSKABIFRS 2012 – nu også som e-bog

– Nuogså som

e-bog

Page 115: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

115

Klassen Object

static void Test2()

{

ZipCode z1 = new ZipCode(“7800”, “Skive”);

ZipCode z2 = new ZipCode(”7800”, ”Skive”);

Console.WriteLine(z1.Equals(z2));

}

vil den skrive False på skærmen, og det var ikke det, som man umiddelbart ville forvente. De to objekter z1 og z2 har den samme værdi, men det er to forskellige objekter, der hver refererer til deres objekt på heapen. Den Equals(), der er defineret i klassen Object, sammenligner objektreferencer, og da z1 og z2 er to forskellige objekter, vil Equals() returnere false, selv om de to objekter har den samme værdi. Skal det være anderledes, er det op til programmøren at overstyre metoden Equals(), så den sammenligner på værdier frem for på referencer. Hvis man vil overstyre Equals() i klassen ZipCode kan man gøre følgende:

public override bool Equals(object obj){if (obj is ZipCode){ZipCode z = (ZipCode)obj;return code.Equals(z.code) && name.Equals(z.name);

}return false;

}

Bemærk først is operatoren, der kan anvendes til at teste, om et objekt har en bestemt type. For at Equals() skal returnere true, skal obj som minimum være af typen ZipCode. Er det tilfældet, kan man typecaste den til et ZipCode. Herefter er obj lig med det aktuelle objekt, hvis både postnummer og bynavn er ens. Bemærk at denne test i virkeligheden bygger på, at String klassen overstyrer Equals() med værdi semantik.

Jeg vil nævne endnu en metode i klassen Object som hedder GetHashCode(). Det er en metode, der for et objekt returnerer et heltal, som kan opfattes som en identifikation af objektet. Generelt er denne kode bestemt ud fra objektets reference, men det er på samme måde som for ToString() og Equals() op til programmøren at overstyre metoden, hvis den skal returnere en kode bestemt ud fra objektets værdi. Der findes forskellige retningslinje for, hvordan denne kode skal bestemmes, men først kan man bemærke, at det ikke er et krav, at to forskellige objekter returnerer forskellige hash koder. Derimod skal det gælde, at hvis man har to objekter obj1 og obj2 og obj1.Equals(obj2) er sand, da skal obj1.GetHashCode() være lig med obj2.GetHashCode(). Jeg vil ikke på dette sted give eksempler på anvendelsen af denne metode, men eksemplerne kommer senere. En anden grund til at nævne GetHashCode() på dette sted er, at hvis man overstyrer Equals() uden at overstyre GetHashCode(), så får man en advarsel fra oversætteren. I det fleste tilfælde kan denne advarsel ignoreres.

Page 116: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

116

Klassen Object

Betragt følgende metode, hvor du især skal bemærke, at metoden har en object som parameter:

static void Print(object obj){Console.WriteLine(obj.GetType());Console.WriteLine(obj.GetHashCode());Console.WriteLine(obj);

}

Du skal også bemærke metoden GetType(), som er en metode i klassen Object, og som i dette tilfælde anvendes til at printe navnet på objektets type. Den følgende metode opretter et array af typen object og printer dets elementer på skærmen:

static void Test3(){object[] t = { 23, 3.14, “Volmer”, new Postnummer(“7800”, “Skive”) };for (int i = 0; i < t.Length; ++i) Print(t[i]);

}

Kører man metoden er resultatet følgende:

Du skal primært bemærke to ting:

- at en metode der som formel parameter har et object kan have en aktuel parameter af vilkårlig type

- at et array af typen object kan indeholde hvad som helst uanset type

Umiddelbart kan det lyde smart, men man skal være opmærksom på, at det betyder at compileren ikke kan type kontrollere og dermed at koden, der bygger på typen object, meget let kan indeholde fejl.

Ovenstående eksempel vedr. klassen Object hedder Exam28.

Page 117: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

117

Abstrakte klasser

13 Abstrakte klasserI dette kapitel vil jeg indføre begrebet en abstrakt klasse. Det er en klasse som ikke kan instantieres - man kan altså ikke oprette objekter af en abstrakt klasse, men abstrakte klasser kan f.eks. være basisklasser for andre konkrete klasser.

Exam32 Abstrakte punkter

Jeg vil igen starte med et eksempel, som alene har til formål at vise syntaksen, og eksemplet er i det væsentlige det samme som Exam31. Klassen Point er nu abstract:

public abstract class Point{private int x;private int y;

public Point(int x, int y){this.x = x;this.y = y;

}

public int X{get { return x; }set { x = value; }

}

public int Y{get { return y; }set { y = value; }

}

public override string ToString(){return string.Format(“({0}, {1})”, x, y);

}

public abstract void Dec();public abstract void Inc();

}

Der er to forskelle. Klassen har nu to abstrakte metoder Dec() og Inc(). Det er metoder, som ingen kode har, og dermed blot er en definition. Det betyder, at dem som bruger klassen Point ved at disse metoder findes, men ikke hvordan de virker. Den anden forskel er, at klassen selv er defineret abstract. Det skal den være, og det betyder, at klassen ikke kan instantieres - man kan ikke oprette objekter af typen Point.

Klassen NewPoint arver Point, og den skal derfor implementere de to abstrakte metoder, så de bliver

Page 118: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

Click on the ad to read more

C# 1: Introduktion til programmering og programmeringssproget C#

118

Abstrakte klasser

konkrete metoder, der udfører noget:

public class NewPoint : Point{public NewPoint(int x, int y) : base(x, y){}

public override void Dec(){--X;--Y;

}

public override void Inc(){++X;++Y;

}}

Bemærk, at en abstrakt metode som implementeres i en afledt klasse, skal foranstilles ordet override.

Herunder er vist en Main() metode, som bruger klassen NewPoint:

Page 119: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

119

Abstrakte klasser

static void Main(string[] args){Point p = new NewPoint(2, 3);Console.WriteLine(p);p.Inc();Console.WriteLine(p);p.Dec();Console.WriteLine(p);

}

p er et NewPoint objekt, men det er i programmet defineret som en Point. Det er muligt, da en NewPoint specielt er en Point, men du skal især bemærke, at selv om p er et Point, så kan man alligevel skrive

p.Inc();

Da Point har en abstract metode Inc(), ved oversætteren at et Point objekt har en sådan metode (selv om den er defineret i en afledt klasse), hvorfor ovenstående sætning giver mening.

Exam29 Lån

Som eksempel skal der skrives en klasse, der kan repræsentere et lån i et pengeinstitut. Et lån er (i dette eksempel) karakteriseret ved en hovedstol, et antal ydelser samt en rentefod. Jeg vil antage, at rentefoden er konstant under hele afviklingsperioden, samt at der betales én ydelse hver termin på terminsdagen, samt at første ydelse falder 1 termin efter lånets stiftelse. Jeg vil desuden antage, at man er interesseret i følgende oplysninger

- den n’te ydelse - afdraget ved den n’te ydelse - renten ved den n’te ydelse - restgælden efter at den n’te ydelse er betalt

Det færdige program skal printe en amortisationsplan, der er en oversigt over, hvordan lånet ser ud efter hver termin.

Fremgangsmåde

Svarende hertil kan et lån repræsenteres af følgende klasse:

Page 120: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

Click on the ad to read more

C# 1: Introduktion til programmering og programmeringssproget C#

120

Abstrakte klasser

Loan

principal: doublerate: doubleperiods: int

Principal: doubleRate: doublePeriods: intPayment(n): doubleInterest(n): doubleRepayment(n): doubleOutstanding(n):double

Nu findes der flere slags lån, og som eksempel kan man se på et serielån, der er karakteriseret ved, at man hver termin betaler det samme i afdrag plus renten af det til enhver tid skyldige beløb. Ved et sådant lån falder ydelsen hen over tilbagebetalingsperioden. Hvis man f.eks. har et serielån på 1000 kr. og der er 10 terminer, betales der 10 ydelser, hvor afdraget hver gang er 100 kr.

Man kan også se på et annuitetslån, som er karakteriseret ved, at ydelsen er konstant gennem hele tilbagebetalingsperioden. Det betyder, at forholdet mellem rente og afdrag ændres således, at i starten er en stor del af ydelsen rente og kun en mindre del er afdrag, og mod slutningen af perioden er forholdene modsat. Sammenhængen mellem lånets hovedstol og ydelsen kan udtrykkes i følgende formel:

Tænker du også på fremtidens vand?

Så bliv en del af Nordens mest kompetente medarbejderstab specialiseret i vand.

Service | Value | Respo

nsib

ility

Vil du med på holdet?

Tjek vores jobside for ledige

stillinger og upload dit CV på

www.kruger.dk/da/job

Foto

: K

rüg

er

Sta

fett

en

rrn

ddn

dddn

dn

dddu

ndd

un

t o

t o

to

t ooo

t ooo

t o ot o

to

t ooo ooot ooo

t o

t o

too

t o

tm

CCm

Cm

Cm

CCm

Cm

Cm

CCm

CCm

Cm

Cm

CCm

CCCCCCCm

CCm

Cm

Cm

Cm

Cm

Cm

Cm

Cm

Cm

CCCmmmmmmmmmmmmmmmmm

hririiri

hri

hri

hri

hri

hririirii

hri

hriiiii

hri

hri

hri

hriiiirrr

hrr

hr

hr

hr

hrrrrrrrrrrrrrrrrrrr

hr

hrrrr

hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhst

ist

ist

ist

ist

ist

ist

ist

ist

ist

ist

ist

ist

ist

ist

ist

ist

ist

ist

ist

ist

ist

ist

ist

ist

ist

itisti

sti

sti

sti

sti

sti

stititistiiii

sti

sti

stii

sti

sti

sti

sti

sti

stiii

stii

stitistii

stii

sti

sstststststtsssssssssssn

sn

ssssssssn

sn

sa

ns

nssss

nss

ns

nss

an

sa

nss

nssss

an

sn

ssssa

ns

ns

an

sa

ns

an

ssn

ssa

nss

an

sa

ns

an

sa

nss

an

sa

ns

an

sa

ns

an

ssa

na

na

na

na

nnnnnna

na

na

nnnnna

nnnnnnnnna

nnnna

nna

na

nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnna

nnnnnnnnaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa

or

or

or

or

or

or

orr

or

or

orr

or

orrr

or

or

or

or

or

orr

orr

orr

or

orr

or

or

orr

oooooob

ooob

ob

oob

oob

ooobbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb

ggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggg

Page 121: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

121

Abstrakte klasser

Endelig kan restgælden umiddelbart efter betalingen af den n’te ydelse beregnes som:

Hvis man ser på ovenstående klasse Loan er der således behov for to versioner: Én til et serielån og én til et annuitetslån. Da to klasser har meget til fælles, er det oplagt at tænke på et design med en fælles basisklasse og to afledte klasser:

Loan

principal: doublerate: doubleperiods: int

Principal: doubleRate: doublePeriods: intPayment(n): doubleInterest(n): doubleRepayment(n): doubleOutstanding(n):double

SerialLoan AnnuityLoan

Payment(n): doubleInterest(n): doubleRepayment(n): doubleOutstanding(n):double

Payment(n): doubleInterest(n): doubleRepayment(n): doubleOutstanding(n):double

De tre klasser kan implementeres på følgende måde:

public abstract class Loan{protected double principal;protected double rate;protected int periods;

public Loan(double principal, double rate, int periods){this.principal = principal;this.rate = rate;this.periods = periods;

}

Page 122: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

122

Abstrakte klasser

public double Principal{get { return principal; }

}

public double Rate{get { return rate; }

}

public int Periods{get { return periods; }

}

abstract public double Payment(int n);abstract public double Interest(int n);abstract public double Repayment(int n);abstract public double Outstanding(int n);

}

public class SerialLoan : Loan{public SerialLoan(double principal, double rate, int periods) :base(principal, rate, periods)

{}

public override double Repayment(int n){return principal / periods;

}

public override double Outstanding(int n){return Repayment(0) * (periods - n);

}

public override double Interest(int n){return Outstanding(n - 1) * rate;

}

public override double Payment(int n){return Repayment(n) + Interest(n);

}}

public class AnnuityLoan : Loan{public AnnuityLoan(double principal, double rate, int periods) :base(principal, rate, periods)

{}

public override double Payment(int n){return principal * rate / (1 - Math.Pow(1 + rate, -periods));

Page 123: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

123

Abstrakte klasser

}

public override double Outstanding(int n){return principal * Math.Pow(1 + rate, n) - Payment(0) *

(Math.Pow(1 + rate, n) - 1) / rate;}

public override double Interest(int n){return Outstanding(n - 1) * rate;

}

public override double Repayment(int n){return Payment(n) - Interest(n);

}}

Programmet skal kunne printe en amortisationsplan, som er en tabel, der viser status for lånet hver termin:

public class Amortisation{private Loan loan;

public Amortisation(Loan loan){this.loan = loan;

}

public void Print(){Console.WriteLine(”Principal: {0, 10:F}”, loan.Principal);Console.WriteLine(”Rate of interest: {0, 10:F}”, loan.Rate);Console.WriteLine(”Number of periods: {0, 10:D}\n”, loan.Periods);Console.WriteLine(”Periods Payment Repayment Interest Outstanding”);

for (int n = 1; n <= loan.Periods; ++n)Console.WriteLine(”{0, 7:D}{1, 15:F}{2, 15:F}{3, 15:F}{4, 15:F}”, n,loan.Payment(n), loan.Repayment(n), loan.Interest(n), loan.Outstanding(n));

}}

Forklaring

Bemærk først, at klassen Loan er defineret abstract. Det skal den, fordi den har abstrakte metoder. En abstract metode er en metode, der ikke er defineret - dens kode er ikke skrevet. I dette tilfælde er der fire abstrakte metoder. Årsagen til at metoderne er abstrakte er, at hvordan ydelsen mv. beregnes afhænger af hvilken slags lån, der er tale om. De kan først implementeres, når man kender lånebetingelserne. En abstrakt metode er blot en prototype definition, hvor en metode defineres ved dens navn, returtype og parametre, men metodens krop mangler.

Page 124: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

Click on the ad to read more

C# 1: Introduktion til programmering og programmeringssproget C#

124

Abstrakte klasser

Loan er en type, og selv om den er abstrakt, og man dermed ikke kan oprette objekter af typen Loan, kan typen f.eks. anvendes som parametertype til en metode. Alle der får oplyst, at de har at gøre med noget af typen Loan ved, at det er noget, der ud over de tre properties har fire metoder til hhv. ydelsen, renten, afdraget og restgælden, og man kan anvende de fire abstrakte metoder, som om de eksisterede.

Klassen SerialLoan arver Loan, og det er således op til klassen SerialLoan at implementere de fire abstrakte metoder, således at SerialLoan bliver en konkret klasse. Klassen SerialLoan kan netop implementere de abstrakte metoder, fordi den har den viden der skal til - en viden der ikke er kendt i klassen Loan. Implementeringen af de abstrakte metoder er trivielle, men bemærk at et SerialLoan specielt er en Loan.

Klassen AnnuityLoan er også let at implementere, og det består blot i at skrive ovenstående formler i C#. Her skal du bemærke metoden Pow(), der er en statisk metode i klassen Math, og som opløfter et argument i en potens.

Til sidst er der klassen Amortisation, som kan printe en amortisationsplan, dvs. en oversigt over lånets afvikling. Her skal du bemærke, at klassen har en instance variabel af typen Loan, der initialiseres i konstruktøren. Man kan altså sagtens have en variabel, hvis type er en abstrakt klasse, da konkrete objekter af typerne hhv. SerialLoan og AnnuityLoan jo også er af typen Loan. Vær opmærksom på, at klassen Amortisation intet kender til de konkrete låneklasser, men alligevel kan man skrive metoden Print(), da alle metoder er defineret for den abstrakte type Loan. Klassen Amortisation vil således også understøtte og virke på nye lånetyper, når blot de arver klassen Loan.

Jeg udvikler og udviklesPrevas startede i 1985 og er i dag hovedleverandør og udviklingspartner til førende virksomhederindenfor Life Science, telecom, automotive, forsvar, energi og fremstillingsindustrien. Vi er mereend 500 ingeniører som brænder for at finde effektive løsninger for vores kunder. ”Innovation for Growth” er vores mantra.Hos Prevas møder du kompetente og spændende mennesker hver dag. Det kan være dine nyekollegaer eller det kan være vores kunders medarbejdere. Hos os får du mulighed for at arbejdemed nye teknologier i mange forskellige brancher for spændende virksomheder.Som medarbejder hos Prevas kommer du derfor altid til at udvikles - så længe du selv vil.

iNNovATioN For groWTHwww.prevas.com

Page 125: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

125

Abstrakte klasser

Test

Hvis man tester ovenstående klasser med følgende program:

class Program{static void Main(string[] args){Amortisation table1 = new Amortisation(new SerialLoan(10000, 0.02, 10));Amortisation table2 = new Amortisation(new AnnuityLoan(10000, 0.02, 10));table1.Print();table2.Print();

}}

får man følgende resultat:

Bemærkning

I de sidste eksempler har der typisk været flere klasser og i dette tilfælde fire klasser ud over Main programmet. I alle eksemplerne har klassernes kode været i den samme fil, men efterhånden som eksemplerne bliver større, er der ikke en farbar vej af hensyn til overskueligheden. Mange vælger konsekvent at placere hver klasse i sin egen file, og det er en ganske fornuftig strategi, da man på den måde for små source filer, som er langt lettere at overskue.

Page 126: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

Click on the ad to read more

C# 1: Introduktion til programmering og programmeringssproget C#

126

Abstrakte klasser

Bemærkning

Bemærk specielt, at en klasse kan være abstract, selv om den ikke har abstrakte metoder. Det kan man bruge, hvis man ønsker at sikre, at en klasse ikke kan instantieres.

Dine fordele ved forsikring hosPantaenius

DEN

10083 w

ww

.hqh

h.de

04/2

012

Østerbro 11 · 7800 SkiveTel. +45-9751 3388 · [email protected]

www.pantaenius.dk

Hjælp ved uheld

Du har behov for bugsering til nærmeste værft?Pantaenius overtager omkostningerne dog begrænset op til DKK 37.500,00!

Kontakt osHar du spørgsmål til dine forsikringer?Du kan ringe +45-9751 33 88 eller skrive til os på e-mail [email protected]

Inspektionsomkostninger

Du har haft en grundstødning og vil have bunden inspiceret?Pantaenius dækker inspektionen uden selvrisiko!

Ingen selvrisiko

Indbrud, transportskade, brand, lynnedslag eller totalskade?Ved disse skadesårsager er der ingen selvrisiko hos Pantaenius!

Page 127: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

127

Interfaces

14 InterfacesEn abstract class er en type, der kan indeholde alt hvad en klasse kan i form af variabler, konstruktører, metoder mv., blot kan nogle af metoderne være abstrakte svarende til at de endnu ikke er kodet - det udskydes til de konkrete klasser, der har den fornødne viden. I modsætning hertil er et interface en type, som kun kan indeholde abstrakte metoder.

Exam33 Punkter igen

Følgende interface definerer et punkt:

public interface IPoint{int X { get; set; }int Y { get; set; }

}

Grundlæggende ligner det en class, blot står der i stedet interface. Et interface definerer metoder og properties og i dette tilfælde to properties. Man kan tænke på et interface som en class, der kun kan indeholde abstrakte metoder. Bemærk specielt, at i et interface har metoderne ikke nogen visibility - de er som default public.

Herunder er vist en klasse, som implementerer interfacet:

public class Point : IPoint{private int x;private int y;

public Point(int x, int y){this.x = x;this.y = y;

}

public int X{get { return x; }set { x = value; }

}

public int Y{get { return y; }set { y = value; }

}

public override string ToString(){return string.Format(“({0}, {1})”, x, y);

}}

Page 128: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

128

Interfaces

Bemærk, at der anvendes samme syntaks som ved arv:

public class Point : IPoint

Når en klasse implementerer et interface, skal klassen implementere de metoder og properties, som interfacet definerer.

Følgende Main() metode anvender interfacet:

static void Main(string[] args){IPoint p = new Point(2, 3);Console.WriteLine(p);

}

p er et Point objekt, men i programmet er det kendt ud fra dets definerende interface.

Exam30 Penge

Der skal skrive et program, som opretter en pung med pengesedler. Pungen skal stille følgende services til rådighed:

- man kan lægge en seddel i pungen

- man kan spørge om pungen er tom

- man kan spørge om pungen er fuld

- man kan spørge om pungen har (indeholder) en bestemt seddel

- man kan tage (betale med) en seddel med en bestemt værdi

- man kan få at vide hvor mange penge der er i pungen

Når pungen er implementeret, skal den testes af et program, som ligger sedler i pungen og dernæst bruger nogle af sedlerne.

Fremgangsmåde

Første step er at definere en pengeseddel, og jeg vil arbejde med danske sedler, som har værdier 50, 100, 200, 500 og 1000 og dermed 5 forskellige sedler.

Page 129: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

129

Interfaces

En seddel er et meget simpelt begreb, som primært er karakteriseret ved en værdi (én af ovenstående), og den kan defineres af et interface:

public interface IBankNote{int Value { get; }

}

som blot er en definition, der fortæller, at en pengeseddel - et IBankNote objekt - er noget, som har en get property, som returnerer en int.

Jeg vil dernæst definere en abstrakt klasse, som implementerer ovenstående interface samt de metoder, der skal gælde for alle sedler:

public abstract class BankNote : IBankNote{public abstract int Value { get; }

public override bool Equals(object obj){if (!(obj is IBankNote)) return false;return ((IBankNote)obj).Value == Value;

}

public override int GetHashCode(){return Value;

}

public override string ToString(){return Value + “ Danish Crowns”;

}}

Med denne klasse til rådighed kan man definere konkrete klasser for de forskellige sedler, f.eks.

public class BankNote50 : BankNote{public override int Value{get { return 50; }

}}

Det svarer til, at der er defineret følgende klassehierarki:

Page 130: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

Click on the ad to read more

C# 1: Introduktion til programmering og programmeringssproget C#

130

Interfaces

BankNote50 BankNote1000BankNote500BankNote200BankNote100

BankNote

IBankNote

Forklaring

Inden jeg ser på implementering af pungen, vil jeg knytte et par kommentarer til ovenstående diagram og herunder, hvad et interface er.

Interfacet IBankNote definerer alene en enkelt readonly property, der skal returnere sedlens værdi. Bemærk, at den ikke har nogen visibility. Det er som default public, og man kan slet ikke angive nogen visibility, da det giver en oversættelsesfejl. Et interface er således et meget simpelt begreb, som alene definerer at en type har bestemte egenskaber, men interfacet implementerer ikke de pågældende egenskaber.

Get “Bookboon’s Free Media Advice” Email [email protected]

See the light! The sooner you realize we are right, the sooner your life will get better!

A bit over the top? Yes we know!

We are just that sure that we can make your media activities more effective.

Page 131: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

131

Interfaces

Du skal specielt være opmærksom på, at et interface er en type på samme måde som en class, og man kan som sådan have variabler, hvis type er et interface, men man kan - naturligvis nok - ikke instantiere et interface. F.eks. ville følgende være en ulovlig sætning:

IBankNote note = new IBankNote(); // ulovligt, et interface kan ikke instantieres

Som en sidste bemærkning vedr. interfaces er det sædvane i C# at lade navnet på et interface starte med et stort I, altså f.eks. IBankNote, og det kan anbefales at overholde denne praksis.

Interfaces skal implementeres af klasser og klassen BankNote implementerer interfacet IBankNote. Bemærk, at syntaksen er den samme som for arv:

public abstract class BankNote : IBankNote

altså et kolon efterfulgt af interfacets navn. Klassen BankNote indeholder ikke meget nyt, da den primært overstyrer tre metoder fra klassen Object. Selv om det ikke er angivet, så arver BankNote klassen Object, og det er faktisk tilladt (men unødvendigt) at skrive:

public abstract class BankNote : Object, IBankNote

Da klassen implementerer interfacet IBankNote, skal den implementere interfacets properties og metoder. Det kan den ikke, da klassen ikke ved, hvilken værdi sedlen skal have, så i stedet må den gøre propertyen Value abstract. BankNote er derfor en abstrakt klasse.

Bemærk også, at implementeringen af f.eks. ToString() anvender propertyen Value, og det er der ikke noget i vejen for, selv om den endnu ikke er implementeret.

Så er der endelig de konkrete klasser, og de er yderst simple og kræver ingen særlig forklaring, men vær opmærksom på at f.eks. en BankNote50 også er en BankNote og dermed også en IBankNote.

Klassen Purse

Opgaven gik ud på at implementere en pung til sedler, hvor pungen skal have 6 egenskaber. Da dette eksempel omhandler interfaces, vil jeg definere en pung i form af et interface:

public interface IPurse{bool Put(IBankNote note);bool IsEmpty();bool IsFull();bool Has(IBankNote note);IBankNote Pay(int value);int Value();

}

Page 132: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

132

Interfaces

Interfacet definerer at en pung skal have seks metoder, og dermed hvilke egenskaber en pung skal have, og hvad man kan med en pung, men interfacet definerer intet om, hvordan pungen skal implementeres. Det kræver en klasse, som implementerer interfacet:

public class Purse : IPurse{private IBankNote[] list;private int count;

public Purse(int size){list = new IBankNote[size];

}

public bool Put(IBankNote note){if (count >= list.Length) return false;list[count++] = note;return true;

}

public bool IsEmpty(){return count == 0;

}

public bool IsFull(){return count == list.Length;

}

public bool Has(IBankNote note){for (int i = 0; i < count; ++i) if (list[i].Equals(note)) return true;return false;

}

public IBankNote Pay(int value){for (int i = 0; i < count; ++i)if (list[i].Value == value){IBankNote note = list[i];list[i] = list[--count];return note;

}return null;

}

public int Value(){int sum = 0;for (int i = 0; i < count; ++i) sum += list[i].Value;return sum;

}}

Page 133: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

133

Interfaces

Forklaring

Bemærk først, at klassen implementerer interfacet IPurse. Bemærk dernæst, at der er defineret et array list til pungens sedler, samt at typen af dette array er IBankNote, der er et interface. Arrayet oprettes i konstruktøren, der har en parameter, som fortæller, hvor mange sedler pungen skal have plads til. Der også en variabel count, som holder styr på, hvor mange sedler der er i pungen. Efter at pungen er oprettet er den tom.

De fleste af metoderne er simple. Metoden Put() skal lægge en seddel i pungen, men det kan den kun gøre, hvis der er plads. Derfor tester den, om det er tilfældet. Hvis der ikke er plads, returnerer metoden false uden at gøre noget. Ellers lægger den sedlen i pungen og returnerer true. De to metoder IsEmpty() og IsFull() er helt trivielle. Metoden Has() ”bladrer” pungens sedler igen med en for løkke for at undersøge om man har den seddel, der spørges på. Bemærk, at det her er en forudsætning, at seddelklasserne implementerer metoden Equals() korrekt med værdi semantik. Det er noget af det, som den abstrakte klasse BankNote løser.

Den metode, hvor der er mest at bemærke, er metoden Pay(). Grundlæggende består den af en løkke, som gennemløber pungens sedler for at finde en seddel med den rigtige værdi. Finder man en seddel, skal der ske to ting: Sedlen skal fjernes fra pungen, og metoden skal returnere sedlen. Det første løses ved at lægge sedlen på sidste pladsen hen på den plads, hvor sedlen skal fjernes. Bemærk, at det kræver, at man først gemmer en kopi af den seddel, der skal returneres. Bemærk også, at variablen count tælles ned med 1. Hvis pungen ikke har en seddel med den ønskede værdi, er der et problem, forbi at metoden skal returnere noget. Det er løst ved at lade metoden returnere en null referencen. Det er en løsning, som man kan diskutere meget, men omvendt en løsning, der er meget brugt, og i det mindste giver det brugeren mulighed for at teste, om punge havde den ønskede seddel.

Det er vigtigt at bemærke, at både interfacet IPurse og implementering Purse intet kender til de konkrete seddelklasser, men alene kender interfacet IBankNote. Det betyder, at man uden problem kan udvide med nye sedler og uden det er nødvendigt at ændre i koden for Purse.

Den sidste metode kræver ingen særlig kommentar, og består blot at et simpelt gennemløb, som sammentæller alle værdier.

Programmet

Tilbage er der så selve programmet, som skal oprette en pung, lægge sedler ud i den og dernæst bruge nogle penge:

class Program{static Random rand = new Random();

Page 134: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

134

Interfaces

static void Main(string[] args){IPurse purse = new Purse(10);Init(purse);Console.WriteLine(purse.Value());for (int i = 0; i < 20; ++i) Buy(purse, Create());Console.WriteLine(purse.Value());

}

static void Buy(IPurse purse, IBankNote note){if (purse.Has(note)){purse.Pay(note.Value);Console.WriteLine(“Bought for {0} crones”, note.Value);

}elseConsole.WriteLine(“Does not have a “ + note);

}

static void Init(IPurse purse){while (!purse.IsFull()) purse.Put(Create());

}

static IBankNote Create(){switch (rand.Next(15)){case 0: return new BankNote1000();case 1:case 2: return new BankNote500();case 3:case 4:case 5: return new BankNote200();case 6:case 7:case 8:case 9: return new BankNote100();default: return new BankNote50();

}}

}

Forklaring

Bemærk første metoden Init(), som fylder en pung med sedler.

Sedler oprettes af metoden Create(), som opretter en tilfældig seddel. Bemærk, at det er det sted i hele programmet, hvor de konkrete seddel klasser optræder - alle andre steder er en seddel alene kendt af interfacet IBankNote. Faktisk kunne man med fordel flytte koden for metoden Create() ud i sin egen factory klasse, så man fik en endnu bedre adskillelse af programmet og de konkrete seddel klasser.

Page 135: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

Click on the ad to read more

C# 1: Introduktion til programmering og programmeringssproget C#

135

Interfaces

Metoden Buy() skal simulere, at man betaler med en bestemt seddel. Metoden spørger, om pungen har en bestemt seddel, og er det tilfældet ”køber den for beløbet”. Ellers må den sige ”desværre”. Du skal bemærke, at metoden kun kender pungen gennem interfacet IPurse, og metoden vil derfor virke, selvom en pung blev implementeret på en anden måde, når blot den implementerer interfacet.

Programmet er følgende:

static void Main(string[] args){Pung pung = new ArrPung(10);Init(pung);Console.WriteLine(pung.Ialt());for (int i = 0; i < 20; ++i) Koeb(pung, Create());Console.WriteLine(pung.Ialt());

}

og herunder er vist et eksempel på en afprøvning af programmet.

Mangler du dygtige callcenter medarbejdere?Lad Assistance finde din nye medarbejderVi sætter en ære i at indhente viden om din virksomhed, jeres kultur og værdier, strategi, mission og vision. Herigennem danner vi os et præcist indtryk af jeres foretrukne profil. I rekrutteringsprocessen lægger vi vægt på følgende forhold:

• Grundig behovsafdækning – for et optimalt match• Jobprofil og stillingsopslag• Rådgivning i forhold til valg af annonceringsmedie• Screening af relevante ansøgere (test, analyse og problemløsning)

Kontakt os for et uforpligtende møde på telefon 33 55 00 90

Page 136: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

136

Interfaces

Bemærkning

Der er grundlæggende to mål med interfaces. For det første er det et godt programmeringsprincip at definere et begreb i form af et interface, altså som f.eks. IPurse ovenfor. Man taler om, at man skal programmere til et interface. På den måde adskiller man definitionen og implementeringen, men det vigtigste er, at den kode, der bruger et begreb, alene kender det gennem interfacet og på den måde er fuldstændig uafhængig af implementeringen. Man sikrer, at man kan ændre implementeringen, uden det er nødvendigt at ændre den kode, som anvender begrebet. Programmering til et interface kan derfor medvirke til, at man får en kode, der er lettere at modificere. Ovenstående program er ”næsten” uafhængig af implementeringen af interfacet IPurse, og der er som nævnt kun et sted, hvor implementeringen er tydelig, nemlig hvor man i Main() opretter pungen:

IPurse pung = new Purse(10);

Et andet mål med interfacet er at give mulighed for på design niveau at kunne arbejde med multipel arv. Som nævnt ovenfor kan en klasse kun have én basisklasse - en klasse kan kun arve én klasse. Det kalder man undertiden for lineær arv. Man kan altså ikke have et design som vist herunder:

A B

C

Page 137: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

Click on the ad to read more

C# 1: Introduktion til programmering og programmeringssproget C#

137

Interfaces

hvor en klasse C arver både en klasse A og en klasse B. Der er flere grunde til at det ikke er muligt. For det første er der vanskeligheder med at implementere begrebet i et programmeringssprog på en fornuftig måde, og for det andet kan man diskutere, om det er et hensigtsmæssigt design, da det udtrykker at C er både et A og et B. Det er der nu eksempler på er fornuftigt, og C# går en mellemvej, idet en klasse kan arve en enkelt klasse, men implementere alle de interfaces, som den måtte have lyst til eller behov for. Det vil du få set mange eksempler på senere.

Page 138: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

138

Statiske medlemmer

15 Statiske medlemmerJeg vil endnu en gang at se på statiske medlemmer i en klasse. Både variabler og metoder kan være statiske, ja faktisk kan også en klasse være statisk.

Når man opretter et objekt af en klasse, opretter man samtidig de dataelementer i form af simple variabler og andre objekter, som klassens instance variabler definerer. Hvert objekt af klassen har således sine egne kopier af alle instance variabler, og hvis et objekt ændrer værdien af en instance variabel vedr. det kun objektet selv.

Anderledes er det med statiske variabler, da en statisk variabel kun oprettes første gang, der oprettes et objekt af klassen. Det betyder, at alle objekter oprettet på grundlag af samme klasse deler en statiske variabel, eller sagt anderledes at en statisk variabel ikke er knyttet til et bestemt objekt.

Et godt eksempel på anvendelse af en statisk variabel er en tilfældighedsgenerator - et objekt af typen Random - som i klasserne Coin og Dice. Her er det vigtigt, at alle objekter (f.eks. terninger) anvender den samme tilfældighedsgenerator. Den statiske tilfældighedsgenerator er initialiseret i erklæringen af den statiske variabel:

private static Random rand = new Random();

Det er ikke altid at det er muligt eller ønskeligt, og man kan i stedet initialisere statiske variabler i en statisk konstruktør, der ikke har anden formål end at initialisere statiske variabler. F.eks. kunne man skrive klassen Dice på følgende måde:

public class Dice{private static Random rand;private int oejne;

static Dice(){rand = new Random();

}

Der er ingen begrundelse for det i dette tilfælde, men en statisk konstruktør udføres, den første gang et program opretter et objekt af klassen. En statisk konstruktør kan ikke overstyres - der er ingen muligheder for at overføre parametre.

Også metoder kan være statiske. Hvis man har en statisk metode, kan man anvende den uden at have et objekt af klassen, og metoden refereres ved at sætte klassenavnet foran metodens navn.

Page 139: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

139

Statiske medlemmer

Exam34 StringBuilder

I dette eksempel vil jeg vise en klasse, som udelukkende indeholder statiske metoder. Klassen vil bestå af metoder, som manipulerer strenge, og som kan være nyttige i praksis. Jeg vil desuden omtale klassen StringBuilder, der er en klasse, som kan der kan give øget effektivitet i situationer med mange operationer på strenge. Endelig indeholder eksemplet et testprogram, som tester klassen.

Fremgangsmåde

Udgangspunktet er en klasse Str med 4 statiske metoder:

public static class Str{public static string Cut(string text, int width){if (text.Length > width) return text.Substring(0, width);return text;

}

public static string FillRight(string text, int width, char ch){StringBuilder builder = new StringBuilder(text);while (builder.Length < width) builder.Append(ch);return builder.ToString();

}

public static string FillLeft(string text, int width, char ch){if (text.Length >= width) return text;StringBuilder builder = new StringBuilder(width - text.Length);for (int i = 0; i < builder.Capacity; ++i) builder.Append(ch);return builder.ToString() + text;

}

public static string FillCenter(string text, int width, char ch){return FillRight(FillLeft(text, text.Length + (width - text.Length) / 2, ch),

width, ch);}

}

I dette tilfælde er klassen Str placeret i sin egen fil. Det giver bedre muligheder for at anvende klassen i andre programmer.

Herunder er vist et testprogram:

class Program{static void Main(string[] args){

Page 140: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

Click on the ad to read more

C# 1: Introduktion til programmering og programmeringssproget C#

140

Statiske medlemmer

Test1();Test2();

}

static void Test1(){Console.WriteLine(Str.Cut(“1234567890”, 8));Console.WriteLine(Str.Cut(“1234567890”, 12));

}

static void Test2(){Console.WriteLine(Str.FillRight(“abc”, 10, ‘x’));Console.WriteLine(Str.FillLeft(“abc”, 10, ‘x’));Console.WriteLine(Str.FillCenter(“abc”, 10, ‘x’));

}}

Hvor mange skal tage en beslutning, før man kan føre

en beslutning ud i livet?

Slip for komplekse kommandoveje. Hos NNIT løser vi de store it-opgaver i små teams, der ikke skal spørge om lov til at tage

en beslutning. Se ledige job på nnit.dk/job

RE

TH

INK

PIP

EL

INE

Hvor mange skal tage en beslutning, før man kan føre

en beslutning ud i livet?

Slip for komplekse kommandoveje. Hos NNIT løser vi de store it-opgaver i små teams, der ikke skal spørge om lov til at tage

en beslutning. Se ledige job på nnit.dk/job

RE

TH

INK

PIP

EL

INE

Hvor mange skal tage en beslutning, før man kan føre

en beslutning ud i livet?

Slip for komplekse kommandoveje. Hos NNIT løser vi de store it-opgaver i små teams, der ikke skal spørge om lov til at tage

en beslutning. Se ledige job på nnit.dk/job

RE

TH

INK

PIP

EL

INE

Hvor mange skal tage en beslutning, før man kan føre

en beslutning ud i livet?

Slip for komplekse kommandoveje. Hos NNIT løser vi de store it-opgaver i små teams, der ikke skal spørge om lov til at tage

en beslutning. Se ledige job på nnit.dk/job

RE

TH

INK

PIP

EL

INE

Page 141: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

141

Statiske medlemmer

Forklaring

Den første metode afkorter en streng, så den har en maksimal bredde:

public static string Cut(string text, int width){if (text.Length > width) return text.Substring(0, width);return text;

}

Det er en statisk metode (faktisk en meget simpel, men nyttig metode), og den kan f.eks. anvendes på følgende måde:

Console.WriteLine(Str.Cut(“1234567890”, 8));

Du skal bemærke, at metoden refereres ved at skrive klassenavnet Str foran.

Grundlæggende kan en statisk metode det samme som andre metoder, og det vigtige er, at den kan anvendes uden at have et objekt. Til gengæld kan en statisk metode ikke referere til instance variabler, men det er der også mange eksempler på, at metoder ikke gør. Et godt eksempel er klassen Math, som indeholder en række matematiske funktioner. De er alle implementeret som statiske metoder.

Den næste metode, der udvider en streng til en minimal bredde, sådan at der fyldes ud til højre med et bestemt tegn ch. Metoden anvender en StringBuilder, men den kunne være skrevet anderledes:

public static string FillRight(string text, int width, char ch){while (text.Length < width) text += ch;return text;

}

Et string objekt kan ikke ændre tilstand - man kan ikke ændre indholdet af en string. Hvis man ser på udtrykket

text += ch;

betyder det, at der oprettes string objekt, som indeholder det tidligere indhold af text og udvidet med værdien ch. Dvs. at der skal oprettes et objekt på heapen, og den gamle streng skal kopieres hertil. I de fleste tilfælde er det ikke vigtigt, men skal der tilføjes mange fyldtegn svarende til at løkken gentages mange gange, kan det have betydning for performance og være målbar. Det er her typen StringBuilder kommer ind i billedet. Der er en form for buffer til tegn, som kan udvide sig dynamisk og efter behov. Sætningen

StringBuilder builder = new StringBuilder(text);

Page 142: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

142

Statiske medlemmer

opretter en ny StringBuilder med indholdet af text. Den næste løkke tilføjer tegn, indtil builderen indeholder det ønskede antal tegn, og bemærk at den automatisk udvider sig efter behov.

Det er svært præcis at sige, hvornår man skal anvende en StringBuilder, men er der over 10 udvidelser, bør man overveje, om det kan betale sig at tage denne klasse i brug.

Den tredje metode minder om FillRight(), men den fylder tegn ind fra venstre. Den anvender også en StringBuilder, men parameteren til builderens konstruktør er denne gang er et tal, nemlig det antal fyldtegn der skal anvendes. Det betyder, at builderen fra starten har plads til det nødvendige antal tegn og dermed ikke skal udvide sig. Bemærk også, hvordan man i for løkken anvender propertyen Capacity til at bestemme, hvor mange tegn, der skal tilføjes.

Hvis man betragter klassen Str, så er alle metoder statiske. Er det tilfældet kan man også definere klassen som statisk:

public static class Str{

Er det tilfældet, er det ikke muligt at oprette objekter af typen Str, og det giver jo heller ingen mening i dette tilfælde.

Bemærkning

Når man i Visual Studio opretter en ny konsolapplikation, oprettes der automatisk en klasse med en Main() metode. Det er en statisk metode, og det skal den være, da den skal kunne kaldes af runtime systemet uden at have et objekt. I de fleste testprogrammer har klassen med Main() kun haft statiske metoder, f.eks.

static void Test2(){Console.WriteLine(Str.FillRight(“abc”, 10, ‘x’));Console.WriteLine(Str.FillLeft(“abc”, 10, ‘x’));Console.WriteLine(Str.FillCenter(“abc”, 10, ‘x’));

}

og metoden er sædvanligvis kaldt fra Main(). Da man i sådanne situationer ikke har noget objekt, skal metoden være statisk, og det er årsagen til, at metoder i Main() klassen altid har været statiske.

Page 143: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

Click on the ad to read more

C# 1: Introduktion til programmering og programmeringssproget C#

143

Mere om arrays

16 Mere om arraysJeg har tidligere defineret et array som en række elementer af en bestemt type, der kan refereres via et fælles navn. Billedet af et array er en struktur som følgende

0 1 2 3 4 5 6 7 8 9

hvor hver kasse har plads til et element af den pågældende type. De enkelte elementer kan refereres via arrayets navn og et indeks, der altid starter fra 0. Typen kan være hvad som helst, og i klassen Cup var det en Dice, mens det i klassen Purse var en IBankNote. Det eneste man skal være opmærksom på er, at hvis typen er en værditype, så indeholder kasserne direkte den værdi, som er knyttet til de enkelte indekser, men hvis typen er en referencetype, så indeholder kasserne blot referencer til de objekter, som er knyttet til de enkelte pladser. Det er sjældent, at det betyder så meget i praksis, men man skal være opmærksom på, at hvis man skriver noget i retning af følgende

Dice[] t = new Dice[5];

Page 144: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

144

Mere om arrays

så er der nok oprettet et array, men der er endnu ikke oprettet Dice objekter. Arrayet er tomt svarende til at alle pladser indeholder null.

Et array som ovenstående er et 1-dimensionalt array. Man kan også arbejde med arrays af flere dimensioner. F.eks. er et 2-dimensionalt array en struktur organiseret i rækker og kolonner, og hvor hvert element kan refereres via arrayets navn samt et indeks par. F.eks. kan man definere et 2-dimensionalt array med elementer af typen int, der har 4 rækker og 5 kolonner på følgende måde:

int[,] t = new int[4, 5];t[2, 3] = 43;

Det kan illustreres på nedenstående figur. Bemærk, at som ved et 1-dimensionalt array starter indekser med 0 - både for rækker og kolonner.

43

0

1

2

3

1 2 3 40

Det er sjældent man anvender arrays med mere end to dimensioner, men der er ingen øvre grænse for antallet af dimensioner, blot kan det for os mennesker være svært at give arrayet en geometrisk fortolkning. F.eks. er herunder defineret et 3-dimensionalt array:

int[,,] t = new int[3, 4, 2];

Det kan illustreres som en kube (eller flere 2-dimensionale arrays, som ligger bag hinanden):

0

1

2

1 30 2

01

Det enkelte element refereres med tre indekser, f.eks.

Page 145: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

145

Mere om arrays

t[1, 2, 1] = 53;

Herefter er det let at gætte syntaksen for, hvordan man definerer arrays af dimension større end 3.

Exam35 Flerdimensionale arrays

I dette eksempel vil jeg vise nogle eksempler på flerdimensionale arrays.

Fremgangsmåde

Eksemplerne er følgende:

static void Test1(){char[,] t = new char[5, 4];char ch = ‘A’;for (int i = 0; i < t.GetLength(0); ++i)for (int j = 0; j < t.GetLength(1); ++j) t[i, j] = ch++;

Print(t);}

static void Test2(){char[,,] t = new char[3, 5, 4];char ch = ‘A’;for (int i = 0; i < t.GetLength(0); ++i)for (int j = 0; j < t.GetLength(1); ++j)for (int k = 0; k < t.GetLength(2); ++k) t[i, j, k] = ch++;

Print(t);}

static void Test3(){int[,] t = { { 2, 3, 5, 7 }, { 11, 13, 17, 19 }, { 23, 29, 31, 37 } };Print(t);

}

static void Test4(){char[][] t = new char[4][];t[0] = new char[3];t[1] = new char[5];t[2] = new char[2];t[3] = new char[7];char ch = ‘A’;for (int i = 0; i < t.Length; ++i)for (int j = 0; j < t[i].Length; ++j) t[i][j] = ch++;

Print(t);}

static void Test5(){int[] t = { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29 };

Page 146: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

146

Mere om arrays

foreach (int n in t) Console.WriteLine(n);}

static void Test6(){int[] t = { 23, 7, 5, 11, 3, 17, 29, 2, 19, 13 };Array.Sort(t);foreach (int n in t) Console.WriteLine(n);

}

static void Print(char[,] t){for (int i = 0; i < t.GetLength(0); ++i){for (int j = 0; j < t.GetLength(1); ++j) Console.Write(“{0} “, t[i, j]);Console.WriteLine();

}}

static void Print(char[,,] t){for (int i = 0; i < t.GetLength(0); ++i){for (int j = 0; j < t.GetLength(1); ++j){for (int k = 0; k < t.GetLength(2); ++k) Console.Write(“{0} “, t[i, j, k]);Console.WriteLine();

}Console.WriteLine();

}}

static void Print(int[,] t){for (int i = 0; i < t.GetLength(0); ++i){for (int j = 0; j < t.GetLength(1); ++j) Console.Write(“{0, 3:D} “, t[i, j]);Console.WriteLine();

}}

static void Print(char[][] t){for (int i = 0; i < t.Length; ++i){for (int j = 0; j < t[i].Length; ++j) Console.Write(“{0} “, t[i][j]);Console.WriteLine();

}}

Page 147: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

Click on the ad to read more

C# 1: Introduktion til programmering og programmeringssproget C#

147

Mere om arrays

Forklaring

Det første eksempel opretter et 2-dimensionalt array af typen char og printer det. Du skal især bemærke, hvordan man refererer til antallet af elementer i hver dimension med metoden GetLength(), hvor parameteren angiver den dimension, som man refererer til.

Det næste eksempel ligner, men her er der i stedet tale om et 3-dimensionalt array. Du skal især være opmærksom på, hvordan man opretter et 3-dimensionalt array - her med 5 rækker, 4 kolonner og 3 lag. Bemærk også, hvordan man refererer til et element ved hjælp af tre indekser.

SÆT LYD PÅ FREMTIDENWidex udvikler højteknologiske høreapparater til gavn for de 500 millioner mennesker verden over, der har nedsat hørelse.

Mere end fem årtiers intensiv forskning og udvikling har gjort os til en af verdens førende høreapparatproducenter, og vi udvikler digital teknologi af en kvalitet, kun få kan måle sig med.

Som videnbaseret virksomhed betragter vi medarbejderne som vores vigtigste kapital. Vi kan godt lide at gøre tingene selv og sætter en ære i at være selvforsynende inden for de fl este om-råder. Det skaber et spændende, tværfagligt arbejdsmiljø med plads til initiativ og rig mulighed for personlig og faglig udvikling.

Vil du være med til at sætte lyd på fremtiden? Følg med i vores jobopslag på www.widex.dk/job eller skriv til [email protected]

www.widex.com

Page 148: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

148

Mere om arrays

Det er også muligt at initialisere et flerdimensionalt array i erklæringen ved hjælp af en liste. Det tredje eksempel viser, hvordan man kan oprette et 2-dimensionalt array bestående af 3 rækker og 4 kolonner.

Typen af et array kan være hvad som helst og dermed specielt også et andet array. Det giver mulighed for at definere arrays, hvor de enkelte rækker har forskellige antal elementer. Det fjerde eksempel opretter et array med 4 rækker, hvor antallet af elementer pr. række er hhv. 3, 5, 2 og 7:

Som endnu en bemærkning vedr. arrays, vil jeg nævne en anden løkke konstruktion. Den har faktisk ikke specielt noget med arrays at gøre, men den kan være nyttig i forbindelse med arrays. Det femte eksempel definerer et almindeligt 1-dimensionalt array med 10 elementer. Arrayet printes på skærmen ved at gennemløbe det med en løkke, men denne gang anvendes en foreach løkke. Syntaksen består simpelthen i at definere en variabel af samme type som arrayet, og denne variabel vil herefter gennemløbe alle arrayets elementer. Fordelen ved foreach frem for en almindelig for sætning er blot, at den kan være mere læsbar.

Som en sidste bemærkning vedr. arrays vil jeg nævne klassen Array, der er basisklasse for ethvert array, og dermed også stiller en række metoder og properties til rådighed. Speciel stiller klassen flere statiske metoder til rådighed til at manipulere arrays. Det er værd at undersøge denne klasse og se, hvad der er at gøre godt med. Det sidste eksempel definerer et array og sorterer det.

Page 149: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

Click on the ad to read more

C# 1: Introduktion til programmering og programmeringssproget C#

149

Typer

17 TyperC# har flere kategorier af typer og herunder class typer og interface typer, men også simple typer som int og double. Variabler af disse typer behandles meget forskelligt mht. hvordan de allokeres, og de kan som nævnt tidligere overordnet inddeles i værdityper og referencetyper.

En variabel af en værditype allokerer plads på stakken til dens data, og man kan sige, at variablen har sin egen kopi af eller indeholder de data, der gemmes i den. Variablen bliver automatisk nedlagt (fjernet fra stakken), når programmet afslutter den blok, hvor variablen er erklæret. En variabel af en værditype bruger dermed det antal bytes af stakken, som typen angiver.

En variabel af en referencetype indeholder ikke data direkte, men den indeholder i stedet en reference til data, der er allokeret på heapen. Det betyder bl.a. at man kan have flere variabler, der refererer til de samme data. Det betyder også, at en referencevariabel altid fylder det samme på stakken, nemlig størrelsen af en reference (4 bytes). En reference kan specielt have værdien null, der betyder, at den ikke refererer til noget. Referencetyper kan inddeles i class typer, arrays, og interface typer.

De næste kapitler omhandler mere om typer og primært værdityper, men desuden behandles generiske typer og exception handling, men jeg vil starte med lidt flere bemærkninger vedr. de simple typer.

Dedicated Analytical Solutionswww.foss.dk/careers

Protein 13.2%

Moisture 8.4%

Starch 67%

FOSS is known throughout the world for efficient analytical solutions that help to improve both food quality and safety in the global food market. We are playing an increasingly important role in ensuring optimal use of valuable natural resources, and have throughout the years created ground-breaking innovations. And there’s more to come. At FOSS you will find professional challenges, training and development in a work environment that offers good work/ life balance. Join us and make a difference.

80% of the grain traded in the world is analysed on a FOSS solution

Page 150: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

150

Typer

De simple eller indbyggede typer er f.eks. int, char, double osv. Hver type har et navn, der er et reserveret ord, men disse navne er i virkeligheden blot et alias for en tilsvarende struct i System namespacet. Det betyder, at der også er knyttet metoder til de simple typer. F.eks. er en int et alias for System.Int32, der er et 4 bytes heltal.

Følgende tabel viser de simple typer i namespacet System:

C# alias Type i System Betydning

sbyte SByte 8 bit heltal med fortegn

byte Byte 8 bit ikke-negativt heltal

short Int16 16 bit heltal med fortegn

ushort UInt16 16 bit ikke-negativt heltal

int Int32 32 bit heltal med fortegn

uint UInt32 32 bit ikke-negativt heltal

long Int64 64 bit heltal med fortegn

ulong UInt64 64 bit ikke-negativt heltal

char Char 16 bit Unicode karakter

float Single 32 bit flydende tal

double Double 64 bit flydende tal

bool Boolean 8 bit der er en true eller false

decimal Decimal 96 bit decimal tal med 28 betydende cifre

De simple typer er alle afledt af typen ValueType (der er en struct, og begrebet struct forklares nedenfor) og som igen er afledt af Object. Typerne kan grundlæggende inddeles som

- char - bool - typer til heltal (sbyte, byte, short, ushort, int, uint, long, ulong) - typer til decimal tal (float, double, decimal)

Typen char er simpel, da den repræsenterer de enkelte tegn ved en 16 bits talkode i unicode systemet. Der findes ganske enkelt tabeller, der viser hvilke koder de enkelte tegn har. Her under er vist en metode, der printer tegnene med koder fra og med 32 og til og med 255:

static void Test1(){for (char c = ‘ ‘; c <= 255; ++c) Console.WriteLine(“{0}{1, 4:D}”, c, (int)c);

}

Page 151: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

151

Typer

Bemærk specielt sammenligningen i for sætningen, hvor en char sammenlignes med en int, samt at ++ operatoren også giver mening for en char. Ved sammenligning er det tegnets talkode, der sammenlignes med, og ++ virker, fordi det er talkoden, der tælles op.

Typen bool kan der ikke knyttes flere kommentarer til, men heltalstyperne er værd at se lidt nærmere på. En sbyte fylder 1 byte og dermed 8 bits. Den kan derfor repræsentere alle heltal som binært kan skrives med 8 bits, hvilket er tallene fra -128 til 127. Det lidt skæve interval har at gøre med den interne repræsentation, hvor et negativt heltal er repræsenteret ved dets 2-komplement. Hvis man i stedet har en byte er dens værdiområde fra 0 til 255. Forskellen mellem en sbyte og en byte er således bare en parallelforskydning af det interval, som typerne repræsenterer, hvor den ene er et symmetrisk interval om 0, mens den anden er de ikke negative heltal startende med 0. Det samme gælder for short, int og long og forskellen er alene, hvor stort et interval af heltal, der er til rådighed. Følgende metode printer disse intervaller for alle 8 heltals typer:

static void Test2(){Console.WriteLine(“sbyte {0, 25:D}{1, 25:D}”, sbyte.MinValue, sbyte.MaxValue);Console.WriteLine(”byte {0, 25:D}{1, 25:D}”, byte.MinValue, byte.MaxValue);Console.WriteLine(”short {0, 25:D}{1, 25:D}”, short.MinValue, short.MaxValue);Console.WriteLine(”ushort {0, 25:D}{1, 25:D}”, ushort.MinValue, ushort.MaxValue);Console.WriteLine(”int {0, 25:D}{1, 25:D}”, int.MinValue, int.MaxValue);Console.WriteLine(”uint {0, 25:D}{1, 25:D}”, uint.MinValue, uint.MaxValue);Console.WriteLine(”ulong {0, 25:D}{1, 25:D}”, long.MinValue, long.MaxValue);Console.WriteLine(”ulong {0, 25:D}{1, 25:D}”, ulong.MinValue, ulong.MaxValue);

}

Man kan ikke umiddelbart kopiere et heltal af én type over i en anden type uden at foretage en type cast, men hovedreglen er dog, at man kan kopiere en mindre type over i en større type. Hvis man prøver at oversætte følgende kode

Page 152: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

Click on the ad to read more

C# 1: Introduktion til programmering og programmeringssproget C#

152

Typer

static void Test3(){sbyte b1 = 2;byte b2 = b1;int n = 3;short s = n;long t = n;

}

vil man få to oversættelsesfejl. Sætningen

byte b2 = b1;

giver fejl, fordi man prøver at kopiere et tal, der kan være negativ over i en variabel, som kun kan indeholder ikke negative tal. På samme måde vil sætningen

short s = n;

give fejl, da man forsøger at kopiere 4 bytes over i 2 bytes. I begge tilfælde må problemet løses med en eksplicit type cast:

HD – vejen tilen karrierei erhvervslivet

Læs mereAarhus: hd.au.dkHerning: auhe.au.dk/hd

LÆS HD I ØKONOMI OG LEDELSE

HD er en anerkendt diplom- uddannelse, som giver dig mulighed for at specialisere dig inden for det erhvervsøkonomiske fagområde ved siden af dit job.

Page 153: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

153

Typer

static void Test3(){sbyte b1 = 2;byte b2 = (byte)b1;int n = 3;short s = (short)n;long t = n;

}

Som en sidste bemærkning vedr. heltal vil jeg nævne muligheden for at angive konstanter som hexadecimale tal:

int a = 0x1abc23;

hvor 0x fortæller, at værdien skal fortolkes som et hexadecimalt tal.

Tilbage er der decimaltallene, der er repræsenteret ved typerne float, double og decimal. De to første er såkaldte flydende tal, mens den sidste er et decimaltal. Forskellen er, at float og double tilgodeser meget store intervaller med færre betydende cifre, mens den sidste understøtter mange betydende cifre og til gengæld et mere begrænset interval. Fælles for de tre typer er, at de kun repræsenterer en del af tallene inden for de intervaller, som de spænder over, ganske enkelt fordi at ethvert interval indeholder uendelige mange reelle tal, og en uendelig mængde kan ikke repræsenteres med et endeligt antal bits. Det er derfor vigtigt at gøre sig klart, at når man arbejder med decimaltal, vil mange af resultaterne være afrundede og tilnærmede værdier, et forhold der også er kendt fra en almindelig lommeregner. Især i forbindelse med sammenligninger skal man være opmærksom på dette forhold.

Forskellen mellem float og double er, hvor stort et interval, de spænder over. Den interne repræsentation består af et fortegn, en mantisse med cifre samt en eksponent. Hvis man f.eks. udfører

Console.WriteLine(Math.Pow(3.14, 50));

får man resultatet

der betyder . Det svarer til, at en double kan arbejde med ca. 15 betydende cifre. Ovenstående er således et afrundet resultat.

Bemærk, at man også kan anvende den notation for en konstant, f.eks.

double x = 1234.678E+20;

Page 154: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

154

Typer

Typerne float og double definerer flere konstanter, og du kan bl.a. betragte følgende metode:

static void Test4(){Console.WriteLine(“float {0, 30:E20}{1, 30:E20}”, float.MinValue, float.MaxValue);

Console.WriteLine(float.Epsilon);Console.WriteLine(“double {0, 30:E20}{1, 30:E20}”, double.MinValue, double.MaxValue);

Console.WriteLine(double.Epsilon);}

Her kan du se de intervaller, som de to typer spænder over, men du skal også bemærke konstanten Epsilon, som angiver det mindste positive tal. Der findes også værdier, som ikke repræsenterer tal:

- double.PositiveInfinity der repræsenterer plus uendelig - double.NegativeInfinity der repræsenterer minus uendelig - double.NaN der detyder, at en variabel ikke repræsenterer et tal

Typen decimal spænder over et mindre interval, men til gengæld med op til 29 betydende cifre:

static void Test5(){Console.WriteLine(decimal.MinValue);Console.WriteLine(decimal.MaxValue);Console.WriteLine(decimal.Zero);Console.WriteLine(decimal.One);Console.WriteLine(decimal.MinusOne);decimal x = 2;Console.WriteLine(Sqrt(x));

}

Bemærk, at typen definerer flere konstanter. Bemærk også den sidste sætning, der printer kvadratroden af 2. Kvadratrodsfunktionen i klassen Math er ikke implementeret for variabler af typen decimal, så ønsker man at bestemme kvadratroden af en decimal som en decimal, må man selv skrive funktionen:

Page 155: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

Click on the ad to read more

C# 1: Introduktion til programmering og programmeringssproget C#

155

Typer

static decimal Sqrt(decimal x){decimal y = x;while (true){decimal v = y + x / y;decimal z = v / 2;if (Math.Abs(y - z) <= decimal.Zero) break;y = z;

}return y;

}

Generelt er de simple typer unchecked. Dvs. at der ikke testes for overflow, hvis en værdi bliver for stor. Hvis man f.eks. udfører følgende metode

static void Test6(){

int a = 1234567;int b = 1234567;Console.WriteLine(a * b);

}

får man nedenstående resultat, der tydeligvis ikke er korrekt (resultatet kan ikke være inden for det interval, som en int spænder over):

������������� ����������������������������������������������� �� ���������������������������

������ ������ ������������������������������ ����������������������!���"���������������

�����#$%����&'())%�*+����������,����������-

.��������������������������������� ��

���������� ���������������� ������������� ���������������������������� �����������

The Wakethe only emission we want to leave behind

Page 156: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

156

Typer

Når det er sådan, er det fordi, at det tager tid at teste for overflow, og hvis det skulle ske for samtlige beregninger i et program, kunne det gå ud over programmets effektivitet. I stedet har man overladt det til programmøren at tage hånd om situationer, der kan give overflow. Det kan man gøre på følgende måde:

static void Test6(){checked{int a = 1234567;int b = 1234567;Console.WriteLine(a * b);

}}

Hvis man udfører metoden nu, vil programmet stoppe med en fejlmeddelelse - en exception. Det er også muligt, at sætte en option til compileren om, at al koden skal være checked. Gør man det, findes der også en unchecked, der kan anvendes til markere blokke, som man ikke ønsker, skal være checked.

I det fleste tilfælde er forskellen mellem værdityper og referencetyper ikke speciel vigtig, men en variabel af en værditype og dermed også speciel en variabel af en simpel type vil altid have en værdi. Det er i modsætning til en variabel af en referencetype, der kan være null, og som betyder, at variablen ikke har en værdi. Undertiden er det nyttigt eller ønskeligt også kan operere med variabler af værdityper, som ikke har en værdi, og der findes derfor nogle specielle værdityper, som kan være null. Syntaksen er simpel, og man skal blot skrive ? efter typen, altså f.eks.

long? n;

double? x;

Sådanne typer siges at være nullable. Det er simpelthen et spørgsmål om, at typen udvides med en mulighed for, at den kan være null. Betragt følgende kode:

static void Test7(){int a = 0;int? b = null;Console.WriteLine(”a = ” + a);Console.WriteLine(”b = ” + b);b = 3;Console.WriteLine(”b = ” + b);int?[] t = new int?[5];for (int i = 0; i < t.Length; ++i) t[i] = Number();

Page 157: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

157

Typer

Print(t);for (int i = 0; i < t.Length; ++i) t[i] = Number() ?? 0;Print(t);

}

static void Print(int?[] t){foreach (int? n in t) Console.Write(”{0, -3}|”, n);Console.WriteLine();

}

static int? Number(){if (rand.Next(2) == 1) return rand.Next(1, 10);return null;

}

Først erklæres to variabler: En almindelig int og en nullable int. Den første gang b printes er den null, men anden gang har den fået en værdi. Det skal illustrere, at bortset fra at en nullable variabel kan være null, anvendes den fuldstændig som alle andre variabler. int? er en type som alle andre typer, og derfor kan man speciel også oprette et array med elementer af denne type. På samme måde kan typen være både returtype og type for en parameter. Metoden Number() returnerer en værdi, der enten er et tal eller er null, og metoden Print() printer et nullable array. Bemærk også operatoren ??, der betyder at værdien er udtrykket efter ??, hvis den foranstillede værdi er null.

Alle ovenstående testmetoder findes i eksemplet Exam35.

Page 158: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

Click on the ad to read more

C# 1: Introduktion til programmering og programmeringssproget C#

158

Enum

18 EnumVærditypen enum tildeler navne til konstanter af én af typerne byte, short, int og long. Som default tildeles konstanterne værdier fra 0 og frem, men man kan også eksplicit tildele en konstant en værdi. En enum erklæres på følgende måde:

public enum Weekday : byte{Monday,Tuesday,Wednesday,Thursday,Friday,Saturday,Sunday,Error = 10

}

hvor der erklæres 8 konstanter. Typen er her byte og konstanten Monday har værdien 0, Tuesday værdien 1 osv. Konstanten Error initialiseres eksplicit til værdien 10.

I nedenstående metode skal brugeren indtaste en tekst: Mo, Tu, We, Th, Fr, Sa eller Su. Denne tekst konverteres herefter til en enum, der til sidst printes på skærmen.

We are a global specialist in energy management represented in more than 100 countries. We provide technology and integrated solutions to optimise energy usage across multiple market segments. We are more than 130,000 colleagues worldwide and 1.000 of us are situated in Denmark.

We invest in our employees, in the environment and in the future. Each year 5% of our revenue is allocated for research and development activities. In Schneider Electric you have many career paths to choose from – also internationally.

Would you like take on the challenge of transforming the way people and organisations use energy?

Do you know Schneider Electric?

Meet us at: www.schneider-electric.dk/job

Page 159: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

159

Enum

static void Test1(){Weekday dag;Console.Write(“(Mo, Tu, We, Th, Fr, Sa, Su)? “);string text = Console.ReadLine();switch (text){case “Mo”:dag = Weekday.Monday; break;

case “Tu”:dag = Weekday.Tuesday; break;

case “We”:dag = Weekday.Wednesday; break;

case “Th”:dag = Weekday.Thursday; break;

case “Fr”:dag = Weekday.Friday; break;

case “Sa”:dag = Weekday.Saturday; break;

case “Su”:dag = Weekday.Sunday; break;

default:dag = Weekday.Error; break;

}Console.WriteLine(dag);

}

Bemærk, at der i switch sætningen switches på en streng, der er tilladt i C#. Bemærk også, at programmet skriver Thursday, altså konstantens navn.

En enum som ovenstående definerer 8 værdier, men det betyder ikke, at en variabel af typen fylder 8 bytes. Den fylder kun én byte, og det er alene et spørgsmål om, at der er tildelt et navn bestemt af variablens værdi.

Defaulttypen er int, og man kan således blot skrive:

public enum Color{Diamonds, Hearts, Spades, Clubs

}

Enum typer er dels effektive og er en bedre løsning end at definere en række konstanter for et begreb, og dels kan enum typer anvendes til at øge læsbarheden.

Ovenstående eksempler vedr. enums findes i Exam36.

Page 160: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

160

Struct

19 StructDen sidste værditype er en struct, der er en konstruktion, der ligner en class til forveksling, og den vigtigste forskel er, at en struct er en værditype. Herunder er vist en struct, der repræsenterer et punkt i et koordinatsystem:

struct Point{public double x;public double y;

public Point(double x, double y){this.x = x;this.y = y;

}

public double Length{get { return Math.Sqrt(x * x + y * y); }

}

public override string ToString(){return string.Format(“({0},{1})”, x, y);

}}

Typen hedder Point, og der er to instance variabler af typen double. Det betyder, at hver gang der oprettes et Point allokeres der 16 bytes på stakken. Typen har en konstruktør, der initialiserer de to koordinater, og der er en enkelt property, der returnerer afstanden fra (0,0) til punktet. Desuden er der en ToString() metode. Faktisk er der også en implicit default konstruktør, der sætter begge variabler til 0 - og denne konstruktør kan ikke overstyres. Herunder er vist en metode, der anvender typen Point:

static void Test1(){Point p1;Point p2 = new Point(4, 5);p1.x = 2;p1.y = 3;Point p3 = p1;p3.y = 8;Show(p1);Show(p2);Show(p3);Console.WriteLine(p3.Length);

}

private static void Show(Point p){Console.WriteLine(“({0},{1})”, p.x, p.y);

}

Page 161: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

Click on the ad to read more

C# 1: Introduktion til programmering og programmeringssproget C#

161

Struct

Programkørsel:

Forklaring

Først oprettes et punkt

Point p1;

Det betyder, at der oprettes en variabel p1 på stakken og default konstruktøren udføres. Bemærk, at det ikke blot er en reference der oprettes, men en variabel der på stakken fylder 16 byte’s. Dernæst oprettes en anden variabel p2 med new operatoren:

Point p2 = new Point(4, 5);

og selv om p2 er oprettet med new, er den stadig oprettet på stakken. new operatoren anvendes her til at få konstruktøren udført og har altså en anden betydning, end tilfældet er med en class. Som næste punkt tildeles værdier til koordinaterne i p1. Bemærk, at det er muligt, da begge variabler er public. Derefter oprettes en tredje variabel:

Vil du også stå på ski i fremtiden?

Verden har brug for nye løsninger, og Topsøe har de katalysatorer og teknologier, der kan løse centrale udfordringer på den globale agenda: verdens energi- og miljøudfordringer.

Vi har fart på. Vores løsninger skal fortsat udvikles, udbredes og implementeres på det globale marked. Derfor vil vi gerne have endnu flere kolleger, som vil være med til at skabe værdi og fremdrift.

Du får mulighed for fordybelse, kundekontakt og rejseaktivitet. Og adgang til en verden af viden.

Vi arbejder i en fri og uformel atmosfære. Vi er stolte af at tage ansvar og bidrage til et bedre miljø.

Vil du være med?

WWW.TOPSOE.COM/JOBS

Need for speed?

Page 162: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

162

Struct

Point p3 = p1;

Det betyder, der oprettes endnu en variabel på stakken, som bliver en kopi af p1. Bemærk, at p3 er en ny variabel, der har samme værdi som p1, men det er ikke en reference til p1. Det kan man se, ved at ændre p3, og at denne ændring ikke påvirker p1.

Bemærkning

Syntaksen for en struct er som for en class bortset fra, at ordet class er erstattet af ordet struct. En struct kan på samme måde som en class have konstruktører, properties og metoder, og den eneste forskel her er som nævnt, at en struct altid har en default konstruktør, der ikke kan overstyres. En struct kan også implementere et interface, men en struct kan ikke arve. Bortset fra det er der ingen forskel.

Forskellen mellem struct og class går dermed på anvendelsen. Typisk anvendes en struct til indkapsling af få simple datatyper for at opnå en bedre performance svarende til at det er en værditype. Derfor vil man også ofte spare properties og gøre variabler public, som tilfældet overfor med typen Point. Da et objekt allokeres på stakken, kan der kun være én reference til det, og behovet for dataindkapsling er derfor ikke den samme som for heap allokerede objekter.

Kopiering af struct’s

Da en struct type er en værditype betyder det, at hvis man tildeler en variable til en anden variabel, så sker der en egentlig kopiering

Point p1 = new Point(2, 3);Point p2 = p1;

hvor p1 kopieres til p2. Det er et forhold man især skal være opmærksom på, hvis en struct har instance variabler, som er af reference type. Da er det blot referencerne, der kopieres, og ikke de objekter, som de refererer til. Hvis ikke man er opmærksom på det, kan det undertiden give uventede resultater. Som eksempel kan man betragte klassen Dice:

class Dice{private static Random rand = new Random();private int eyes;

public Dice(){Throw();

}

public int Eyes{get { return eyes; }

}

Page 163: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

163

Struct

public void Throw(){eyes = rand.Next(1, 7);

}}

Der ikke noget at bemærke om den, ud over at det er en referencetype. Følgende type definerer et par terninger - et bæger med to terninger:

struct Par{public Dice d1;public Dice d2;

public void Throw(){d1.Throw();d2.Throw();

}

public override string ToString(){return d1.Eyes + “ “ + d2.Eyes;

}}

Det er en værditype med to instance variabler, som begge er referencetyper. Det betyder bl.a., at hvis man kopierer et Par, så er det disse referencer der kopieres:

static void Test2(){Par p1;p1.d1 = new Dice();p1.d2 = new Dice();Console.WriteLine(p1);Par p2 = p1;Console.WriteLine(p2);p1.Throw();Console.WriteLine(p1);Console.WriteLine(p2);

}

I første linje oprettes et Par objekt, hvorefter variablerne initialiseres til nye Dice objekter. Det er nødvendigt, da default konstruktøren ikke opretter disse objekter og heller ikke kan overstyres. I fjerde linje oprettes endnu et Par, som sættes lig med p1. Bemærk, at det betyder, at objektet p1 kopieres til p2, men det der kopieres er de to instance variabler og dermed referencer til to Dice objekter. Resultatet er, at de to Par objekter godt nok indeholder hver deres referencevariabler, men de referere til de samme Dice objekter. Det bliver tydeligt, hvis man slår med det ene Par (p1):

Page 164: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

164

Struct

Nullable struct’s

En struct er en værditype, og den kan derfor ikke være null, men som vist ovenfor kan en simpel type være nullable, og det samme gælder for en struct. Idet Point er samme type som ovenfor kan man betragte følgende:

static void Test3(){Nullable<Point> p = null;Console.WriteLine(“: “ + p);p = new Point(3.14, 1.41);Console.WriteLine(“: “ + p);Console.WriteLine(p.Value.Length);Point v = p.Value;v.x = 11;v.y = 13;Console.WriteLine(“: “ + p);

}

Her er p ikke et Point, men et Nullable<Point>, der er et Point, som kan være null. Det er i virkeligheden et spørgsmål om, at værditype indkapsles i en referencetype. Herover er p indledningsvis null. Dernæst sættes p til et nyt Point objekt, men man har nu skjult egenskaberne ved typen Point. Man kan derimod referere til det indkapslede objekt med propertyen Value. Bemærk specielt, at når man skriver

Point v = p.Value;

så får man en kopi af det indkapslede objekt.

Man skal derfor ikke gøre værdier nullable, med mindre man har et særligt behov. Bemærk specielt, at

int? a

blot er en kort notation for

Nullable<int> a

Ovenstående eksempler vedr. struct’s findes i Exam37.

Page 165: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

Click on the ad to read more

C# 1: Introduktion til programmering og programmeringssproget C#

165

Generiske typer

20 Generiske typerGeneriske typer er knyttet til de såkaldte collection klasser, der behandles senere, men målet her er at vise, hvordan man skriver brugerdefinerede generiske typer. Kort kan man sige, at formålet er at skrive typer, der er generelle og kan anvendes i mange sammenhænge. I stedet for generiske typer taler man også om parametriserede typer svarende til, at det er typer, der afhænger af én eller flere parametre.

Generiske metoder

Inden jeg viser, hvordan man skriver en brugerdefineret generisk type, vil jeg se på en relateret problemstilling, nemlig hvad man forstår ved en generisk metode. Som eksempel er herunder vist en metode, der bytter om på to heltal af typen int:

static void Swap(ref int a, ref int b){int t = a;a = b;b = t;

}

IFRS 2012, Standarder og fortolk-ningsbidrag – på dansk fås nu både som trykt bog samt som e-bog til smartphone, tablet og pc.

Introduktionspris: e-bog og trykt bog kr. 1545,-

E-bog inkl. opdateringer i 2012

Læs mere og køb e-bogen sammen med den trykte bog her: shop.magnus.dk

REGNSKABIFRS 2012 – nu også som e-bog

– Nuogså som

e-bog

Page 166: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

166

Generiske typer

Det er en meget simpel metode, men en metode der har stor anvendelse, f.eks. hvis man skal sortere et array. Metoden har dog et problem, at den er tæt knyttet til typen int forstået sådan, at hvis man også har brug for en metode, der kan bytte rundt på to objekter af typen double, så er det nødvendigt at skrive en ny Swap() metode, der virker på double og tilsvarende for alle andre typer, hvor der er behov for en Swap() metode. Det kan derfor være ønskeligt at skrive en generel metode, som kan klare alle typer. Det er her generiske metoder kommer ind i billedet:

static void Swap<T>(ref T a, ref T b){T t = a;a = b;b = t;

}

Man kalder det også for en parametriseret metode svarende til, at der til metoden er knyttet en typeparameter, der her hedder T. Ud over at der efter metodenavnet står <T> svarer det til at int alle steder er skiftet ud med typeparameteren T. F.eks. kan metoden anvendes på følgende måde, hvor den bytter om på to strenge:

string s1 = “Svend”;string s2 = “Knud”;Swap(ref s1, ref s2);Console.WriteLine(s1);Console.WriteLine(s2);

Som et andet eksempel er herunder vist en generisk metode, der printer et array:

static void Print<T>(T[] arr){foreach (T t in arr) Console.Write(t + “ “);Console.WriteLine();

}

Bemærk, at koden skrives fuldstændig, som T var en eksisterende type - en konkret type. Det har dog sine begrænsninger, idet at det eneste man kan med objekter af typen T er, hvad man kan med object - compileren kan jo umuligt have kendskab til andre egenskaber ved typen T. Der er dog mulighed for at lægge restriktioner på parametertypen T, således at compileren kan forudsætte bestemte metoder eller properties.

Exam38 Sortering af et array

Der skal skrives en metode, der kan sortere et array af objekter af en vilkårlig type.

Page 167: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

167

Generiske typer

Fremgangsmåde

Der findes mange forskellige sorteringsmetoder, og her vil jeg anvende en metode, der kan beskrives på følgende måde

- gennemløb arrayet og find det mindste element - byt det om med elementet på plads 0 - nu står det første element korrekt - gennemløb de sidste n-1 elementer og find det mindste blandt disse - byt det om med elementet på plads 1 - nu står de første to elementer rigtigt - gennemløb de sidste n-2 elementer og finde det mindste blandt disse - byt det om med elementer på plads 2 - nu er de tre første elementer på plads - fortsæt nu indtil arrayet er sorteret - for hvert gennemløb findes det mindste af de elementer,

der ikke allerede er på plads, og det sættes på plads

Resultatet er, at efter k gennemløb er de første k elementer sorterede, mens man mangler at sortere de sidste n-k elementer. Det er en meget simpel sorteringsmetode, men det er til gengæld ikke den mest effektive - i det mindste ikke for store arrays.

At skrive en metode, der kan sortere et array af vilkårlig type, er for stort et krav, da en sortering af elementer altid vil omfatte, at elementerne kan sammenlignes og ordnes i størrelses orden. Mange af de indbyggede typer kan det, som f.eks. de simple typer og typen string, der kan sammenlignes med sammenligningsoperatorerne, men også andre typer kan sammenlignes, og det sker typisk ved, at de implementerer et interface, som hedder IComparable. Dette interface definerer kun en enkelt metode, som hedder CompareTo(), og som har et object som parameter. Protokollen er, at metoden skal returnere -1, hvis det aktuelle objekt er mindre end parameteren, 1 hvis det aktuelle objekt er større end parameteren og ellers 0. Nu findes interfacet også i en generisk version, og metoden CompareTo() er dermed også generisk parametriseret med den slags elementer, der skal sammenlignes. Summen af alt det er, at sorteringsmetoden kan skrives på følgende måde:

static void Sort<T>(T[] arr) where T : IComparable<T>{for (int i = 0; i < arr.Length - 1; ++i){int k = i;for (int j = i + 1; j < arr.Length; ++j)if (arr[j].CompareTo(arr[k]) < 0) k = j;

if (i != k) Swap(ref arr[i], ref arr[k]);}

}

Page 168: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

168

Generiske typer

Forklaring

Metoden er simpel og udtrykker ovenstående algoritme, men der er dog et par vigtige ting at bemærke. Bemærk først, at det er en generisk metode parametriseret med T, samt at den har en parameter arr, som er et array af typen T. Dernæst skal du bemærke where delen, som udtrykker, at parametertypen T skal implementere interfacet IComparable<T> - altså en parametriseret version af IComparable. Sagt lidt anderledes, kan metoden kun virke på arrays af typer, som implementerer dette interface. Forsøger man at anvende metoden på andre typer, får man en oversættelsesfejl. Bemærk også, hvordan metoden anvender CompareTo() til at sammenligne elementer, og bemærk endelig hvordan den generiske metode Swap() anvendes.

Test

Herunder er vist, hvordan metoden kan anvendes til at sortere et array med elementer af typen int:

static void Test1(){int[] t = { 17, 13, 29, 3, 19, 11, 5, 2, 7, 23 };Print(t);Sort(t);Print(t);

}

static void Print<T>(T[] arr){foreach (T t in arr) Console.Write(“{0} “, t.ToString());Console.WriteLine();

}

Bemærk at også metoden Print() er generisk.

Når det går godt, skyldes det at typen int implementerer interfacet IComparable<int>.

Jeg vil endnu en gang vende tilbage til typen Dice, men denne gang med en udvidelse, så den implementerer interfacet IComparable:

class Dice : IComparable<Dice>{private static Random rand = new Random();private int eyes;

public Dice()

Page 169: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

Click on the ad to read more

C# 1: Introduktion til programmering og programmeringssproget C#

169

Generiske typer

{Throw();

}

public int Eyes{get { return eyes; }

}

public void Throw(){eyes = rand.Next(1, 7);

}

public override string ToString(){return “” + eyes;

}

public int CompareTo(Dice d){return eyes < d.eyes ? -1 : eyes > d.eyes ? 1 : 0;

}}

Det betyder, at terninger nu kan ordnes, så f.eks. en toer er mindre end en treer osv. Bemærk, at hvordan de ordnes, er noget som programmøren har bestemt i implementeringen af metoden CompareTo(), og at man i princippet kunne have valgt alle andre mulige ordninger.

Page 170: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

170

Generiske typer

Som næste punkt vil jeg gerne have oprettet et array med terninger, men jeg vil hertil skrive en generisk metode, der som parameter har arrayets størrelse:

static T[] Create<T>(int n) where T : new(){T[] arr = new T[n];for (int i = 0; i < arr.Length; ++i) arr[i] = new T();return arr;

}

Bemærk først where delen. Den betyder, at parametertypen T skal have en default konstruktør - er det ikke tilfældet, får man en oversættelsesfejl. Resultatet er, at når arrayets elementer oprettes i for løkken, så kan man være sikker på, at de bliver korrekt initialiseret. Bemærk at klassen Dice opfylder denne egenskab med en default konstruktør.

Herunder er vist en kode, der opretter et array med terninger, og sorterer det:

static void Test2(){Dice[] b = Create<Dice>(10);Print(b);Sort(b);Print(b);

}

Her skal du bemærke, at metoden Create() er generisk, og at parameteren ikke afhænger af parametertypen. Hvis man bare skriver Create(10), kan oversætteren ikke vide, hvilken Create() man ønsker at udføre, og man skal derfor angive parametertypen efter metodenavnet. I de andre eksempler er det unødvendigt (men lovligt), da oversætteren ud fra den aktuelle parameter kan se, hvilken type det drejer sig om. Når man f.eks. skriver

Print(b);

kan oversætteren ud fra typen af b se, hvilken parametertype der er tale om, men det er lovligt at skrive

Print<Dice>(b);

Bemærkning

I ovenstående eksempler har jeg vist to anvendelser af where til at sætte restriktioner på en parametertype. Der er endnu et par muligheder:

- where T : struct - where T: class

Page 171: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

171

Generiske typer

hvor den første betyder, at parametertypen skal være en værditype, mens den anden betyder at typen skal være en referencetype. Endelig har jeg i metoden Sort() angivet, at typen skal implementere et interface, men man kan med samme syntaks angive, at typen skal arve en klasse.

Parametriserede typer

Også typer kan være generiske, og blot for at vise syntaksen vil jeg starte med en type, som repræsenterer et par af objekter:

class Par<T1, T2>{private T1 arg1;private T2 arg2;

public Par(){}

public Par(T1 t1, T2 t2){arg1 = t1;arg2 = t2;

}

public T1 Arg1 {get { return arg1; }set { arg1 = value; }

}

public T2 Arg2{get { return arg2; }set { arg2 = value; }

}

public override string ToString(){return string.Format(“({0}, {1})”, Arg1.ToString(), Arg2.ToString());

}}

Det er en yderst simpel type, der er parametriseret med to typeparametre. Klassen definerer properties for de to variabler. Udover disse properties har klassen to konstruktører samt en ToString().

Du skal primært bemærke syntaksen for at parametrisere en type, samt at der kan være én eller flere parametertyper (det gælder også for en parametriseret metode).

Herunder er vist et program, som anvender typen:

Page 172: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

Click on the ad to read more

C# 1: Introduktion til programmering og programmeringssproget C#

172

Generiske typer

class Program{static void Main(string[] args){Par<int, int> p1 = new Par<int, int>(2, 3);Par<int, double> p2 = new Par<int, double>();p2.Arg1 = 23;p2.Arg2 = Math.PI;Par<string, Dice> p3 = new Par<string, Dice>(”Red”, new Dice());Console.WriteLine(p1);Console.WriteLine(p2);Console.WriteLine(p3);

}}

Der er ikke så meget at forklare, og udfører man metoden, er resultatet følgende:

Eksemplet hedder Exam39.

Tænker du også på fremtidens vand?

Så bliv en del af Nordens mest kompetente medarbejderstab specialiseret i vand.

Service | Value | Respo

nsib

ility

Vil du med på holdet?

Tjek vores jobside for ledige

stillinger og upload dit CV på

www.kruger.dk/da/job

Foto

: K

rüg

er

Sta

fett

en

rrn

ddn

dddn

dn

dddu

ndd

un

t o

t o

to

t ooo

t ooo

t o ot o

to

t ooo ooot ooo

t o

t o

too

t o

tm

CCm

Cm

Cm

CCm

Cm

Cm

CCm

CCm

Cm

Cm

CCm

CCCCCCCm

CCm

Cm

Cm

Cm

Cm

Cm

Cm

Cm

Cm

CCCmmmmmmmmmmmmmmmmm

hririiri

hri

hri

hri

hri

hririirii

hri

hriiiii

hri

hri

hri

hriiiirrr

hrr

hr

hr

hr

hrrrrrrrrrrrrrrrrrrr

hr

hrrrr

hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhst

ist

ist

ist

ist

ist

ist

ist

ist

ist

ist

ist

ist

ist

ist

ist

ist

ist

ist

ist

ist

ist

ist

ist

ist

ist

itisti

sti

sti

sti

sti

sti

stititistiiii

sti

sti

stii

sti

sti

sti

sti

sti

stiii

stii

stitistii

stii

sti

sstststststtsssssssssssn

sn

ssssssssn

sn

sa

ns

nssss

nss

ns

nss

an

sa

nss

nssss

an

sn

ssssa

ns

ns

an

sa

ns

an

ssn

ssa

nss

an

sa

ns

an

sa

nss

an

sa

ns

an

sa

ns

an

ssa

na

na

na

na

nnnnnna

na

na

nnnnna

nnnnnnnnna

nnnna

nna

na

nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnna

nnnnnnnnaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa

or

or

or

or

or

or

orr

or

or

orr

or

orrr

or

or

or

or

or

orr

orr

orr

or

orr

or

or

orr

oooooob

ooob

ob

oob

oob

ooobbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb

ggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggg

Page 173: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

173

Generiske typer

Exam40 Klassen Set

I dette eksempel vil jeg vise en type Set, der implementerer det matematiske begreb en mængde. En mængde er en samling af objekter - en collection - der grundlæggende giver mulighed for at spørge, om et objekt er med i mængden eller ej. Endelig skal mængde implementere de grundlæggende mængdeoperationer som foreningsmængde, fællesmængde og mængdedifference. Helt præcis skal typen have følgende egenskaber:

- at man kan få at vide, hvor mange elementer mængden indeholder - at man kan aflæse elementet på plads n - at man kan tilføje et element til mængden - at man kan fjerne et bestemt element til mængden - at man kan spørge om et bestemt element er med i mængden - at man kan danne foreningsmængden af to mængder - at man kan danne fællesmængden af to mængder - at man kan danne mængdedifferencen af to mængder

Det skal være en generisk type, så det er en mængde, som kan anvendes til vilkårlige objekter.

Fremgangsmåde

En mængde defineres på følgende måde:

public interface ISet<T>{int Count { get; }T this[int n] { get; }void Add(T elem);void Remove(T elem);bool Contains(T elem);ISet<T> Union(ISet<T> set);ISet<T> Intersection(ISet<T> set);ISet<T> Difference(ISet<T> set);

}

En mængde kan herefter defineres som en klasse, der implementerer dette interface:

public class Set<T> : ISet<T>{private T[] elems = new T[10];private int count = 0;

public int Count{get { return count; }}

public T this[int n]{get { return elems[n]; }}

Page 174: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

174

Generiske typer

public void Add(T elem){if (IndexOf(elem) >= 0) return;if (count == elems.Length) Expand();elems[count++] = elem;

}

public void Remove(T elem){int n = IndexOf(elem);if (n >= 0) elems[n] = elems[--count];}

public bool Contains(T elem){return IndexOf(elem) >= 0;}

public ISet<T> Union(ISet<T> set){Set<T> tmp = new Set<T>();for (int i = 0; i < set.Count; ++i) tmp.Add(set[i]);for (int i = 0; i < count; ++i) if (!set.Contains(elems[i])) tmp.Add(elems[i]);return tmp;

}

public ISet<T> Intersection(ISet<T> set){Set<T> tmp = new Set<T>();for (int i = 0; i < count; ++i) if (set.Contains(elems[i])) tmp.Add(elems[i]);return tmp;

}

public ISet<T> Difference(ISet<T> set){Set<T> tmp = new Set<T>();for (int i = 0; i < count; ++i) if (!set.Contains(elems[i])) tmp.Add(elems[i]);return tmp;

}

public override string ToString(){StringBuilder builder = new StringBuilder();builder.Append(”{”);for (int i = 0; i < count; ++i){builder.Append(’ ’);builder.Append(elems[i]);

}builder.Append(” }”);return builder.ToString();

}

private int IndexOf(T elem){

Page 175: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

Click on the ad to read more

C# 1: Introduktion til programmering og programmeringssproget C#

175

Generiske typer

for (int i = 0; i < count; ++i) if (elems[i].Equals(elem)) return i;return -1;}

private void Expand(){T[] temp = new T[2 * elems.Length];for (int i = 0; i < count; ++i) temp[i] = elems[i];elems = temp;

}}

Forklaring

Bemærk først, at interfacet er generisk og dermed at et interface på samme måde som en class kan defineres generisk. Der er ikke meget at forklare om det, ud over at over alt anvendes parametertypen T som var det en konkret type.

Hvad angår en implementering er der alene en default konstruktør, der opretter en tom mængde. Desuden at Add() metoden tester, at det samme element ikke tilføjes to gange, og hvis elementet allerede er der, skal der intet ske. Det samme gælder for Remove(), at hvis man forsøger at slette et element der ikke findes i mængden, skal sletningen blot ignoreres. Man kan diskutere disse valg, og man kunne i stedet have valgt en løsning, hvor brugeren på én eller anden måde (f.eks. gennem en returværdi) kunne få besked, om operationen blev udført korrekt. Vedr. implementeringen har jeg primært har tænkt på at gøre koden simpel, men til gengæld er det ikke særlig effektive algoritmer.

Jeg udvikler og udviklesPrevas startede i 1985 og er i dag hovedleverandør og udviklingspartner til førende virksomhederindenfor Life Science, telecom, automotive, forsvar, energi og fremstillingsindustrien. Vi er mereend 500 ingeniører som brænder for at finde effektive løsninger for vores kunder. ”Innovation for Growth” er vores mantra.Hos Prevas møder du kompetente og spændende mennesker hver dag. Det kan være dine nyekollegaer eller det kan være vores kunders medarbejdere. Hos os får du mulighed for at arbejdemed nye teknologier i mange forskellige brancher for spændende virksomheder.Som medarbejder hos Prevas kommer du derfor altid til at udvikles - så længe du selv vil.

iNNovATioN For groWTHwww.prevas.com

Page 176: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

176

Generiske typer

Typen er generisk og parametriseret med parametertypen T, og en mængde kan således indeholde elementer af typen T. Der stilles ikke noget krav til parametertypen - der er ingen where del. Dvs. at typen Set<T> kan anvendes til alle typer af objekter. Bemærk dog metoden IndexOf(), som er en private metode, der finder placeringen af et bestemt element i arrayet. Den anvender metoden Equals() til sammenligning af elementer. Det betyder, at for at alt virker efter hensigten, skal parametertypen T implementere metoden Equals() med værdi semantik.

Det meste af koden er direkte ud ad landevejen, men der er dog en enkelt ting, som du bør bemærke. Typen er implementeret ved hjælp af et array, som er den container, der indeholder mængdens elementer. Når en mængde oprettes, afsættes der plads til 10 elementer, der virker ret vilkårligt, hvad det dog også er, og spørgsmålet er, hvad der skal ske, hvis man forsøger at tilføje mere end 10 elementer til mængden. Her anvendes et princip, hvor kapaciteten fordobles, hvis man forsøger at tilføje elementer ud over den aktuelle kapacitet. Det består i at oprette et array af dobbelt størrelse, og kopiere det gamle array til det nye. Det klares af metoden Expand(), som evt. kaldes fra metoden Add(). Det er en simpel implementering, som betyder, at en mængde i princippet ikke har nogen øvre grænse på antallet af elementer - og som i øvrigt også anvendes af collection klasserne.

Bemærkning

Hvis man ser på metoderne til foreningsmængde, fællesmængde og mængdedifference er de ikke særlig effektive. Der er simpelthen for mange løkker inden i hinanden. Det fremgår måske ikke helt tydeligt, men undersøger man nærmere hvad der sker, kommer problemet frem i lyset. Problemet er egentlig metode IndexOf(), som består af en løkke, som gennemløber alle mængdens elementer. Betragt som eksempel følgende sætning (fra metoden Union()):

for (int i = 0; i < count; ++i) if (!set.Contains(elems[i])) tmp.Add(elems[i]);

Den består af en løkke, som gennemløber mængdens elementer. Det er i princippet ok, men for hvert element kaldes Contains() som kalder IndexOf(), der så udfører endnu en løkke, og det giver en dårlig effektivitet. Man taler om, at algoritmen har en dårlig tidskompleksitet.

Det er muligt at gøre det bedre ved at organisere elementer mere smart end ved blot at tilføje dem til et array, men det skyder over målet for denne bog og er ikke temaet for dette eksempel. Målet er her at give et eksempel på en generisk type med nogen nytteværdi, og indeholde mængden ikke alt for mange elementer, virker den da også udmærket.

Bemærkning

Som forklaret herover er klassen Set<T> implementeret, så dens metoder ikke er helt så effektive, som man kunne ønske. Det er præcis derfor, at man skal programmere til et interface. Hvis man overholder det, og hvis man i sit program overalt kender og bruger typen gennem det definerende interface, så kan man senere implementere Set klassen på en anden og mere effektiv måde, uden det har betydning for de programmer, som anvender en Set.

Page 177: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

177

Generiske typer

Test

Herunder er vist en metode, som tester klassen:

static void Test1(){ISet<int> A = new Set<int>();A.Add(2);A.Add(3);A.Add(5);A.Add(7);A.Add(11);A.Add(13);A.Add(17);A.Add(19);A.Add(23);A.Add(29);ISet<int> B = new Set<int>();B.Add(2);B.Add(4);B.Add(8);B.Add(7);B.Add(16);Console.WriteLine(A);Console.WriteLine(B);ISet<int> C = A.Union(B);ISet<int> D = A.Difference(B);ISet<int> E = A.Intersection(B);Console.WriteLine(C);Console.WriteLine(D);Console.WriteLine(E);B.Remove(2);B.Remove(4);B.Remove(6);Console.WriteLine(B);for (int i = 0; i < 28; ++i) B.Add(i);Console.WriteLine(B);

}

Også en struct kan være generisk. Herunder er således vist en type, som implementerer et generisk punkt, men hvor koordinaterne skal være en værditype:

Page 178: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

Click on the ad to read more

C# 1: Introduktion til programmering og programmeringssproget C#

178

Generiske typer

public struct Point<T> where T : struct{public T x;public T y;

public Point(T x, T y){this.x = x;this.y = y;

}

public override string ToString(){return string.Format(“({0}, {1})”, x, y);

}

public override bool Equals(object obj){if (!(obj is Point<T>)) return false;Point<T> p = (Point<T>)obj;return p.x.Equals(x) && p.y.Equals(y);

}}

Bemærk, at også Equals() metoden er overstyret, så typen kan anvendes til elementer i en Set.

Herunder er vist en simpel anvendelse af klassen:

Dine fordele ved forsikring hosPantaenius

DEN

10083 w

ww

.hqh

h.de

04/2

012

Østerbro 11 · 7800 SkiveTel. +45-9751 3388 · [email protected]

www.pantaenius.dk

Hjælp ved uheld

Du har behov for bugsering til nærmeste værft?Pantaenius overtager omkostningerne dog begrænset op til DKK 37.500,00!

Kontakt osHar du spørgsmål til dine forsikringer?Du kan ringe +45-9751 33 88 eller skrive til os på e-mail [email protected]

Inspektionsomkostninger

Du har haft en grundstødning og vil have bunden inspiceret?Pantaenius dækker inspektionen uden selvrisiko!

Ingen selvrisiko

Indbrud, transportskade, brand, lynnedslag eller totalskade?Ved disse skadesårsager er der ingen selvrisiko hos Pantaenius!

Page 179: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

179

Generiske typer

static void Test2(){Point<int> p1 = new Point<int>(2, 3);Point<double> p2 = new Point<double>(1.41, 3.14);Point<Point<int>> p3 =new Point<Point<int>>(new Point<int>(1, 4), new Point<int>(2, 5));

Console.WriteLine(p1);Console.WriteLine(p2);Console.WriteLine(p3);

}

Her skal du især bemærke punktet p3, hvis koordinater har typen Point<int>, som er lovlig, men måske næppe giver nogen mening.

Som et sidste eksempel er herunder vist en metode, som opretter en Set med punkter:

static void Test3(){ISet<Point<int>> A = new Set<Point<int>>();A.Add(new Point<int>(2, 3));A.Add(new Point<int>(4, 5));A.Add(new Point<int>(6, 7));Console.WriteLine(A);

}

Effektivitet

Jeg omtalte ovenfor, at klassen ikke er særlig effektiv. For at undersøge effektiviteten vil jeg prøve med følgende metode:

static void Test4(){int N = 10000;ISet<int> A = Create(N, 2 * N);ISet<int> B = Create(N, 2 * N);Stopwatch sw = new Stopwatch();sw.Start();ISet<int> C = A.Union(B);sw.Stop();Console.WriteLine(sw.ElapsedMilliseconds);sw.Start();

Page 180: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

Click on the ad to read more

C# 1: Introduktion til programmering og programmeringssproget C#

180

Generiske typer

ISet<int> D = A.Intersection(B);sw.Stop();Console.WriteLine(sw.ElapsedMilliseconds);

}

static ISet<int> Create(int n, int m){ISet<int> S = new Set<int>();while (n-- > 0) S.Add(rand.Next(m));return S;

}

Her er Create() en metode, som opretter en mængde med n elementer af typen int, der ligger mellem 0 og 2n. Metoden Test4() anvender denne metode til at oprette to mængder hver med 10000 elementer. Dernæst anvender den klassen StopWatch (defineret i namespacet System.Diagnostics) til at måle, hvor lang tid (målt i millisekunder) det tager at danne foreningsmængden, og til sidst gentager metoden det for fællesmængden. Udføres metoden, kunne resultatet være følgende:

Dvs. at hver operation tager mellem 2 og 3 sekunder.

Get “Bookboon’s Free Media Advice” Email [email protected]

See the light! The sooner you realize we are right, the sooner your life will get better!

A bit over the top? Yes we know!

We are just that sure that we can make your media activities more effective.

Page 181: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

181

Exception handling

21 Exception handlingNår man skriver et program, kan der forekomme fejl. F.eks. kan man skrive programkoden forkert, så programmet ikke kan oversættes. Det skyldes, at programmet er skrevet med en forkert syntaks, og den slags fejl er sjældent problematiske, da de fanges af compileren. Man taler derfor også om compiler fejl. Disse fejl skal naturligvis rettes, hvilket - indtil man bliver øvet - kan være vanskelig nok, men når jeg kalder dem uproblematiske, er det fordi, at compileren finder dem, og programmet kan slet ikke køre, før de er rettet.

En anden type fejl er logiske fejl, hvor programmet kan oversættes og køre, men hvor det gør noget andet, end tanken var. Det kan f.eks. være en beregning, der giver et forkert resultat, eller en forkert værdi, der gemmes i en database. Det er de sværeste fejl, fordi de ikke kan fanges af compileren, og fordi at programmet faktisk kan køre i en periode, inden fejlen erkendes, men også fordi det kan være fejl, der er svære at lokalisere. Brugeren af programmet opdager symptomet, men det kan være svært at finde, hvor i koden det er, at det går galt. Midlet mod den slags fejl hedder test, test og test igen. At teste et program er på ingen måde simpelt, og det kræver både tid og procedurer.

En tredje slags fejl skyldes omgivelserne og er fejl, man som programmør ikke rigtig kan gardere sig imod, men omvendt også fejl man på én eller anden måde skal tage hånd om. Som et eksempel kan det være en bruger, der skal indtaste noget - f.eks. et tal - og her har man ingen kontrol over, hvad brugeren indtaster. Som et andet eksempel kan man tænke sig et program, der skal anvende en fil, der ikke findes. I de situationer skal programmet håndtere fejlen, hvilket vil sige, at det skal kunne opdage, at der er en fejl og i givet fald beslutte, hvad der så skal ske. Typisk vil det være sådan, at en metode kan fange, at der er en fejl, men metoden kan ikke vide, hvordan fejlen skal håndteres, men den må i stedet gøre det sted, hvorfra den blev kaldt, opmærksom på, at der er indtruffet en fejl og overlade fejlbehandlingen til den kaldende kode. En måde at løse problemet på er at lade den metode, der kan detektere fejlen returnere en fejlkode, og den kaldende kode kan så teste fejlkoden og foretage en passende handling bestemt af koden. Denne strategi er såmænd udmærket, men den kan kun anvendes i situationer, hvor metoden ellers ikke har en returværdi.

En anden strategi er at anvende exception handling. Idéen er ret simpel. En metode kan i tilfælde af en fejl rejse en exception, og sker det, bliver metoden straks afbrudt. Det sted hvorfra metoden blev kaldt kan så vælge at fange den pågældende exception og iværksætte en passende handling. Betragt som eksempel (der hedder Exam41) følgende metode, der skal betegne kvotienten af to heltal:

static int Div(int a, int b){if (b == 0) throw new ApplicationException(“Division med 0...”);return a / b;

}

Page 182: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

182

Exception handling

Man kan som bekendt ikke dividere med 0. Hvis b er 0, kan metoden ikke udføre beregningen, men den kan heller ikke vide, hvad den så skal gøre. Den kan ikke bare returnere noget, for det ville af den kaldende kode kunne fortolkes som et resultat, der så var ulovligt. Metoden kan imidlertid teste værdien af b, og hvis den er 0 rejse en exception. Det betyder, at metoden stopper med en exception, som sendes til den kaldende kode. Herunder er vist en kode som anvender ovenstående:

static void Test1(){try{Console.WriteLine(Div(23, 5));Console.WriteLine(Div(23, 0));

}catch (ApplicationException ex){Console.WriteLine(ex.Message);Console.WriteLine(“The method is completed with an error...”);

}}

Den kode, der kan rejse en exception - her metoden Div() - er anbragt et en try blok. Hvis Div() rejser en exception, bliver kontrollen overført til den efterfølgende catch handler, der så udfører fejlhåndteringen, som her blot består i at printe en besked på skærmen.

En exception er en type, som er en class. Ovenfor er typen ApplicationException, men der er andre muligheder. For at en exception kan fanges i den kaldende kode, skal der være overensstemmelse mellem typen af den exception der rejses - typen efter throw - og typen efter catch.

Den kaldende kode behøver ikke at fange en exception. Er det tilfældet, og den pågældende exception ikke på noget niveau bliver behandlet, bliver programmet afsluttet med en default exception handling:

static void Test2(){Console.WriteLine(Div(23, 5));Console.WriteLine(Div(23, 0));

}

Page 183: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

Click on the ad to read more

C# 1: Introduktion til programmering og programmeringssproget C#

183

Exception handling

Som nævnt findes der flere exception typer, faktisk mange, og de fleste klasser i .NET frameworket kan rejse en række forskellige exceptions. Den grundlæggende basisklasse hedder Exception, og hører hjemme i System namespacet. ApplicationException er en afledt klasse, og selv om en brugerdefineret kode udmærket kan rejse en Exception (og ofte gør det), er det tanken at typen af en exception rejst af en brugerdefineret metode enten skal være ApplicationException eller en type, der er afledt heraf.

Som eksempel på, hvordan exception handling virker i C# vil jeg bruge den generiske klasse Set defineret ovenfor. Den har en metode Add() og en metode Remove(), der begge virker uhensigtsmæssigt. Problemet er, at begge metoder evt. ikke kan udføre den ønskede operation (et element kan ikke tilføjes mængden, hvis det allerede er der, og et element kan ikke fjernes, hvis det ikke er med i mængden), og er det tilfældet, gør metoderne intet. Det er en uheldig løsning, idet brugeren ikke får besked om, at den pågældende operation ikke er udført. Hovedproblemet er, at de to metoder kan teste, om operationen kan udføres, men de kan umuligt vide, hvad der i givet fald skal ske.

Mangler du dygtige callcenter medarbejdere?Lad Assistance finde din nye medarbejderVi sætter en ære i at indhente viden om din virksomhed, jeres kultur og værdier, strategi, mission og vision. Herigennem danner vi os et præcist indtryk af jeres foretrukne profil. I rekrutteringsprocessen lægger vi vægt på følgende forhold:

• Grundig behovsafdækning – for et optimalt match• Jobprofil og stillingsopslag• Rådgivning i forhold til valg af annonceringsmedie• Screening af relevante ansøgere (test, analyse og problemløsning)

Kontakt os for et uforpligtende møde på telefon 33 55 00 90

Page 184: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

184

Exception handling

Løsningen er, at lade metoderne rejse en exception, hvis operationen ikke kan udføres.

Jeg vil starte med følgende exception type:

public class SetException : ApplicationException{public SetException(string message): base(message)

{}

}

Her skal du bemærke, at typen arver ApplicationException, og det eneste der sker, er at der er en konstruktør, der sender en tekst videre til basisklassens konstruktør. Det er en meget simpel type, som i virkeligheden ikke udvider ApplicationException, og det eneste formål er at få en type, som er speciel rettet mod den aktuelle problemstilling. Jeg vil definere endnu to typer til exceptions, der begge arver typen SetException:

public class AddException : SetException{public AddException(): base(“The element already exists in the set and can not be added”)

{}

}

public class RemoveException : SetException{public RemoveException(): base(“The element is not found in the set and can not be removed”)

{}

}

Af navngivningen og teksten fremgår det tydeligt, hvad de skal bruges til, og det vigtige er, at der nu er følgende klassehierarki til rådighed:

Exception

ApplicationException

SetException

AddException RemoveException

Page 185: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

Click on the ad to read more

C# 1: Introduktion til programmering og programmeringssproget C#

185

Exception handling

Jeg vil nu indføre kode i klassen Set, så der evt. rejses en exception, men jeg har kun vist de metoder, der er ændret:

public class Set<T> : ISet<T>{private T[] elems = new T[10];private int count = 0;

public void Add(T elem){if (IndexOf(elem) >= 0) throw new AddException();if (count == elems.Length) Expand();elems[count++] = elem;

}

public void Remove(T elem){int n = IndexOf(elem);if (n < 0) throw new RemoveException();elems[n] = elems[--count];

}

.....}

Add() og Remove() metoderne rejser nu en exception, hvis den pågældende operation ikke kan udføres. Bemærk, at de exceptions, der rejses, er af forskellig type.

Page 186: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

186

Exception handling

Herunder er vist en metode, der anvender klassen Set og fanger evt. exceptions:

static void Test3(){ISet<int> A = new Set<int>();try{for (int i = 0; i < 20; ++i){try{int t = rand.Next(30);A.Add(t);t = rand.Next(30);A.Remove(t);

}catch (AddException ex){Console.WriteLine(ex.Message);

}catch (RemoveException ex){Console.WriteLine(ex.Message);

}catch (SetException ex){Console.WriteLine(ex.Message);

}finally{Console.WriteLine(A);

}}Print(A, A.Count);

}catch{Console.WriteLine(“There was an error”);

}}

Her er en del ting, der skal forklares. Bemærk først, at der er to try blokke: En ydre uden om for løkken, og en indre, som indkapsler kroppen af for løkken. Altså kan du bemærke, at man kan have try blokke inden i hinanden. I for løkken sker der to ting:

1. der tilføjes et tilfældigt tal (mellem 0 og 29) til mængden A2. der fjernes et tilfældigt tal fra mængden

Page 187: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

187

Exception handling

I begge tilfælde kan der forekomme en exception. Derfor er koden anbragt i en try blok. Efter try blokken er der tre catch handlere, og det skal illustrere, at der kan være flere catch handlere til en try blok. Hvis blokken rejser en exception, vil programkontrollen overføres til den catch handler som matcher typen på den exception, der er rejst. Det er derfor, at exceptions kan have forskellig type, så man med flere catch handleren kan styre, hvad der skal ske i forskellige situationer.

Bemærk også, at den inderste try blok har tilknyttet en finally handler. Denne handler - hvis den er med, hvad der ikke er nødvendigt - bliver udført uanset, om der er en exception eller ej.

Endelig er der den ydre try blok. Det er et eksempel på en anonym catch handler, og dermed en catch handler der udføres, når der kommer en exception og det uanset type - man fanger hvad som helst.

SystemException

Når programmer rejser en exception, bør det altid være af typen ApplicationException eller en type, som er direkte eller indirekte afledt heraf. Klassen ApplicationException er som nævnt afledt af klassen Exception, og der er derfor ikke noget til hinder for, at man kan rejse en exception af typen Exception. Når man ikke bør gøre det, skyldes det, at der en anden exception klasse, som hedder SystemException og som også er afledt af Exception. Exceptions af denne type er beregnet til exeptions rejst af runtime systemet eller grundlæggende klasser fra frameworket, og de indikere helt basale og alvorlige fejl, hvor den typiske håndtering er at terminere programmet med en fejlmeddelelse. Nedenstående hierarki separerer således exceptions i to kategorier, hvor den ene kategori indikerer fejl, der typisk resulterer i at programmet afsluttes med en fejlmeddelelse, mens den anden kategori indikerer fejl forårsaget af programmets omgivelser eller brug, og dermed fejl der skal håndteres af programmet.

ApplicationExceptionSystemException

Exception

Som et eksempel er herunder vist en metode, som resulterer i en fejl, ved at den indekserer uden for et array:

static void Test4(){int[] t = { 2, 3, 5, 7, 11, 13, 17, 19 };try{int s = 0;for (int i = 0; i < 10; ++i) s += t[i];

Page 188: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

Click on the ad to read more

C# 1: Introduktion til programmering og programmeringssproget C#

188

Exception handling

Console.WriteLine(s);}catch (Exception ex){Console.WriteLine(ex.GetType().Name);Console.WriteLine(ex.GetType().BaseType.Name);Console.WriteLine(ex.GetType().BaseType.BaseType.Name);

}}

Resultatet er følgende:

Hvor mange skal tage en beslutning, før man kan føre

en beslutning ud i livet?

Slip for komplekse kommandoveje. Hos NNIT løser vi de store it-opgaver i små teams, der ikke skal spørge om lov til at tage

en beslutning. Se ledige job på nnit.dk/job

RE

TH

INK

PIP

EL

INE

Hvor mange skal tage en beslutning, før man kan føre

en beslutning ud i livet?

Slip for komplekse kommandoveje. Hos NNIT løser vi de store it-opgaver i små teams, der ikke skal spørge om lov til at tage

en beslutning. Se ledige job på nnit.dk/job

RE

TH

INK

PIP

EL

INE

Hvor mange skal tage en beslutning, før man kan føre

en beslutning ud i livet?

Slip for komplekse kommandoveje. Hos NNIT løser vi de store it-opgaver i små teams, der ikke skal spørge om lov til at tage

en beslutning. Se ledige job på nnit.dk/job

RE

TH

INK

PIP

EL

INE

Hvor mange skal tage en beslutning, før man kan føre

en beslutning ud i livet?

Slip for komplekse kommandoveje. Hos NNIT løser vi de store it-opgaver i små teams, der ikke skal spørge om lov til at tage

en beslutning. Se ledige job på nnit.dk/job

RE

TH

INK

PIP

EL

INE

Page 189: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

189

Kommentarer

22 KommentarerBetragt som eksempel følgende klasse, som jeg har set på i Exam34:

using System;using System.Text;

/*This namespace contains several classes with miscellaneous methods.One can perceive the namespace as a custom class library.

*/namespace Exam42{/// <summary>/// Class with static methods for text operations./// </summary>public static class String{/// <summary>/// Method, which cuts off a string to a maximum width./// If the width does not exceed the desired width,/// the method simply returns the string unchanged./// </summary>/// <param name=”text”>The string that must be cut</param>/// <param name=”length”>The maximum width of the return string</param>/// <returns>A string whose width is less than or equal to the length</returns>public static string Cut(string text, int length){if (text.Length > length) return text.Substring(0, length);return text;

}

/// <summary>/// Method to adjust a text string within a given field with the width length./// If the length of the text is larger than length, the method simply/// returns the text./// Otherwise the method returns a string of length length, where text/// is left-aligned, and where the field is filled with the character fill./// </summary>/// <param name=”text”>The text to be adjusted</param>/// <param name=”length”>Field width</param>/// <param name=”fill”>Fill character</param>/// <returns>Justifyed text</returns>public static string FillRight(string text, int length, char fill){if (text.Length >= length) return text;StringBuilder builder = new StringBuilder(text, length);while (builder.Length < length) builder.Append(fill);

Page 190: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

190

Kommentarer

return builder.ToString();}

/// <summary>/// Method to adjust a text string within a given field with the width length./// If the length of the text is larger than length, the method simply/// returns the text./// Otherwise the method returns a string of length length, where text/// is right-aligned, and where the field is filled with the character fill./// </summary>/// <param name=”text”>The text to be adjusted</param>/// <param name=”length”>Field width</param>/// <param name=”fill”>Fill character</param>/// <returns>Justifyed text</returns>public static string FillLeft(string text, int length, char fill){if (text.Length >= length) return text;// here are created a StringBuilder with the required capacity to the fill// characters you could instead have used the method Insert(), but it has a// worse complexity than Add()length -= text.Length;StringBuilder builder = new StringBuilder(length);while (builder.Length < length) builder.Append(fill);return builder.ToString() + text;

}

/// <summary>/// Method to adjust a text string within a given field with the width length./// If the length of the text is larger than length, the method simply/// returns the text./// Otherwise the method returns a string of length length, where text/// is center-aligned, and where the field is filled with the character fill./// </summary>/// <param name=”text”>The text to be adjusted</param>/// <param name=”length”>Field width</param>/// <param name=”fill”>Fill character</param>/// <returns>Justifyed text</returns>public static string FillCenter(string text, int length, char fill){if (text.Length >= length) return text;return FillRight(FillLeft(text, (text.Length + length) / 2, fill), length, fill);

}}

}

Page 191: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

Click on the ad to read more

C# 1: Introduktion til programmering og programmeringssproget C#

191

Kommentarer

Jeg har denne gang indsat kommentarer i koden. Kommentarer har ingen betydning for det oversatte program, men har alene betydning for os mennesker, som skal læse og forstå koden. Der kan siges meget om kommentarer, så derfor nogle ord om det.

Det er vigtigt at kommentere sin kode. Ja mere end det - det bør faktisk være en fast del af programmeringsopgaven helt på lige fod med det at skrive selve koden, og det er der i det mindste to grunde til:

1. Al programkode skal vedligeholdes over tid, og det ofte af andre end den der har skrevet koden. Derfor er det utrolig vigtigt, at der i koden er kommentarer, der fortæller om vigtige beslutninger, og hvorfor koden er skrevet som den er. Kommentarer er vigtige ikke blot af hensyn til andre, men også fordi man heller ikke selv kan huske sin egen kode, hvis den blot er få måneder gammel.

2. Selve processen at kommentere koden er vigtig, fordi man under denne proces tænker koden igennem og overvejer, hvorfor koden er skrevet som den er. Det er en utrolig effektiv metode til at finde fejl og uhensigtsmæssigheder i koden - og få disse rettet.

Hvis man ser mine eksempler, vil man i de fleste tilfælde lede forgæves efter kommentarer. Det skyldes dels, at det er små eksempler og ikke egentlig applikationer, som skal løse konkrete dagligdagsproblemer, og dels at koden jo netop er forklaret i her i bogen. Man kan egentlig sige, at en del af bogens indhold i stedet kunne være kommentarer i eksemplerne.

Page 192: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

192

Kommentarer

I C# har man tre slags kommentarer. Ovenfor har jeg skrevet en kommentar foran namespacet:

/*This namespace contains several classes with miscellaneous methods.One can perceive the namespace as a custom class library.

*/

Det er en lidt ældre form for kommentar, der er arvet fra programmeringssproget C, men tegnene /* starter en kommentar, og den fortsætter frem til man møder tegnene */ og mellem disse to markeringer kan så stå alt den tekst, som man måtte have lyst til - på en enkelt linje eller fordelt på flere linjer. Denne form for kommentar anvendes ikke så hyppigt længere, men der er ikke noget galt med den, og har man brug for i starten af en source file at skrive en længere dokumentation, er det en udmærket form for kommentar.

Den mest anvendte form for kommentar i C# er den, der er anvendt foran de enkelte metoder. Det skyldes bl.a. at Visual Studio autogenerer et skelet, som man så skal udfylde. Hvis man f.eks. placerer markøren foran metoden FillCenter() og trykker på tasten / tre gange, genererer VS følgende kommentarskelet:

/// <summary>/// /// </summary>/// <param name=”text”></param>/// <param name=”length”></param>/// <param name=”fill”></param>/// <returns></returns>

Her skal programmøren så dokumentere følgende:

- En beskrivelse af metoden og hvad den laver, og herunder generelt hvad den der skal anvende metoden har brug for at vide.

- Forklaring på metodens parametre og herunder hvilke regler (prebetingelser), som parametrene skal overholde.

- En forklaring af metodens returværdi.

Fordelen ved at anvende den form for dokumentation - ikke blot for metoder, men for alle programelementer - er

- at dokumentationen har en standard form, og at man husker at dokumentere alle vigtige elementer som parametre og returværdi

- at dokumentationen anvendes af intellisense i Visual Studio - at dokumentationen er på XML form, og at man derfor kan anvende et værktøj til at danne

en færdig dokumentation for et helt program, f.eks. som HTML

Page 193: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

193

Kommentarer

Den sidste form for kommentar er simplere og går ud på at alt efter // og til slutningen af linjen er en kommentar (se metoden FillLeft() ovenfor). Denne kommentar anvendes typisk til at dokumenterer enkelte sætninger i f.eks. en metode, eller betydningen af en variabel eller tilsvarende.

Det er let at skrive kommentarer, men en hel anden ting er, hvad man så skal skrive, og det er der mange holdninger til, og det følgende må så være mine. Generelt skal man skrive, hvad man mener at andre og herunder også én selv har brug for at vide, for at kunne læse og forstå koden og dermed kunne vedligeholde den. Man skal ikke dokumentere selvfølgeligheder. Man må gå ud fra, at den der skal læse koden kender sproget, og man skal ikke dokumentere selve sproget, men forklaringer på de valg der er gjort - man skal dokumentere algoritmen. Er der løsninger, som er svære at forstå og gennemskue, så skal man tilføje forklarende kommentarer. Det er også fornuftig altid at dokumentere variabler, og hvad de anvendes til - i det mindst instance variabler. Det kan også være en god ide, at tilføje en kommentar, som fortæller om en ændring af koden, om hvornår ændringer er foretaget, at hvem og hvorfor og naturligvis også hvad der er ændret.

Specielt vedr. de autogenerede kommentarer bør man være konsekvent og medtage dem - i det mindste for alle public programelementer. Især er det vigtigt for klassebiblioteker, som ofte skal anvendes af andre end den programmør, som har skrevet klasserne. Det kan være svært at skrive den form for dokumentation, ganske enkelt fordi det kan svært at finde på noget at skrive (mange metoder og properties er indlysende og selvforklarende) og ofte synes man, at man skriver selvfølgeligheder. Alligevel er det et sted, hvor man bør være konsekvent og medtage disse kommentarer. Man bør være opmærksom på, at man her henvender sig til dem, der skal anvende koden, og ikke til dem, der skal vedligeholde koden.

Programkodens læsbarhed er uhyre vigtig, og man kan endda gå så langt, at kode som ikke let at læse er værdiløs. Man kan imidlertid gøre andet for at gøre koden læsbar end at skrive kommentarer, og herunder følgende nogle få retningslinjer:

- en blok starter på en ny linje, der kun indeholder tegnet { - fra næste linje gør man en indrykning på to tegn - når en blok slutter ophæves indrykningen, og man rykker på pladser til venstre - en blok slutter altid på en ny linje, der kun indeholder tegnet } - sæt altid et mellemrum på begge sider af en operator - navnet på en variabel starter altid med et lille bogstav - navnet på en metode, property og brugerdefineret type starter altid med et stort bogstav - vær konsekvent mht. store og små bogstaver - brug gode og forklarende navne, men ikke for lange navne - de er svære at læse - brug blanke linjer, hvor man synes det øger læsbarheden

Page 194: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

Click on the ad to read more

C# 1: Introduktion til programmering og programmeringssproget C#

194

Kommentarer

Og så vær konsekvent og have en stil. Retningslinjer er gode, men der vil altid være steder, hvor man fraviger, men gør man det konsekvent, er det udmærket. Ovenstående retningslinjer er med til at gøre koden selvdokumenterende, og man kan sige, at kommentarer skal anvendes, hvis koden ikke kan dokumentere sig selv.

Man kan næsten ikke sige nok om vigtigheden af at skrive læsbar programkode, men man kan mht. kommentarer også gå for langt. Generelt føler jeg, at kommentarer inde i en metode, gør koden sværere at læse. Det kan være svært at få øje på, hvad der er kode, og hvad der er kommentarer - kommentarerne skygger for koden. Kommentarer inde i koden medtager jeg kun, hvor jeg synes, de er absolut nødvendige - og det er bestemt ofte tilfældet. Konklusionen er, at dokumentation er vigtig, men overdrivelse kan have den modsatte effekt.

SÆT LYD PÅ FREMTIDENWidex udvikler højteknologiske høreapparater til gavn for de 500 millioner mennesker verden over, der har nedsat hørelse.

Mere end fem årtiers intensiv forskning og udvikling har gjort os til en af verdens førende høreapparatproducenter, og vi udvikler digital teknologi af en kvalitet, kun få kan måle sig med.

Som videnbaseret virksomhed betragter vi medarbejderne som vores vigtigste kapital. Vi kan godt lide at gøre tingene selv og sætter en ære i at være selvforsynende inden for de fl este om-råder. Det skaber et spændende, tværfagligt arbejdsmiljø med plads til initiativ og rig mulighed for personlig og faglig udvikling.

Vil du være med til at sætte lyd på fremtiden? Følg med i vores jobopslag på www.widex.dk/job eller skriv til [email protected]

www.widex.com

Page 195: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

195

Extension metoder

23 Extension metoderHvis man ønsker at udvide en klasse med nye metoder, er fremgangsmåde at skrive en afledt klasse, som tilføjer de nye metoder. Det er stadig den “rigtige” strategi, men det er ikke altid muligt, f.eks. hvis klassen er sealed - det er en klasse, som man ikke kan arve. Man kan da delvis opnå det samme med en extension metode.

Betragt følgende klasse, der definerer tre statiske metoder til heltal:

public static class Integer{public static long DiffSum(this int n){return (n + 1L) * n / 2;

}

public static int Add(this int n, params int[] t){int s = n;for (int i = 0; i < t.Length; ++i) s += t[i];return s;

}

public static bool IsPrim(this int n){if (n == 2 || n == 3 || n == 5 || n == 7) return true;if (n < 11 || n % 2 == 0) return false;for (int k = 3, m = (int)Math.Sqrt(n) + 1; k <= m; k += 2)if (n % k == 0) return false;

return true;}

}

Den første bestemmer summen af differensrækken 1 + 2 + 3 + 4 + ... + n. Det kan man gøre med en løkke, men man kan også anvende en formel, som der er gjort ovenfor. Den anden metode returnerer summen af en række heltal, mens den sidste metode tester, om et heltal er et primtal. Da alle metoder er statiske, kan de udføres på følgende måde:

Console.WriteLine(Integer.Add(2, 3, 5, 7, 11, 13, 17, 19));Console.WriteLine(Integer.DiffSum(100));Console.WriteLine(Integer.IsPrim(97));

hvilket der ikke er noget underligt i. Du skal imidlertid bemærke, at klassen er statisk, samt at den første parameter til hver af de tre metoder har typen int, og at erklæringen af denne parameter er foranstillet ordet this. Det er de to forhold der gør, at der er tale om extension metoder. Det betyder, at metoderne kan udføres, som var de instance metoder defineret for typen int:

Page 196: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

196

Extension metoder

int a = 2;Console.WriteLine(a.Add(3, 5, 7, 11, 13, 17, 19));int b = 100;Console.WriteLine(b.DiffSum());int c = 97;Console.WriteLine(c.IsPrim());

og ikke nok med det - de pågældende metoder kendes af Intellisense i Visual Studio.

Tilsyneladende er typen int udvidet med nye metoder, men det er naturligvis ikke tilfældet. En extension metode er en sædvanlig statisk metode, og den skal skrives på samme måder som andre statiske metoder og kan ikke referere til instance medlemmer i den klasse, som den er extension til. Der er alene tale om, at man med ordet this foran den første parameter giver mulighed for, at man syntaktisk kan anvende metoden, som var det en instance metode. Hvis du sammenligner ovenstående anvendelser af metoderne i klassen Integer, er det tydeligt, at det alene er et spørgsmål om, hvordan man angiver den første parameter - som en sædvanlig værdi eller ved anvendelse af dot notationen.

Extension metoder har alligevel deres anvendelser, og f.eks. anvender Microsoft det i stor udstrækning i forbindelse med LINQ.

I det forrige afsnit viste jeg en klasse String. Det var en statisk klasse med statiske metoder, hvor den første parameter alle steder havde typen string (altså typen System.String). Det er derfor yderst simpelt at ændre disse metoder til extension metoder for String klassen - det er blot at tilføje ordet this foran den første parameter til alle metoder:

public static class Str{public static string Cut(this string text, int length){if (text.Length > length) return text.Substring(0, length);return text;

}

public static string FillRight(this string text, int length, char fill){if (text.Length >= length) return text;StringBuilder builder = new StringBuilder(text, length);while (builder.Length < length) builder.Append(fill);return builder.ToString();

}

public static string FillLeft(this string text, int length, char fill){if (text.Length >= length) return text;length -= text.Length;StringBuilder builder = new StringBuilder(length);while (builder.Length < length) builder.Append(fill);return builder.ToString() + text;

Page 197: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

Click on the ad to read more

C# 1: Introduktion til programmering og programmeringssproget C#

197

Extension metoder

}

public static string FillCenter(this string text, int length, char fill){if (text.Length >= length) return text;returnFillRight(FillLeft(text, (text.Length + length) / 2, fill), length, fill);

}}

Dedicated Analytical Solutionswww.foss.dk/careers

Protein 13.2%

Moisture 8.4%

Starch 67%

FOSS is known throughout the world for efficient analytical solutions that help to improve both food quality and safety in the global food market. We are playing an increasingly important role in ensuring optimal use of valuable natural resources, and have throughout the years created ground-breaking innovations. And there’s more to come. At FOSS you will find professional challenges, training and development in a work environment that offers good work/ life balance. Join us and make a difference.

80% of the grain traded in the world is analysed on a FOSS solution

Page 198: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

198

Collection klasser

Del 3 Collection klasserAlle moderne sprog og herunder C# har et udvalg af collection klasser. En collection klasse kan opfattes som en container, der kan indeholde objekter. De enkelte collection klasser adskiller sig mht. hvordan de organiserer objekterne, og hvad man kan gøre med dem, dvs. hvilken adgang der er til containerens indhold. I det følgende beskrives de vigtigste af de collection klasser, der er indeholdt i .NET frameworket.

.NET er født med ofte anvendte collection klasser færdig implementeret og lige til at anvende. De er alle implementeret som generiske klasser, og jeg vil i denne del af bogen omtale følgende:

• List<T>• Stack<T>• Queue<T>• LinkedList<T>• Dictionary<K, V>• SortedDictionary<K, V>

Jeg vil udelukkende lægge vægt på, hvordan klasserne kan anvendes, og for en fuld dokumentation af klasserne og deres metoder vil jeg henvise til dokumentationen på MSDN.

Inden jeg tager fat på det, vil jeg kort minde om et array, der jo også er en container. Betragt som eksempel følgende program:

using System;

namespace Exam44{class Program{static void Main(string[] args){int[] t = { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29 };string[] s = new string[6];s[0] = “Svend”;s[1] = “Valborg”;s[2] = “Knud”;s[3] = “Abelone”;s[4] = “Valdemar”;s[5] = “Gudrun”;Array.Reverse(t);Array.Sort(s);foreach (int n in t) Console.Write(“{0} “, n);Console.WriteLine();foreach (string v in s) Console.Write(“{0} “, v);Console.WriteLine();

}}

}

Page 199: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

199

Collection klasser

Kører man programmet, får man følgende resultat:

Der er ikke så meget mystisk i det, og du skal især bemærke klassen Array, som stiller en række statiske metoder til rådighed til at manipulere arrays.

I langt de fleste tilfælde vil et array være et alternativ til en collection klasse, og mange collection klasser er i virkeligheden en indkapsling af et array. Der er ikke noget problem i at anvende arrays frem for collection klasser, men omvendt så giver collection klasserne store fordele. F.eks. så har et array en fast størrelse, og det er op til programmøren at holde styr på, hvor de enkelte elementer er, og om der er plads. Er der ikke plads, er det nødvendigt at oprette et større array og kopiere indholdet af det gamle til det nye. Det er al den logik, der er indkapslet i en collection klasse, og dermed noget der sker automatisk bag programmørens ryg. Ud over det, så stiller collection klasserne forskellige services til rådighed, som passer på typiske anvendelser.

Som nævnt ovenfor er collection klasserne generiske og dermed typestærke. Dvs. at de objekter, som en konkret collection kan indeholde, skal være af en bestemt type. Der findes imidlertid også en samling af ikke generiske collection klasser:

- ArrayList - Stack - Queue - SortedList - Hashtable

som er collections, hvor objekterne har typen Object. Disse klasser stammer fra de første versioner af .NET frameworket, som ikke havde generiske typer til rådighed. Klasserne er stadig til rådighed og kan anvendes, men det kan dog anbefales at anvende de nyere generiske versioner, da resultatet er en mere stabil kode, svarende til at oversætteren kan teste typen af objekter.

Page 200: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

Click on the ad to read more

C# 1: Introduktion til programmering og programmeringssproget C#

200

List<T>

24 List<T>Denne type kan bedst fortolkes som et dynamisk array, dvs. en type der på mange måder anvendes som et array, men som kan vokse dynamisk efter behov. Det er i modsætning til et almindeligt array, hvor man skal angive, hvor mange elementer der skal være plads til, når arrayet oprettes. Man må dog ikke drage sammenligningen alt for langt, og en anden fortolkning er at tænke på typen som en sekvens af elementer, hvor man hele tiden kan tilføje elementer til enden af listen. En List er således en struktur, der på et givet tidspunkt har en kapacitet, og så kan man tilføje elementer til enden af listen. Billedet kunne således være som vist herunder, hvor kapaciteten er 15, mens der er anvendt 8 pladser:

2 3 5 7 11 13 17 19

Man kan tilføje elementer, der hvor pilen peger, og hvis man på et tidspunkt overstiger kapaciteten, vil den automatisk blive udvidet. Det sker ved at kapaciteten fordobles.

HD – vejen tilen karrierei erhvervslivet

Læs mereAarhus: hd.au.dkHerning: auhe.au.dk/hd

LÆS HD I ØKONOMI OG LEDELSE

HD er en anerkendt diplom- uddannelse, som giver dig mulighed for at specialisere dig inden for det erhvervsøkonomiske fagområde ved siden af dit job.

Page 201: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

201

List<T>

Ud over at man kan tilføje elementer til slutningen af en List, tilbyder klassen en række andre metoder, f.eks. at man kan slette et element, indsætte et element på en bestemt plads osv. Internt er en List et array, og det betyder også, at man skal være opmærksom på kompleksiteten af de forskellige metoder. En List kan ikke have tomme pladser, og det betyder, at hvis man f.eks. sletter et element, skal alle elementer til højre for det der slettes rykkes en plads til venstre. Tilsvarende, hvis man indsætter et element. Så skal alle elementer til højre for det sted, hvor elementet indsættes, rykkes en plads til højre for at give plads til det nye element. I modsætning hertil er Add(), der tilføjer et element til slutningen af listen, særdeles effektiv, da den umiddelbart kan placere elementet det sted, hvor pilen peger - bortset fra den situation hvor det er nødvendigt at fordoble kapaciteten.

Exam45 List af strenge

Som et eksempel er herunder vist en metode, der opretter en list til strenge:

static void Main(string[] args){List<string> navne = new List<string>();Console.WriteLine(navne.Capacity);navne.Add(“Svend”);Console.WriteLine(navne.Capacity);navne.Add(“Knud”);navne.Add(“Valdemar”);Console.WriteLine(navne.Capacity);Console.WriteLine(navne.Count);navne.Insert(0, “Olga”);navne.Insert(0, “Gudrun”);Console.WriteLine(navne.Capacity);Console.WriteLine(navne.Count);navne.Remove(“Knud”);navne.RemoveAt(1);Console.WriteLine(navne.Capacity);Console.WriteLine(navne.Count);for (int i = 0; i < navne.Count; ++i) Console.WriteLine(navne[i]);

}

Page 202: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

202

List<T>

Forklaring

Først printes listens kapacitet, der i starten er 0. Det er dog muligt at oprette en list, hvor man som en parameter til konstruktøren angiver startkapaciteten. Efter der er tilføjet et element, printes kapaciteten igen. Den er nu 4, der betyder, at første gang der tilføjes et element til listen, afsættes der plads til 4 elementer. Efter der er tilføjet endnu to elementer, printes kapaciteten igen samt antallet af elementer, der er hhv. 4 og 3, hvilket ikke er overraskende. Som næste step indsættes to elementer i starten af listen (på plads 0) med metoden Insert(). Kapaciteten er herefter 8 (er fordoblet) og antallet af elementer er 5. Dernæst slettes to elementer, hvorefter kapaciteten stadig er 8. Det er værd at bemærke, at en List ikke automatisk skrumper. Den sidste for løkke printer listens elementer, og det vigtige er her at bemærke, at man kan anvende indeksoperatoren.

Bemærkning

Af de collection klasser, der er nævnt ovenfor, er en List den hyppigst anvendte, og den anvendes grundlæggende, når man ikke har muligheder for at estimere størrelsen af et array.

Exam68 Indtast varesalg

Målet med dette eksempel er at vise endnu en anvendelse af en List.

Der skal skrives et program, hvor brugeren kan indtaste oplysninger om et varesalg. Der skal indtaste en række oplysninger (registreringer) bestående af et månedsnummer og et varebeløb, og det gentages indtil der ikke er flere oplysninger. Indtastningsgrundlaget kunne således f.eks. være

Måned Beløb5 8008 10003 1205 2003 7005 1500....

Dvs. at tallene kan komme i vilkårlig rækkefølge for måned, og der kan være flere beløb for den samme måned.

Efter indtastningen skal programmet printe en oversigt, der for hver måned viser en linje for hvert varesalg samt det totale salg - dvs. summen af alle varebeløb for den aktuelle måned.

Page 203: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

Click on the ad to read more

C# 1: Introduktion til programmering og programmeringssproget C#

203

List<T>

Fremgangsmåde

Grundlæggende kan opgaven nedbrydes i to delproblemer:

- Indtast - Print

En registrering består af et månedsnummer og et beløb, og jeg vil derfor starte med en type, som kan repræsentere en enkelt registrering:

struct Sale : IComparable<Sale>{public int month;public double value;

public int CompareTo(Sale sale){return month.CompareTo(sale.month);

}}

Da registreringerne kommer i vilkårlig rækkefølge, skal de gemmes et sted, inden resultatet kan tælles sammen, og hertil vil jeg bruge en list. Hver gang der er indtastet en registrering, vil jeg tilføje den til listen. Listen kan defineres på følgende måde:

������������� ����������������������������������������������� �� ���������������������������

������ ������ ������������������������������ ����������������������!���"���������������

�����#$%����&'())%�*+����������,����������-

.��������������������������������� ��

���������� ���������������� ������������� ���������������������������� �����������

The Wakethe only emission we want to leave behind

Page 204: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

204

List<T>

static List<Sale> sales = new List<Sale>();

Det første delproblem kan beskrives som:

gentag{indtast månedsnummerhvis måned == 0 så afslutindtast beløbtilføje et Sale objekt til listen

}

Indtastningsrutinen kan nu skrives i C# som:

static void AddSales(){while (true){Sale sale;sale.month = Enter.EnterInt(“Enter 1, 2, ..., 12 for month or 0 for stop”);if (sale.month == 0) break;if (sale.month >= 1 && sale.month <= 12){sale.value = Enter.EnterDouble(“Enter item amount”);sales.Add(sale);

}else Console.WriteLine(“Ulovlig værdi for måned...”);

}}

Så er der det andet delproblem. Tallene skal printes ordnet efter måned, så jeg vil starte med at sortere indholdet af listen efter måned, så jeg ved et gennemløb af listen kommer til tallene i den rigtige orden. Herefter er opgaven i princippet simpel og består primært i at opsummere månedstotalen og printe varebeløbene. Det sværeste er et få printet på de rigtige tidspunkter:

sæt sum = 0sålænge der er flere varesalg i listen gentag{hvis det er samme måned så{opsummer sum med varebeløbet

}ellers{print månedstotalenstart på en ny måned

}print varebeløbet

}

Page 205: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

205

List<T>

Algoritmen kan skrives i C# på følgende måde:

static void Print(){int month = 0;double sum = 0;foreach (Sale sale in sales){if (sale.month == month)sum += sale.value;

else{if (month > 0) Console.WriteLine(“Month {0, 2}{1, 12:F2}”, month, sum);sum = sale.value;month = sale.month;

}Console.WriteLine(“{0, 20:F2}”, sale.value);

}Console.WriteLine(“Month {0, 2}{1, 12:F2}”, month, sum);

}

Tilbage er der Main() metoden, og her er det eneste udestående at kunne sortere listen, men List klassen har en metode til formålet, der klarer det hele, når blot listens objekter implementerer interfacet IComparable, men det gælder jo netop for typen Sale:

static void Main(string[] args){AddSales();sales.Sort();Print();

}

Page 206: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

Click on the ad to read more

C# 1: Introduktion til programmering og programmeringssproget C#

206

List<T>

Forklaring

Hvad angår typen Sale er der ikke så meget at forklare udover endnu en gang at bemærke, at den implementerer interfacet IComparable, så Sale objekter kan sammenlignes og dermed sorteres. At typen er en struct i stedet for en class er der ikke nogen særlig begrundelse for udover endnu en gang at minde om en struct, samt at vise at en struct kan implementere et interface. Selv om der i denne sammenhæng ikke er nogen særlig fordel ved at anvende en struct, så er Sale faktisk en god kandidat til en struct, da typen alene består af to simple variabler.

Selve listen er defineret som en statisk variabel i klassen, og du skal primært bemærke, hvordan listen defineres til at indeholde Sale objekter. Bemærk også, hvordan den sorteres i Main().

Det vigtigste i metoden AddSales() er, hvordan man opretter Sale objekter (da Sale er en struct, er det ikke nødvendigt at oprette et objekt med new) og tilføjer dem til listen. Det meste af metoden har at gøre med indtastning, og hertil anvendes to indtastningsmetoder, som ikke er vist ovenfor. Du kan finde dem i den færdige kode.

I Print() metode er der to lokale variabler: - month til at holde styr på nummeret for den aktuelle måned - sum til at sammentælle totalen for en bestemt måned

Ellers består metoden af en loop over listens elementer, og her er det vigtigste at holde styr på, om der er skiftet måned. I givet fald skal totalen printes, og de to hjælpevariabler skal initialiseres for en ny måned.

We are a global specialist in energy management represented in more than 100 countries. We provide technology and integrated solutions to optimise energy usage across multiple market segments. We are more than 130,000 colleagues worldwide and 1.000 of us are situated in Denmark.

We invest in our employees, in the environment and in the future. Each year 5% of our revenue is allocated for research and development activities. In Schneider Electric you have many career paths to choose from – also internationally.

Would you like take on the challenge of transforming the way people and organisations use energy?

Do you know Schneider Electric?

Meet us at: www.schneider-electric.dk/job

Page 207: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

207

Stack<T> og Queue<T>

25 Stack<T> og Queue<T>En stak er en collection, der grundlæggende har to operationer

- man kan lægge et element på stakken, en operation der kaldes push - man kan fjerne det element, der sidst er lagt på stakken, en operation der kaldes pop

I forbindelse med værdityper og referencetyper har jeg flere steder omtalt programstakken. Det er et eksempel på en datastruktur, der er en stak. Man omtaler også undertiden datastrukturen som en LIFO (Last In First Out) struktur, svarende til at der kun er adgang det element, der sidst et lagt på stakken. Man tænker typisk på strukturen som en container, hvor man kan placere et element øverst, der hvor pilen peger, og hvor man kun kan fjerne det element, som pilen peger på - man stakker elementer ovenpå hinanden og deraf navnet.

7

5

3

2

En konkret implementering af typen, og det gælder også typen Stack<T> i C#, vil sædvanligvis også definere andre metoder. F.eks. en metode, så man kan referere til elementet øverst på stakken uden at fjerne det, og en metode så man kan teste om stakken er tom.

Exam46 Stak af heltal

Som eksempel er herunder vist et program, der opretter en stak til heltal og placerer 8 tal på stakken. Dernæst tømmes stakken, og tallene printes på skærmen:

static void Main(){Stack<int> s = new Stack<int>();s.Push(2);s.Push(3);s.Push(5);s.Push(7);

Page 208: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

208

Stack<T> og Queue<T>

s.Push(11);s.Push(13);s.Push(17);s.Push(19);while (s.Count > 0) Console.WriteLine(s.Pop());

}

Man skal bemærke, at tallene printes i omvendt orden af, hvordan de er lagt på stakken - det tal der sidst er lagt på stakken printes først.

Exam69 StackSort

Der er mange anvendelser af en stak, og i bogens sidste del vil jeg vise en typisk anvendelse. I dette eksempel vil jeg vise, hvordan en stak kan anvendes til at sortere et array.

Fremgangsmåde

Givet to stakke - i det følgende kaldet den venstre stak og den højre stak - kan man sortere et array på følgende måde:

for hvert element t i arrayet gentag{sålænge t er mindre end toppen af den venstre stak udfør{pop den venstre stak og push elementet på den højre stak

}sålænge t er større end toppen af den højre stak udfør{pop den højre stak og push elementet på den venstre stak

}push t på den venstre stak

}sålænge den venstre stak ikke er tom udfør{pop den venstre stak og push elementet på den højre stak

}loop over arrayet fra start til slut{pop den højre stak og indsæt elementet i arrayet

}

Page 209: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

Click on the ad to read more

C# 1: Introduktion til programmering og programmeringssproget C#

209

Stack<T> og Queue<T>

Det er ikke så let at gennemskue, at der faktisk er tale om en sortering, og det letteste er at gennemføre en skrivebordstest med et simpel eksempel. Givet et array med 8 elementer:

11 7 13 19 5 2 17 3

Herunder er illustreret, hvad der sker med de to stakke, når arrayet gennemløbes fra venstre mod højre:

venstre højre11 7

1319

5 2

17

3

venstre højre11 7

venstre højre

1113

7venstre højre

11

1913

7

venstre højre

11

5

1913

7

venstre højre

11

25

19

13

7

venstre højre

11

172

5

19

13

7

venstre højre

11

1. gennemløb

8. gennemløb7. gennemløb6. gennemløb5. gennemløb

4. gennemløb3. gennemløb2. gennemløb

Hvis man nu tømmer den venstre stak over på den højre, indeholder den alle elementerne sorteret i stigende orden.

Vil du også stå på ski i fremtiden?

Verden har brug for nye løsninger, og Topsøe har de katalysatorer og teknologier, der kan løse centrale udfordringer på den globale agenda: verdens energi- og miljøudfordringer.

Vi har fart på. Vores løsninger skal fortsat udvikles, udbredes og implementeres på det globale marked. Derfor vil vi gerne have endnu flere kolleger, som vil være med til at skabe værdi og fremdrift.

Du får mulighed for fordybelse, kundekontakt og rejseaktivitet. Og adgang til en verden af viden.

Vi arbejder i en fri og uformel atmosfære. Vi er stolte af at tage ansvar og bidrage til et bedre miljø.

Vil du være med?

WWW.TOPSOE.COM/JOBS

Need for speed?

Page 210: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

210

Stack<T> og Queue<T>

Herunder er vist, hvordan algoritmen kan skives som en generisk metode i C#:

class Program{static void Main(string[] args){int[] v = { 23, 17, 7, 19, 29, 2, 11, 5, 3, 13 };Print(v);Sort(v);Print(v);

}

static void Sort<T>(T[] arr) where T : IComparable<T>{Stack<T> s1 = new Stack<T>();Stack<T> s2 = new Stack<T>();foreach (T t in arr){while (s1.Count > 0 && s1.Peek().CompareTo(t) > 0) s2.Push(s1.Pop());while (s2.Count > 0 && s2.Peek().CompareTo(t) < 0) s1.Push(s2.Pop());s1.Push(t);

}while (s1.Count > 0) s2.Push(s1.Pop());for (int i = 0; i < arr.Length; ++i) arr[i] = s2.Pop();

}

static void Print<T>(T[] arr){Console.Write(arr[0]);for (int i = 1; i < arr.Length; ++i) Console.Write(“ “ + arr[i]);Console.WriteLine();

}}

Forklaring

Algoritmen er implementeret af metoden Sort(). Du skal bemærke, at det er en generisk metode, og at parametertypen er IComparable. Det er nødvendigt, for at elementerne kan ordnes (sammenlignes). Bemærk også, at klassen Stack har en property Count, som angiver antallet af elementer på stakken. Alle collection klasser har denne property. I dette eksempel anvendes Count til at undersøge om stakken er tom. En Stack har også en metode, som hedder Peek(). Den anvendes til at referere til det element, som ligger på toppen af stakken, men uden at fjerne det.

Bemærkning

Ovenstående sorteringsmetode er simpel og fylder ikke meget, men den er ikke særlig effektiv, og den er alene medtaget her som et eksempel på anvendelse af en stak samt for algoritmens egen skyld. Problemet med algoritmen er, at der sker for mange flytninger af elementer mellem de to stakke.

Page 211: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

211

Stack<T> og Queue<T>

Hvis en stak er en LIFO datastruktur, er en kø en FIFO (First In First Out) datastruktur, hvor det altid er det første (det ældste) element, der fjernes fra køen. Billedet af en kø er noget i retning af følgende

2 3 5 7 11 13 17 19

head tail

hvor man indsætter (tilføjer til køen) det sted som tail pilen peger, og fjerner fra køen det sted som head pilen peger. Klassen Queue<T> repræsenterer en kø, og de to grundlæggende operationer for at indsætte og fjerne elementer hedder hhv. Enqueue() og Dequeue(). Som eksempel er herunder vist et program, der opretter en kø:

static void Main(){Queue<int> q = new Queue<int>();q.Enqueue(2);q.Enqueue(3);q.Enqueue(5);q.Enqueue(7);q.Enqueue(11);q.Enqueue(13);q.Enqueue(17);q.Enqueue(19);while (q.Count > 0) Console.WriteLine(q.Dequeue());

}

I praksis er der ikke så mange anvendelser af en kø som en stak.

Page 212: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

Click on the ad to read more

C# 1: Introduktion til programmering og programmeringssproget C#

212

LinkedList<T>

26 LinkedList<T>Ovenfor har jeg behandlet typen List<T> som en sekvens af elementer. Dens vigtigste egenskab er, at man kan tilføje elementer til den, og den vil udvide sig efter behov, og det er endda sådan, at tilføje elementer til slutningen af listen er særdeles effektiv. Den har dog også et par ulemper. For det første er indsættelse eller sletning af elementer midt i listen ikke særlig effektiv, da alle efterfølgende elementer skal flyttes. For det andet kan det at listen udvider sig ved fordobling betyde, at der kan være et stort pladsspil, og det tager tid at oprette et nyt array og kopiere indholdet af det gamle til det nye. Betragt som eksempel følgende metode:

static void Main(){List<int> list = new List<int>();for (int i = 0; i <= 1048576; ++i) list.Add(i);Console.WriteLine(list.Capacity);Console.WriteLine(list.Count);

}

IFRS 2012, Standarder og fortolk-ningsbidrag – på dansk fås nu både som trykt bog samt som e-bog til smartphone, tablet og pc.

Introduktionspris: e-bog og trykt bog kr. 1545,-

E-bog inkl. opdateringer i 2012

Læs mere og køb e-bogen sammen med den trykte bog her: shop.magnus.dk

REGNSKABIFRS 2012 – nu også som e-bog

– Nuogså som

e-bog

Page 213: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

213

LinkedList<T>

Listen indeholder 1048577 elementer, men har desuden 1048575 pladser, der ikke anvendes. Det er her en LinkedList (en hægtet liste) kommer ind i billedet som en list, der allokere hukommelse på en anden måde. Idéen er, at der til hvert element knyttes to referencer, som kan referere til hhv. det foranstående og det efterfølgende element. Man kan tænke på en hægtet liste som følgende struktur

7 3 11 2 5

start end

hvor der er en reference til starten af listen og en reference til slutningen af listen. Det enkelte element (kasse) i listen kaldes sædvanligvis for en node. Denne struktur løser problemet med indsættelse og sletning, da man kan indsætte et nyt element midt i listen ved blot at ændre nogle referencer, og på samme måde kan man fjerne et element. På figuren herunder er vist, hvordan det set ud, hvis man indsætter et element med værdien 13 mellem 3 og 11 - det er nødvendigt at ændre 4 referencer:

7 3 11 2 5

start end

13

Herunder er på samme måde vist, hvor det ser ud, hvis man fjerner elementet 3. Det er nødvendigt at ændre to referencer, og der er herefter ingen referencer til elementet 3, hvorfor det automatiske nedlægges.

7 3 11 2 5

start end

Til gengæld er problemet med pladsforbruget ikke løst, for godt nok er der ikke længere allokeret plads til elementer, der ikke anvendes, men til gengæld er der til hvert element knyttet to ekstra referencer, som også tager plads.

En hægtet liste løser problemet med indsættelse og sletning midt i listen, men til gengæld kan man ikke direkte referere til de enkelte elementer med et indeks. Der et nødvendigt at søge fra starten (eller slutningen) af listen, indtil man finder det element, som man er interesseret i.

Klassen LinkedList implementerer en hægtet liste, og den adskiller sig fra klassen List ved at have andre metoder.

Page 214: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

214

LinkedList<T>

Exam48 LinkedList af navne

Herunder er vist, hvordan man kan oprette en LinkedList og placere elementer i den:

static void Main(string[] args){LinkedList<string> list = new LinkedList<string>();list.AddLast(“Svend”);list.AddLast(“Knud”);list.AddLast(“Valdemar”);list.AddAfter(list.Find(“Knud”), “Karlo”);list.AddBefore(list.Find(“Karlo”), “Frede”);list.AddFirst(”Gudrun”);Print1(list);list.AddFirst(”Olga”);list.AddFirst(”Abelone”);Print2(list);Print3(list);

}

static void Print1(LinkedList<string> list){foreach (string name in list) Console.WriteLine(name);Console.WriteLine(”-----------------”);

}

static void Print2(LinkedList<string> list){for (LinkedListNode<string> node = list.Last; node != null; node = node.Previous)Console.WriteLine(node.Value);

Console.WriteLine(”-----------------”);}

static void Print3(LinkedList<string> list){for (int i = 0; i < list.Count; ++i) Console.WriteLine(list.ElementAt(i));Console.WriteLine(“-----------------”);

}

Forklaring

Der er fire måder til at indsætte et element

1. indsæt i slutningen af listen2. indsæt i starten af listen3. indsæt efter et eksisterende element4. indsæt før et eksisterende element

Vedr. de sidste skal du bemærke, hvordan man med metoden Find() finder det element, der skal indsættes relativ til. Den returnerer en LinkedListNode, som er en struktur svarende til en node.

Page 215: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

215

LinkedList<T>

Bemærk de tre Print() metoder. Den første er der ikke meget at sige til, da den printer listen med en sædvanlig foreach løkke. I den anden metode anvendes en property til få en reference til den sidste node - bemærk igen typen LinkedListNode. Dernæst gennemløbes listen bag fra. I en LinkedList kan man ikke referere elementerne med et indeks, men der findes en metode ElementAt(), som giver det samme resultat. Det viser den sidste printmetode. Bemærk, at ElementAt() i virkeligheden tæller fra starten af listen og frem, så det er ikke nogen hensigtsmæssig løsning på print problemet.

Bemærkning

Om man skal anvende en LinkedList eller en List er bestemt af opgaven, da begge datastrukturer har deres fordele og ulemper. Der er dog ingen tvivl om, at en List er den hyppigst anvendte.

Page 216: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

Click on the ad to read more

C# 1: Introduktion til programmering og programmeringssproget C#

216

Dictionary<K,V> og SortedDictionary<K,V>

27 Dictionary<K,V> og SortedDictionary<K,V>

Et dictionary er en collection, hvor de enkelte elementer er identificeret af en nøgle. Derfor omtaler man også undertiden et dictionary som en collection af key/value par, idet hver value er identificeret af en key. Man kan godt sammenligne et dictionary med en list, for i en list er elementerne identificeret af et indeks. Når man skal finde et element i listen, søger man ikke efter elementet, men man beregner dens plads ud fra indekset. På samme måde er det med et dictionary, at når man skal finde et element, så beregner man elementets plads ud fra nøglens værdi - man søger ikke efter elementet. Den følgende figur skal illustrere lidt af teknikken, hvor man gemmer key/value par bestående af postnummer og bynavn:

Page 217: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

217

Dictionary<K,V> og SortedDictionary<K,V>

Hobro

Blokhus

Gjern

Klovborg

Frederiksberg

0

1

2

3

4

5

6

7

8

9

9500

9492

8883

8765

1808

Der er brug for funktion, der kan omregne et postnummer til en plads i containeren. En sådan funktion kaldes sædvanligvis for en hash funktion, og i stedet for dictionary omtaler man ofte strukturen som en hashtabel. I dette tilfælde skal hash funktionen være simpel, og den består blot i at tage det sidste ciffer. F.eks. skal (9492, Blokhus) gemmes på plads 2, da postnummeret slutter med 2. Tilsvarende skal (8765, Klovborg) gemmes på plads 5, og (8883, Gjern) gemmes på plads 3.

Ovenstående er naturligvis meget simplificeret, men det illustrerer to helt fundamentale problemer:

- Hvad gør man hvis strukturen fyldes op og skal udvides - ovenfor er der jo kun plads til 10 elementer.

- Hvad gør man hvis der kommer en kollision - med ovenstående hash funktion skal (8543, Hornslet) gemmes på samme plads som Gjern.

Jeg skal ikke her komme ind på, hvordan man løser disse problemer, men blot nævne, at det er problemer som en implementering af strukturen nødvendigvis må løse.

Klassen Dictionary er en collection klasse til et dictionary eller en hashtabel.

Exam49 Tabel over stillingsbetegnelser

Herunder er vist et eksempel, hvor nøglen er et navn, mens værdien er en stillingsbetegnelse:

static void Main(){Dictionary<string, string> map = new Dictionary<string, string>();map.Add(“Knud”, “Konge”);

Page 218: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

218

Dictionary<K,V> og SortedDictionary<K,V>

map.Add(“Gudrun”, “Heks”);map.Add(“Svend”, “Kriger”);map.Add(“Olga”, “Spåkone”);map.Add(“Valdemar”, “Skarpretter”);map.Add(“Abelone”, “Klog kone”);Print1(map);map[“Gudrun”] = “Sin mands kone”;Print1(map);Print2(map);Print3(map);

}

static void Print1(Dictionary<string, string> map){for (int i = 0; i < map.Count; ++i) Console.WriteLine(map.ElementAt(i));Console.WriteLine(”-----------------”);

}

static void Print2(Dictionary<string, string> map){foreach (string name in map.Keys) Console.WriteLine(map[name]);Console.WriteLine(”-----------------”);

}

static void Print3(Dictionary<string, string> map){

foreach (string job in map.Values) Console.WriteLine(job);Console.WriteLine(“-----------------”);

}

Forklaring

Bemærk først, hvordan man tilføjer værdier til et dictionary. Bemærk dernæst den første printmetode, hvor man printer key/value par. Nøglerne skal være entydige, og hvis man forsøger at tilføje en værdi med en eksisterende nøgle, får man en exception. Man kan imidlertid ændre en værdi ved at anvende nøglen som indeks:

map[“Gudrun”] = “Sin mands kone”;

Bemærk endelig de to sidste print metoder, hvor man dels løber over alle nøgler, og dels over alle værdier. Her skal du bemærke, hvordan man får en collection med alle nøgler (metoden Print2()) og en collection med alle værdier (metoden Print3()).

Udføres metoden, får man følgende resultatet:

Page 219: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

Click on the ad to read more

C# 1: Introduktion til programmering og programmeringssproget C#

219

Dictionary<K,V> og SortedDictionary<K,V>

Exam50 Brugerdefineret nøgle

I et dictionary kan typerne for både nøgle og værdi være hvad som helst - næsten. Betragt følgende type:

Tænker du også på fremtidens vand?

Så bliv en del af Nordens mest kompetente medarbejderstab specialiseret i vand.

Service | Value | Respo

nsib

ility

Vil du med på holdet?

Tjek vores jobside for ledige

stillinger og upload dit CV på

www.kruger.dk/da/job

Foto

: K

rüg

er

Sta

fett

en

rrn

ddn

dddn

dn

dddu

ndd

un

t o

t o

to

t ooo

t ooo

t o ot o

to

t ooo ooot ooo

t o

t o

too

t o

tm

CCm

Cm

Cm

CCm

Cm

Cm

CCm

CCm

Cm

Cm

CCm

CCCCCCCm

CCm

Cm

Cm

Cm

Cm

Cm

Cm

Cm

Cm

CCCmmmmmmmmmmmmmmmmm

hririiri

hri

hri

hri

hri

hririirii

hri

hriiiii

hri

hri

hri

hriiiirrr

hrr

hr

hr

hr

hrrrrrrrrrrrrrrrrrrr

hr

hrrrr

hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhst

ist

ist

ist

ist

ist

ist

ist

ist

ist

ist

ist

ist

ist

ist

ist

ist

ist

ist

ist

ist

ist

ist

ist

ist

ist

itisti

sti

sti

sti

sti

sti

stititistiiii

sti

sti

stii

sti

sti

sti

sti

sti

stiii

stii

stitistii

stii

sti

sstststststtsssssssssssn

sn

ssssssssn

sn

sa

ns

nssss

nss

ns

nss

an

sa

nss

nssss

an

sn

ssssa

ns

ns

an

sa

ns

an

ssn

ssa

nss

an

sa

ns

an

sa

nss

an

sa

ns

an

sa

ns

an

ssa

na

na

na

na

nnnnnna

na

na

nnnnna

nnnnnnnnna

nnnna

nna

na

nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnna

nnnnnnnnaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa

or

or

or

or

or

or

orr

or

or

orr

or

orrr

or

or

or

or

or

orr

orr

orr

or

orr

or

or

orr

oooooob

ooob

ob

oob

oob

ooobbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb

ggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggg

Page 220: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

220

Dictionary<K,V> og SortedDictionary<K,V>

public class Name{private string firstname;private string lastname;

public Name(string firstname, string lastname){this.firstname = firstname;this.lastname = lastname;

}

public override string ToString(){return firstname + “ “ + lastname;

}}

Betragt dernæst et dictionary, der har typen Name som nøgle:

static void Main(string[] args){Dictionary<Name, string> map = new Dictionary<Name, string>();map.Add(new Name(“Knud”, “Madsen”), “Konge”);map.Add(new Name(”Gudrun”, ”Jensen”), ”Heks”);map.Add(new Name(“Svend”, “Andersen”), “Kriger”);map.Add(new Name(”Olga”, ”Olesen”), ”Spåkone”);map.Add(new Name(“Gudrun”, “Jensen”), “Sin mands kone”);Print(map);

}

static void Print(Dictionary<Name, string> map){for (int i = 0; i < map.Count; ++i) Console.WriteLine(map.ElementAt(i));Console.WriteLine(“-----------------”);

}

Bemærk, at det kan oversættes og køre, men resultatet er ikke som forventet, da nøgle Gudrun Jensen forekommer to gange:

Årsagen er, at typen Name ikke overstyrer GetHashCode(). Som nævnt bygger et dictionary på en hashfunktion til beregning af de enkelte elementers plads, som igen anvender typens GetHashCode(). Nøgletypen skal derfor altid overstyre GetHashCode():

Page 221: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

221

Dictionary<K,V> og SortedDictionary<K,V>

public class Name{...

public override int GetHashCode(){return firstname.GetHashCode() + lastname.GetHashCode();

}}

Exam51 Et ordnet dictionary

Et dictionary garanterer generelt ikke noget om, hvordan elementerne er ordnet, og i hvilken orden de mødes ved en traversering af strukturen. I modsætning hertil er en SortedDictionary et dictionary, hvor elementerne er ordnet efter nøglen:

static void Main(){SortedDictionary<string, string> map = new SortedDictionary<string, string>();map.Add(“Knud”, “Konge”);map.Add(“Gudrun”, “Heks”);map.Add(“Svend”, “Kriger”);map.Add(“Olga”, “Spåkone”);map.Add(“Valdemar”, “Skarpretter”);map.Add(“Abelone”, “Klog kone”);foreach (string navn in map.Keys) Console.WriteLine(“{0}, {1}”, navn, map[navn]);

}

Dvs. at resultatet er sorteret efter nøglen, som er navn, og bemærk at det ikke er samme rækkefølge som objekterne er tilføjet strukturen.

Exam52 Sammenlignelige nøgler

Følgende vil ikke umiddelbart virke (man får en exception):

static void Test11(){SortedDictionary<Name, string> map = new SortedDictionary<Name, string>();map.Add(new Navn(“Knud”, “Madsen”), “Konge”);map.Add(new Navn(“Gudrun”, “Jensen”), “Heks”);

Page 222: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

Click on the ad to read more

C# 1: Introduktion til programmering og programmeringssproget C#

222

Dictionary<K,V> og SortedDictionary<K,V>

map.Add(new Navn(“Svend”, “Andersen”), “Kriger”);map.Add(new Navn(“Olga”, “Olesen”), “Spåkone”);foreach (Navn navn in map.Keys) Console.WriteLine(“{0}, {1}”, navn, map[navn]);

}

For at nøglerne kan sorteres, skal de kunne sammenlignes, og det vil sige, at nøgletypen skal implementere interfacet IComparable:

public class Name : IComparable<Name>{...

public int CompareTo(Name name){if (lastname.CompareTo(name.lastname) == 0)return firstname.CompareTo(name.firstname);

return lastname.CompareTo(name.lastname);}

}

Her sorteres, så der først sammenlignes på efternavn, og er efternavnene ens, sammenlignes der på fornavn.

Jeg udvikler og udviklesPrevas startede i 1985 og er i dag hovedleverandør og udviklingspartner til førende virksomhederindenfor Life Science, telecom, automotive, forsvar, energi og fremstillingsindustrien. Vi er mereend 500 ingeniører som brænder for at finde effektive løsninger for vores kunder. ”Innovation for Growth” er vores mantra.Hos Prevas møder du kompetente og spændende mennesker hver dag. Det kan være dine nyekollegaer eller det kan være vores kunders medarbejdere. Hos os får du mulighed for at arbejdemed nye teknologier i mange forskellige brancher for spændende virksomheder.Som medarbejder hos Prevas kommer du derfor altid til at udvikles - så længe du selv vil.

iNNovATioN For groWTHwww.prevas.com

Page 223: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

223

Dictionary<K,V> og SortedDictionary<K,V>

Bemærkning

En SortedDictionary er internt et binært søgetræ, og uden at jeg på dette sted skal uddybe hvad det er, kan jeg nævne, at det er en struktur, som optimerer søgning på elementer. Der findes faktisk endnu en collection klasse

SortedList<K, V>

der set fra programmøren er det samme som en SortedDictionary, men internt også er et binært søgetræ. Forskellen er, at en SortedList bruger mindre hukommelse end en SortedDictionary, og omvendt er en SortedDictionary mere effektiv mht. indsættelse og sletning af elementer.

Exam70 Stikordsliste

I dette eksempel vil jeg vise, hvordan man kan repræsentere en stikordsliste til en bog. Formålet er primært at vise, hvordan man kan anvende et SortedDictionary, men også en LinkedList.

Et stikord består af et navn og et antal sidereferencer, hvor et navn er en streng, mens en sidereference er et heltal, og en stikordsliste er en liste af stikord. Opgaven er at skrive et program, som kan oprette en stikordsliste og printe listen på skærmen.

Fremgangsmåde

Jeg vil starte med at definere en klasse, som kan repræsentere et stikord bestående af et navn og sidereferencer:

public class PageReferences{private string name;private LinkedList<int> list = new LinkedList<int>();

public PageReferences(string name, int page){this.name = name;list.AddFirst(page);

}

public string Name{get { return name; }

}

Page 224: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

224

Dictionary<K,V> og SortedDictionary<K,V>

public int Count{get { return list.Count; }

}

public int this[int n]{get { return list.ElementAt(n); }

}

public int[] References{get { return list.ToArray(); }

}

public void Add(int page){for (LinkedListNode<int> node = list.First; node != null; node = node.Next)if (node.Value == page) return;else if (node.Value > page){list.AddBefore(node, page);return;

}list.AddLast(page);

}

public override string ToString(){StringBuilder builder = new StringBuilder(name + “,”);for (LinkedListNode<int> node = list.First; node != null; node = node.Next)builder.Append(“ “ + node.Value);

return builder.ToString();}

}

Jeg vil opbevarer stikordene i et SortedDictionary med navnet som nøgle. Det giver to fordele:

- listen kan gennemløbes og dermed printes ordnet efter navnet - man kan finde siderefenrencer til et bestemt stikord uden at søge, men ved direkte opslag

Når der skal sammenlignes på nøgler, er jeg ikke interesseret i, at der skal skelnes mellem store og små bogstaver. Derfor har jeg skrevet min egen nøgletype:

class PageKey : IComparable<PageKey>{private string name;

public PageKey(string name){this.name = name;

}

Page 225: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

Click on the ad to read more

C# 1: Introduktion til programmering og programmeringssproget C#

225

Dictionary<K,V> og SortedDictionary<K,V>

public string Value{get { return name; }

}

public override bool Equals(object obj){if (!(obj is string)) return false;return name.Equals((string)obj, StringComparison.CurrentCultureIgnoreCase);

}

public override int GetHashCode(){return name.ToUpper().GetHashCode();

}

public int CompareTo(PageKey key){return string.Compare(name, key.name, true);

}}

Herefter kan klassen til stikordslisten skrives:

Dine fordele ved forsikring hosPantaenius

DEN

10083 w

ww

.hqh

h.de

04/2

012

Østerbro 11 · 7800 SkiveTel. +45-9751 3388 · [email protected]

www.pantaenius.dk

Hjælp ved uheld

Du har behov for bugsering til nærmeste værft?Pantaenius overtager omkostningerne dog begrænset op til DKK 37.500,00!

Kontakt osHar du spørgsmål til dine forsikringer?Du kan ringe +45-9751 33 88 eller skrive til os på e-mail [email protected]

Inspektionsomkostninger

Du har haft en grundstødning og vil have bunden inspiceret?Pantaenius dækker inspektionen uden selvrisiko!

Ingen selvrisiko

Indbrud, transportskade, brand, lynnedslag eller totalskade?Ved disse skadesårsager er der ingen selvrisiko hos Pantaenius!

Page 226: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

226

Dictionary<K,V> og SortedDictionary<K,V>

class Index{private SortedDictionary<PageKey, PageReferences> table =new SortedDictionary<PageKey, PageReferences>();

public bool Add(string name, int page){name = name.Trim();if (name.Length == 0) return false;PageKey key = new PageKey(name);if (table.ContainsKey(key)) table[key].Add(page); else table.Add(key, new PageReferences(name, page));return true;

}

public int[] Pages(string name){PageKey key = new PageKey(name);if (table.ContainsKey(key)) return table[key].References;else return new int[0];

}

public void Print(){char ch = ‘ ‘;foreach (PageKey key in table.Keys){PageReferences pages = table[key];if (ch != char.ToUpper(pages.Name[0])){ch = char.ToUpper(pages.Name[0]);Console.WriteLine(ch);

}Console.WriteLine(pages);

}}

}

Forklaring

Der er denne gang en del af bemærke. Hvis man starter med klassen PageReferences, skal du bemærke, at listen til sidetal er en LinkedList. Årsagen er, at jeg vil indsætte sidetallene i stigende orden, hvilket sker i metoden Add(). Listen oprettes i konstruktøren, og når Add() metoden udføres, vil listen derfor altid indeholde mindst én sidereference. Add() metoden gennemløber sidereferencerne til det aktuelle stikord. Hvis sidereferencen allerede er der, sker der ikke andet, end indsættelsen ignoreres (det samme sidetal skal ikke forekomme flere gange). Finder man en sidereference, som er større end den nye reference, skal det indsættes foran det element, som man er nået til, og man har dermed opnået, at listen med sidereferencer er ordnet. Hvis man når gennem listen, uden at den nye reference er indsat, skyldes det, at referencen skal indsættes som den sidste reference i listen.

Page 227: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

227

Dictionary<K,V> og SortedDictionary<K,V>

Ud over metoden Add() har klassen PageReferences forskellige properties. Bemærk bl.a., at der er en overstyring af indeksoperatoren (som ikke anvendes i eksemplet). Bemærk også propertyen References, der returnerer et array med sidetal. Dette array dannes med LinkedList klassens ToArray() metode. Alle collection klasser har denne metode.

Klassen PageKey definerer nøglen som en indkapsling af en string. Bemærk, hvordan klassen implementerer interfacet IComparable, så sammenligningen ikke skelner mellem store og små bogstaver (det angiver den sidste parameter). Bemærk også, at Equals() heller ikke skelner mellem store og små bogstaver, samt at GetHashCode() også er implementeret.

Endelig er der klassen Index, som er stikordlisten. Klassen stiller tre services til rådighed: - Man kan tilføje et nyt stikord til listen, som enten indsætter et nyt ord eller opdaterer et

eksisterende. - Man kan få et array med sidereferencer til et bestemt ord, og her skal du især bemærke syntaksen

for, hvordan man opretter et tomt array, hvis det pågældende ord ikke findes. - Man kan printe listen på skærmen, som i princippet blot er et spørgsmål om at gennemløbe

listen i den orden, som nøglerne angiver.

Test

Til slut vil jeg vise et testprogram:class Program{static Random rand = new Random();static string[] words = { “Write”, “if”, “for”, “while”, “Variable”, ..... };

static void Main(string[] args){Index index = new Index();for (int i = 0; i < 50; ++i) index.Add(words[rand.Next(words.Length)], rand.Next(200));

index.Print();Console.WriteLine();Print(“Variable”, index.Pages(“Variable”));Print(“variable”, index.Pages(“variable”));Print(“Variables”, index.Pages(“Variables”));

}

static void Print(string name, int[] pages){Console.Write(name);if (pages.Length > 0){Console.Write(“, “);for (int i = 0; i < pages.Length; ++i) Console.Write(“ “ + pages[i]);

}Console.WriteLine();

}}

Page 228: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

Click on the ad to read more

C# 1: Introduktion til programmering og programmeringssproget C#

228

Dictionary<K,V> og SortedDictionary<K,V>

I starten er der defineret nogle ord. Disse indsættes herefter tilfældigt i en stikordsliste med tilfældige sidereferencer:

Get “Bookboon’s Free Media Advice” Email [email protected]

See the light! The sooner you realize we are right, the sooner your life will get better!

A bit over the top? Yes we know!

We are just that sure that we can make your media activities more effective.

Page 229: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

229

IO

Del 4 IOTidligere var filer et centralt begreb inden for programmering, og selv om det ikke spiller den samme rolle som tidligere, er det stadigt vigtigt at vide, hvordan man kan skrive til og læse fra en fil.

Når IO og filer ikke spiller den samme rolle som før, skyldes det, at applikationer med behov for at manipulere persistente data gemt på disk sædvanligvis anvender database produkter, og alt vedr. tilgang til filer og adgang til data er dermed overladt til det aktuelle databasesystem. Ikke desto mindre er der stadig situationer, hvor der er behov for at kunne tilgå almindelige filer, og det drejer sig især om to situationer, nemlig hvordan man læser og skriver en almindelig tekstfile, samt hvordan man serialiserer og deserialiserer et objekt.

Som overalt i .NET er adgang til filer lettet for programmøren gennem et antal færdige klasser, som primært findes i namespacet System.IO. Det er et omfattende namespace med mange klasser, men heldigvis er det ikke nødvendigt at have kendskab til dem alle, så jeg vil koncentrere mig om dem, der som minimum er nødvendige.

Set fra et program er en file grundlæggende en sekvens af bytes, og på mange måder kan man tænke på en file som et 1-dimensionalt array uden nogen øvre grænse (størrelsen er naturligvis begrænset af den plads, der er til rådighed på disken). Det sted, hvor næste fileoperation (læsning eller skriving) udføres, er bestemt af en såkaldt filepointer, som egentlig blot er en tæller relativ til filens start. Svarende hertil kan man illustere en file på følgende måde, hvor hver kasse er en byte:

Offset for næste læsning/skrivning

Set fra et program er udfordringen at styre hvor der læses og skrives i filen, samt at fortolke det resultat der læses og konvertere det til det korrekte dataformat. Det er faktisk alt det som klasserne i IO-systemet og deres metoder indkapsler.

Page 230: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

230

Tekstfiler

28 TekstfilerEn tekstfile er en file, som indeholder et antal linjer, hvor hver linje er en streng. Da strenge i .NET repræsenteres som unicode sekvenser af tegn, skal der for hvert tegn skrives 2 bytes til filen, men det er indkapslet af IO-systemet. Tekstfiler er stadig vigtige. F.eks. anvendes tekstfiler ofte til udveksling af data i form af kommaseparerede filer eller tilsvarende. Man bør også være opmærksom på, at f.eks. HTML-filer eller XML-filer er tekstfiler.

Exam51 Skriv og læs tekst

Jeg vil skrive et program, der viser, hvordan man skriver og læser en simpel tekstfil. Når programmet kører, skal brugeren indtaste tekstlinjer, og de gemmes i en fil. Indtastningen afsluttes, når brugeren blot taster Enter, og herefer læses filen og indholdet printes på skærmen.

Fremgangsmåde

At oprette en tekstfil og skrive til den kan beskrives som følgende algoritme:

åbn/opret filenskaf datasålænge der er dataskrive linje i filenskaf data

luk filen

og det vigtige er, at det faktisk sker på den samme måde hver gang, og det bare er operationen skaf data som kan variere. På sammen måde kan læsning af en tekstfil skrives som følgende algoritme:

åbn filenlæs liniesålænge der er en linjeanvend linjenlæs linie

luk filen

og her er det igen vigtig at bemærke, at fremgangsmåden er den samme uanset indholdet af filen, og det alene er operationen anvend linje, som varierer.

Programmet kan således skrives på følgende måde:

using System;using System.IO;

namespace Exam53{class Program{static void Main(string[] args)

Page 231: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

231

Tekstfiler

{Write();Read();

}

public static string GetLine(){Console.Write(“? “);return Console.ReadLine();

}

public static void PutLine(string line){Console.WriteLine(line);

}

public static void Write(){StreamWriter writer = new StreamWriter(“Tekst.txt”);string line = GetLine();while (line.Length > 0){writer.WriteLine(line);line = GetLine();

}writer.Close();

}

public static void Read(){StreamReader reader = new StreamReader(“Tekst.txt”);string line = reader.ReadLine();while (line != null){PutLine(line);line = reader.ReadLine();

}reader.Close();

}}

}

Forklaring

Bemærk først, at der er en using sætning til System.IO. Det vil der typisk være i alle programmer, som anvender filer.

Metoden GetLine() svarer til skaf data i algoritmen, og den skriver en simpel prompt i form af et spørgsmålstegn på skærmen, og dernæst udføres en ReadLine(). Metoden returnerer en streng med brugerens indtastning.

Metoden Write() opretter og åbner en tekstfil for skrivning:

Page 232: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

Click on the ad to read more

C# 1: Introduktion til programmering og programmeringssproget C#

232

Tekstfiler

StreamWriter writer = new StreamWriter(“Tekst.txt”);

Filen hedder Tekst.txt og oprettes i samme bibliotek som programmet. Filens navn er parameter til konstruktøren til en klasse af typen StreamWriter, som repræsenterer en tekstfile, hvortil man kan skrive. Man kan angive en fuld sti til filen, hvis man ønsker at den skal placeres et andet sted. Efter at brugeren har indtastet en linje, skrives den til filen ved hjælp af writeren og metoden WriteLine():

writer.WriteLine(line);

Bemærk, at denne metode har de samme egenskaber som den tilsvarende metode i Console, og at man dermed også kan printe en formateret tekst til en fil.

Efter at løkken er afsluttet, lukkes filen.

Der er et par ting, som man skal være opmærksom på. Når filen åbnes ved at oprette et StringWriter objekt, bliver filen oprettet, hvis den ikke findes. Hvis filen derimod allerede er oprettet, bliver den overskrevet. Hvis man ikke ønsker filen overskrevet, kan man angive endnu en parameter til konstruktøren, som åbner filen i append mode. Der bliver da tilføjet til enden af filen. Når man skriver en linje i filen med WriteLine(), skrives strengens tegn ud i filen efterfulgt af et linieskift. Endelig skal man bemærke den sidste Close() sætning. Den er nødvendig, da der faktisk ikke skrives fysisk til filen for hver WriteLine(), men i stedet til en buffer i memory. Close() bevirker, udover at forbindelsen til filen afbrydes, at indholdet af bufferen skrives til filen.

Mangler du dygtige callcenter medarbejdere?Lad Assistance finde din nye medarbejderVi sætter en ære i at indhente viden om din virksomhed, jeres kultur og værdier, strategi, mission og vision. Herigennem danner vi os et præcist indtryk af jeres foretrukne profil. I rekrutteringsprocessen lægger vi vægt på følgende forhold:

• Grundig behovsafdækning – for et optimalt match• Jobprofil og stillingsopslag• Rådgivning i forhold til valg af annonceringsmedie• Screening af relevante ansøgere (test, analyse og problemløsning)

Kontakt os for et uforpligtende møde på telefon 33 55 00 90

Page 233: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

233

Tekstfiler

Metoden Read() viser, hvordan man læser indholdet af en tekstfil og printer det på skærmen. Her svarer metoden PutLine() til algoritmens anvend linje, og i dette tilfælde er metoden triviel og gør ikke andent end at skrive en streng som en linje på skærmen. Metoden Read() starter med at åbne filen for læsning med et StreamReader objekt:

StreamReader reader = new StreamReader(“Tekst.txt”);

Dernæst forsøges at læse en linje i filen:

string line = reader.ReadLine();

Hvis det går godt - line er forskellig fra null - udføres PutLine() med linjen som parameter, og der forsøges at læse i filen igen. Resultatet er, at løkken gentages, indtil der ikke er flere data i filen. Til sidst lukkes filen.

Det er faktisk hvad der er om tekstfiler, men det er klart, at hvordan man skaffer data, og hvordan man behandler en linje afhænger af den konkrete opgave.

Exam54 Skriv en kommasepareret file

Det følgende eksempel er i princippet identisk med ovenstående, men behandlingen af data er ikke helt så simpel, og det er samtidig et lidt mere realistisk eksempel på, hvor man kan møde tekstfiler. Faktisk er der tale om to programmer, og det næste program vedr. samme eksempel.

En kommasepareret fil er en tekstfil, som indeholder et antal linier, hvor hver linie består af flere elementer, og hvor de enkelte elementer er adskilt af et skilletegn. Skilletegnet vil ofte være et komma (deraf navnet), men det kan i princippet være hvad som helst, blot skal det være et tegn, som ikke forekommer i de enkelte tekstelementer. I dette tilfælde anvendes semikolon som skilletegn.

Det første program skal oprette en tekstfile, hvor brugeren indtaster et telefonnumer efterfulgt af et eller flere varebeløb, der fortolkes som salgstal og angiver således salg til et givet telefonnummer. For hvert telefonnummer skrives en linje i filen bestående af telefonnummeret og varebeløbene og med felterne adskilt af semikolon. Resultatet kunne være følgende file:

Bemærk, at det samme telefonnummer godt kan forekomme flere gange, og at der også kan være linjer med blot et telefonnummer og ingen tal.

Page 234: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

234

Tekstfiler

Koden er følgende:

class Program{static void Main(string[] args){StreamWriter writer = new StreamWriter(”F:\\Temp\\Salg.txt”, true);string line = PhoneNumber();while (line.Length > 0){writer.WriteLine(line);line = PhoneNumber();

}writer.Close();

}

static string PhoneNumber(){while (true){Console.Write(”Enter phone no. as 8 digits: ”);string phone = Console.ReadLine().Trim();if (phone.Length == 0) return ””;if (PhoneOk(ref phone)){StringBuilder builder = new StringBuilder(phone);double amount = Amount();while (amount > 0){builder.Append(string.Format(”;{0:F2}”, amount));amount = Amount();

}return builder.ToString();

}Console.WriteLine(”Illegal phone no.”);

}}

static bool PhoneOk(ref string tlfnr){tlfnr = tlfnr.Trim();StringBuilder builder = new StringBuilder();for (int i = 0; i < tlfnr.Length; ++i)if (tlfnr[i] >= ’0’ && tlfnr[i] <= ’9’)builder.Append(tlfnr[i]);

else if (tlfnr[i] != ’ ’)return false;

tlfnr = builder.ToString();return tlfnr.Length == 8;

}

static double Amount(){while (true){Console.Write(“Enter the amount: “);

Page 235: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

Click on the ad to read more

C# 1: Introduktion til programmering og programmeringssproget C#

235

Tekstfiler

try{string text = Console.ReadLine().Trim();if (text.Length == 0) return 0;return Convert.ToDouble(text);

}catch{

Console.WriteLine(“Illegal amount”);}

}}

}

Forklaring

Metoden PhoneOk() kontrollerer om en streng er et lovligt telefonnummer: Det skal bestå af 8 cifre. I kontrollen skippes evt. mellemrum (det er altså tilladt at indtaste mellemrum i et telefonnummer), men da jeg ikke ønsker disse mellemrum gemt i filen er parameteren til PhoneOk() en reference parameter, således at mellemrum er fjernet.

Metoden PhoneNumber() er indtastningsmetoden, som returnerer en streng bestående af telefonnummer og salgsbeløb adskilt af semikolon - eller en tom streng, hvis brugeren blot taster Enter. Faktisk er det en relativ kompleks metode, som kalder metoden Amount() til indtastning af et beløb.

Page 236: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

236

Tekstfiler

Der skrives til filen i Main(), og du skal bemærke, at det er fuldstændig samme algoritme som i det forrige eksempel. Generelt er eksemplet noget mere kompleks end det forrige eksempel, men det skyldes alene indtastningen, og det er ikke filebehandlingen, der komplicerer opgaven.

Exam55 Læs en kommasepareret file

Det er en fortsættelse af ovenstående eksempel, men hvor opgave i stedet er at læse den komma separerede fil dannet i Exam54, summere resultatet for hvert telefonnummer og printe det på skærmen. Da det samme telefonnummer kan forekomme flere gange, er det nødvendigt at læse hele filen, inden resultatet kan printes. De enkelte tal skal opbevares et sted, og da man ikke kender antallet af telefonnumre anvendes et Dictionary med telefonnummer som key, mens værdien er en List til beløbene:

private static Dictionary<string, List<double>> table = new Dictionary<string, List<double>>();

Læsningen af filen sker på samme måde, som i det første eksempel om tekstfiler, og forskellen er alene, at behandlingen af den linje der læses denne gang er mere kompleks. Programmet skrives på følgende måde:

class Program{private static Dictionary<string, List<double>> table =new Dictionary<string, List<double>>();

static void Main(string[] args){StreamReader reader = new StreamReader(“F:\\Temp\\Salg.txt”);string line = reader.ReadLine();while (line != null){ParseLine(line);line = reader.ReadLine();

}reader.Close();Print();

}

static void ParseLine(string line){string[] elem = line.Split(‘;’);try{if (elem.Length == 0)Console.WriteLine(”Empty line...”);

else{string phone = elem[0];List<double> list;if (table.ContainsKey(phone))list = table[phone];

else{

Page 237: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

237

Tekstfiler

list = new List<double>();table.Add(phone, list);

}for (int i = 1; i < elem.Length; ++i){try{list.Add(Convert.ToDouble(elem[i]));

}catch{Console.WriteLine(”Illegal ammount:” + line);

}}

}}catch{Console.WriteLine(”Error: ” + line);

}}

static void Print(){foreach (string phone in table.Keys){Console.WriteLine(phone);List<double> list = table[phone];double total = 0;foreach (double number in list){total += number;Console.WriteLine(”{0, 12:F2} ”, number);

}Console.WriteLine(”Ialt: {0, 12:F2}”, total);

}}

}

Forklaring

Behandlingen sker i metoden ParseLine(). Den splitter en linie på semikolon. Resten består blot i at teste, om et telefonnummer allerede er i tabellen, eller om det er et nyt nummer, der skal tilføjes tabellen. Herefter parses beløbene. Bemærk, at de skal konverteres, og ved fejl skrives en besked på skærmen.

Den sidste metode Print() er en simpel traversering af de indlæste tal, som skriver resultatet på skærmen.

Page 238: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

Click on the ad to read more

C# 1: Introduktion til programmering og programmeringssproget C#

238

Binære filer

29 Binære filerLigesom der findes klasser til at arbejde med tekstfiler, findes der klasser til behandling af binære filer, dvs. filer der indeholder tal eller andre binære data.

Exam56 Print 100 tal til en fil

Skriv et program, som skriver 100 tilfældige tal af typen double i en fil med navnet Number.dat.

Fremgangsmåde

class Program{static Random rand = new Random();

static void Main(string[] args){FileStream stream = new FileStream(“F:\\Temp\\Numbers.dat”,

FileMode.OpenOrCreate, FileAccess.Write);BinaryWriter writer = new BinaryWriter(stream);for (int i = 0; i < 100; ++i) writer.Write(rand.NextDouble() * 10000);writer.Close();stream.Close();

}}

Hvor mange skal tage en beslutning, før man kan føre

en beslutning ud i livet?

Slip for komplekse kommandoveje. Hos NNIT løser vi de store it-opgaver i små teams, der ikke skal spørge om lov til at tage

en beslutning. Se ledige job på nnit.dk/job

RE

TH

INK

PIP

EL

INE

Hvor mange skal tage en beslutning, før man kan føre

en beslutning ud i livet?

Slip for komplekse kommandoveje. Hos NNIT løser vi de store it-opgaver i små teams, der ikke skal spørge om lov til at tage

en beslutning. Se ledige job på nnit.dk/job

RE

TH

INK

PIP

EL

INE

Hvor mange skal tage en beslutning, før man kan føre

en beslutning ud i livet?

Slip for komplekse kommandoveje. Hos NNIT løser vi de store it-opgaver i små teams, der ikke skal spørge om lov til at tage

en beslutning. Se ledige job på nnit.dk/job

RE

TH

INK

PIP

EL

INE

Hvor mange skal tage en beslutning, før man kan føre

en beslutning ud i livet?

Slip for komplekse kommandoveje. Hos NNIT løser vi de store it-opgaver i små teams, der ikke skal spørge om lov til at tage

en beslutning. Se ledige job på nnit.dk/job

RE

TH

INK

PIP

EL

INE

Page 239: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

239

Binære filer

Forklaring

Denne gang er filen repræsenteret af en FileStream. Konstruktøren har ud over filens navn yderligere to parametre. Filens mode angiver, hvordan filen skal åbnes. Her angiver man, at den skal åbnes, hvis den findes, og ellers skal den oprettes. Som alternativ kan man angive

- CreateNew, der opretter en ny fil, men hvis den allerede findes, får man en exception - Create, der opretter en ny fil, og hvis den allerede findes, overskrives den - Open, der åbner en fil, og hvis den ikke findes, får man en exception - Truncate, der åbner en fil og tømmer den - Append, der åbner en fil og placerer filepointeren i slutningen af filen - hvis filen ikke findes,

oprettes den

Den sidste parameter angiver adgang til filen, og her åbnes filen for skrivning. Som alternativ kan filen åbnes for læsning eller både læsning og skrivning.

Efter at filen er åbnet oprettes en BinaryWriter til filen, som anvendes til at skrive tal i den. Bemærk metoden Write(), som findes i 18 overstyringer og dermed en overstyring til hver af de indbyggede datatyper.

Exam57 Læs en binær file

Skriv et program, som læser indholdet af filen dannet af ovenstående program og printer antallet af tal, der er læst, summen af tallene, gennemsnittet samt det mindste og det største tal.

Fremgangsmåde

class Program{static void Main(string[] args){double sum = 0;double min = double.MaxValue;double max = double.MinValue;int count = 0;FileStream stream =new FileStream(“F:\\Temp\\Numbers.dat”, FileMode.Open, FileAccess.Read);

BinaryReader reader = new BinaryReader(stream);try{while (true){double tal = reader.ReadDouble();sum += tal;++count;if (min > tal) min = tal;if (max < tal) max = tal;

}}catch (EndOfStreamException)

Page 240: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

Click on the ad to read more

C# 1: Introduktion til programmering og programmeringssproget C#

240

Binære filer

{}reader.Close();stream.Close();if (count > 0) Result(sum, min, max, count);

}

private static void Result(double sum, double min, double max, int count){Console.WriteLine(“It has been read {0} numbers”, count);Console.WriteLine(“The sum of the numbers are {0}”, sum);Console.WriteLine(“The average is {0}”, sum / count);Console.WriteLine(“The minimum number is {0}”, min);Console.WriteLine(“The maximum number is {0}”, max);

}}

Forklaring

Grundlæggende er der ikke meget nyt, men der er to ting, man skal være opmærksom på. Det ene er, hvordan man håndterer end of file, og dermed hvornår der ikke er flere tal i filen. For at læse i filen anvendes en BinaryReader, og hvis man forsøger at læse ud over enden af filen, får man en exception. Den anden ting man skal være opmærksom på er, hvordan man læser i filen med metoden ReadDouble(). Denne metode læser de næste 8 bytes og konverterer disse til en double uanset indhold. Det er således brugerens ansvar (brugeren skal vide), at disse 8 bytes rent faktisk repræsenterer en double. Denne information er ikke gemt i filen. Klassen BinaryReader har tilsvarende metoder til at læse andre indbyggede typer.

Page 241: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

241

Binære filer

Exam58 Seek

En FileStream er altid en sekvens af bytes, og det er op til det program, der læser filen, at fortolke indholdet korrekt. Til en FileStream er knyttet en såkaldt filepointer, som blot er et heltal, der angiver den position i filen, hvor næste læse- eller skrive operation finder sted. Programmet kan manipulere denne filepointer med en metode Seek(), der kan positionere filepointeren et vilkårligt sted - igen er det op til programmet at sikre, at det er et fornuftigt sted. Det næste eksempel viser, hvordan man flytter filepointeren.

Fremgangsmåde

public static void Main(){FileStream stream = new FileStream(“Tal.dat”, FileMode.Create, FileAccess.ReadWrite);BinaryWriter writer = new BinaryWriter(stream);BinaryReader reader = new BinaryReader(stream);for (int i = 0; i < 10; ++i) writer.Write(Math.Sqrt(i));stream.Seek(5 * sizeof(double), SeekOrigin.Begin);writer.Write(Math.PI);Console.WriteLine(reader.ReadDouble());stream.Seek(5 * sizeof(double), SeekOrigin.End);writer.Write(Math.E);stream.Seek(0, SeekOrigin.Begin);try{while (true) Console.WriteLine(reader.ReadDouble());

}catch (EndOfStreamException){}reader.Close();writer.Close();stream.Close();

}

Forklaring

Først åbnes en FileStream, men denne gang med readwrite adgang. Bemærk også, at dens mode er Create, således at filen oprettes, hver gang metoden udføres. Som næste step tilknyttes både en writer og en reader, og der skrives 10 tal i filen. Dernæst skrives tallet pi i filen, men først placeres filepointeren, så tallet skrives som det 5. tal (det første tal er det 0. tal). Da en double fylder 8 bytes, skal tallet starte med byte nr. 40. Efter at pi er skrevet, læses et tal, men da en skrivning flytter filepointeren 8 bytes, bliver det det næste tal, der læses. Nu flyttes filepointeren igen 40 bytes, men denne gang fra slutningen af filen. Dvs. at filepointeren placeres 40 bytes efter filen, og der skrives et tal. Spørgsmålet er, hvad der sker med de mellemliggende pladser, der i princippet er tomme. Svaret er, at de sættes til 0 - alle bytes er 0. Til sidst læses hele indholdet af filen. Bemærk, hvordan filepointeren først sættes til starten af filen.

Udføres metoden, er resultatet følgende:

Page 242: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

Click on the ad to read more

C# 1: Introduktion til programmering og programmeringssproget C#

242

Binære filer

SÆT LYD PÅ FREMTIDENWidex udvikler højteknologiske høreapparater til gavn for de 500 millioner mennesker verden over, der har nedsat hørelse.

Mere end fem årtiers intensiv forskning og udvikling har gjort os til en af verdens førende høreapparatproducenter, og vi udvikler digital teknologi af en kvalitet, kun få kan måle sig med.

Som videnbaseret virksomhed betragter vi medarbejderne som vores vigtigste kapital. Vi kan godt lide at gøre tingene selv og sætter en ære i at være selvforsynende inden for de fl este om-råder. Det skaber et spændende, tværfagligt arbejdsmiljø med plads til initiativ og rig mulighed for personlig og faglig udvikling.

Vil du være med til at sætte lyd på fremtiden? Følg med i vores jobopslag på www.widex.dk/job eller skriv til [email protected]

www.widex.com

Page 243: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

243

Info om biblioteker og filer

30 Info om biblioteker og filerSystem.IO indeholder to klasser, som er nyttige for at bestemme informationer om filer og biblioteker:

- FileInfo - DirectoryInfo

Den første repræsenterer en file, mens den anden repræsenterer et bibliotek eller directory. Der er ikke så meget at sige om dem, men de har begge et antal properties, som angiver oplysninger om en konkret fil eller directory.

Exam59 FileInfo

Herunder er vist et program, som printer oplysninger om en fil:

static void Main(string[] args){string filename = “E:\\USA\\001.jpg”;FileInfo info = new FileInfo(filename);Console.WriteLine(info.FullName);Console.WriteLine(info.Name);Console.WriteLine(info.CreationTime);Console.WriteLine(info.Attributes.ToString());Console.WriteLine(info.Length);Console.WriteLine(info.Extension);Console.WriteLine(info.DirectoryName);

}

Forklaring

Der er ikke meget at forklare, men programmet kræver, at den pågældende fil findes.

Exam60 DirectroryInfo

Det næste eksempel er i princippet identisk med ovenstående, blot printer det i stedet oplysninger om et bibliotek:

Page 244: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

244

Info om biblioteker og filer

static void Main(string[] args){string dirname = “F:\\Temp”;DirectoryInfo info = new DirectoryInfo(dirname);Console.WriteLine(info.FullName);Console.WriteLine(info.Name);Console.WriteLine(info.CreationTime);Console.WriteLine(info.Attributes.ToString());Console.WriteLine(info.Root);Console.WriteLine(“Subdirectories:”);foreach (DirectoryInfo dir in info.GetDirectories()) Console.WriteLine(dir.Name);Console.WriteLine(“Files:”);foreach (FileInfo file in info.GetFiles()) Console.WriteLine(file.Name);

}

Page 245: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

Click on the ad to read more

C# 1: Introduktion til programmering og programmeringssproget C#

245

Objekt serialisering

31 Objekt serialiseringObjekt serialisering betegner den proces, hvor et objekts tilstand konverteres til en sekvens af bytes, og dermed til data, der kan sendes til en stream som f.eks. en file eller over en kommunikationslinje. Det er muligt at serialisere vilkårlige objekter til en stream, og for at man igen kan læse et serialiseret objekt, er det nødvendigt sammen med serialiseringen af objektets data også at gemme oplysninger om typen. Når man læser et serialiseret objekter, kalder man det for deserialisering af objektet.

Set fra programmøren er serialisering og deserialisering af objekter simpel, og man skal ikke skrive ret meget, men hvis man tænker lidt nærmere over det, er det en relativ kompleks proces. Et objekt er defineret på grundlag af en klasse og kan indeholde både simple variabler, arrays og referencer til andre objekter, og ikke nok med det, så kan klassen også arve variabler fra en basisklasse. Når et objekt skal serialiseres, skal alle disse elementer gemmes sammen med alle de informationer, der er nødvendige for at kunne opbygge hele strukturen igen i forbindelse med deserialisering. Konklusionen er, at selv om de følgende eksempler viser, at det er simpelt at serialisere objekter, så foregår der en hel del bagved, som varetages af de klasser, der ligger til grund for serialiseringen.

Datatypes

Inden jeg viser nogle eksempler på serialisering, vil jeg oprette et class library. Åbn Visual Studio og vælg Class Library som projekttemplate:

Dedicated Analytical Solutionswww.foss.dk/careers

Protein 13.2%

Moisture 8.4%

Starch 67%

FOSS is known throughout the world for efficient analytical solutions that help to improve both food quality and safety in the global food market. We are playing an increasingly important role in ensuring optimal use of valuable natural resources, and have throughout the years created ground-breaking innovations. And there’s more to come. At FOSS you will find professional challenges, training and development in a work environment that offers good work/ life balance. Join us and make a difference.

80% of the grain traded in the world is analysed on a FOSS solution

Page 246: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

246

Objekt serialisering

Visual Studio vil så oprette et dll med klasser. I dette tilfælde hedder det Datatypes.dll. Efter at projektet er oprettet indeholder det en klasse, som hedder Class1. Jeg starter typisk med at slette denne klasse.

Jeg tilføjer dernæst en ny klasse, som jeg har kaldt Person:

using System;

namespace Datatypes{[Serializable]public class Person{private string name;private string position;

public Person(){name = “”;position = “”;

}

public Person(string name, string position){this.name = name;this.position = position;

}

public string Name{get { return name; }set { name = value; }

Page 247: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

247

Objekt serialisering

}

public string Position{get { return position; }set { position = value; }

}

public override string ToString(){return name + “, “ + position;

}}

}

Herefter oversættes projektet.

Forklaring

Klassen er ganske simpel, og der er ikke meget at forklare, men klassen er defineret Serializable:

[Serializable]public class Person{

og det er en nødvendig forudsætning for at et objekt af typen Person kan serialiseres.

Bemærkning

Et class library er ikke et program, og det er således ikke noget man umiddelbart kan afprøve, men det er et dll, som kan anvendes i andre programmer. Hvad man skal gøre, er forklaret i det næste eksempel. Et class library kan indeholde flere ting, men vil typisk indeholder brugerdefinerede klasser. Målet er et dll med klasser, som man ofte har brug for, og som er færdige, testet og fundet fri for fejl. Et sådant dll kan herefter stilles til rådighed for andre programmer, og dets klasser vil indgå på ligefod med alle andre klasser fra .NET frameworket.

Exam61 Binær serialisering

Der skal skrives et program, der oprette et Person objekt og serialiserer det til en file.

Fremgangsmåde

Starten er som sædvanlig et Console Application projekt. Denne gang vil jeg starte med at knytte ovenstående dll til projektet. I Solution Explorer højreklikker jeg på References og vælger Add Reference...

Page 248: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

Click on the ad to read more

C# 1: Introduktion til programmering og programmeringssproget C#

248

Objekt serialisering

I det efterfølgende vindue klikker jeg på knappen Browse nederst i vinduet. Man får så en stifinder og kan browse sig frem til dll’et (Datatypes.dll under projektet Datatypes):

HD – vejen tilen karrierei erhvervslivet

Læs mereAarhus: hd.au.dkHerning: auhe.au.dk/hd

LÆS HD I ØKONOMI OG LEDELSE

HD er en anerkendt diplom- uddannelse, som giver dig mulighed for at specialisere dig inden for det erhvervsøkonomiske fagområde ved siden af dit job.

Page 249: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

249

Objekt serialisering

Når man herefter klikker OK, kopieres dll’et til det aktuelle projekt, og dets klasser er herefter til rådighed for programmet. Hvis man herefter åbner References i Solution Explorer, kan man se hvilke dll’er programmet har adgang til og herunder nu Datatypes. De øvrige dll’er er nogle som Visual Studio automatisk har sat referencer til, og de indeholder alle de vigtigste klasser i .NET frameworket.

Efter at dll’et med klassen Person er knyttet til programmet, kan koden skrives på følgende måde:

using System;using System.IO;using System.Runtime.Serialization.Formatters.Binary;using Datatypes;

Page 250: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

250

Objekt serialisering

namespace Exam61{class Program{static void Main(string[] args){Person pers = new Person(“Valborg Kristensen”, “Klog kone”);Serialiser(pers);

}

private static void Serialiser(Person pers){BinaryFormatter bf = new BinaryFormatter();FileStream stream = File.Create(”F:\\Temp\\Person.dat”);bf.Serialize(stream, pers, null);stream.Close();

}}

}

Forklaring

Bemærk først programmets using sætninger. Ud over System.IO er der også defineret namespacet

using System.Runtime.Serialization.Formatters.Binary;

som indeholder de klasser, der er nødvendige for at kunne serialisere et objekt. Bemærk også, at der er en definition af namespacet med Person klassen:

using Datatypes;

I Main() defineres et objekt

Person pers = new Person(“Valborg Kristensen”, “Klog kone”);

og opgaven er at skrive dette objekt til en fil. Det betyder, at det er nødvendigt at gemme de to medlemsvariabler name og position, og de er i sig selv objekter af typen String. Én ting er at gemme objektet, men da man også skal kunne læse objektet igen, er det som nævnt ovenfor nødvendigt også at gemme oplysninger om objektets type. Det der gemmes er rå bytes, og for at det igen kan indlæses som et Person objekt - bestående af to andre objekter af typen String - skal denne information være gemt sammen med objektets databytes. Det er denne proces, som kaldes serialisering, og for at det er muligt, skal dels objektets type være defineret Serializable, og dels skal alle objektets instance varaibler være Serializable. I dette tilfælde er det hele opfyldt, da Person er defineret Serializable, og medlemsvariablerne har typen String, der er Serializable. Det samme gælder i øvrigt alle de simple typer og mange af typerne i .NET frameworket.

Page 251: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

Click on the ad to read more

C# 1: Introduktion til programmering og programmeringssproget C#

251

Objekt serialisering

For at serialisere et objekt skal man anvende en såkaldt Formatter. Der er flere muligheder, og de forskellige Formatter typer er defineret i namespacet System.Runtime.Formatters, men fælles for dem er, at de serialiserer et objekt med de informationer, som er nødvendige for at objektet kan deserialiseres. De adskiller sig derimod mht. det format, som objektet gemmes i. I dette tilfælde anvender jeg en binary formatter, som gemmer et objekt i et binært format.

Metoden Serialiser() serialiserer et objekt af typen Person til filen F:\Temp\Person.dat. Først oprettes en BinaryFormatter og dernæst en fil med navnet F:\Temp\Person.dat. Endelig anvendes formatteren til at serialisere objektet. Det er altså relativt simpelt at serialisere et objekt. Man bør dog være opmærksom på, at da der skrives til en fil, bør koden sædvanligvis placeres i en try blok og en evt. exception håndteres.

Exam62 Binær deserialisering

Formålet med dette eksempel er at skrive et program, som læser det objekt, der er gemt i det forrige eksempel og printer objektet på skærmen.

Fremgangsmåde

Først sættes på samme måde som ovenfor en reference til dll’et med klassen Person. Dernæst skrives programmet:

������������� ����������������������������������������������� �� ���������������������������

������ ������ ������������������������������ ����������������������!���"���������������

�����#$%����&'())%�*+����������,����������-

.��������������������������������� ��

���������� ���������������� ������������� ���������������������������� �����������

The Wakethe only emission we want to leave behind

Page 252: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

252

Objekt serialisering

using System;using System.IO;using System.Runtime.Serialization.Formatters.Binary;using Datatypes;

namespace Exam62{class Program{static void Main(string[] args){Person pers = DeSerialiser();if (pers != null) Console.WriteLine(pers);

}

private static Person DeSerialiser(){Person pers = null;try{BinaryFormatter bf = new BinaryFormatter();FileStream stream = File.OpenRead(“F:\\Temp\\Person.dat”);pers = (Person)bf.Deserialize(stream);stream.Close();

}catch{}return pers;

}}

}

Forklaring

Metoden DeSerialiser() forsøger at deserialisere et objekt af typen Person gemt i filen F:\Temp\Person.dat. Først oprettes en BinaryFormatter. Dernæst oprettes en stream til den pågældende file, og objektet deserialiseres. Metoden returnerer objektet, hvis det er muligt at deserialisere et Person objekt (hvis filen findes, og hvis den indeholder et Person objekt). Er det ikke tilfældet, returnerer metoden null. Bemærk, at det er nødvendigt at type caste objektet til en Person.

Bemærkning

Når man deserialiserer et objekt, skal det være til samme type, som typen af det objekt, som er serialiseret. Her skal man huske, at et objekts type også identificeres af det namespace, som indeholder dets type. Det er derfor, at jeg i ovenstående eksempler har placeret klassen i et class library, så Person er samme type i begge programer.

Page 253: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

253

Objekt serialisering

Exam63 XML serialisering

Dette eksempel er i princippet fuldstændig identiske med de to forrige, men i stedet for en BinaryFormatter anvendes en XmlSerializer, så objektet gemmes som xml i stedet for binære data.

Fremgangsmåde

Igen startes med at sætte en reference til dll’et med klassen Person. Koden er følgende:

using System;using System.IO;using System.Xml.Serialization;using Datatypes;

namespace Exam63{class Program{static void Main(string[] args){Save();Load();

}

public static void Save(){Person pers = new Person(“Knud Andersen”, “Skarpretter”);Serialiser(pers);

}

public static void Load(){Person pers = DeSerialiser();if (pers != null) Console.WriteLine(pers);

}

private static void Serialiser(Person pers){XmlSerializer xs = new XmlSerializer(typeof(Person));FileStream stream = File.Create(”F:\\Temp\\Person.xml”);xs.Serialize(stream, pers);stream.Close();

}

private static Person DeSerialiser(){Person pers = null;try{XmlSerializer xs = new XmlSerializer(typeof(Person));FileStream stream = File.OpenRead(”F:\\Temp\\Person.xml”);pers = (Person)xs.Deserialize(stream);stream.Close();

}

Page 254: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

Click on the ad to read more

C# 1: Introduktion til programmering og programmeringssproget C#

254

Objekt serialisering

catch{}return pers;

}}

}

Forklaring

Koden er næste uændret og den vigtigste forskel er, at der anvendes et andet namespace og dermed også andre serialiseringsobjekter.

Fordelen ved at serialisere et objekt som xml er, at alle der kan læse en tekstfile kan læse indholdet og fortolke det. Det kræver ikke kendskab til det binære format, som en BinaryFormatter anvender.

Indholdet af filen Person.xml er følgende:

<?xml version=”1.0”?><Person xmlns:xsi= ”http://www.w3.org/2001/XMLSchema-instance”

xmlns:xsd=”http://www.w3.org/2001/XMLSchema”><Navn>Knud Andersen</Navn><Stilling>Skarpretter</Stilling>

</Person>

We are a global specialist in energy management represented in more than 100 countries. We provide technology and integrated solutions to optimise energy usage across multiple market segments. We are more than 130,000 colleagues worldwide and 1.000 of us are situated in Denmark.

We invest in our employees, in the environment and in the future. Each year 5% of our revenue is allocated for research and development activities. In Schneider Electric you have many career paths to choose from – also internationally.

Would you like take on the challenge of transforming the way people and organisations use energy?

Do you know Schneider Electric?

Meet us at: www.schneider-electric.dk/job

Page 255: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

255

Objekt serialisering

Hvis man ser på den xml, der er dannet, kan man næsten se, at det ikke er nok til at man kan deserialisere objektet. For at et objekt kan xml serialiseres er der yderligere et par ting der skal være opfyldt:

- der skal være en default konstruktør - der skal være get og set properties til alle instance variabler

og begge dele opfylder klassen Person. Selv om binær serialisering (og SOAP serialisering som vises herunder) ikke kræver det, er det en god idé at knytte både en default konstruktør og de nødvendige properties til klasser, som defineres serializable.

Exam64 SOAP serialisering

Dette eksempel er fuldstændig identisk med ovenstående med den forskel, at objektet denne gang serialiseres efter SOAP protokollen.

Fremgangsmåde

Som i de andre eksempler skal der sættes en reference til dll’et med typen Person, men denne gang er der en lille ekstra krølle. Klassen til soap formatering er i namespacet:

using System.Runtime.Serialization.Formatters.Soap;

men dette namespace er ikke med i de dll’er som Visual Studio sætter referencer til som default. Det er derfor nødvendigt at sætte en reference til dette namespace manuelt (se nedenfor). Herefter kan koden skrives:

using System;using System.IO;using System.Runtime.Serialization.Formatters.Soap;using Datatypes;

namespace Exam64{class Program{static void Main(string[] args){Save();Load();

}

public static void Save(){Person pers = new Person(“Gudrun Mortensen”, “Heks”);Serialiser(pers);

}

public static void Load()

Page 256: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

256

Objekt serialisering

{Person pers = DeSerialiser();if (pers != null) Console.WriteLine(pers);

}

private static void Serialiser(Person pers){SoapFormatter sf = new SoapFormatter();FileStream stream = File.Create(“F:\\Temp\\Person.txt”);sf.Serialize(stream, pers);stream.Close();

}

private static Person DeSerialiser(){Person pers = null;try{SoapFormatter sf = new SoapFormatter();FileStream stream = File.OpenRead(“F:\\Temp\\Person.txt”);pers = (Person)sf.Deserialize(stream);stream.Close();

}catch{}return pers;

}}

}

Page 257: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

Click on the ad to read more

C# 1: Introduktion til programmering og programmeringssproget C#

257

Objekt serialisering

Forklaring

Jeg skal ikke her fortolke resultatet (dvs. forklare SOAP protokollen), men det vigtige er at bemærke, at det er XML og dermed tekst og alle dermed i princippet kan læse indholdet.

<SOAP-ENV:Envelope xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance”xmlns:xsd=”http://www.w3.org/2001/XMLSchema”xmlns:SOAP-ENC=”http://schemas.xmlsoap.org/soap/encoding/” xmlns:SOAP-ENV=”http://schemas.xmlsoap.org/soap/envelope/”xmlns:clr=”http://schemas.microsoft.com/soap/encoding/clr/1.0”SOAP-ENV:encodingStyle=”http://schemas.xmlsoap.org/soap/encoding/”>

<SOAP-ENV:Body><a1:Person id=”ref-1”

xmlns:a1=”http://schemas.microsoft.com/clr/nsassem/IO/IO%2C%20Version%3D1.0.0.0%2C%

20 Culture%3Dneutral%2C%20PublicKeyToken%3Dnull”><navn id=”ref-3”>Gudrun Mortensen</navn><stilling id=”ref-4”>Heks</stilling>

</a1:Person></SOAP-ENV:Body></SOAP-ENV:Envelope>

Exam65 Serialsering af en collection

Målet med dette eksempel er at vise, at man man også kan serialisere en collection af objekter og i dette tilfælde en collection af Person objekter.

Vil du også stå på ski i fremtiden?

Verden har brug for nye løsninger, og Topsøe har de katalysatorer og teknologier, der kan løse centrale udfordringer på den globale agenda: verdens energi- og miljøudfordringer.

Vi har fart på. Vores løsninger skal fortsat udvikles, udbredes og implementeres på det globale marked. Derfor vil vi gerne have endnu flere kolleger, som vil være med til at skabe værdi og fremdrift.

Du får mulighed for fordybelse, kundekontakt og rejseaktivitet. Og adgang til en verden af viden.

Vi arbejder i en fri og uformel atmosfære. Vi er stolte af at tage ansvar og bidrage til et bedre miljø.

Vil du være med?

WWW.TOPSOE.COM/JOBS

Need for speed?

Page 258: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

258

Objekt serialisering

namespace Exam65{class Program{static void Main(string[] args){Save();Load();

}

public static void Save(){List<Person> list = CreateList();Serialiser(list);

}

public static void Load(){List<Person> list = DeSerialiser();if (list != null) Show(list);

}

private static List<Person> CreateList(){List<Person> list = new List<Person>();list.Add(new Person(“Frede Andersen”, “Mestersvend”));list.Add(new Person(“Gudrun Knudsen”, “Spåkone”));list.Add(new Person(“Karl Petersen”, “Natmand”));list.Add(new Person(“Maren Hansen”, “Sin mands kone”));return list;

}

private static void Show(List<Person> list){for (int i = 0; i < list.Count; ++i) Console.WriteLine(list[i]);

}

private static void Serialiser(List<Person> list){BinaryFormatter bf = new BinaryFormatter();FileStream stream = File.Create(”F:\\Temp\\List.dat”);bf.Serialize(stream, list);stream.Close();

}

private static List<Person> DeSerialiser(){List<Person> list = null;try{BinaryFormatter bf = new BinaryFormatter();FileStream stream = File.OpenRead(”F:\\Temp\\List.dat”);list = (List<Person>)bf.Deserialize(stream);stream.Close();

}catch{

Page 259: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

Click on the ad to read more

C# 1: Introduktion til programmering og programmeringssproget C#

259

Objekt serialisering

}return list;

}}

}

Forklaring

Der er i virkeligheden ikke meget at forklare, og det eneste er at gøre opmærksom på, at de forskellige collection klasser generelt er Serializable, og en list med Serializable objekter (objekter af typen Person) kan derfor umiddelbart serialiseres.

IFRS 2012, Standarder og fortolk-ningsbidrag – på dansk fås nu både som trykt bog samt som e-bog til smartphone, tablet og pc.

Introduktionspris: e-bog og trykt bog kr. 1545,-

E-bog inkl. opdateringer i 2012

Læs mere og køb e-bogen sammen med den trykte bog her: shop.magnus.dk

REGNSKABIFRS 2012 – nu også som e-bog

– Nuogså som

e-bog

Page 260: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

260

Brugerdefineret serialisering

32 Brugerdefineret serialiseringSerialiseringsprocessen som beskrevet er generelt set fra programmøren ukompliceret, og der er sjældent grund til at gøre mere end beskrevet ovenfor. Der er dog mulighed for selv at gribe ind i processen, hvis der er særlige behov.

Som eksempel kan man tænke sig, at en klasse har variabler, som man af den ene eller anden grund ikke ønsker skal serialiseres. Herunder er vist en klasse Employee, som arver Person og udvider med to variabler, hvor den første er ansættelsesdatoen, mens den anden er det aktuelle årstal. Klassen har en metode Seniority(), som - lidt forenklet - returnerer en ansats anciennitet som antal år mellem ansættelsesåret og det aktuelle år. Klassen er serialiserbar, men det giver ingen mening at serialisere variablen year, da dens værdi afhænger af, hvornår programmet køres. Man kan imidlertid mærke en variabel med attributten NonSerialized, der fortæller, at den ikke skal serialiseres.

[Serializable]public class Employee : Person{private DateTime date;

[NonSerialized]protected int year = DateTime.Now.Year;

[OnDeserialized]public void InitYear(StreamingContext context){year = DateTime.Now.Year;

}

public Employee(string name, string position, DateTime date): base(name, position)

{this.date = date;

}

public int Seniority(){return year - date.Year;

}}

Det giver dog et lille problem med at få denne variabel initialiseret, når et objekt deserialiseres. Det klares af metoden InitYear(), som er en metode, der udføres efter deserialiseringsprocessen. Her skal du bemærke attributten, som fortæller, at det er en metode, der skal udføres efter deserialiseringen, samt metodens signatur og parametertypen StreamingContext, der er enum, der sjældent anvendes til noget.

Det følgende program serialiserer og deserialiserer et Employee objekt:

Page 261: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

261

Brugerdefineret serialisering

namespace Exam66{class Program{static void Main(string[] args){Save();Load();

}

public static void Save(){Employee employee = new Employee(“Karlo Andersen”, “Tater”, new DateTime(2002, 03, 15));Serialiser(employee);

}

public static void Load(){Employee employee = DeSerialiser();if (employee != null) Console.WriteLine(employee);

}

private static void Serialiser(Employee employee){BinaryFormatter bf = new BinaryFormatter();FileStream stream = File.Create(“Employee.dat”);bf.Serialize(stream, employee, null);stream.Close();

}

private static Employee DeSerialiser(){Employee employee = null;try{BinaryFormatter bf = new BinaryFormatter();FileStream stream = File.OpenRead(“Employee.dat”);employee = (Employee)bf.Deserialize(stream);stream.Close();

}catch{}return employee;

}}

}

Der er andre tilsvarende attributter, der kan anvendes til at dekorere metoder med en lignende signatur:

- OnDeserializing til at angive en metode som udføres inden deserialiseringsprocessen - OnSerialized angiver en metode der udføres umiddelbart efter serialiseringsprocessen - OnSerializing som angiver en metode der udføres inden serialiseringsprocessen

Page 262: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

262

Brugerdefineret serialisering

Ud over at man som illustreret herover kan definere metoder, som udføres før og efter hhv. serialisering og deserialisering, er det også muligt direkte at styre processen mht. hvordan data serialiseres og deserialiseres. Princippet illustreres af følgende klasse, som repræsenterer et medlem, der er en specialisering af klassen Person:

[Serializable]public class Member : Person, ISerializable{private string ssn;private string phone;private string email;

public Member(string ssn, string name, string position, string phone, string email): base(name, position)

{this.ssn = ssn;this.phone = phone;this.email = email;

}

public Member(SerializationInfo info, StreamingContext context){ssn = info.GetString(“ssn”);Name = info.GetString(“name”);Position = info.GetString(“position”);phone = info.GetString(“phone”);email = info.GetString(“email”).ToLower();

}

public string Ssn{get { return ssn; }set { ssn = value; }

}

public string Phone{get { return phone; }set { phone = value; }

}

public string Email{get { return email; }set { email = value; }

}

public void GetObjectData(SerializationInfo info, StreamingContext context){info.AddValue(“ssn”, FormatSsn());info.AddValue(“name”, Name);info.AddValue(“position”, Position);info.AddValue(“phone”, FormatPhone());info.AddValue(“email”, email.ToUpper());

}

Page 263: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

Click on the ad to read more

C# 1: Introduktion til programmering og programmeringssproget C#

263

Brugerdefineret serialisering

private string FormatSsn(){StringBuilder builder = new StringBuilder();for (int i = 0; i < ssn.Length; ++i)if (ssn[i] >= ‘0’ && ssn[i] <= ‘9’){builder.Append(ssn[i]);if (builder.Length == 6) builder.Append(‘-’);

}return builder.ToString();

}

private string FormatPhone(){StringBuilder builder = new StringBuilder();for (int i = 0, j = 0; i < phone.Length; ++i)if (phone[i] >= ‘0’ && phone[i] <= ‘9’){builder.Append(phone[i]);++j;if (j == 2){builder.Append(‘ ‘);j = 0;

}}

return builder.ToString();}

Page 264: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

264

Brugerdefineret serialisering

public override string ToString(){return string.Format(“{0}\n{1}\n{2}\n{3}”, ssn, base.ToString(), phone, email);

}}

Det vigtige er at bemærke, at klassen implementerer interfacet ISerializable, der er et interface, som definerer en enkelt metode: GetObjectData(). Hvis en serialiserbar klasse implementerer dette interface, vil en formatter kalde metoden GetObjectData(), og her kan man så i form af key/value par definere, hvordan de enkelte elementer skal serialiseres. En key er en streng, og ofte vil man anvende navnet på en variabel, men det er ikke et krav. I dette tilfælde - blot for at gøre noget - skal metoden sikre, at et cprnummer gemmes som 6 cifre, en bindestreg og 4 cifre, at et telefonnummer gemmes som par af cifre adskilt af mellemrum, og at email adressen kun har store bogstaver. Bemærk at metoden ikke kontrollerer om cprnummer og telefonnummer er lovlige. I praksis burde det være kontrolleret et eller andet sted, men det er ikke med her for ikke at gøre koden mere kompleks end nødvendigt.

Klassen har også en ny konstruktør, der bl.a. har en SerializationInfo parameter. Denne konstruktør er nødvendig for at deserialisere et ISerializable objekt, og her kan man med en række get metoder få fat de værdier, som er serialiseret i metoden GetObjectData().

namespace Exam67{class Program{static void Main(string[] args){Save();Load();

}

public static void Save(){Member member = new Member(“1234567890”, “Nikoline Frederiksen”,

“SinMandsKone”, “87654321”, “[email protected]”);Serialiser(member);

}

public static void Load(){Member member = DeSerialiser();if (member != null) Console.WriteLine(member);

}

private static void Serialiser(Member member){BinaryFormatter bf = new BinaryFormatter();FileStream stream = File.Create(”Member.dat”);bf.Serialize(stream, member, null);stream.Close();

Page 265: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

Click on the ad to read more

C# 1: Introduktion til programmering og programmeringssproget C#

265

Brugerdefineret serialisering

}

private static Member DeSerialiser(){Member member = null;try{BinaryFormatter bf = new BinaryFormatter();FileStream stream = File.OpenRead(”Member.dat”);member = (Member)bf.Deserialize(stream);stream.Close();

}catch{}return member;

}}

}

Tænker du også på fremtidens vand?

Så bliv en del af Nordens mest kompetente medarbejderstab specialiseret i vand.

Service | Value | Respo

nsib

ility

Vil du med på holdet?

Tjek vores jobside for ledige

stillinger og upload dit CV på

www.kruger.dk/da/job

Foto

: K

rüg

er

Sta

fett

en

rrn

ddn

dddn

dn

dddu

ndd

un

t o

t o

to

t ooo

t ooo

t o ot o

to

t ooo ooot ooo

t o

t o

too

t o

tm

CCm

Cm

Cm

CCm

Cm

Cm

CCm

CCm

Cm

Cm

CCm

CCCCCCCm

CCm

Cm

Cm

Cm

Cm

Cm

Cm

Cm

Cm

CCCmmmmmmmmmmmmmmmmm

hririiri

hri

hri

hri

hri

hririirii

hri

hriiiii

hri

hri

hri

hriiiirrr

hrr

hr

hr

hr

hrrrrrrrrrrrrrrrrrrr

hr

hrrrr

hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhst

ist

ist

ist

ist

ist

ist

ist

ist

ist

ist

ist

ist

ist

ist

ist

ist

ist

ist

ist

ist

ist

ist

ist

ist

ist

itisti

sti

sti

sti

sti

sti

stititistiiii

sti

sti

stii

sti

sti

sti

sti

sti

stiii

stii

stitistii

stii

sti

sstststststtsssssssssssn

sn

ssssssssn

sn

sa

ns

nssss

nss

ns

nss

an

sa

nss

nssss

an

sn

ssssa

ns

ns

an

sa

ns

an

ssn

ssa

nss

an

sa

ns

an

sa

nss

an

sa

ns

an

sa

ns

an

ssa

na

na

na

na

nnnnnna

na

na

nnnnna

nnnnnnnnna

nnnna

nna

na

nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnna

nnnnnnnnaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa

or

or

or

or

or

or

orr

or

or

orr

or

orrr

or

or

or

or

or

orr

orr

orr

or

orr

or

or

orr

oooooob

ooob

ob

oob

oob

ooobbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb

ggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggg

Page 266: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

266

Afsluttende eksempler

Del 5 Afsluttende eksemplerJeg vil slutte bogen med at vise to programmer, som er lidt større end bogens øvrige eksempler, og målet er at have lidt mere fokus på udviklingsprocessen, samt at vise anvendelsen af bogens mange begreber i lidt større sammenhænge. Målet er altså at have fokus på anvendelsen af bogens stof, og eksemplerne tilføjer som sådan ikke noget nyt.

Lotto

Dette eksempel har primært fokus på klasser og valg af klasser, og hvordan disse klasser spiller sammen for løse den konkrete opgave.

Opgaveformulering

Opgaven er at skrive et konsolprogram, der kan printe lottokuponer, men som også kan anvendes til ud fra ugens lottotal at bestemme antallet af rigtige rækker. Programmet skal anvendes som en kommando fra en prompt, hvor man ved hjælp af options angiver, hvad programmet skal lave.

Et typisk brug af programmet er, at man anvender programmet til at danne de rækker, som man ønsker at spille. Når ugens vindertal er trukket, bruger man så programmet til at bestemme spillets resultat.

Der findes flere slags lotto, og som eksempel kan nævnes det almindelige lotto med 36 tal og onsdags lotto med 48 tal. Programmet bør laves på en sådan måde, at det kan anvendes til alle lottospil, som er af den natur.

Bemærkning

Ovenstående opgaveformulering beskriver ikke opgaven tilstrækkelig. Der er flere ting, der skal afklares, inden man kan tage fat på at løse opgaven og herunder især brugerens interaktion med programmet og dermed formatet for de enkelte kommandoer, ligesom det er nødvendigt med en afklaring af formatet af resultatet.

Udviklingen af et program vil typisk starte med en sådan præcisering af opgaven, et arbejde som man sædvanligvis kalder for analyse, og hvor resultatet er en egentlig kravspecifikation, hvor de endelige krav til det færdige program er fastlagt. Arbejdet kan være alt fra simpel afklaring af spørgsmål i relation til opgaveformuleringen til en fase som strækker sig over længere tid, og hvor man måske kun præciserer dele af opgaven af gangen. Ved meget store programmer og især hvis der er knyttet usikkerhed til målene viser erfaringen, at det er umuligt at præcisere alle krav på forhånd, men at man løbende må arbejde med kravene, efterhånden som man får større indsigt i og forståelse for den opgave, der skal løses. Resultatet er, at analyse er vigtig, og i praksis kan analyse være både omfattende og tidskrævende. Til gengæld må man ikke undervurdere betydningen, da forkerte beslutninger kan være katastrofale for det færdige produkt.

Page 267: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

267

Afsluttende eksempler

Analyse

I denne opgave vil jeg definere et lottospil, som et antal lottorækker, og hvor en lottorække består af et antal forskellige lottotal, der er heltal inden for et interval. Et lottospil er således karakteriseret ved følgende parametre:

-a det mindste tilladte tal 1-b det største tilladte tal 36-r antal lottotal pr. række 7-n antal rækker, der skal spilles

hvor den sidste kolonne er en default værdi. Dvs. at jeg har valgt et almindeligt lotto som default. Disse værdier kan oplyses som options på kommandolinjen.

Man kan desuden angive følgende options:

-o output file til resultatet, hvor default er skærmen-i input file i forbindelse med kontrol af ugens lotto-u ugens lottotal adskilt af mellemrum

Her vedrører de to sidste options kontrol af ugens lottotal, mens de øvrige 5 options vedrører at danne lottorækker.

Programmet skal hedde lotto, og herunder er vist eksempler på lovlige kommandoer:

lotto -n 20lotto -a 1 -b 48 -r 6 -n 20 -o uge42.txtlotto -i uge42.txt -u 2 13 18 22 34 35lotto -i uge42.txt -u 2 13 18 22 34 35 -o uge42Res.txt

Generelt stilles der følgende krav til argumenter på kommandolinjen:

- Alle options som har en default værdi (a, b, r, o) må undlades. - Options må forekomme i vilkårlig rækkefølge. - Der må ikke forekomme konfliktende options (f.eks. -r og -i) på samme kommandolinje.

Begrebet lottokupon er ikke medtaget, da det i relation til programmets anvendelse ikke giver mening - et lottospil er i princippet én stor kupon, der kan have et vilkårligt antal rækker.

Vedr. resultatet af at danne lottorækker stilles der følgende krav:

Page 268: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

Click on the ad to read more

C# 1: Introduktion til programmering og programmeringssproget C#

268

Afsluttende eksempler

- Tallene i de enkelte lottorækker skal være sorterede i stigende orden. - Den samme række må ikke forekomme flere gange. - Rækkerne skal indbyrdes være sorteret i stigende orden (efter det første tal, efter det næste

tal, osv.). - Den første række definerer spillet og indeholder dato, det mindste og det største lovlige tal

samt antallet af tal pr. række.

Vedr. resultatet af kontrollen skal det være en file (skærmen som default), som indeholder alle rækker, men hvor der til hver række er tilføjet et tal, som angiver antallet af rigtige. Resultatet skal være sorteret efter dette tal i faldende orden.

En særlig problemstilling er fejlhåndteringen. Hvis der indtastes en ulovlig kommando, f.eks. fordi det er forkerte, manglende eller konfliktende options, ulovlige lottotal, ulovlige filer mv., skal programmet terminere med en fejlmeddelelse samt programmets syntax. Det er standard for kommandoer.

Hvis der ved kontrol af ugens lotto forekommer en ulovlig række, skal antallet af rigtige erstattes med en kort fejlmeddelelse, og evt. ulovlige rækker skal stå sidst i resultatet.

En sidste ting vedr. afgrænsning af programmets parametre:

Jeg udvikler og udviklesPrevas startede i 1985 og er i dag hovedleverandør og udviklingspartner til førende virksomhederindenfor Life Science, telecom, automotive, forsvar, energi og fremstillingsindustrien. Vi er mereend 500 ingeniører som brænder for at finde effektive løsninger for vores kunder. ”Innovation for Growth” er vores mantra.Hos Prevas møder du kompetente og spændende mennesker hver dag. Det kan være dine nyekollegaer eller det kan være vores kunders medarbejdere. Hos os får du mulighed for at arbejdemed nye teknologier i mange forskellige brancher for spændende virksomheder.Som medarbejder hos Prevas kommer du derfor altid til at udvikles - så længe du selv vil.

iNNovATioN For groWTHwww.prevas.com

Page 269: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

269

Afsluttende eksempler

Sagt lidt anderledes kan et lottotal højst være på to cifre, og en lottorække kan højst have 15 tal. På samme måde er der stillet nogle minimumskrav. Der er egentlig ikke så mange begrundelse for disse krav udover at det gør det lettere at formatere resultatet, og at man undgår nogle specielle tilfælde som f.eks. at spillet kan være tomt, der i praksis er uinteressante. Kravene er begrundet i praktiske spil, således at programmet kan spille typisk forekommende lottospil.

Bemærkning

Ovenfor har jeg under en analyse fastlagt kravene til programmet og herefter kan man starte på arbejdet med at skrive programmet. Her bør man også starte med nogle overvejelser mht. hvordan programmet skal laves og herunder, hvilke klasser som programmet skal bestå af. Det er et arbejde, som man i praksis kalder for design.

Når man laver et program, er det vigtigste at programmet er fejlfrit og opfylder kravene. Gør programmet det, er opgaven i princippet løst, men der er også andre mål, som er vigtige. Især er det vigtigt, at programmet er lavet på en sådan måde, at det fremover er let at vedligeholde programmet. Alle programmer skal vedligeholdes og modificeres over tid, og derfor skal programmet være lavet, så det er let at læse og forstå, og det skal være lavet sådan, at en ændring et sted ikke betyder, at ændringen spreder sig ud over hele programmet, så meget store dele af koden skal ændres. Det er derfor, man skal bruge tid på design, så man gør sig de nødvendige overvejelser vedr. programmets arkitektur. Man kan tænke på design som et sted, hvor man laver arbejdstegninger, noget som man gør alle andre steder, hvor man skal bygge eller producere noget.

Ud over vedligeholdelse kan også performance være vigtig, og det er et spørgsmål om algoritme. At skrive gode algoritmer er også en designaktivitet.

Design

Det centrale i ovenstående program er en lottorække, som består af lottotal svarende til det aktuelle lottospil. Et program må således have tilknyttet et objekt, som definerer spillet:

Page 270: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

270

Afsluttende eksempler

Lotto

min: intmax: intsize: int

og programmet skal have præcis et af den slags objekter, som er til rådighed for programmets øvrige klasser.

Et lottotal er ikke meget andet end et heltal med en tilfældig værdi inden for det interval, der er defineret af Lotto objektet

LottoNumber

rand: Randomnumber: int

og et objekt af typen LottoNumber skal egentlig ikke kunne ændre værdi. En LottoRow består af et antal LottoNumber objekter samt et tal, som angiver, hvor mange rigtige der er:

LottoRow

correct: int

Validate(LottoRow)

Det er en relativ kompleks klasse. Metoden Validate() skal validere række ud fra ugens lotto og bestemme antallet af rigtige. Desuden skal klasse have en konstruktør, som dels skal sikre at alle LottoNumber objekter er forskellige, og dels at rækken er sorteret i stigende orden.

Selve spillet er en klasse, som har et antal lottorækker, og det er programmets vigtigste klasser.

LottoGame

Create()Validate()

Klassen skal have to metoder til hhv. at oprette lottorækker og til at validere et eksisterende spil op mod ugens lotto. Begge metoder er forholdsvis komplekse og skal bl.a. sortere lottorækkerne, men efter forskellige kriterier. Det er også disse metoder der skal printe til filer og læse et eksisterende spil fra en fil.

Page 271: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

Click on the ad to read more

C# 1: Introduktion til programmering og programmeringssproget C#

271

Afsluttende eksempler

Sammenhængen mellem ovenstående klasser kan illustreres på følgende figur:

LottoGame LottoNumberLottoRow

Program

LottoFile

Lotto

n n

1

1

0..2

1

Her er klassen LottoFile en tekstfile, som indeholder lottorækker. Egentlig er der tale om to slags filer: - én som indeholder lottorækker for et nyt spil - dannet af metoden Create() i LottoGame - én som indeholder lottorækker som er valideret mod ugens lotto - dannet af metoden Validate()

i LottoGame

Man kan derfor overveje, om man i stedet skal anvende et design, som er en specialisering:

Dine fordele ved forsikring hosPantaenius

DEN

10083 w

ww

.hqh

h.de

04/2

012

Østerbro 11 · 7800 SkiveTel. +45-9751 3388 · [email protected]

www.pantaenius.dk

Hjælp ved uheld

Du har behov for bugsering til nærmeste værft?Pantaenius overtager omkostningerne dog begrænset op til DKK 37.500,00!

Kontakt osHar du spørgsmål til dine forsikringer?Du kan ringe +45-9751 33 88 eller skrive til os på e-mail [email protected]

Inspektionsomkostninger

Du har haft en grundstødning og vil have bunden inspiceret?Pantaenius dækker inspektionen uden selvrisiko!

Ingen selvrisiko

Indbrud, transportskade, brand, lynnedslag eller totalskade?Ved disse skadesårsager er der ingen selvrisiko hos Pantaenius!

Page 272: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

272

Afsluttende eksempler

LottoFile

LottoResult

Endelig er der klassen Program, som er klassen med Main() metoden. Det er faktisk også en kompleks klasse, da det er den, som skal validere parametre fra kommandolinjen.

Med ovenstående er det væsentlige vedr. programmet klasser og dermed programmets arkitektur på plads.

Så er der algoritmer, og umiddelbart er der følgende algoritmer, som ikke er trivielle: - Sortering af lottorækker og collections/arrays af lottorækker - Validering af kommandolinjen i Main() - Metoden Create() i LottoGame - Metoden Validate() i LottoGame

Sortering er generel ikke simpel, og der findes flere algoritmer med hver deres fordele og ulemper, men sortering ligger faktisk som en færdig metode i .NET frameworket, så der ingen grund til at skrive sin egen sorteringsmetode.

Så er der validering af kommandolinjen, hvor der skal ske følgende:

hvis option -i forekommer så valider for Validate ellers valider for Createhvis der er en fejl så{print fejlmeddelseafslut program

}

Valider for Create indtil der forekommer en fejl eller alle argumenter er okvalider option -a, -b, -rhvis ok så opret Lotto objektvalider n, der skal være større end 0hvis der en -o option så valider filenavnet ellers sæt filenavnet til skærmenhvis ok så opret et LottoFile objekt

Valider for Validate indtil der forekommer en fejl eller alle argumenter er okvalider inputfile og herunder om det er en LottoFilehvis ok så Opret et Lotto objekt på grundlag af inputfilenValider ugens lottohvis ok så Opret et LottoRow objekt for ugens lotto

Page 273: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

273

Afsluttende eksempler

hvis der en -o option så valider filenavnet ellers sæt filenavnet til skærmenhvis ok så opret et LottoFile objekt

Algoritmen for at oprette lottorækker består primært af en løkke, som opretter rækker i overensstemmelse med kravene og printer det færdige resultat i en file:

Metoden Create()

Opret en container (array, list) til lottorækkergentag indtil alle rækker er dannet{

opret en ny rækkehvis den ikke allerede er i containeren så tilføj den til containeren

}Sorter indholdet af containeren i stigende ordenfor hver række i containeren{print rækken til output filen

}

Til sidst er der ud fra ugens lottotal at validere et spil for antallet af rigtige og printe resultatet i en file:

Metoden Validate()

Opret en container (array, list) til lottorækkergentag for hver række i input filen{hvis row er en lovlig række så {valider row mod ugens lotto

}ellers {marker row som ulovlig

}indsæt row i containeren

}Sorter indholdet af containeren i faldende ordenfor hver række i containeren{print rækken til output filen

}

Bemærkning

Efter man har gennemført et design, har man lavet en overordnet arkitektur for programmet og truffet vigtige beslutninger for det færdige program. Man er herefter klar til at skrive programkoden, men uanset hvor omhyggelig man har været både under analysen og under designet, kan det ske, at der kommer nye ting, og måske opstår der endda nye krav, så kravspecifikationen må opdateres. På samme måde vil programmeringen ofte føre til, at der forekommer ændringer til designet, måske med nye klasser som har indflydelse på programmets arkitektur. I givet fald må også designet opdateres.

Page 274: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

Click on the ad to read more

C# 1: Introduktion til programmering og programmeringssproget C#

274

Afsluttende eksempler

Der er i det væsentlige to grunde til at lave et design. Den vigtigste er, at designarbejdet er en nødvendig proces for at få vigtige beslutninger på plads, inden man tager fat på programmeringen, og den anden er, at resultatet af et design senere kan tjene som dokumentation for, hvordan programmet er lavet. Af hensyn til det sidste skal designet opdateres med væsentlige ændringer, da dokumentationsværdien ellers ikke er til stede.

Hvad angår det første med design som en vigtig aktivitet frem mod opgavens løsning, skal man være opmærksom på detaljeringsgraden. Design er som nævnt en proces, hvis formål er at træffe vigtige beslutninger vedr. programmets arkitektur og gøre valg vedr. algoritmer mv. Designet må imidlertid ikke blive for detaljeret, og der er ikke noget galt i, at der under programmeringen opstår klasser, som ikke fremgår af det oprindelige design. Det er typisk klasser, som ikke repræsentere centrale begreber inden for programmets problemområde, men klasser som en programmør indfører, fordi de er nyttige for at få en god og vedligeholdelsesvenlig kode ud af det. Omvendt kan der også ske det, at der under programmeringen opstår nye klasser for vigtige begreber, og er det tilfældet, må designet opdateres. Mht. detaljeringsgraden skal man hele tiden have for øje, at et design skal give overblik og fastlægge den grundlæggende arkitektur, men et design må ikke være så detaljeret, at det begynder at ligne det færdige program skrevet ved hjælp af figurer og pseudokode. Er det tilfældet, har man lavet noget, som alligevel ikke passer på det færdige resultat, og i bedste fald har man ikke nået andet end at bruge sin tid på en uhensigtsmæssig måde.

Get “Bookboon’s Free Media Advice” Email [email protected]

See the light! The sooner you realize we are right, the sooner your life will get better!

A bit over the top? Yes we know!

We are just that sure that we can make your media activities more effective.

Page 275: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

275

Afsluttende eksempler

Programmering

Jeg vil ikke vise programkoden her, da den er relativ omfattende, men jeg vil referere til den færdige kode, som i øvrigt er fuldt dokumenteret med kommentarer. Jeg vil i stedet have fokus på, hvad der er sket med kravene og designet efter at koden er færdig.

Kravene udvidet med en anmærkning om, at spillet ikke skal tage hensyn til begrebet tillægstal.

Desuden er der lavet en enkelt tilføjelse. Når man har oprettet et lottospil og ønsker at validere det mod ugens lotto, skal resultatet efterfølges en fordeling, som viser, hvor mange rækker der er med 1 rigtig, hvor mange rækker der er med 2 rigtige, osv. Resultatet kunne f.eks. være følgende:

Vedr. designet er der kun foretaget én vigtig ændring. Oprindelig havde jeg arbejdet med en LottoFile og evt. en specialisering heraf. Det har jeg ændret, så der i stedet er tale om to File typer. Programmets overordnede arkitektur er derfor følgende:

LottoGame LottoNumberLottoRow

Program

OutputFile

Lotto

n n1

1

1

InputFile

1

Man kan få Visual Studio til at oprette et klasse diagram. I Solution Explorer vælger man

Add | New Item

og her vælger man Class Diagram. Man kan så trække klasser fra Solution Explorer ind i diagrammet og få et billede, som ligner nedenstående (se næste side). Man skal ikke overvurdere betydningen af denne facilitet, men diagrammet kan anvendes som en dokumentation for, hvordan programmet er bygget op.

Page 276: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

Click on the ad to read more

C# 1: Introduktion til programmering og programmeringssproget C#

276

Afsluttende eksempler

Test

Når programmet er skrevet, skal det testes, og evt. fejl skal rettes. Umiddelbart lyder det måske simpelt, men det er det ikke, og hvis ikke man går systematisk frem, vil man næsten med sikkerhed komme til at overse nogle situationer og med risiko for, at programmet leveres med fejl. Selv dette program, som trods alt ikke er særlig stor, kræver at man gør sig nogle overvejelser vedr. test.

Jeg vil dele testet op i tre dele:

- At options behandles korrekt - At resultatet er korrekt - Hvordan programmet opfører sig ved et stort antal rækker

Mangler du dygtige callcenter medarbejdere?Lad Assistance finde din nye medarbejderVi sætter en ære i at indhente viden om din virksomhed, jeres kultur og værdier, strategi, mission og vision. Herigennem danner vi os et præcist indtryk af jeres foretrukne profil. I rekrutteringsprocessen lægger vi vægt på følgende forhold:

• Grundig behovsafdækning – for et optimalt match• Jobprofil og stillingsopslag• Rådgivning i forhold til valg af annonceringsmedie• Screening af relevante ansøgere (test, analyse og problemløsning)

Kontakt os for et uforpligtende møde på telefon 33 55 00 90

Page 277: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

277

Afsluttende eksempler

I forbindelse med test skal man huske at teste både med et lovligt input og et ulovligt input, og i alle tilfælde undersøge om man får det forventede resultat.

Page 278: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

278

Afsluttende eksempler

I dette tilfælde er der mulighed for 7 forskellige options, som enten kan være der eller ikke være der, og hvis man dertil lægger en ekstra svarende til en ulovlig option er man på 8. For hver af disse options er der tre muligheder svarende til, at der kan være en lovlig værdi, en ulovlig værdi, eller værdien kan mangle, og der er derfor noget der ligner 76823 8 =⋅ muligheder for argumenter på kommandolinjen. Da man desuden skal teste om rækkefølgen af de enkelte options betyder noget, kan man se, at der bliver et overordentlig stort antal tilfælde at teste - så stort at det i praksis er umuligt at efterprøve alle tilfælde ved almindelig afprøvning. Det skal sammenholdes med, at hvis et test fejler, skal fejlen rettes, og alle tests skal i princippet gå om for at være sikker på, at den ændring man har lavet ikke har utilsigtede sideeffekter.

I en sådan situation skriver jeg undertiden en bat file med kommanoder:

lottolotto -n 5lotto -n 5 -a 1 -b 48 -r 6lotto -n 5 -a 1 -b 48 -r 16lotto -n 5 -a 1 -b 48 -x 5 -r 6lotto -n 5 -a 1 48 -b -r 6lotto -n 20 -o test1.txtlotto -o result1.txt -i test1.txtlotto -o result1.txt -i test1.txt -u 2 5 10 15 20 25 30 35lotto -o result1.txt -i test1.txt -u 5 10 15 20 25 30 35lotto -o result1.txt -u 5 10 15 20 25 30 35 -i test1.txtlotto -b 48 -r 6 -n 10000 -o test2.txtlotto -i test2.txt -o result2.txt -u 8 16 24 32 40 48

Her er nogle kommandoer lovlige, mens andre er ulovlige. Hvis filen hedder Test.bat og man herefter kører kommandoerne som:

Test > test.txt

får man oprettet en file med resultatet, hvor det er let at kontrollere, om kommandoerne er udført korrekt, og frem for alt er det let at gentage testet.

Expression

Programmet Lotto har primært fokus på klasser og valg af klasser, mens det næste program i højere grad har fokus på algoritmer.

Opgaveformulering

Der skal skrives et program, hvor man kan indtaste et matematisk udtryk, som afhænger af én eller flere variabler, f.eks.

Page 279: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

Click on the ad to read more

C# 1: Introduktion til programmering og programmeringssproget C#

279

Afsluttende eksempler

som afhænger af to variabler. Herefter skal man kunne indtaste værdier for programmets variabler, og programmet skal så evaluere udtrykket for disse variabler.

Hvis der forekommer en fejl:

- der indtastes et udtryk, der ikke er syntaktisk korrekt - der indtastes argumenter, som ikke er lovlige i henhold til det aktuelle udtryk - der opstår en fejl, når udtrykket evalueres

skal programmet printe en fejlmeddelelse.

I eksempeludtrykket ovenfor indgår sinus og kvadratrod. Programmet skal understøtte de mest almindelige matematiske funktioner lidt svarende til hvad der gælder for en matematisk lommeregner, men det er et ønske, at det skal være let at udvide programmet med nye funktioner, hvis der opstår behov.

I dette tilfælde er programmet en konsolapplikation, men det er et ønske, at de basale dele af koden vedr. udtryk kan anvendes i andre sammenhænge og derfor så godt som muligt er adskilt fra den del, der har at gøre med brugerens indtastninger.

Page 280: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

280

Afsluttende eksempler

Analyse

Inden man kan tage fat på opgaven er der et par ting som skal afklares:

- hvad er et udtryk helt præcis - hvad er syntaksen for et udtryk - hvad forstår man ved at evaluere et udtryk - hvordan skal bruger interaktionen være

Hvad angår det første stilles der følgende krav:

- Et udtryk er ikke case sensitive, og det skal være ligegyldigt om man skriver med små eller store bogstaver.

- Et udtryk kan indeholde et vilkårligt antal variabler, som betegnes x0, x1, x2, ..., dvs. et x efterfulgt af et ikke negativt heltal eller nummer. Der skal ikke stilles krav om, at nummereringen er fortløbende. Endelig skal det være tilladt blot at skrive x, der skal være et alias for x0.

- Man angiver altid tal (konstanter) med punktum som decimaltegn. - Et udtryk skal understøtte de fire almindelige regneoperatorer +, -, * og /. - Det skal være tilladt at sætte parenteser. - Hvis en matematiske funktioner har flere argumenter, skal de adskilles af komma.

En matematisk funktion er identificeret af et navn og derefter kan følge en parameterliste i parentes. I et udtryk skal man kunne anvende følgende funktioner:

- konstante funktioner (funktioner uden parametre) - pi - e

- funktioner af 1 variabel - sin - asin - cos - acos - tan - atan - cot - acot - ln - exp - log - alog - sqr

Page 281: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

281

Afsluttende eksempler

- sqrt - abs - frac - floor

- funktioner af 2 variabler - pow - root

Det er de grundlæggende krav til et udtryk, men det er nødvendigt at være mere præcis og i detaljer beskrive hvilke udtryk, der må forekomme. Det vil jeg gøre ved hjælp af syntaksdiagrammer.

Overordnet skal et udtryk være følgende:

argument

operator expression

expression

Dvs. at et udtryk kan være et enkelt argument, eller det kan være et argument efterfulgt af en operator, der igen følges af et nyt udtryk. Bemærk, at det er en rekursiv definition, hvor et begreb - her en expression - defineres ved hjælp af sig selv.

Tilbage er der at definere, hvad man skal forstå ved hhv. et argument og en operator. Jeg vil starte med det sidste, som blot er et symbol for én af de fire regningsarter. Det kan også beskrives på følgende måde:

+

-

*

/

operator

Dernæst er der et argument, som er et noget mere komplekst begreb:

Page 282: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

Click on the ad to read more

C# 1: Introduktion til programmering og programmeringssproget C#

282

Afsluttende eksempler

sign

const

var

function

( expression )

argument

Et argument kan starte med et eller flere fortegn (plus eller minus). Dernæst er der fire muligheder

- const, der altid vil være et ikke negativt tal - en streng der kan konverteres til en double - var, der er en variabel og dermed en streng på formen Xn, hvor n er et indeks - function, der er en matematisk funktion - et udtryk i parentes

Tilbage er der så at få defineret, hvad en funktion er, der kan beskrives på følgende måde:

Hvor mange skal tage en beslutning, før man kan føre

en beslutning ud i livet?

Slip for komplekse kommandoveje. Hos NNIT løser vi de store it-opgaver i små teams, der ikke skal spørge om lov til at tage

en beslutning. Se ledige job på nnit.dk/job

RE

TH

INK

PIP

EL

INE

Hvor mange skal tage en beslutning, før man kan føre

en beslutning ud i livet?

Slip for komplekse kommandoveje. Hos NNIT løser vi de store it-opgaver i små teams, der ikke skal spørge om lov til at tage

en beslutning. Se ledige job på nnit.dk/job

RE

TH

INK

PIP

EL

INE

Hvor mange skal tage en beslutning, før man kan føre

en beslutning ud i livet?

Slip for komplekse kommandoveje. Hos NNIT løser vi de store it-opgaver i små teams, der ikke skal spørge om lov til at tage

en beslutning. Se ledige job på nnit.dk/job

RE

TH

INK

PIP

EL

INE

Hvor mange skal tage en beslutning, før man kan føre

en beslutning ud i livet?

Slip for komplekse kommandoveje. Hos NNIT løser vi de store it-opgaver i små teams, der ikke skal spørge om lov til at tage

en beslutning. Se ledige job på nnit.dk/job

RE

TH

INK

PIP

EL

INE

Page 283: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

283

Afsluttende eksempler

( argumentlist )

functionname

og hvor name er en af de funktioner, der er nævnt ovenfor.

Til sidst er der kun at definere hvad argumentlist er:

Expression

, argumentlist

argumentlist

Bemærk, at det igen er en rekursiv definition, og at et argumentlist er et eller flere udtryk adskilt af komma.

Hermed har jeg ret præcist beskrevet, hvad man forstår ved et lovligt udtryk.

Mht. at evaluere et udtryk er det et spørgsmål om at indsætte værdier for udtrykkets variabler, hvorefter udtrykkets værdi kan bestemmes. Værdien af et udtryk skal altid være en double.

Det sidste problem er brugerinteraktionen. Den kan beskrives på følgende måde:

indtast udtryksålænge udtrykket ikke er tomt gentag{hvis udtrykket er syntaktisk korrekt så{indtast argumentersålænge der er indtastet argumenter gentag{hvis argumenterne er lovlige så{evaluer udtrykketprint resultatet

}ellers print en fejlmeddelelseindtast argumenter

}}ellers print en fejlmeddelelseindtast udtryk

}

Dvs. at indtastning af enten et udtryk eller argumenter afsluttes, når der blot tastes enter. Vedr. indtastning af argumenter indtastes de som et antal tal på kommandolinjen adskilt af mellemrum.

Page 284: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

284

Afsluttende eksempler

Design

Grundlæggende vil jeg tænke på et udtryk som en class, og udover en konstruktør som opretter udtrykket ud fra en streng skal klassen i virkeligheden kun have en enkelt metode, som kan evaluere udtrykket. Svarende hertil og med udgangspunkt i ovenstående skitse vedr. brugerinteraktionen kan man skitsere programmet som:

Program

Main()EnterExpression()EnterArguments()Print()

Expression

Expression(string)Value(arguments)

Her er programmet og dermed klassen Program i princippet simpel og består grundlæggende af

- brugerinteraktionen svarende til skitsen fra analysen - indtastning og parsing af et udtryk med kontrol af, om et udtryk er lovligt - indtastning og parsing af argumenter til et udtryk - print af resultatet af evaluering af et udtryk - fejlhåndteringen

Hvad angår det første, er skitsen fra analysen egentlig en algoritme for Main() metoden, og der er ikke meget at tage stilling til.

Indtastning af et udtryk er blot indtastning af en streng, men parsingen og kontrol af om et udtryk er lovligt er på ingen måde simpel og er hele udfordringen i opgaven. Jeg vil imidlertid udskyde denne opgave til Expression klassens konstruktør, så den får en streng som parameter, og det er så konstruktørens opgave ud fra analysens syntaksdiagrammer at kontrollere, om strengen repræsenterer et lovligt udtryk. Er det ikke tilfældet, skal konstruktøren rejse en exception.

Når et udtryk skal evalueres, skal brugeren indtaste et eller flere argumenter adskilt af mellemrum. Hver af disse argumenter skal parses til en double, og det skal ske i Program klassen, så metoden Value() i Expression klassen som argumenter har et array af typen double som parameter.

Print() er en simpel metode, som skal printe udtrykket, argumenterne og hvad udtrykket er evalueret til, f.eks. noget i retning af

Page 285: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

Click on the ad to read more

C# 1: Introduktion til programmering og programmeringssproget C#

285

Afsluttende eksempler

Når resultatet skrives på flere linjer, er det af hensyn til, at udtryk inkl. argumenter kan blive lange.

Endelig er der fejlhåndteringen. Ved fejl skal der komme en forklarende fejlmeddelelse på skærmen, og der kan i princippet forekomme fejl i tre situationer:

- Brugeren indtaster et udtryk, som ikke er syntaktisk korrekt. I det tilfælde rejser konstruktøren i klassen Expression en exception.

- Brugeren indtaster argumenter til et udtryk, som ikke er lovlige. I dette tilfælde er det Program klassen, som skal både fange og behandle fejlen.

- Et udtryk kan ikke valideres, fordi der opstår en fejl i beregningerne (f.eks. ved division med 0). Her vil Expression klassen rejse en exception.

I klassen Expression er der to udfordringer i form af konstruktøren og metoden Value(), og her er den første udfordring den største. Konstruktøren har en parameter i form af en streng, og den skal udføre tre operationer:

Page 286: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

286

Afsluttende eksempler

- Scanne udtrykket, som betyder, at strengen skal splittes op i de elementer (tokens), som indgår i udtrykket.

- Parse udtrykket, som betyder kontrol af udtrykkets syntaks svarende til syntaksdiagrammerne fra analysen.

- Konvertere udtrykket til postfix form, der betyder at udtrykkets elementer omorganiseres til en sekvens af tokens på postfix form.

For at løse det første problem, skal parameterstrengen opdeles i elementer, som sædvanligvis kaldes tokens. Et token er således et objekt, som angiver et element, der indgår i et udtryk. Hvis man f.eks. betragter udtrykket

består det af 7 tokens:

Når strengen er delt op, har man en række tokens, som hver er en streng. De enkelte tokens skal behandles forskelligt og skal have forskellige egenskaber, så jeg vil skrive en klasse til hver af de tokens, der kan forekomme, og klasserne er ordnet i et hierarki (se næste side). Alle typer er overordentlig simple, og årsagen til hierarkiet er dels, at det giver mulighed for at behandle alle tokens på samme måde, og dels at det på den måde bliver let at udvide med nye tokens, hvis et udtryk f.eks. skal understøtte en ny funktion.

Efter scanningen har man en liste af tokens, og parsingen gå ud på at undersøge om denne liste med tokens er i overensstemmelse med syntaksreglerne. I koden svarer det til at skrive en metode svarende til hver af ovenstående diagrammer, og det er princippet simpelt, men kræver dog en teknik, som kaldes rekursion, og som er beskrevet nedenfor.

Sædvanligvis skriver man udtryk på infix form, der betyder, at man skriver operatoren mellem to operander, altså f.eks.

32 +

som betyder summen af 2 og 3. Hvis der indgår flere operatorer, er det nødvendigt med regler for, hvordan udtrykket skal evalueres. F.eks. betyder

43*2 +

Page 287: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

Click on the ad to read more

C# 1: Introduktion til programmering og programmeringssproget C#

287

Afsluttende eksempler

at man først beregner produktet af 2 og 3 og dernæst adderer dette resultat til 4 - resultatet er 10. I modsætning betyder

4*32 +

at man først beregner produktet af 3 og 4, da man tillægger multiplikation højere prioritet end addition - resultatet er altså 14. Ønsker man at undertrykke denne regel, så additionen udføres først, er det nødvendigt at sætte en parentes:

4*)32( +

der har værdien 20.

Hvis der i et udtryk forekommer flere operatorer af samme prioritet, er reglen, at operatorerne evalueres fra venstre. Herunder beregnes først summen af 2 og 3 og dernæst subtraheres 4, fordi addition og subtraktion har samme prioritet:

432 −+

SÆT LYD PÅ FREMTIDENWidex udvikler højteknologiske høreapparater til gavn for de 500 millioner mennesker verden over, der har nedsat hørelse.

Mere end fem årtiers intensiv forskning og udvikling har gjort os til en af verdens førende høreapparatproducenter, og vi udvikler digital teknologi af en kvalitet, kun få kan måle sig med.

Som videnbaseret virksomhed betragter vi medarbejderne som vores vigtigste kapital. Vi kan godt lide at gøre tingene selv og sætter en ære i at være selvforsynende inden for de fl este om-råder. Det skaber et spændende, tværfagligt arbejdsmiljø med plads til initiativ og rig mulighed for personlig og faglig udvikling.

Vil du være med til at sætte lyd på fremtiden? Følg med i vores jobopslag på www.widex.dk/job eller skriv til [email protected]

www.widex.com

Page 288: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

288

Afsluttende eksempler

Token

ArgToken

ConstToken

VarToken

OprToken

AddToken

SubToken

MulToken

DivToken

SignToken

LeftToken

RightToken

SepToken

FuncToken

PiToken

SinToken

AsinToken

RootToken

………..

Et udtryk kan være mere kompleks, f.eks.

)7*)65/(())43(*21( +++

Page 289: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

289

Afsluttende eksempler

altså, hvor der er parenteser inden i parenteser. Udtrykkets værdi er i øvrigt 0,194805. Når et udtryk indeholder parenteser, skal parenteserne evalueres først startende med de inderste parenteser. Det er bestemt muligt at skrive en metode, som klarer det, men bliver udtrykket mere kompleks med matematiske funktioner og mange parenteser, er det ikke simpelt, og derfor går man typisk en anden vej og i stedet konvertere udtrykket til postfix form. Det betyder, at en operator skrives efter de argumenter, som den skal virke på. Således kan ovenstående udtryk skrives som

Hvis man f.eks. skal udregne værdien af +4*23 , foregår det som

Idéen er, at et ethvert udtryk kan skrives på postfix form uden anvendelse af parenteser. Når udtrykket skal evalueres, gennemløbes det bare fra venstre mod højre. Hver gang man kommer til en operand, lægges den på en stak. Kommer man til en operator, poper man stakken to gange (hvis det er en operator med to argumenter), beregner resultatet, og lægger det på stakken. Til sidst vil stakken blot indeholde et element, som er resultatet. Fremgangsmåden kan med udgangspunkt i det sidste af ovenstående udtryk illustreres på følgende måde:

1 12

123

1234

1 2 3 4127

+1

14

*15+

155

5155

6

6

15+

111511

7

7

*1577

/0.1948

Konklusionen er, at det er langt lettere at evaluere et udtryk på postfix form end på infix form, og det kan derfor betale sig at søge en strategi (en algoritme) til at konvertere et udtryk fra infix til postfix form. Det kan man klare på følgende måde ved hjælp af en stak:

udtrykket gennemløbes fra venstre, og for hvert element

1. hvis det er et fortegn push det på stakken

2. hvis det er en funktion push det på stakken

3. hvis det er en variabel push det på stakken

Page 290: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

Click on the ad to read more

C# 1: Introduktion til programmering og programmeringssproget C#

290

Afsluttende eksempler

4. hvis det er en konstant push det på stakken

5. hvis det er en venstre parentes push det på stakken

6. hvis det er en højre parentes, så pop stakken og tilføj toppen

af stakken til resultatet indtil man kommer til en venstre

parentes

7. hvis det er en operator så pop stakken og tilføj toppen til

resultatet så længe prioriteten af toppen af stakken er mindre

end eller lig med prioriteten af elementet, push elementet på

stakken

pop stakken og tilføj toppen af stakken til resultatet indtil stakken

er tom

Som du kan se, er det helt afgørende i algoritmen, at der er tildelt de rigtige prioriteter til de enkelte elementer. Det er prioriteterne der afgør, hvornår der flyttes fra stakken til resultatet, der blot er en list. De to vigtige punkter i algoritmen er 6 og 7. Hvis man kommer til en operator - f.eks. en multiplikation - så skal man først flytte alt på stakken med en bedre prioritet end multiplikation til resultatlisten. Det vil være konstanter, variabler og funktioner, og herefter lægges multiplikations operatoren på stakken. Dvs. at hvis udtrykkets tokens er konverteret til postfix form, er det simpelt at implementere metode Value() i klassen Expression.

Hvis man ser på udtrykket

Dedicated Analytical Solutionswww.foss.dk/careers

Protein 13.2%

Moisture 8.4%

Starch 67%

FOSS is known throughout the world for efficient analytical solutions that help to improve both food quality and safety in the global food market. We are playing an increasingly important role in ensuring optimal use of valuable natural resources, and have throughout the years created ground-breaking innovations. And there’s more to come. At FOSS you will find professional challenges, training and development in a work environment that offers good work/ life balance. Join us and make a difference.

80% of the grain traded in the world is analysed on a FOSS solution

Page 291: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

291

Afsluttende eksempler

)7*)65/(())43(*21( +++

kan det konverteres til postfix form på følgende måde:

((

1(1

(+

+

1

(+

2

2

(+

*

*

1 2

(+*

(

(

(+*(

3

3

(+*(

+

+

1 2 3

(+*(+

4

4

(+*

)

1 2 3 4 +

)

1 2 3 4 + * +

//

/(

(

(/(

(

(

/(

5

5

1 2 3 4 + * + 5

(

/(

+

+(

/(

+

6

6

/(

)

1 2 3 4 + * + 5 6 +

/(

/(

7

7*

*

*

/)

1 2 3 4 + * + 5 6 + 7 *1 2 3 4 + * + 5 6 + 7 * /

I den konkrete opgave, vil jeg anvende følgende prioriteter:

- konstant, variabel 0 - fortegn 1 - funktion 2 - multiplikation, division 3 - addition, subtraktion 4 - venstre parentes 9 - højre parentes, komma 99

Bemærkning

I forbindelse med løsning af opgaven (syntakskontrollen) får jeg brug for rekursion og derfor et par ord om, hvad det er.

En metode i en klasse kan opfattes som en isoleret kode, der udfører en bestemt operation på grundlag af parametre, og som evt. returnerer en værdi. Metodens sætninger, er de kommandoer den udfører, og der er ingen begrænsninger på, hvad det kan være. Det kan f.eks. være kald af en anden metode, og en metode kan dermed specielt også kalde sig selv. Er det tilfældet, siger man at metoden er rekursiv. Som et eksempel på en rekursiv metode - og en metode som ikke vedrører den konkrete opgave - er herunder vist en metode, som bestemmer fakultetet af n:

Page 292: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

292

Afsluttende eksempler

static ulong Fakultet(uint n){if (n == 0 || n == 1) return 1;return n * Fakultet(n - 1);

}

Ved første øjekast kan rekursive metoder være svære at gennemskue, men er man først fortrolig med princippet, er det ikke specielt svært. Herover er princippet, at hvis n er 0 eller 1, så kan man direkte bestemme resultatet. Hvis n er større end 1, kan man bestemme fakultetet af n som n gange fakultetet af n-1. Man kan tænke på det på den måde, at bestemme fakultetet af n er reduceret til at bestemme fakultetet af n-1, som er et mindre problem, end det man startede med: At bestemme fakultet af n. Hvis man gentager det tilstrækkelig mange gange, kommer man til sidst til det simple tilfælde, hvor n er 0 eller 1, og hvor man direkte kan bestemme resultatet.

Princippet i en rekursiv metode er således, at et problem kan opdeles i to problemer: Et simpelt problem, som man umiddelbart kan løse, og et simplere (mindre) problem af samme slags som det oprindelige.

Formelt kan fakultetet af n defineres på følgende måde:

>−==

=1)!1(*

101!

nfornnnellernfor

n

Altså ved en rekursiv definition, og i sådanne situationer er rekursion ofte en god løsning. I dette tilfælde er metoden Fakultet() simpelthen blot en omskrivning af den matematiske formel til en metode i C#.

Det er klart, at i dette tilfælde kunne metoden skrives iterativt ved hjælp af en simpel løkke, og denne løsning ville endda være at foretrække, men i andre situationer er rekursion en god løsning, der kan give simple løsninger og endda en kode, der er lettere at læse og forstå end en tilsvarende iterativ løsning. Der er dog grund til altid at være opmærksom på rekursive metoder, da hvert rekursiv kald opretter en aktiveringsblok på stakken. Der er derfor en fare for, at rekursive metoder bruger hele stakken med det resultat, at programmet vil gå ned.

Programmering

Denne gang er der ingen ændringer til hverken analyse eller design, og programmet er skrevet helt i overensstemmelse med ovenstående design.

I følge opgaveformuleringen var der to særlige ønsker:

- At det skulle være let at udvide et udtryk med nye funktioner. - At et udtryk skulle kunne anvendes i andre sammenhænge end den konkrete opgave.

Jeg vil derfor se på i hvilke udstrækning disse mål er indfriet.

Page 293: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

293

Afsluttende eksempler

Programmet består primært af klassen Expression og i tilknytning hertil et stort antal andre typer i form af interfaces og klasser for de enkelte tokens. Endelig er der en statisk klasse Tokens med en enkelt metode, som skal oversætte navnet for et token til et Token objekt, samt en statisk klasse Tokenizer med to statiske hjælpemetoder til at scanne input strengen.

For bedre at kunne genbruge disse klasser i andre sammenhænge, er de placeret i et class libray, og resultatet er derfor et dll, som anvendes i hovedprogrammet - og dermed på samme måde kan anvendes i andre programmer, som måtte have behov for typen Expression. Da jeg kun én gang tidligere har vist, hvordan man laver et class libray vil jeg her gennemgå processen.

Jeg starter med et nyt Console Application projekt, som jeg har kaldt Expression. Herved oprettes en Solution med navnet Expression og herunder et projekt med navnet Expression. En Solution i Visual Studio kan have flere projekter, og i dette tilfælde højreklikker jeg på Solution navnet i Solution Explorer og vælger Add | New Project:

Herefter får man det sædvanlige projektvindue, og jeg opretter et Class Library projekt, som jeg har kaldt MathExpression:

Page 294: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

Click on the ad to read more

C# 1: Introduktion til programmering og programmeringssproget C#

294

Afsluttende eksempler

Jeg sletter den autogenererede klasse med navnet Class1 og tilføjer og skriver de klasser som mit library skal indeholde.

HD – vejen tilen karrierei erhvervslivet

Læs mereAarhus: hd.au.dkHerning: auhe.au.dk/hd

LÆS HD I ØKONOMI OG LEDELSE

HD er en anerkendt diplom- uddannelse, som giver dig mulighed for at specialisere dig inden for det erhvervsøkonomiske fagområde ved siden af dit job.

Page 295: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

295

Afsluttende eksempler

Jeg har foretaget endnu et lille tiltag mht. at lave et genbrugeligt klassebibliotek. Klassen Expression er hovedklassen, og er den som skal anvendes af selve programmet, og den er derfor defineret public. Det samme gælder for klassen Tokenizer, da den også kan have interesse i andre sammenhænge end det aktuelle program, men alle de øvrige klasser er defineret internal (som i øvrigt er default) og angiver, at de kun kan anvendes inden for det dll som indeholder klasserne. Det er selvfølgelig ikke nødvendigt, men det er klasser, som alle kan opfattes som hjælpeklasser til Expression, og de bør derfor i princippet ikke være til rådighed uden for dll’et. Med Visual Studio termer kan man tænke på en internal type, som en type der kun kan anvendes for det projekt, som den er en del af.

Med dll’et færdigt skal man i hovedprogrammet have sat en reference til det. Det er let, da begge projekt tilhører samme Solution. I projektet Expression højreklikker man på References:

og har vælger man Add Reference. Man kan nu finde dll’et under Solution:

Herefter er dll’et tilføjet til programmets projekt og kan anvendes.

Page 296: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

296

Afsluttende eksempler

Så er der problemet med, at det skal være muligt at udvide programmet med nye funktioner, og det er kun løst delvis. Som eksempel vil jeg udvide klassen Expression med en funktion, som bestemmer fakultetet. Det kræver to ændringer i dll’et. Først skal der tilføjes et nyt token:

internal class FactorialToken : FuncToken{public override int Count{get { return 1; }

}

public override double Value(params double[] x){if (x.Length != Count || x[0] < 0)throw new ExpressionException(“Factorial(x), x >= 0: Ulovligt argument...”);

uint n = (uint)x[0];ulong u = 1;for (uint i = 2; i <= n; ++i) u *= i;return u;

}

public override string ToString(){return “Factorial”;

}}

Dernæst skal der indsættes en ny indgang i switch sætningen i klassen Tokens:

case “factorial”: return new FactorialToken();

Det er også alt, og Expression har nu en ny funktion. Bemærk, at det er nødvendigt at ændre i koden, men kun to steder og alene i internal klasser, og koden til klassen Expression er uændret.

Bemærkning

Som afslutning på denne bog vil jeg nævne debuggeren, der er et vigtigt værktøj i Visual Studio. Det følgende er på ingen måde en komplet gennemgang af debuggeren, men det er en antydning af, hvad den kan bruges til.

Når man har skrevet et program og skal afprøve det, vil det ofte være sådan at det fejler. Måske får man et forkert resultat, eller også går programmet ned. Opgave er da at finde fejlen og rette den, og her kan debuggeren hjælpe. Man kan sætte et breakpoint, som betyder at kørslen stopper, når programmet når til det sted i koden, og man kan så se værdien af variabler og undersøge om de har den rigtige værdi. Man kan også steppe fremad i koden sætning for sætning og hele tiden følge, hvad der sker med variabler. Debuggeren er et uroligt værktøj til at finde, hvor et program fejler, men generelt kan debuggeren anvendes til at analysere koden.

Page 297: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

Download gratis bøger på bookboon.com

C# 1: Introduktion til programmering og programmeringssproget C#

297

Afsluttende eksempler

Som eksempel har dette program en metode ParseArguments(), som anvendes til at parse argumenter til et udtryk. Her har jeg sat et breakpoint ud for metodens første sætning, hvilket man gør ved blot at klikke med musen:

Hvis man nu kører programmet som Start Debugging, indtaster et udtryk og herefter indtaster argumenter til udtrykket, vil kørslen stoppe på den linje, hvor der er sat et breakpoint. Samtidig kan man se de lokale variabler og parametre og deres værdier. Man kan herefter ved at taste F10 steppe programmet igennem og se, hvad der sker med variablerne. Ved at vælge fanen Watch er det også muligt at holde øje med instance variabler.

Page 298: ,QWURGXNWLRQWLOSURJUDPPHULQJRJVSURJHW& … · C# 1 Introduktion til programmering og ... Download gratis bøger på bookboon.com C# 1: ... som ønsker at beskæftige sig med programmering

C# 1: Introduktion til programmering og programmeringssproget C#

298

Afsluttende eksempler