Поделиться через


Типы значений (справочник по C#)

Типы значений и ссылочные типы — это две основные категории типов C#. Переменная типа значения содержит экземпляр типа. Это отличается от переменной ссылочного типа, которая содержит ссылку на экземпляр типа. По умолчанию при назначении, передаче аргумента в метод и возврате результата метода копируются значения переменных. В случае переменных типа значения копируются соответствующие экземпляры типа. В следующем примере продемонстрировано такое поведение.

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)

Как показано в предыдущем примере, операции с переменной типа значения влияют только на этот экземпляр типа значения, хранящийся в переменной.

Если тип значения содержит элемент данных ссылочного типа, то при копировании экземпляра типа значения копируется только ссылка на экземпляр ссылочного типа. Как скопированный, так и исходный экземпляр типа значения имеют доступ к одному и тому же экземпляру ссылочного типа. В следующем примере продемонстрировано такое поведение.

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

Примечание.

Чтобы сделать код менее подверженным ошибкам и более надежным, определите и используйте неизменяемые типы значений. В этой статье изменяемые типы значений используются только в демонстрационных целях.

Виды типов значений и ограничения типов

Тип значения может относится к одному из двух следующих видов:

  • тип структуры, который инкапсулирует данные и связанные функции;
  • тип перечисления, который определяется набором именованных констант и представляет выбор или сочетание вариантов для выбора.

Тип T? значения, допускающего значение NULL, представляет все значения базового типа T значения и дополнительное значение NULL. Вы не можете назначить null переменной типа значения, если только это не тип, допускающий значение NULL.

Вы можете использовать ограничение struct, чтобы указать, что параметр типа является типом значения, не допускающим значения NULL. Типы структуры и перечисления удовлетворяют ограничению struct. Можно использовать System.Enum в ограничении базового класса (которое называется ограничением перечисления), чтобы указать, что параметр типа является типом перечисления.

Встроенные типы значений

C# предоставляет следующие встроенные типы значений, которые также называются простыми типами.

Все простые типы являются типами структур и отличаются от других типов структур тем, что разрешают некоторые дополнительные операции.

  • Литералы можно использовать для предоставления значения простого типа. Например, 'A' — это литерал типа char, а 2001 — литерал типа int.

  • Константы простых типов можно объявить с помощью ключевого слова const. Невозможно использовать константы других типов структур.

  • Константные выражения, операнды которых являются константами простых типов, вычисляются во время компиляции.

Кортеж значений — это тип значения, но не простой тип.

Спецификация языка C#

Дополнительные сведения см. в следующих разделах статьи Спецификация языка C#:

См. также