Udostępnij za pośrednictwem


Typy wartości (odwołanie w C#)

Typy wartości i typy referencyjne to dwie główne kategorie typów języka C#. Zmienna typu wartości zawiera wystąpienie typu. To zachowanie różni się od zmiennej typu odwołania, która zawiera odwołanie do wystąpienia typu. Domyślnie przy przypisaniu przekazujesz argument do metody i zwracasz wynik metody, kopiujesz wartości zmiennych. W przypadku zmiennych typu wartości skopiuj odpowiednie wystąpienia typu. W poniższym przykładzie pokazano, że zachowanie:

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)

Jak pokazano w poprzednim przykładzie, operacje na zmiennej typu wartości mają wpływ tylko na to wystąpienie typu wartości przechowywane w zmiennej.

Jeśli typ wartości zawiera element członkowski danych typu odwołania, należy skopiować tylko odwołanie do wystąpienia typu odwołania podczas kopiowania wystąpienia typu wartości. Zarówno wystąpienie kopiowania, jak i oryginalnego typu wartości ma dostęp do tego samego wystąpienia typu odwołania. W poniższym przykładzie pokazano, że zachowanie:

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

Uwaga

Aby kod był mniej podatny na błędy i bardziej niezawodny, zdefiniuj i użyj niezmiennych typów wartości. W tym artykule używane są tylko typy wartości modyfikowalne tylko w celach demonstracyjnych.

Rodzaje typów wartości i ograniczeń typu

Typ wartości może być jednym z następujących rodzajów:

  • Typ struktury, który hermetyzuje dane i powiązane funkcje.
  • Typ wyliczenia, który jest definiowany przez zestaw nazwanych stałych i reprezentuje wybór lub kombinację wyborów.
  • Deklaracja unii, która definiuje zamknięty zestaw typów przypadków, które może reprezentować wartość.

TypT? wartości dopuszczanej do wartości null reprezentuje wszystkie wartości bazowego typu T wartości i dodatkową wartość null. Nie można przypisać null do zmiennej typu wartości, chyba że jest to typ wartości dopuszczalnej wartości null.

struct Użyj ograniczenia, aby określić, że parametr typu jest typem wartości innej niż null. Oba typy struktury i wyliczenia spełniają struct ograniczenie. Użyj System.Enum w ograniczeniu klasy bazowej (znanej jako ograniczenie wyliczenia), aby określić, że parametr typu jest typem wyliczenia.

Wbudowane typy wartości

Język C# udostępnia następujące wbudowane typy wartości, znane również jako proste typy:

Wszystkie proste typy to typy struktur. Różnią się one od innych typów struktur, które zezwalają na pewne dodatkowe operacje:

  • Aby podać wartość prostego typu, można użyć literałów.
    Na przykład 'A' jest literałem typu char, 2001 jest literałem typu , i int jest literałem typu 12.34mdecimal.

  • Stałe prostych typów można zadeklarować przy użyciu słowa kluczowego const .
    Można na przykład zdefiniować const decimal = 12.34mwartość .
    Nie można zadeklarować stałych innych typów struktur.

  • Wyrażenia stałe, których operandy są stałymi prostych typów, są obliczane w czasie kompilacji.

Krotka wartości jest typem wartości, ale nie prostym typem.

specyfikacja języka C#

Aby uzyskać więcej informacji, zobacz następujące sekcje specyfikacji języka C#:

Zobacz też