что делает общая система типов common type system

Система общих типов CTS и спецификация CLS

Система общих типов CTS

Чтобы сделать это без каких-либо затруднений, требуется способ описания всех поддерживаемых типов. Именно за это и отвечает система общих типов CTS. Она предназначена для выполнения следующих задач:

Система CTS определяет две разновидности типов, которые должны поддерживаться: типы значений и ссылочные типы. Имена разновидностей указывают на их определения.

Объекты ссылочных типов представлены ссылкой на фактическое значение объекта. Здесь ссылка аналогична указателю в C/C++. Она просто указывает на адрес памяти, где находятся значения объектов. Это оказывает значительное влияние на способ использования этих типов. Если назначить ссылочный тип переменной, а затем передать эту переменную, например, в метод, любые изменения объекта будут отражены на основном объекте. Копирование при этом не выполняется.

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

Система CTS определяет несколько категорий типов, каждый из которых имеет собственную семантику и способ использования:

Система CTS также определяет все другие свойства типов, такие как модификаторы доступа, которые являются допустимыми членами типа, порядок наследования и перегрузки и т. п. К сожалению, детальное рассмотрение этих аспектов выходит за рамки данной вводной статьи, но вы можете обратиться к разделу Дополнительные ресурсы в конце статьи, где приведены ссылки на более подробные материалы по этой теме.

Спецификация CLS

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

Источник

Система общих типов CTS

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

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

Предоставляет объектно-ориентированную модель, поддерживающую полную реализацию многих языков программирования.

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

Предоставляет библиотеку, которая содержит типы-примитивы (например, Boolean, Byte, Char, Int32 и UInt64), используемые в разработке приложений.

Типы значений — это типы данных, объекты которых представлены фактическим значением объекта. Если экземпляр типа значения присваивается переменной, то эта переменная получает новую копию значения.

Ссылочные типы — это типы данных, объекты которых представлены ссылкой (аналогичной указателю) на фактическое значение объекта. Если экземпляр ссылочного типа присваивается переменной, то эта переменная будет ссылаться (указывать) на исходное значение. Копирования при этом не происходит.

Классы

Класс — это ссылочный тип, который может быть прямым производным от другого класса и является неявным производным от типа System.Object. В классе определяются операции, которые объект (являющийся экземпляром класса) может выполнять (методы, события или свойства), и данные, которые объект содержит (поля). Обычно класс включает и определение, и реализацию (в отличие, например, от интерфейса, который содержит только определение без реализации), однако один или несколько членов класса могут не иметь реализации.

ХарактеристикаОписание
sealedУказывает, что наследование от данного класса не допускается.
реализуетПоказывает, что в классе используется один или несколько интерфейсов за счет предоставления реализаций их членов.
abstractУказывает, что создавать экземпляры этого класса нельзя. Чтобы его использовать, необходимо создать из данного класса производный класс.
наследуетПоказывает, что экземпляры класса можно использовать везде, где задан базовый класс. Производный класс, который наследует от базового, может использовать реализацию любых открытых членов, предоставляемых базовым классом, либо переопределить реализацию этих открытых членов собственной их реализацией.
exported или not exportedПоказывает, виден ли класс за пределами сборки, в которой он определен. Эта характеристика применима только к классам верхнего уровня, но не к вложенным классам.

Класс может также быть вложен в родительский класс или родительскую структуру. Вложенные классы также имеют характеристики членов. Дополнительные сведения см. в разделе Вложенные типы.

Члены классов, не имеющие реализации, являются абстрактными. Класс, содержащий несколько абстрактных членов, сам является абстрактным. Новые экземпляры этого класса создать нельзя. Некоторые языки, ориентированные на среду выполнения, позволяют пометить класс как абстрактный даже в том случае, если он не содержит ни одного абстрактного члена. Абстрактный класс можно использовать, когда требуется инкапсулировать базовый набор функциональных возможностей, которые производные классы могут наследовать или переопределять. Классы, не являющиеся абстрактными, называются конкретными классами.

Класс может реализовывать любое число интерфейсов, однако он может наследовать только от одного базового класса в дополнение к System.Object, от которого неявно наследуют все классы. Любой класс должен иметь по крайней мере один конструктор, который инициализирует новые экземпляры класса. Если конструктор не определен явно, большинство компиляторов автоматически предоставят заданный конструктор без параметров.

Структуры

