Värdetyper (C#-referens)
Värdetyper och referenstyper är de två huvudkategorierna för C#-typer. En variabel av en värdetyp innehåller en instans av typen. Detta skiljer sig från en variabel av en referenstyp, som innehåller en referens till en instans av typen. Som standard kopieras variabelvärden vid tilldelning, skickar ett argument till en metod och returnerar ett metodresultat. När det gäller variabler av värdetyp kopieras motsvarande typinstanser. Följande exempel visar det beteendet:
using System;
public struct MutablePoint
{
public int X;
public int Y;
public MutablePoint(int x, int y) => (X, Y) = (x, y);
public override string ToString() => $"({X}, {Y})";
}
public class Program
{
public static void Main()
{
var p1 = new MutablePoint(1, 2);
var p2 = p1;
p2.Y = 200;
Console.WriteLine($"{nameof(p1)} after {nameof(p2)} is modified: {p1}");
Console.WriteLine($"{nameof(p2)}: {p2}");
MutateAndDisplay(p2);
Console.WriteLine($"{nameof(p2)} after passing to a method: {p2}");
}
private static void MutateAndDisplay(MutablePoint p)
{
p.X = 100;
Console.WriteLine($"Point mutated in a method: {p}");
}
}
// Expected output:
// p1 after p2 is modified: (1, 2)
// p2: (1, 200)
// Point mutated in a method: (100, 200)
// p2 after passing to a method: (1, 200)
Som föregående exempel visar påverkar åtgärder på en värdetypsvariabel endast den instans av värdetypen som lagras i variabeln.
Om en värdetyp innehåller en datamedlem av en referenstyp kopieras endast referensen till instansen av referenstypen när en värdetypsinstans kopieras. Både kopierings- och originalinstansen av värdetyp har åtkomst till samma referenstypsinstans. Följande exempel visar det beteendet:
using System;
using System.Collections.Generic;
public struct TaggedInteger
{
public int Number;
private List<string> tags;
public TaggedInteger(int n)
{
Number = n;
tags = new List<string>();
}
public void AddTag(string tag) => tags.Add(tag);
public override string ToString() => $"{Number} [{string.Join(", ", tags)}]";
}
public class Program
{
public static void Main()
{
var n1 = new TaggedInteger(0);
n1.AddTag("A");
Console.WriteLine(n1); // output: 0 [A]
var n2 = n1;
n2.Number = 7;
n2.AddTag("B");
Console.WriteLine(n1); // output: 0 [A, B]
Console.WriteLine(n2); // output: 7 [A, B]
}
}
Kommentar
Om du vill göra koden mindre felbenägen och mer robust definierar och använder du oföränderliga värdetyper. Den här artikeln använder endast föränderliga värdetyper i demonstrationssyfte.
Typer av värdetyper och typbegränsningar
En värdetyp kan vara en av följande två typer:
- en strukturtyp som kapslar in data och relaterade funktioner
- en uppräkningstyp som definieras av en uppsättning namngivna konstanter och representerar ett val eller en kombination av val
En nullbar värdetyp T?
representerar alla värden av dess underliggande värdetyp T
och ytterligare ett null-värde . Du kan inte tilldela null
till en variabel av en värdetyp, såvida det inte är en nullbar värdetyp.
Du kan använda villkoret struct
för att ange att en typparameter är en värdetyp som inte kan nulleras. Både struktur- och uppräkningstyper uppfyller villkoret struct
. Du kan använda System.Enum
i en basklassbegränsning (som kallas uppräkningsbegränsningen) för att ange att en typparameter är en uppräkningstyp.
Inbyggda värdetyper
C# innehåller följande inbyggda värdetyper, även kallade enkla typer:
- Integral numeriska typer
- Numeriska typer av flyttal
- bool som representerar ett booleskt värde
- tecken som representerar ett Unicode UTF-16-tecken
Alla enkla typer är strukturtyper och skiljer sig från andra strukturtyper eftersom de tillåter vissa ytterligare åtgärder:
Du kan använda literaler för att ange ett värde av en enkel typ.
Är till exempel'A'
en literal av typenchar
,2001
är en literal av typenint
och12.34m
är en literal av typendecimal
.Du kan deklarera konstanter av de enkla typerna med nyckelordet const .
Du kan till exempel definieraconst decimal = 12.34m
.
Det går inte att ha konstanter av andra strukturtyper.Konstanta uttryck, vars operander är konstanter av de enkla typerna, utvärderas vid kompileringstillfället.
En värdetupppel är en värdetyp, men inte en enkel typ.
Språkspecifikation för C#
Mer information finns i följande avsnitt i C#-språkspecifikationen: