Tæt på datatyper i C#

Tags:    c#
Skrevet af Bruger #2730 @ 06.05.2005
Denne artikel er for begynderen der ønsker at vide lidt mere om de datatyper der benyttes når man programmerer i C#, samt hvorfor objekter opfører sig som de gør.

Datatyper


Der findes to slags datatyper i C#, der er de datatyper der altid overføres med værdien samt de værdier der blot overføres med en reference. Disse datatyper kaldes henholdsvis "Value types" og Reference types". Fælles for begge disse datatyper er at de arver begge fra Object klassen og derfor er de pr. definition et objekt. I C# er de primitive datatyper (int, string, bool, char) altid "value types" mens alle andre objekter samt hjemmelavede objekter er "reference types". At en datatype er en "value type" betyder at når man tildeler værdi til/fra en "value type" datatype, bliver værdien kopieret over i den nye variabel. Det vil også sige at ved "reference type" datatyper bliver værdien ikke kopieret, men der bliver blot assignet en pointer til værdien som så peger ud på objektet der findes i hukommelsen. Dette har naturligvis nogle konsekvenser og muligvis noget man skal tage højde for når man sidder og koder sit C# program.

Fold kodeboks ind/udKode 

Hvad er værdien af variablen y? Hvis vi lige husker på at int er en "value type" så ved vi med det samme at værdien af y er 15, da værdien i "value types" bliver kopieret og ikke bliver refereret som en pointer ned i hukommelsen ligesom ved "reference types". Hvis vi laver det samme eksempel med en "reference type" er vi nødt til at lege med et fiktivt objekt "Bil".

Fold kodeboks ind/udKode 

Hvad er værdien af bil2.Model? Nu ved vi så at objektet bil er en "reference type" og derved bliver der ikke kopieret data over i det nye objekt (bil2), derimod bliver bil2 tildelt en pointer ned til et objekt i hukommelsen, så nu peger bil1 og bil 2 på det samme objekt nede i hukommelsen. Det betyder at hvis et af de to objekter ændrer i objektet Bil, vil det slå igennem på de andre objekter der også peger på dette objekt. Det betyder at værdien af bil2.Model er "Ferrari".

Stakken og Heapen


For at forstå de forskellige datatyper er det også godt at vide lidt om hukommelsen i en applikation. Hukommelsen en applikation optager deles ind i to hovedgrupper: Stakken og Heapen. Stakken er en del af hukommelsen reserveret at applikationen til at udføre programmet i. En stak fungerer således at man smider noget i toppen af stakken og det er så også det første der skal tages af stakken. Når man kalder en funktion i C# bliver denne funktions variable smidt (pushed) på stakken, når funktionen går ud af scope (afsluttes) tages (poppes) disse variable af stakken igen og hukommelsen frigives og er klar til næste funktion. Stakken er den "hurtigste" hukommelse af de to typer, da den er klar til at blive brugt hele tiden. Heapen er derimod et separat stykke hukommelse der er reserveret til at oprette objekter i, det er .NET frameworket (rent faktisk er det kun Common Language Runtime (CLR) der vedligeholder denne hukommelse) der står for at vedligeholde heapen og sørge for at objekter der ikke længere benyttes bliver destrueret og den hukommelse de optog bliver genbrugt (dette kaldes garbage collection). Som beskrevet tidligere så er alle "value type" datatyper allokeret på stakken, mens "reference type" datatyper rent faktisk er allokeret to steder, både på stakken op på heapen! Selve objektet og alle de parametre og værdier det indeholder er allokeret i heapen, mens en pointer (pegepind) til objektet er allokeret på stakken. Det betyder at når (som i ovenstående eksempel med bilerne) at jeg har to objekter der peger på samme opjekt, har både bil1 og bil2 en pointer på stakken der peger ned på det samme objekt i heapen. Når så jeg nedlægger bil1 objektet, bliver dens pointer slettet fra stakken, men selve objektet bil1 bliver ved med at eksistere, da bil2 også peger på dette objekt. Når jeg så sletter dette objekt, og derved mister bil objektet i heapen sin sidste reference fra stakken, bliver objektet i heapen nedlagt og dens hukommelse frigjort til senere brug.

Klasser og strukturer


For at afrunde denne artikel omkring datatyper i C# vil jeg kort beskrive hvordan klasser (class) og strukturer (struct) opfører sig, rent hukommelsesmæssigt. En klasse bliver på et tidspunkt i dets livscyklus instantieret til et objekt. Når dette sker, ved vi fra tidligere, at dette bliver allokeret på heapen med en pointer i stakken. En struct derimod bliver allokeret direkte på stakken og vil derfor altid performe bedre end en klasse. Man skal dog passe på med at smide for meget på stakken, da stakken kun har en bestemt størrelse og hvis man kommer ud over denne størrelse får man en stack overflow fejl. Structs bør kun benyttes til mindre "objekter" der bliver oprettet og nedlagt ofte eller der er begrænsede i størrelse.

Hvad synes du om denne artikel? Giv din mening til kende ved at stemme via pilene til venstre og/eller lægge en kommentar herunder.

Del også gerne artiklen med dine Facebook venner:  

Kommentarer (1)

User
Bruger #6701 @ 05.09.05 14:42
Rimelig artikel men måske lidt kortfattet !
Du skal være logget ind for at skrive en kommentar.
t