Как и в классах, в структурах определяются и данные (поля структуры), и операции, которые можно выполнять над этими данными (методы структуры). Это означает, что применительно к структурам можно вызывать методы, в том числе виртуальные методы, определенные в классах System.Object и System.ValueType, а также любые методы, определенные в самом типе значения. Другими словами, структуры могут иметь поля, свойства и события, а также статические и нестатические методы. Можно создавать экземпляры структур, передавать их в качестве параметров, хранить их в качестве локальных переменных либо в поле другого типа значения или ссылочного типа. Структуры также могут реализовывать интерфейсы.

Кроме того, типы значений отличаются от классов в ряде других вопросов. Во-первых, хотя они неявно наследуют от System.ValueType, они не могут напрямую наследовать ни от какого типа. Аналогичным образом, все типы значений являются запечатанными. Это значит, что наследование от них не допускается. Им также не требуются конструкторы.

Для каждого типа значения среда CLR предоставляет соответствующий упакованный тип — класс, имеющий то же состояние и поведение, что и тип значения. Экземпляр типа значения упаковывается при передаче в метод, принимающий параметр типа System.Object. Распаковка (преобразование из экземпляра класса обратно в экземпляр типа значения) производится при возврате управления после вызова метода, принимающего тип значения в качестве параметра по ссылке. В некоторых языках необходимо применение специального синтаксиса, когда требуется упакованный тип; в других упакованный тип используется автоматически, когда он нужен. При определении типа значений определяется и упакованный, и неупакованный тип.

Перечисления

Перечисление — это тип значения, который напрямую наследует от System.Enum и предоставляет альтернативные имена для значений базового типа-примитива. Тип перечисления имеет имя, базовый тип, который должен быть одним из встроенных целочисленных знаковых или беззнаковых типов (например, Byte, Int32 или UInt64), а также набор полей. Поля являются статическими полями литералов, каждое из которых представляет константу. Одно значение можно присвоить нескольким полям. В этом случае необходимо пометить одно из значений как первичное значение перечисления для отражения и преобразования строк.

Значение базового типа можно присвоить перечислению и наоборот (среда выполнения не требует приведения типов). Можно создавать экземпляры перечислений и вызвать методы System.Enum, а также любые методы, определенные в базовом типе перечисления. При этом в некоторых языках передача перечисления в виде параметра может не допускаться, если требуется передать экземпляр базового типа (или наоборот).

К перечислениям применяются следующие дополнительные ограничения.

В них нельзя определять собственные методы.

В них нельзя реализовывать интерфейсы.

В них нельзя определять свойства и события.

Они не могут быть универсальными, если только они становятся таковыми за счет вложения внутрь универсального типа. То есть перечисления не могут иметь свои собственные параметры типов.

Вложенные типы (в том числе перечисления), созданные в Visual Basic, C# и C++, содержат параметры всех включающих их универсальных типов и, таким образом, являются универсальными, даже если они не имеют своих собственных параметров типов. Дополнительные сведения см. в подразделе «Вложенные типы» раздела справки Type.MakeGenericType.

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

Интерфейсы

Интерфейс задает контракт, определяющий отношение типа «может» или «имеет». Интерфейсы часто используются для реализации различных функций, например для сравнения и сортировки (интерфейсы IComparable и IComparable ), проверки равенства (интерфейс IEquatable ) или перечисления элементов коллекции (интерфейсы IEnumerable и IEnumerable ). Интерфейсы могут иметь свойства, методы и события, являющиеся абстрактными членами. Это значит, что хотя в интерфейсе определяются члены и их сигнатуры, за определение функциональности всех членов интерфейса отвечает тип, реализующий данный интерфейс. Любой класс или структура, реализующие интерфейс, должны содержать определения абстрактных членов, объявленных в этом интерфейсе. Обязательным условием реализации интерфейса в классе или структуре также может быть реализация одного или нескольких других интерфейсов.

К интерфейсам применяются следующие ограничения.

Интерфейс может быть объявлен с любой доступностью, однако, члены интерфейса всегда должны иметь доступность уровня public.

В интерфейсах нельзя определять конструкторы.

В интерфейсах нельзя определять поля.

В интерфейсах можно определять только члены экземпляров. Статические члены определять в них нельзя.

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

Делегаты

Если тип параметра делегата является более строгим, чем тип параметра метода, то параметр делегата совместим с соответствующим параметром метода, так как это гарантирует, что аргумент, переданный делегату, может быть безопасно передан методу.

