Freigeben über


Werttypen (C#-Referenz)

Werttypen und Verweistypen sind die beiden Hauptkategorien von C#-Typen. Eine Variable eines Werttyps enthält eine Instanz des Typs. Dieses Verhalten unterscheidet sich von einer Variablen eines Bezugstyps, die einen Verweis auf eine Instanz des Typs enthält. Standardmäßig kopieren Sie bei der Zuweisung ein Argument an eine Methode, und geben Sie ein Methodenergebnis zurück. Bei Werttypvariablen kopieren Sie die entsprechenden Typinstanzen. Das folgende Beispiel veranschaulicht dieses Verhalten:

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)

Wie das vorhergehende Beispiel zeigt, wirken sich Vorgänge auf eine Werttypvariable nur auf die in der Variable gespeicherte Instanz des Werttyps aus.

Wenn ein Werttyp ein Datenelement eines Referenztyps enthält, kopieren Sie nur den Verweis auf die Instanz des Referenztyps, wenn Sie eine Werttypinstanz kopieren. Sowohl die kopierte als auch die ursprüngliche Werttypinstanz haben Zugriff auf dieselbe Verweistypinstanz. Das folgende Beispiel veranschaulicht dieses Verhalten:

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]
    }
}

Hinweis

Definieren und verwenden Sie unveränderliche Werttypen, um Ihren Code weniger fehleranfällig und stabiler zu machen. In diesem Artikel werden veränderbare Werttypen nur zur Veranschaulichung verwendet.

Arten von Werttypen und Typeinschränkungen

Ein Werttyp kann eine der folgenden Arten sein:

  • Ein Strukturtyp, der Daten und zugehörige Funktionen kapselt.
  • Ein Enumerationstyp, der durch einen Satz benannter Konstanten definiert wird und eine Auswahl oder eine Kombination von Auswahlmöglichkeiten darstellt.
  • Eine Union-Deklaration, die einen geschlossenen Satz von Falltypen definiert, die ein Wert darstellen kann.

Ein Werttyp, der NULL zulässt wie T?, stellt alle Werte des zugrunde liegenden Werttyps T und einen zusätzlichen NULL-Wert dar. Sie können einer Variablen eines Werttyps nicht zuweisen null , es sei denn, es handelt sich um einen Nullwerttyp.

Verwenden Sie die struct Einschränkung , um anzugeben, dass ein Typparameter ein nicht nullwertebarer Werttyp ist. Sowohl Struktur- als auch Enumerationstypen erfüllen die struct-Einschränkung. Verwenden Sie System.Enum in einer Basisklasseneinschränkung (die als Enumerationseinschränkung bezeichnet wird), um anzugeben, dass ein Typparameter ein Enumerationstyp ist.

Integrierte Werttypen

C# bietet die folgenden integrierten Werttypen, die auch als einfache Typen bekannt sind:

Alle einfachen Typen sind Strukturtypen. Sie unterscheiden sich von anderen Strukturtypen, da sie bestimmte zusätzliche Vorgänge zulassen:

  • Sie können Literale verwenden, um einen Wert eines einfachen Typs bereitzustellen.
    Ist z. B 'A' . ein Literal des Typs char, 2001 ist ein Literal des Typs intund 12.34m ist ein Literal des Typs decimal.

  • Sie können Konstanten der einfachen Typen mithilfe des Schlüsselworts const deklarieren.
    Sie können z. B. definieren const decimal = 12.34m.
    Konstanten anderer Strukturtypen können nicht deklariert werden.

  • Konstante Ausdrücke, deren Operanden alle Konstanten der einfachen Typen sind, werden zur Kompilierzeit ausgewertet.

Ein Werttupel ist ein Werttyp, aber kein einfacher Typ.

C#-Sprachspezifikation

Weitere Informationen finden Sie in den folgenden Abschnitten der C#-Sprachspezifikation:

Weitere Informationen