Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Подсказка
Вы новичок в разработке программного обеспечения? Сначала начните с учебников для начинающих. Они ведут вас шаг за шагом по процессу написания программ и по ходу дела объясняют типы.
Есть опыт на другом языке? Если вы уже понимаете системы типов, пропустите различия между значением и ссылкой и выберите руководство по типам, а затем перейдите к статьям по определенным типам.
C# — это строго типизированный язык. Каждая переменная, константа и выражение имеют тип. Компилятор применяет безопасность типов , проверяя, является ли каждая операция в коде допустимой для используемых типов. Например, можно добавить два int значения, но нельзя добавить и int :bool
int a = 5;
int b = a + 2; // OK
bool test = true;
// Error. Operator '+' cannot be applied to operands of type 'int' and 'bool'.
// int c = a + test;
Замечание
В отличие от C и C++, в C#, bool не преобразуется в int.
Безопасность типов обнаруживает ошибки на этапе компиляции до выполнения вашего кода. Компилятор также внедряет сведения о типе в исполняемый файл в виде метаданных, которые среда CLR использует для дополнительных проверок безопасности во время выполнения.
Объявление переменных с типами
При объявлении переменной вы указываете его тип явным образом или используете var , чтобы компилятор выводил тип из назначенного значения:
// Explicit type:
int count = 10;
double temperature = 36.6;
// Compiler-inferred type:
var name = "C#";
var items = new List<string> { "one", "two", "three" };
Параметры метода и возвращаемые значения также имеют типы. Следующий метод принимает string и intвозвращает string:
static string GetGreeting(string name, int visitCount)
{
return visitCount switch
{
1 => $"Welcome, {name}!",
_ => $"Welcome back, {name}! Visit #{visitCount}."
};
}
После объявления переменной нельзя изменить его тип или назначить значение, несовместимое с объявленным типом. Значения можно преобразовать в другие типы. Компилятор выполняет неявные преобразования , которые не теряют данные автоматически. Явные преобразования (приведения) требуют указания преобразования в коде. Для получения дополнительной информации см. Приведение и преобразование типов.
Встроенные типы и настраиваемые типы
C# предоставляет встроенные типы для общих данных: целых чисел, чисел с плавающей запятой, boolcharи string. Каждая программа C# может использовать эти встроенные типы без дополнительных ссылок.
Помимо встроенных типов, можно создать собственные типы с помощью нескольких конструкций:
- Классы — ссылочные типы для поведения моделирования и сложных объектов. Поддержка наследования и полиморфизма.
- Структуры — типы значений для небольших, упрощенных данных. Каждая переменная содержит собственную копию.
-
Записи — классы или структуры с равенством, созданным компилятором,
ToStringи недеструктивная мутация с помощьюwithвыражений. - Интерфейсы — контракты, которые определяют элементы, которые могут быть реализованы любым классом или структурой.
- Перечисления — именованные наборы целочисленных констант, такие как дни недели или режимы доступа к файлам.
- Кортежи — упрощенные структурные типы, которые группирует связанные значения без определения именованного типа.
-
Универсальные шаблоны — типо-параметризованные конструкции, такие как
List<T>иDictionary<TKey, TValue>обеспечивающие безопасность типов при повторном использовании одной логики для разных типов.
Типы значений и ссылочные типы
Каждый тип в C# — это тип значения или ссылочный тип. Это различие определяет, как переменные хранят данные и как работает назначение.
Типы значений хранят данные напрямую. При назначении типа значения новой переменной среда выполнения копирует данные. Изменения в одной переменной не влияют на другую. Структуры, перечисления и встроенные числовые типы являются всеми типами значений.
Ссылочные типы хранят ссылку на объект, находящийся в управляемой памяти. При назначении ссылочного типа новой переменной оба переменных указывают на один и тот же объект. Изменения через одну переменную отображаются через другую. Классы, массивы, делегаты и строки являются ссылочными типами.
В следующем примере показано различие. Первый блок показывает определение структуры Coords записи, которая является типом значения. Второй блок демонстрирует различное поведение для типов значений и ссылочных типов.
public readonly record struct Coords(int X, int Y);
// Value type: each variable holds its own copy
var point1 = new Coords(3, 4);
var point2 = point1;
Console.WriteLine($"point1: ({point1.X}, {point1.Y})");
Console.WriteLine($"point2: ({point2.X}, {point2.Y})");
// point1 and point2 are independent copies
// Reference type: both variables refer to the same object
var list1 = new List<int> { 1, 2, 3 };
var list2 = list1;
list2.Add(4);
Console.WriteLine($"list1 count: {list1.Count}"); // 4 — same object
Все типы в конечном счете являются производными от System.Object. Типы значений происходят от System.ValueType, который, в свою очередь, происходит от object. Эта унифицированная иерархия называется common Type System (CTS). Дополнительные сведения о наследовании см. в разделе "Наследование".
Выберите тип типа
При определении нового типа, тип, который вы выбираете, влияет на поведение вашего кода. Используйте следующие рекомендации, чтобы принять первоначальное решение:
- Кортеж — временное группирование значений, которое не требует именованного типа или поведения.
-
structилиrecord struct— небольшие данные (примерно 64 байта или меньше), семантика значений или неизменяемость. Структуры записи добавляют поддержку равенства на основе значений иwithвыражений. -
record class— в первую очередь данные с равенством на основе значений,ToStringа также недеструктивной мутацией. Поддерживает наследование. -
class— сложное поведение, полиморфизм или изменяемое состояние. Большинство пользовательских типов — это классы. -
interface— контракт, который могут реализовать несвязанные типы. Определяет возможности, а не личность. -
enum— фиксированный набор именованных констант, например коды состояния или параметры.
Более одного варианта часто является разумным.
Тип времени компиляции и тип времени выполнения
Переменная может иметь различные типы во время компиляции и во время выполнения. Тип времени компиляции — это объявленный или выводемый тип в исходном коде. Тип времени выполнения — это фактический тип экземпляра, на который ссылается переменная. Тип времени выполнения должен совпадать с типом времени компиляции или типом, производным от него или реализующим его. Назначение допустимо только в том случае, если неявное преобразование существует из типа времени выполнения в тип времени компиляции, например удостоверение, ссылка, бокс или числовое преобразование.
// Compile-time and run-time types match:
string message = "Hello, world!";
// Compile-time type differs from run-time type:
object boxed = "This is a string at run time";
IEnumerable<char> characters = "abcdefghijklmnopqrstuvwxyz";
В предыдущем примере boxed имеет тип object времени компиляции, но тип stringвремени выполнения. Задание работает, так как string является производным от object. Аналогичным образом characters имеет тип времени компиляции IEnumerable<char>, и присваивание выполняется, поскольку string реализует этот интерфейс. Тип времени компиляции управляет разрешением перегрузки и доступными преобразованиями. Тип времени выполнения управляет отправкой виртуальных методов, is выражениями и switch выражениями.
См. также
Спецификация языка C#
Дополнительные сведения см. в спецификации языка C#. Спецификация языка является авторитетным источником синтаксиса и использования языка C#.