Аналогичным образом, тип возвращаемого значения делегата совместим с типом возвращаемого значения метода, если тип возвращаемого значения метода является более строгим, чем тип возвращаемого значения делегата, так как это гарантирует, что возвращаемое значение метода может быть безопасно приведено к типу возвращаемого значения делегата.

Например, делегат с параметром типа IEnumerable и типом возвращаемого значения Object может представлять метод с параметром типа Object и типом возвращаемого значения IEnumerable. Дополнительные сведения и примеры с кодом см. в разделе Delegate.CreateDelegate(Type, Object, MethodInfo).

Делегат называют связанным с методом, который он представляет. Помимо привязки к методу, делегат может быть связан с отдельным объектом. Этот объект представляет первый параметр метода и передается методу при каждом вызове делегата. Если это метод экземпляра, то связанный объект передается как неявный параметр this ( Me в Visual Basic); если метод является статическим, то объект передается как первый формальный параметр метода, и сигнатура делегата при этом должна соответствовать остальным параметрам. Дополнительные сведения и примеры с кодом см. в разделе System.Delegate.

Все делегаты наследуются от System.MulticastDelegate, который наследуется от System.Delegate. Языки C#, Visual Basic и C++ не допускают наследование от этих типов. Вместо этого они предоставляют ключевые слова для объявления делегатов.

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

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

Зачастую, как, например, в случае с методами обратного вызова, делегат представляет только один метод, поэтому единственное действие, которое нужно выполнить, — это создание и вызов делегата.

Применение этих методов к делегатам обработчиков событий в C#, C++ и Visual Basic необязательно, так как эти языки предоставляют синтаксис для добавления и удаления обработчиков событий.

Определения типов

Определение типа включает следующее:

все определенные в типе атрибуты;

доступность (видимость) типа;

базовый тип данного типа;

все интерфейсы, реализованные этим типом;

определения каждого члена типа.

Атрибуты

Атрибуты предоставляют дополнительные пользовательские метаданные. Они чаще всего используются для хранения дополнительной информации о типе в его сборке либо для изменения поведения члена типа во время разработки или выполнения.

Сами атрибуты представляют собой классы, производные от System.Attribute. Любой язык, поддерживающий использование атрибутов, имеет собственный синтаксис для применения атрибутов к элементам языка. Атрибуты можно применять почти к любым элементам языка; конкретные элементы, к которым можно применять определенный атрибут, задаются атрибутом AttributeUsageAttribute, примененным к классу этого атрибута.

Доступность типов

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

Специальные возможностиОписание
publicТип доступен во всех сборках.
сборкаТип доступен только в пределах своей сборки.

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

Имена типов

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

Все имена кодируются в виде строк, состоящих из символов Юникода (16-разрядная кодировка).

Имена не могут иметь внедренное (16-разрядное) значение 0x0000.

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

Базовые типы и интерфейсы

Тип может наследовать значения и поведение другого типа. Система общих типов не разрешает наследование от нескольких базовых типов.

Тип может реализовывать любое число интерфейсов. Для этого он должен реализовать все виртуальные члены этого интерфейса. Виртуальный метод может быть реализован с помощью производного типа и может вызываться либо статически, либо динамически.

Члены типов

Среда выполнения позволяет определять члены типа, задающих поведение и состояние типа. К членам типа относятся:

Константы, значение которых задается во время разработки. Они являются статическими членами класса, хотя и не определяются с помощью ключевого слова static ( Shared в Visual Basic).

Доступные только для чтения переменные, значения которых задаются в конструкторе класса.

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

Свойства

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

MSIL-код типа, который содержит свойство, доступное для чтения, наряду с самим свойством включает метод get_ имя_свойства. MSIL-код типа, который содержит свойство, доступное для чтения, наряду с самим свойством включает метод set_ имя_свойства.

Методы

Метод описывает операции, доступные в определенном типе. Сигнатура метода указывает допустимые типы всех его параметров и возвращаемого значения.

Хотя большинство методов определяют точное число параметров, необходимых для вызовов метода, некоторые методы поддерживают переменное число параметров. Конечный объявленный параметр этих методов помечается атрибутом ParamArrayAttribute. Компиляторы языка обычно предоставляют ключевое слово, такое как params в C# и ParamArray в Visual Basic, которое исключает необходимость явного использования ParamArrayAttribute.

Конструкторы

Конструктор — это специальный метод, который служит для создания новых экземпляров класса или структуры. Как и любой другой метод, конструктор может иметь параметры, однако у конструкторов отсутствует возвращаемое значение (они возвращают void ).

