Programmering

Et dybt dyk: Værdi og referencetyper i .Net

Typer i Microsoft .Net kan være enten værditype eller referencetype. Mens værdityper generelt lagres i stakken, gemmes referencetyper i den administrerede bunke.

En værditype stammer fra System.ValueType og indeholder dataene i sin egen hukommelsesallokering. Med andre ord har variabler eller objekter eller værdityper deres egen kopi af dataene.

En referencetype udvider i mellemtiden System.Object og peger på et sted i hukommelsen, der indeholder de faktiske data. Du kan forestille dig en referencetype svarende til en markør, der implicit henvises til, når du får adgang til dem. De indbyggede referencetyper understøttet af C # inkluderer: objekt, streng og dynamik. Alle grundlæggende datatyper, boolsk, dato, strukturer og enums er eksempler på værdityper. Eksempler på referencetyper inkluderer: strenge, arrays, objekter fra klasser osv. For at oprette referencetyper i C # kan du drage fordel af disse nøgleord: klasse, interface og delegeret.

Bemærk, at du i modsætning til en referencetype ikke kan stamme fra en værditype, og du kan heller ikke tildele en nulværdi direkte til en værditype. Du kan kun tildele en nulværdi til en værditype ved at udnytte de nulbare typer - en funktion tilføjet til de nyere versioner af .Net Framework. Når en værditype kopieres til en anden, kopieres værdien. Derfor kan du manipulere værdierne i dem uafhængigt af den anden - en ændring i den ene påvirker ikke den anden. Tværtimod, når du kopierer en referencetype til en anden, kopieres referencen. Hvis du ændrer en af ​​dem, påvirkes den anden også. For eksempel, hvis en af ​​referencen er indstillet til null, bliver den anden også null.

Opbevaringssteder

CLR gemmer objekter i tre typer opbevaringssteder - registre, stakken eller den administrerede bunke. Mens de kortvarige genstande opbevares i registre eller stak, gemmes de langvarige genstande i bunken. Som jeg nævnte tidligere, gemmes værdityper generelt i stakken.

Det er en almindelig misforståelse, at værdityper altid er gemt i stakken. Jeg vil hellere sige, at værdityper kan gemmes i stakken, når variablen enten er en midlertidig variabel eller er en lokal variabel, og JIT-kompilatoren beslutter ikke at registrere værdien. I det væsentlige afhænger den aktuelle placering af en værditype af implementeringen af ​​JIT-kompilatoren. Bemærk, at en værditype kan lagres i en stabelramme, i CPU-registeret eller endda i bunkehukommelsen, hvis værditypen er indeholdt i et objekt, dvs. hvis det er en del af en referencetype. Tværtimod gemmes referencetyper i GC-bunken. Referencen lagres i en stak, mens objektet tildeles i bunken.

Forekomster eller referencer af en værditype gemmes i stakken, registeret eller i bunken afhængigt af om levetiden for forekomsten eller referencen er kortvarig eller langvarig. En værditype kan findes på stakken, hvis de er lokale variabler og i den administrerede bunke, hvis de er felter i en klasse, dvs. de tilhører eller er en del af en referencetype.

At passere værdi og passere ved reference

Følgende kodeliste illustrerer, hvordan du kan overføre en variabel til en metode efter værdi.

 statisk tomrumsforøgelse (int i)

        {

i = i + 1;

        }

statisk tomrum Main ()

        {

int x = 1;

Forøgelse (x);

Console.WriteLine ("Værdien af ​​x er:" + x);

Console.Read ();

        }

Bemærk, at du kan sende en værditype som reference til en metode ved hjælp af ref-nøgleordet. Følgende kodeliste illustrerer dette.

statisk tomrumsforøgelse (ref int i)

        {

i = i + 1;

        }

statisk tomrum Main ()

        {

int x = 1;

Forøgelse (ref x);

Console.WriteLine ("Værdien af ​​x er:" + x);

Console.Read ();

        }

Når ovenstående kode udføres, vises meddelelsen "Værdien af ​​x er: 2" i konsollen.

Boksning og unboxing

Konvertering af en værditype til en referencetype kaldes boksning. Unboxing er lige det modsatte - det er defineret som processen til konvertering af en referencetype til en værditype. Følgende kodestykke illustrerer boksning og unboxing i C #.

int i = 100;

Objekt obj = i; // Boksning

i = (int) obj; // Unboxing