Содержание
Как мы уже знаем, платформа .NET и язык программирования C# — это не тождественные понятия. В .NET используется общая система типов (Common Type System, CTS). Что это за система типов и зачем она потребовалась в .NET мы и рассмотрим в этой части. Здесь мы рассмотрим состав CTS, а также классифицируем некоторые типы данных, используемые в C# по нескольким признакам.
CTS и цели её разработки
Современное программное обеспечение может разрабатываться сразу на нескольких языках программирования. Например, графический интерфейс приложения может разрабатываться на одном языке, часть программы, отвечающая за сложные вычисления — на другом, а плагины к приложению — вообще на третьем языке программирования. При этом, каждый язык программирования может использовать (и использует) свою систему типов и правила хранения значений переменных в памяти. В результате, раньше, когда мы разрабатывали приложения без .NET, то могли сталкиваться с различными проблемами. Например, языки Delphi и C++ по-разному хранят в памяти строки и при попытке использовать библиотеку (DLL), разработанную на С++ в приложении Delphi мы сталкивались с тем, что нам необходимо было каким-либо образом «научить» программу на Delphi читать и передавать строки в библиотеку на C#. В том числе, чтобы избежать таких проблем и была разработана общая система типов .NET.
Платформа .NET может использоваться для разработки приложений на различных языках программирования, не только на C#. Например, для взаимодействия с .NET мы можем использовать VB.NET, F#, C++ и другие языки. Common Type System позволяет использовать единые правила по использованию тех или иных типов данных. Таким образом, какой бы язык программирования мы бы не использовали для .NET, переменная будет храниться и интерпретироваться приложением абсолютно одинаково.
Сами разработчики .NET указывают следующие основные задачи CTS:
- формирование инфраструктуры, которая позволяет обеспечивать межъязыковую интеграцию, безопасность типов и высокопроизводительное выполнение кода.
- предоставление объектно-ориентированной модели, поддерживающую полную реализацию многих языков программирования.
- определение правил, которых необходимо придерживаться в языке. Эти правила помогают обеспечить взаимодействие объектов, написанных на разных языках.
- предоставление библиотеки, содержащей типы-примитивы (например,
Boolean
,Byte
,Char
,Int32
иUInt64
и так далее), используемые в разработке приложений.
Система общих типов CTS на платформе .NET поддерживает следующие пять категорий типов:
- Классы
- Структуры
- Перечисления
- Интерфейсы
- Делегаты
В каждой категории типов может содержаться свой набор типов данных. Вначале рассмотрим как в .NET/C#, в принципе, классифицируются типы данных.
Ссылочные типы, типы значений, встроенные типы, псевдонимы типов и т.д.
При разработке приложений на C# мы будем часто встречать различные названия типов данных, используемых в приложении, например, «встроенный тип» или «примитивный тип», поэтому стоит потратить немного времени и разобраться с этими терминами немного по-подробнее.
Ссылочные типы и типы значений
Все типы данных в .NET/C# подразделяются на две большие группы — это типы значений и ссылочные типы. Со многими из этих типов данных мы обязательно познакомимся более подробно в других частях учебника, а пока просто классифицируем их по принятым в .NET/C# признакам.
Если переменной присвоить тип, относящийся к типам значений, то она будет хранить непосредственно значение. В соответствии со спецификацией языка C#, к типам значений относятся:
- Простые (встроенные) типы данных
- Перечисления
- Структуры
- Обнуляемые типы
- Кортежи
Если же для переменной используется ссылочный тип, то такая переменная будет хранить не само значение, а ссылку на значение этой переменной в памяти. Опять же, сильно не вдаваясь в подробности, можно привести такую аналогию: переменная ссылочного типа — это «визитка», то есть, обращаясь к значению этой переменной мы можем узнать где находится конкретное значение. К ссылочным типам в .NET/C# относятся следующие типы данных:
- типы классов, включая тип
String
(строка) - интерфейсы
- делегаты
- массивы
Встроенные типы данных в C#
Такие типы данных могут быть как ссылочными, так и типами значений. Встроенный тип C# — это псевдоним типа .NET. Так, в таблице ниже представлены все встроенные типы данных C#, а также соответствующий встроенному типу C# тип .NET и группа, к которой относится тот или иной тип:
Группа | Псевдоним типа в C# | Тип .NET | Описание |
---|---|---|---|
Тип значений | bool |
System.Boolean |
используется для представления логических значений, которые могут иметь значение true (истина) или false (ложь) |
byte |
System.Byte |
целое число в диапазоне от 0 до 255 | |
sbyte |
System.SByte |
целое число в диапазоне от -128 до 127 | |
char |
System.Char |
символ в кодировке UTF-16 | |
decimal |
System.Decimal |
вещественное число в диапазоне от ±1,0 x 10-28 до ±7,9228 x 1028 | |
double |
System.Double |
вещественное число в диапазоне от ±5,0 × 10−324 до ±1,7 × 10308 | |
float |
System.Single |
вещественное число в диапазоне от ±1,5 x 10−45 до ±3,4 x 1038 | |
int |
System.Int32 |
целое число в диапазоне от -2 147 483 648 до 2 147 483 647 | |
uint |
System.UInt32 |
целое число в диапазоне от 0 до 4 294 967 295 | |
nint |
System.IntPtr |
целое число диапазон значений которого зависит от платформы (определяемой во время выполнения) | |
nuint |
System.UIntPtr |
целое число диапазон значений которого зависит от платформы (определяемой во время выполнения) | |
long |
System.Int64 |
целое число в диапазоне от -9 223 372 036 854 775 808 до 9 223 372 036 854 775 807 | |
ulong |
System.UInt64 |
целое число в диапазоне от 0 до 18 446 744 073 709 551 615 | |
short |
System.Int16 |
целое число в диапазоне от -32 768 до 32 767 | |
ushort |
System.UInt16 |
целое число в диапазоне от 0 до 65 535 | |
Ссылочный тип | object |
System.Object |
базовый тип для всех типов CTS |
string |
System.String |
строка, состоящая из символов в кодировке UTF-16 | |
dynamic |
System.Object |
динамический тип |
Также, согласно документации, Microsoft, к встроенным типам относится ссылочный тип delegate
(делегат)
Встроенные типы данных содержатся в пространстве имен System
, а использовать их мы можем либо используя непосредственно тип .NET, либо псевдоним C#. Например, используем тип .NET для объявления переменной целочисленного типа:
System.Int32 i;
или так:
using System; Int32 i;
Во втором случае мы вначале подключаем к нашему проекту пространство имен System
, а затем используем тип переменной уже без названия пространства имен вначале типа. Чтобы сократить исходный код, мы можем использовать псевдоним (этот способ наиболее часто используется при объявлении переменных встроенных типов данных):
int i;
Простые типы
К простым типам данных относятся все типы значений из базовых типов. То есть, если посмотреть на таблицу, представленную выше, то становится понятным, что к простым типам относятся целые числа, вещественные числа, а также типы bool
и char
.
Примитивные типы
Согласно документации на сайте Microsoft, к примитивным типам отнесены следующие типы данных: Boolean
, Byte
, SByte
, Int16
, UInt16
, Int32
, UInt32
, Int64
, UInt64
, IntPtr
, UIntPtr
, Char
, Double
, Single
. Как можно видеть, помимо рассмотренных ранее типов данных, к примитивным типам также относятся типы IntPtr
, UIntPtr
и Single
. Первые два типа определяют указатель (не путать со ссылкой) на адрес в памяти. Для этих типов данных в C# используются псевдонимы nint
и unint
(см. таблицу выше) В этом учебнике мы не будем использовать указатели, так как это отдельный довольно интересный, но сложный для новичков вопрос. Последний тип — Single
представляет собой вещественной число одинарной точности. Для Single в C# отсутствует псевдоним, а сам этот тип используется намного реже, чем, например, double
или float
.
Свое название примитивные типы получили потому, что они поддерживаются непосредственно через инструкции в скомпилированном коде, которые обычно транслируются в прямую поддержку внутри имеющегося процессора.
Структуры
Такие типы данных используются для определения каких-либо сложных сущностей, позволяя объединять свойства этих сущностей в виде отдельно целостной структуры данных. Про структуры мы отдельно поговорим, пока же стоит обратить ваше внимание на следующий момент — .NET все типы-примитивы определяются как структуры. Чтобы убедиться в этом, достаточно определить в приложении какую-либо переменную с типом-примитивом и в следующей инструкции набрать после имени переменной символ точки. В Visual Studio вы увидите все свойства и методы этой структуры:
В качестве примера, давайте воспользуемся примитивом Single
и узнаем какие минимальные и максимальные значения может принимать переменная этого типа. Код программы будем максимально простым:
Console.WriteLine(Single.MinValue); Console.WriteLine(Single.MaxValue);
А после запуска приложения вы увидите в консоли следующие значения:
3,4028235E+38
Перечисления
Перечисление (псевдоним в C# — enum
) — это тип значения, который напрямую наследуется от типа System.Enum
и предоставляет альтернативные имена для значений базового типа-примитива. Тип перечисления имеет имя, базовый тип, который должен быть одним из встроенных целочисленных знаковых или беззнаковых типов. Например, забегая немного вперед, рассмотрим такое перечисление:
enum Colors : byte { Red = 1, Green = 2, Blue = 3, }
Базовый тип-примитив — byte
. Этот тип также относится и к группе встроенных типов данных, альтернативные значения для чисел 1, 2 и 3 — Red
, Green
, Blue
, соответственно.
Такие типы данных, как интерфейсы и делегаты мы будем рассматривать в отдельных главах учебника, поэтому их определения мы пока не будем приводить здесь (тем более, что нам пока вполне хватит для дальнейшей работы знаний о базовых типах). Однако, эти типы данных мы обязательно рассмотрим подробно, когда мы будем обладать необходимыми знаниями в C# для их использования.
Итого
Таким образом наиболее общая классификация типов данных, которые мы изучили на данный момент, может выглядеть следующим образом:
Категория CTS | Тип .NET | Псевдоним в C# | Описание | Тип значений | Встроенный тип | Примитивный тип | Простой тип |
Структуры | System.Boolean |
bool |
используется для представления логических значений, которые могут иметь значение true (истина) или false (ложь) |
Да | Да | Да | Да |
System.Byte |
byte |
целое число в диапазоне от 0 до 255 | Да | Да | Да | Да | |
System.SByte |
sbyte |
целое число в диапазоне от -128 до 127 | Да | Да | Да | Да | |
System.Char |
char |
символ в кодировке UTF-16 | Да | Да | Да | Да | |
Да | Да | Да | Да | ||||
System.Double |
double |
вещественное число в диапазоне от ±5,0 × 10−324 до ±1,7 × 10308 | Да | Да | Да | Да | |
System.Single |
float |
вещественное число в диапазоне от ±1,5 x 10−45 до ±3,4 x 1038 | Да | Да | Да | Да | |
System.Int32 |
int |
целое число в диапазоне от -2 147 483 648 до 2 147 483 647 | Да | Да | Да | Да | |
System.UInt32 |
uint |
целое число в диапазоне от 0 до 4 294 967 295 | Да | Да | Да | Да | |
System.IntPtr |
nint |
целое число диапазон значений которого зависит от платформы (определяемой во время выполнения) | Да | Да | Да | Да | |
System.UIntPtr |
nuint |
целое число диапазон значений которого зависит от платформы (определяемой во время выполнения) | Да | Да | Да | Да | |
System.Int64 |
long |
целое число в диапазоне от -9 223 372 036 854 775 808 до 9 223 372 036 854 775 807 | Да | Да | Да | Да | |
System.UInt64 |
ulong |
целое число в диапазоне от 0 до 18 446 744 073 709 551 615 | Да | Да | Да | Да | |
System.Int16 |
short |
целое число в диапазоне от -32 768 до 32 767 | Да | Да | Да | Да | |
System.UInt16 |
ushort |
целое число в диапазоне от 0 до 65 535 | Да | Да | Да | Да | |
System.Decimal |
decimal |
вещественное число в диапазоне от ±1,0 x 10-28 до ±7,9228 x 1028 | Да | Да | Нет | Да | |
System.Single |
вещественное число в диапазоне от -3,4028235E+38 3,4028235E+38 |
Да | Нет | Да | Нет | ||
Классы | System.Object |
object |
базовый тип для всех типов CTS | Нет | Да | Нет | Нет |
System.String |
string |
строка, состоящая из символов в кодировке UTF-16 | Нет | Да | Нет | Нет | |
System.Object |
dynamic |
динамический тип | Нет | Да | Нет | Нет | |
Перечисление | System.Enum |
enum |
представляет собой перечисление | Да | Нет | Нет | Нет |