Если исходный код класса не содержит явного определения конструктора, то компилятор включает заданный конструктор без параметров. Однако если исходный код класса определяет только параметризованные конструкторы, компиляторы Visual Basic и C# не создают конструктор без параметров.

Если исходный код для структуры определяет конструкторы, они должны быть параметризованы; структура не может определять конструктор (без параметров), и компиляторы не создают конструкторы без параметров для структур и других типов значений. Все типы значений не имеют неявного конструктора без параметров. Этот конструктор реализован средой CLR и инициализирует все поля структуры, задавая для них значения по умолчанию.

События

Событие определяет происшествие, на которое можно реагировать, а также методы подписки, отказа от подписки или порождения события. События часто используются для оповещения других типов об изменениях состояния. Дополнительные сведения см. в статье Events (Visual Basic) (События в Visual Basic).

Вложенные типы

Вложенный тип — это тип, являющийся членом какого-либо другого типа. Вложенные типы должны быть тесно связаны со своим вмещающим типом и не должны использоваться в качестве типа общего назначения. Вложенные типы полезны, когда объявляющий тип использует и создает экземпляры вложенного типа и использование вложенного типа не открывается в публичных членах.

Особенности вложенных типов не всегда понятны некоторым разработчикам; эти типы не должны быть открыто видимыми, если существенной причины для подобной видимости не имеется. В хорошо спроектированной библиотеке разработчикам редко приходится использовать вложенные типы для создания экземпляров объектов или объявления переменных.

Характеристики членов типов

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

ХарактеристикаПрименениеОписание
abstractМетоды, свойства и событияТип не предоставляет реализацию метода. Типы, которые наследуют или реализуют абстрактный метод, должны предоставлять реализацию метода. Единственное исключение — когда производный тип является абстрактным. Все абстрактные методы являются виртуальными.
private, family, assembly, family and assembly, family or assembly, publicВсеОпределяют доступность члена.

private
Доступен только изнутри типа, к которому принадлежит член, или изнутри вложенного типа.

family
Доступен изнутри типа, к которому принадлежит член, а также из производных от него типов.

сборка
Доступен только в сборке, в которой определен тип.

family and assembly
Доступен только в типах с уровнем доступа family и assembly.

family or assembly
Доступен только в типах с уровнем доступа либо family, либо assembly.

public
Доступен в любом типе.

