Типы данных принято разделять на простые и сложные в зависимости от того, как устроены их данные. У простых (скалярных) типов возможные значения данных едины и неделимы. Сложные типы характеризуются способом структуризации данных - одно значение сложного типа состоит из множества значений данных, организующих сложный тип.
Есть и другие критерии классификации типов. Так, типы разделяются на встроенные типы и типы, определенные программистом (пользователем). Встроенные типы изначально принадлежат языку программирования и составляют его базис. В основе системы типов любого языка программирования всегда лежит базисная система типов, встроенных в язык. На их основе программист может строить собственные, им самим определенные типы данных.
Типы данных разделяются также на статические и динамические. Для данных статического типа память отводится в момент объявления, требуемый размер данных (памяти) известен при их объявлении. Для данных динамического типа размер данных в момент объявления обычно неизвестен и память им выделяется динамически по запросу в процессе выполнения программы.
Еще одна важная классификация типов - это их деление на значимые и ссылочные. Для значимых типов значение переменной (объекта) является неотъемлемой собственностью переменной (точнее, собственностью является память, отводимая значению, а само значение может изменяться). Для ссылочных типов значением служит ссылка на некоторый объект в памяти, расположенный обычно в динамической памяти - "куче".
Далее приведен перечень всех встроенных типов языка C# и их основные характеристики.
Логический тип
Имя типа | Системный тип | Значения | Размер |
Bool | System.Boolean | true, false | 8 бит |
Арифметические целочисленные типы
Имя типа | Системный тип | Диапазон | Размер |
Sbyte | System.SByte | -128 — 127 | Знаковое, 8 Бит |
Byte | System.Byte | 0 — 255 | Беззнаковое, 8 Бит |
Short | System.Short | -32768 —32767 | Знаковое, 16 Бит |
Ushort | System.UShort | 0 — 65535 | Беззнаковое, 16 Бит |
Int | System.Int32 | ≈(-2*10^9 — 2*10^9) | Знаковое, 32 Бит |
Uint | System.UInt32 | ≈(0 — 4*10^9) | Беззнаковое, 32 Бит |
Long | System.Int64 | ≈(-9*10^18 — 9*10^18) | Знаковое, 64 Бит |
Ulong | System.UInt64 | ≈(0— 18*10^18) | Беззнаковое, 64 Бит |
Арифметический тип с плавающей точкой
Имя типа | Системный тип | Диапазон | Точность |
Float | System.Single | +1.5*10^-45 - +3.4*10^38 | 7 цифр |
Double | System.Double | +5.0*10^-324 - +1.7*10^308 | 15-16 цифр |
Арифметический тип с фиксированной точкой
Имя типа | Системный тип | Диапазон | Точность |
Decimal | System.Decimal | +1.0*10^-28 - +7.9*10^28 | 28-29 значащих цифр |
Символьные типы
Имя типа | Системный тип | Диапазон | Точность |
Char | System.Char | U+0000 - U+ffff | 16 бит Unicode символ |
String | System.String | Строка из символов Unicode |
Объектный тип
Имя типа | Системный тип | Примечание |
Object | System.Object | Прародитель всех встроенных и пользовательских типов |
Рассмотрим пример объявления переменных и присваивания им значений:
int x=11;
int v = new Int32();
v = 007;
string s1 = "Agent";
s1 = s1 + v.ToString() +x.ToString();
В этом примере переменная x объявляется как обычная переменная типа int. В то же время для объявления переменной v того же типа int используется стиль, принятый для объектов. В объявлении применяется конструкция new и вызов конструктора класса. В операторе присваивания, записанном в последней строке фрагмента, для обеих переменных вызывается метод ToString, как это делается при работе с объектами. Этот метод, наследуемый от родительского класса Object, переопределенный в классе int, возвращает строку с записью целого.
Рассмотрим еще один тип данных – структуру. Синтаксис объявления структуры аналогичен синтаксису объявления класса:
[атрибуты][модификаторы]struct имя_структуры[:список_интерфейсов]
{тело_структуры}
Все, что может быть вложено в тело класса, может быть вложено и в тело структуры: поля, методы, конструкторы и прочее, включая классы и интерфейсы. Аналогично классу, структура может иметь статические и не статические поля и методы, может иметь несколько конструкторов, в том числе статические и закрытые конструкторы. Для структур можно создавать собственные константы, используя поля с атрибутом readonly и статический конструктор. Структуры похожи на классы по своему описанию и ведут себя сходным образом, хотя и имеют существенные различия в семантике присваивания.
Но по сравнению с классами, структуры имеют существенные ограничения.
1) Самое серьезное ограничение связано с ограничением наследования, т.е. у структуры не может быть наследников, не может быть задан родительский класс или родительская структура.
2) Второе серьезное ограничение связано с процессом создания объектов. Пусть T - структура, и дано объявление без инициализации - T x. Это объявление корректно, в результате будет создан объект без явного вызова операции new. Сущности x будет отведена память, и на этой памяти будет развернут объект. Но поля объекта не будут инициализированы и, следовательно, не будут доступны для использования в вычислениях. Об этих особенностях подробно говорилось при рассмотрении значимых типов. В этом отношении все, что верно для типа int, верно и для всех структур.