Основы программирования на C#

         

Система типов


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

Стандарт языка C++ включает следующий набор фундаментальных типов.

  1. Логический тип (bool).
  2. Символьный тип (char).
  3. Целые типы. Целые типы могут быть одного из трех размеров - short, int, long, сопровождаемые описателем signed или unsigned, который указывает, как интерпретируется значение, - со знаком или без оного.
  4. Типы с плавающей точкой. Эти типы также могут быть одного из трех размеров - float, double, long double.

    Кроме того, в языке есть

  5. Тип void, используемый для указания на отсутствие информации.

    Язык позволяет конструировать типы.

  6. Указатели (например, int* - типизированный указатель на переменную типа int).
  7. Ссылки (например, double& - типизированная ссылка на переменную типа double).
  8. Массивы (например, char[] - массив элементов типа char).

    Язык позволяет конструировать пользовательские типы

  9. Перечислимые типы (enum) для представления значений из конкретного множества.
  10. Структуры (struct).
  11. Классы.

Первые три вида типов называются интегральными или счетными. Значения их перечислимы и упорядочены. Целые типы и типы с плавающей точкой относятся к арифметическому типу. Типы подразделяются также на встроенные и типы, определенные пользователем.

Эта схема типов сохранена и в языке C#. Однако здесь на верхнем уровне используется и другая классификация, носящая для C# принципиальный характер. Согласно этой классификации все типы можно разделить на четыре категории:

  1. Типы-значения (value), или значимые типы.
  2. Ссылочные (reference).
  3. Указатели (pointer).
  4. Тип void.

Эта классификация основана на том, где и как хранятся значения типов. Для ссылочного типа значение задает ссылку на область памяти в "куче", где расположен соответствующий объект. Для значимого типа используется прямая адресация, значение хранит собственно данные, и память для них отводится, как правило, в стеке.

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

Особый статус имеет и тип void, указывающий на отсутствие какого-либо значения.

В языке C# жестко определено, какие типы относятся к ссылочным, а какие - к значимым. К значимым типам относятся: логический, арифметический, структуры, перечисление. Массивы, строки и классы относятся к ссылочным типам. На первый взгляд, такая классификация может вызывать некоторое недоумение, почему это структуры, которые в C++ близки к классам, относятся к значимым типам, а массивы и строки - к ссылочным. Однако ничего удивительного здесь нет. В C# массивы рассматриваются как динамические, их размер может определяться на этапе вычислений, а не в момент трансляции. Строки в C# также рассматриваются как динамические переменные, длина которых может изменяться. Поэтому строки и массивы относятся к ссылочным типам, требующим распределения памяти в "куче".

Со структурами дело сложнее. Структуры C# представляют частный случай класса. Определив свой класс как структуру, программист получает возможность отнести класс к значимым типам, что иногда бывает крайне полезно. Замечу, что в хорошем объектном языке Eiffel программист может любой класс объявить развернутым (expanded), что эквивалентно отнесению к значимому типу. У программиста C# только благодаря структурам появляется возможность управлять отнесением класса к значимым или ссылочным типам. Правда, это неполноценное средство, поскольку на структуры накладываются дополнительные ограничения по сравнению с обычными классами.

Рассмотрим классификацию, согласно которой все типы делятся на встроенные и определенные пользователем. Все встроенные типы C# однозначно отображаются, а фактически совпадают с системными типами каркаса Net Framework, размещенными в пространстве имен System. Поэтому всюду, где можно использовать имя типа, например, - int, с тем же успехом можно использовать и имя System.Int32.

Замечание:

Следует понимать тесную связь и идентичность встроенных типов языка C# и типов каркаса. Какими именами типов следует пользоваться в программных текстах - это спорный вопрос. Джеффри Рихтер в своей известной книге "Программирование на платформе Framework .Net" рекомендует использовать системные имена. Другие авторы считают, что следует пользоваться именами типов, принятыми в языке. Возможно, в модулях, предназначенных для межъязыкового взаимодействия, разумны системные имена, а в остальных случаях - имена конкретного языка программирования.

<

Содержание раздела