finalМетоды, свойства и событияВиртуальный метод нельзя переопределить в производном типе.
initialize-onlyПоляЗначение можно только инициализировать и невозможно установить после инициализации.
экземплярПоля, методы, свойства и событияЕсли член не помечен как static (C# и C++), Shared (Visual Basic), virtual (C# и C++) или Overridable (Visual Basic), то он является членом экземпляра (ключевое слово instance не используется). Копий таких членов в памяти будет столько, сколько объектов их использует.
литералПоляЗначение, присвоенное полю, является фиксированным значением встроенного типа значения и становится известным во время компиляции. Поля литералов иногда называются константами.
newslot или overrideВсеОпределяет способ взаимодействия члена с унаследованными членами, имеющими ту же сигнатуру:

newslot
Скрывает унаследованные члены с той же сигнатурой.

переопределенный
Заменяет определение наследуемого виртуального метода.

По умолчанию используется характеристика newslot.

статическийПоля, методы, свойства и событияЧлен принадлежит к типу, в котором он определен, а не к конкретному экземпляру типа. Член существует, даже если экземпляр типа не создан, и является общим для всех экземпляров типа.
виртуальныйМетоды, свойства и событияМетод может реализовываться с помощью производного типа и вызываться либо статически, либо динамически. Если используется динамический вызов, то вызываемая реализация метода определяется типом экземпляра, выполняющего вызов во время выполнения, а не типом, известным во время компиляции. Для статического вызова виртуального метода может потребоваться приведение переменной к типу, который использует нужную версию метода.

Перегрузка

У каждого члена типа есть уникальная сигнатура. Сигнатуры методов содержат имя метода и список параметров (порядок и типы аргументов метода). В типе можно определить несколько методов с одним именем и разными сигнатурами. При этом метод будет называться перегруженным. Например, в System.Char метод IsDigit перегружен. Один метод принимает параметр Char. Другой метод принимает String и Int32.

Тип возвращаемого значения не считается частью сигнатуры метода. Это значит, что методы не могут быть перегружены, если они различаются только типом возвращаемого значения.

Наследование, переопределение и скрытие членов

Производный тип наследует все члены своего базового типа. Эти члены будут определены для производного типа и доступны в нем. Поведение или характеристики наследуемых членов можно изменить двумя способами.

Источник

Общая система типов CTS

что делает общая система типов common type system. Смотреть фото что делает общая система типов common type system. Смотреть картинку что делает общая система типов common type system. Картинка про что делает общая система типов common type system. Фото что делает общая система типов common type system

Типы классов

Давайте рассмотрим основные характеристики классов CTS:

Типы классов CTS

Характеристика классовОписание
ЗапечатанныеЗапечатанные (sealed), или герметизированные, классы не могут выступать в роли базовых для других классов, т.е. не допускают наследования
Реализующие интерфейсыназывается коллекция абстрактных членов, которые обеспечивают возможность взаимодействия между объектом и пользователем этого объекта. CTS позволяет реализовать в классе любое количество интерфейсов
Абстрактные или конкретныеЭкземпляры абстрактных (abstract) классов не могут создаваться напрямую, и предназначены для определения общих аспектов поведения для производных типов. Экземпляры же конкретных (concrete) классов могут создаваться напрямую
Степень видимостиКаждый класс должен конфигурироваться с атрибутом видимости (visibility). По сути, этот атрибут указывает, должен ли класс быть доступным для использования внешним сборкам или только изнутри определяющей сборки

Типы интерфейсов

Интерфейсы представляют собой не более чем просто именованную коллекцию определений абстрактных членов, которые могут поддерживаться (т.е. реализоваться) в данном классе или структуре. В C# типы интерфейсов определяются с помощью ключевого слова interface, как показано ниже:

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

Типы структур

представляют собой удобную программную конструкцию, которая позволяет группировать данные в пары «имя-значение». Например, предположим, что требуется создать приложение видеоигры, в котором игроку бы позволялось выбирать персонажа одной из трех следующих категорий: Wizard (маг), Fighter (воин) или Thief (вор). Вместо того чтобы использовать и отслеживать числовые значения для каждого варианта, в этом случае гораздо удобнее создать соответствующее перечисление с помощью ключевого слова enum:

По умолчанию для хранения каждого элемента выделяется блок памяти, соответствующий 32-битному целому, однако при необходимости (например, при программировании с расчетом на устройства, обладающие малыми объемами памяти, вроде мобильных устройств Windows) это значение можно изменить. Кроме того, в CTS необходимо, чтобы перечисляемые типы наследовались от общего базового класса System.Enum. В этом базовом классе присутствует ряд весьма интересных членов, которые позволяют извлекать, манипулировать и преобразовывать базовые пары «имя-значение» программным образом.

Типы делегатов

Члены типов

В спецификации CTS описываются различные «характеристики», которые могут быть ассоциированы с любым членом. Например, каждый член может обладать характеристикой, отражающей его доступность (т.е. общедоступный, приватный или защищенный). Некоторые члены могут объявляться как абстрактные (для навязывания полиморфного поведения производным типам) или как виртуальные (для определения фиксированной, но допускающей переопределение реализации). Кроме того, почти все члены также могут делаться статическими членами (привязываться на уровне класса) или членами экземпляра (привязываться на уровне объекта).

Встроенные типы данных

И, наконец, последним, что следует знать о спецификации CTS, является то, что в ней содержится четко определенный набор фундаментальных типов данных. Хотя в каждом отдельно взятом языке для объявления того или иного встроенного типа данных из CTS обычно предусмотрено свое уникальное ключевое слово, все эти ключевые слова в конечном итоге соответствуют одному и тому же типу в сборке mscorlib.dll.

В следующей таблице показано, как ключевые типы данных из CTS представляются в C#:

Классы типов данных C#

Типы данных в CTSКлючевое слово в C#
System.Bytebyte
System.SBytesbyte
System.Int16short
System.Int32int
System.Int64long
System.UInt16ushort
System.UInt32uint
System.UInt64ulong
System.Singlefloat
System.Doubledouble
System.Objectobject
System.Charchar
System.StringString
System.Booleanbool

Из-за того факта, что уникальные ключевые слова в любом управляемом языке являются просто сокращенными обозначениями реального типа из пространства имен System, больше не нужно беспокоиться ни об условиях переполнения и потери значимости (overflow/underflow) в случае числовых данных, ни о внутреннем представлении строк и булевских значений в различных языках.

Источник

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *