Россия, Челябинск, Южно-Уральский Государственный Университет (НИУ) |
Введение и обзор платформы .NET
Общая система типов .NET
Для того, чтобы различные языки программирования могли осмысленно общаться между собой, необходимо ввести единую систему типов, которая была бы достаточно полной и при этом оставалась бы ясной. Например, в стандарте CORBA концепции языков и типов определены в Object Management Architecture. В .NET такую роль выполняет Common Type System (CTS). В СТS все типы делятся на следующие категории:
Два основных вида данных в системе типов .NET - это типы-значения (value types) и ссылочные типы (reference types). Основное различие между ними заключается в том, что тип-значение представляет собой просто последовательность битов в памяти, а ссылочный тип дополнительно обладает "индивидуальностью". Например, 32-битовое знаковое целое является типом-значением. Если мы будем сравнивать два любых целых, то они будут считаться равными, если содержат одинаковое число. С другой стороны, рассмотрим объекты, являющиеся ссылочными значениями. Два разных объекта, представляющие один и тот же класс, могут содержать абсолютно одинаковые данные, но при этом не будут равными, так как указывают на разные участки памяти.
Идея различения типов-значений и ссылочных типов не нова - например, в Симуле 67 делалось явное различие между присваиванием значения объекта с помощью символа :=, и присваиванием ссылки на объект, которое производилось с помощью символа :-
Примитивные типы
Некоторые типы данных используются настолько часто, что компиляторы позволяют обращаться с ними по упрощенной схеме. Например, в С# возможно следующее определение:
string s = "Hello C#";
Эта форма записи удобна, коротка и читабельна. Однако на самом деле, под таким оператором подразумевается следующее присваивание:
System.String s = new System.String(); s = "Hello C#";
так как вообще говоря, string является обычным типом, который ничем не отличается от других типов данных. Типы данных, напрямую поддержанные компилятором и допускающие подобные сокращения записи, называются примитивными типами. Примитивные типы преимущественно являются типами-значениями и память под них выделяется на стеке данного потока. Большинство примитивных типов различных языков программирования проецируется на типы данных, существующие в базовой библиотеке классов .NET.
Примитивные типы в .NET
.NET поддерживает достаточно большой набор встроенных типов. Только C# поддерживает полный набор примитивных типов .NET. В следующей таблице приведены некоторые встроенные типы данных и объяснено их назначение:
Типы-значения
Типы-значения не сводятся к примитивным типам и могут состоять из нескольких переменных. В C# для объявления value type используется ключевое слово struct, как в следующем примере:
struct RectVal { public int x, y, cx, cy; }
Важно понять, что тип-значение содержит само значение переменной, а не ссылку на него. Это экономит память, так как нет необходимости хранить таблицу виртуальных методов и дополнительный указатель на значение. Кроме того, использование типов-значений улучшает производительность, так как отпадает потребность в лишнем разыменовывании указателя и создании новой копии объекта в "куче". Но с другой стороны, типы-значения имеют множество ограничений. Например, они не могут наследовать от других типов и от них также нельзя ничего унаследовать - они являются "запечатанными", sealed. Поэтому можно считать, что типы-значения в целом ведут себя как встроенные типы (кстати, часто рекомендуют не делать типы-значения больше 12-16 байт).
Важно понимать, что при присваивании типов-значений происходит копирование значения, поэтому типы-значения редко используются, если их надо часто передавать в качестве параметров.
Сравнение типов-значений имеет более интересную механику: все типы-значения унаследованы от System.ValueType, который предоставляет такие же методы, как и System.Object, за исключением метода Equals, который выдает True, если значения совпадают, и GetHashCode, который учитывает значение переменной. При создании собственных value types настойчиво рекомендуется переопределять эти методы на свои собственные.