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. Det här beteendet skiljer sig från en variabel av en referenstyp som innehåller en referens till en instans av typen. Som standard kopierar du variabelvärden vid tilldelning, skickar ett argument till en metod och returnerar ett metodresultat. När det gäller variabler av värdetyp kopierar du 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 kopierar du bara referensen till referenstypens instans när du kopierar en värdetypsinstans. 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 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 unionsdeklaration som definierar en sluten uppsättning skiftlägestyper som ett värde kan representera.

En nullbar värdetypT? 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.

Använd villkoretstruct för att ange att en typparameter är en värdetyp som inte kan nulleras. Både struktur- och uppräkningstyper uppfyller villkoret struct . Använd 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 structtyper. De skiljer sig från andra structtyper 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 intoch 12.34m är en literal av typen decimal.

  • Du kan deklarera konstanter av de enkla typerna med hjälp av nyckelordet const .
    Du kan till exempel definiera const decimal = 12.34m.
    Du kan inte deklarera konstanter av andra structtyper.

  • 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