Dela via


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:

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 typen char, 2001 är en literal av typen int och 12.34m är en literal av typen decimal.

  • Du kan deklarera konstanter av de enkla typerna med nyckelordet const .
    Du kan till exempel definiera const 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:

Se även