CLS (Common Language Specification)

Материал из Национальной библиотеки им. Н. Э. Баумана
Последнее изменение этой страницы: 18:48, 4 мая 2017.
CTS and CLS
Common Language Specification (сокр. CLS, рус. Общеязыковая спецификация) - документ, в котором говорится, как компьютерные программы могут быть превращены в код MSIL[Источник 1]. Когда несколько языков используют один и тот же байт-код, различные части программы могут быть написаны на разных языках. Чтобы полностью взаимодействовать с другими объектами независимо от языка, в котором они были использованы, объекты должны предоставлять вызывающим только те функции, которые являются общими для всех языков, с которыми они должны обмениваться информацией.

Спецификация CLS определяется в документе Стандарт ECMA-335[Источник 2]. Спецификация CLS является подмножеством системы CTS[Источник 3]. Это означает, что все правила в CTS применяются и к CLS, если только в CLS не действуют более строгие правила. Если компонент создается с использованием только правил CLS, то есть предоставляет в своем API только функции CLS, он считается CLS-совместимым. Например, <framework-librares> являются CLS-совместимыми, так как они должны работать во всех языках, поддерживаемых на платформе .NET.

Понимание взаимосвязи между CTS и CLS

CTS и CLS являются компонентами .NET CLR[Источник 4] и отвечают за безопасность типов в коде. Оба варианта обеспечивают взаимную языковую связь и безопасность типов.
CTS - это система Common Type, которая:

  • определяет правила, за которыми следует Common Language Runtime при объявлении, использовании и управлении типами.
  • позволяет осуществлять кросс-язычную интеграцию, безопасность типов и выполнение высокопроизводительного кода.
  • предоставляет объектно-ориентированную модель для реализации многих языков программирования.
  • определяет правила, которым должен следовать каждый язык, который выполняется в рамках .NET. Это гарантирует, что объекты, написанные на разных языках .NET, такие как C #, VB.NET, F # и т. д. могут взаимодействовать друг с другом.

CLS означает Common Language Specification и является подмножеством CTS.

  • определяет набор правил и ограничений, которым должен следовать каждый язык, который выполняется в рамках .NET. Языки, следующие за этим набором правил, называются CLS Compliant. Проще говоря, CLS допускает кросс-язычную интеграцию.

Например, одно правило состоит в том, что вы не можете использовать множественное наследование в .NET Framework. Как вы знаете, C ++ поддерживает множественное наследование, но, когда вы попытаетесь использовать этот код C ++ в C #, это невозможно, потому что C # не поддерживает множественное наследование. Другим правилом является то, что вы не можете иметь членов с одинаковым именем с разницей только в том случае, если вы не можете иметь методы add () и Add (). Это легко работает на C #, потому что это чувствительно к регистру, но когда вы попытаетесь использовать этот код C # в VB.NET, это невозможно, потому что VB.NET не чувствителен к регистру.

Роль спецификации Common Language Specification (CLS) в обеспечении надежного межъязыкового взаимодействия.

Компиляция исходного кода в управляемые модули

Взаимодействие языков — это способность кода к взаимодействию с кодом, написанным на другом языке программирования. Взаимодействие языков может способствовать повышению уровня повторного использования кода и эффективности процесса разработки. Поскольку разработчики используют широкий набор средств и технологий, каждая из которых поддерживает различные функции и типы, сложилась ситуация, в которой трудно обеспечить взаимодействие разных языков. Тем не менее, встроенная поддержка взаимодействия разных языков в среде выполнения обеспечивает определенные преимущества для языковых компиляторов и средств, обращающихся к среде CLR. Среда CLR предоставляет необходимую основу для взаимодействия языков, определяя и обеспечивая реализацию системы общих типов, а также предоставляя метаданные. Поскольку все языки, предназначенные для среды выполнения, следуют правилам системы общих типов CTS по использованию и определению типов, использование типов является согласованным для всех языков. Метаданные обеспечивают взаимодействие языков за счет определения универсального механизма хранения и извлечения сведений о типах. Компиляторы хранят в виде метаданных сведения, которые в среде CLR используются для предоставления служб в процессе выполнения. Среда выполнения может управлять работой многоязычных приложений, поскольку способ хранения и извлечения всех сведений о типах одинаков для всех языков, на которых создается код. Поддержка взаимодействия языков в среде выполнения дает следующие преимущества при работе с управляемым кодом. Типы могут наследовать реализацию от других типов, передавать объекты методам другого типа и вызывать методы, определенные для других типов, независимо от языка, в которых реализованы эти типы. Отладчики, профилировщики и другие средства должны уметь работать только с одной средой — промежуточным языком MSIL и метаданными для среды CLR. Это позволит поддерживать любой язык программирования, обращающийся к среде выполнения. Обработка исключений проходит согласованно во всех языках. Код может создавать исключение на одном языке, которое может перехватываться и обрабатываться объектом, созданном на другом языке. Даже если среда выполнения предоставляет поддержку выполнения в многоязычной среде для всего управляемого кода, это не дает гарантии того, что все возможности создаваемых типов можно будет полностью использовать в языках программирования, используемых другими разработчиками. Это происходит главным образом потому, что каждый языковой компилятор, обращающийся к среде выполнения, использует систему типов и метаданные для поддержки собственного уникального набора языковых возможностей. Когда неизвестно, на каком языке будет написан вызывающий код, маловероятно предугадать, будут ли предоставляемые компонентом функции доступны вызывающему объекту. Например, если выбранный язык обеспечивает поддержку целых чисел без знака, можно разработать метод с параметром типа UInt32. Однако такой метод был бы бесполезен для языка, в котором отсутствует понятие целого числа без знака. Для обеспечения доступности управляемого кода для разработчиков, использующих другие языки программирования, платформа .NET Framework предоставляет спецификацию Спецификация CLS (CLS), в которой описывается базовый набор языковых функций и определяются правила использования этих функций.

Правила CLS-совместимости

Common Language Specification (CLS) описывает набор функций, общих для разных языков. Он определяет минимальные требования к типам, которые должны поддерживаться любым языком .NET. Правила CLS-совместимости применяются только к открытому интерфейсу компонента и не применяются к закрытой реализации. Наиболее важные правила, применимые к общественным и защищенным членам:

  • все типы, появляющиеся в прототипе метода, должны быть CLS-совместимыми.
  • элементы массива должны иметь CLS-совместимый тип элемента. Массивы также должны быть 0-индексированными.
  • CLS-совместимый класс должен наследовать от CLS-совместимого класса.
  • System.Object соответствует CLS.
  • хотя имена методов в CLS-совместимых классах не чувствительны к регистру, имена двух методов не могут отличаться только в случае букв в их именах.
  • перечисления должны быть типа Int16, Int32 или Int64. Перечисления других типов несовместимы.

Кроме того, существует несколько правил именования, но они не являются обязательными.
Пример несоблюдения CLS
Неподписанные типы поддерживаются C # и MC ++, но не VB.NET (за исключением 'Byte', который отображается на .NET 'Byte' и принимает значения от 0 t o255). Таким образом, любой открытый или защищенный член класса C #, который имеет тип без знака или принимает в качестве параметра неподписанное, не соответствует CLS.
В следующей таблице представлены правила CLS-совместимости[Источник 5].

Категория Правило Номер правила 
Специальные возможности При переопределении унаследованных методов не должна изменяться доступность. Исключение составляют методы, унаследованные из другой сборки с доступностью family-or-assembly. В таких случаях переопределенный метод должен иметь доступность family. 10 
Специальные возможности Видимость и доступность типов и членов должна быть такой, чтобы типы в сигнатуре любого члена были видимы и доступны всегда, когда видим или доступен сам член. Например, открытый метод, видимый за пределами его сборки, не должен иметь аргументов, типы которых видимы только в пределах сборки. Видимость и доступность типов, составляющих экземпляры универсального типа, используемого в сигнатуре любого члена, должна быть такой, чтобы типы в сигнатуре любого члена были видимы и доступны всегда, когда видим или доступен сам член. Например, экземпляр универсального типа в сигнатуре члена, видимого вне его сборки, не должен иметь универсальных аргументов, тип которых видимы только в пределах сборки. 12 
Массивы Элементы массива должны быть CLS-совместимого типа, а измерения массива — иметь нижнюю границу, равную нулю. Для различения перегрузок достаточно, чтобы элемент был массивом и у него был задан тип элементов. Если перегрузка основана на нескольких типах массивов, типы элементов должны быть именованными. 16 
Атрибуты Атрибуты должны иметь тип System.Attribute или унаследованный от него тип. 41 
Атрибуты В спецификации CLS разрешено только подмножество кодировок настраиваемых атрибутов. В этих кодировках разрешается использовать только следующие типы (см. раздел IV): System.Type, System.String, System.Char, System.Boolean, System.Byte, System.Int16, System.Int32, System.Int64, System.Single, System.Double, а также типы перечислений, основанные на CLS-совместимых базовых целочисленных типах. 34 
Атрибуты В спецификации CLS запрещены публично видимые обязательные модификаторы (modreq, см. раздел II), но разрешены необязательные модификаторы (modopt, см. раздел II), которые не распознаются. 35 
Конструкторы Доступ к данным унаследованного экземпляра возможен после того, как конструктор объекта вызвал какой-либо конструктор экземпляра базового класса. (Правило не относится к типам значений, которым не требуются конструкторы). 21 
Конструкторы Конструктор объекта должен вызываться только в ходе создания объекта и объекты не должны инициализироваться дважды. 22 
Перечисления Базовый тип перечисления должен быть встроенным целочисленным типом CLS, имя поля должно быть value__ и это поле должно быть отмечено атрибутом RTSpecialName.
Перечисления Существует два вида перечислений, которые различаются наличием/отсутствием пользовательского атрибута System.FlagsAttribute (см. раздел IV библиотеки). Одно представляет именованные целочисленные значения, другое — именованные битовые флаги, сочетая которые, можно создавать значения без имени. Перечисление enum может принимать и другие значения.
Перечисления Статические поля литералов перечисления должны иметь тип перечисления.
События Реализующие событие методы должны быть отмечены в метаданных атрибутом SpecialName. 29 
События Событие и его методы доступа должны иметь одинаковую доступность. 30 
События У события должны либо присутствовать, либо отсутствовать оба метода add и remove. 31 
События Методы add и remove события должны иметь один параметр, его тип определяет тип события. Тип параметра должен быть производным от типа System.Delegate. 32 
События События должны следовать определенному шаблону именования. Атрибут SpecialName, упоминаемый в правиле 29 спецификации CLS, должен игнорироваться в соответствующих сравнениях имен и соответствовать правилам в отношении идентификаторов. 33 
Исключения Объекты исключений должны иметь тип System.Exception или унаследованный от него тип. Однако не требуется, чтобы CLS-совместимые методы блокировали распространение других типов исключений. 40 
Общие правила Правила CLS-совместимости применяются только к тем составляющим типа, которые доступны или видны за пределами определяющей сборки.
Общие правила Члены типов, не соответствующих правилам CLS-совместимости, не должны быть отмечены как CLS-совместимые.
Универсальные шаблоны У вложенного типа должно не меньше универсальных параметров, чем у включающего его типа. Универсальные параметры вложенного типа соответствуют по позиции универсальным параметрам включающего типа. 42 
Универсальные шаблоны В имени универсального типа должны кодироваться все параметры типа, объявленные в невложенном типе или введенные во вложенном типе, в соответствии с определенными выше правилами. 43 
Универсальные шаблоны В универсальном типе должны повторно объявляться ограничения, обеспечивающие соответствие всем ограничениям базового типа и интерфейсов. 44 
Универсальные шаблоны Типы, используемые в качестве ограничений универсальных параметров, должны быть CLS-совместимыми. 45 
Универсальные шаблоны Реализация видимости и доступности членов (включая вложенные типы) в экземплярах универсального типа должна ограничиваться областью конкретного экземпляра, а не объявлением универсального типа. С учетом этого также применяется правило 12 CLS-совместимости, касающееся видимости и доступности. 46 
Универсальные шаблоны Каждый абстрактный или виртуальный универсальный метод должен иметь конкретную (не абстрактную) реализацию по умолчанию. 47 
Интерфейсы CLS-совместимые интерфейсы должны реализовываться без методов, не соответствующих правилам CLS-совместимости. 18 
Интерфейсы CLS-совместимые интерфейсы не могут определять статические методы и поля. 19 
Члены Глобальные статические static поля и методы не совместимы с CLS. 36 
Члены Значение статического поля литерала задается с помощью метаданных инициализации поля. У CLS-совместимого литерала тип значения должен совпадать с типом литерала (или базовым типом, если литерал — перечисление enum). 13 
Члены Ограничение vararg не входит в спецификацию CLS. В спецификации поддерживается только стандартное соглашение об управляемых вызовах. 15 
Соглашения об именах Допустимые в сборках открывающие и внутренние символы идентификаторов указаны в приложении 7 технического отчета 15 стандарта Юникода версии 3.0[Источник 6]. Идентификаторы должны иметь канонический формат, определяемый формой нормализации Юникода C (NFC). В рамках спецификации CLS два идентификатора считаются одинаковыми, если их записи в нижнем регистре совпадают (т. е. при взаимно-однозначном сопоставлении символов Юникода нижнего регистра без учета языкового стандарта). Таким образом в рамках спецификации CLS отличия регистра недостаточно для различения идентификаторов. Однако чтобы переопределить наследуемое определение, требуется использовать точную кодировку исходного объявления.
Перегрузка Все имена, которые вводятся в CLS-совместимой области, должны быть различными. Это правило не относится к одинаковым именам, конфликт между которыми разрешается во время перегрузки. Другими словами, в системе общих типов CTS разрешено давать одинаковое имя методу и полю, а в спецификации CLS — нет.
Перегрузка Поля и вложенные типы должны отличаться только идентификаторами, хотя в системе общих типов CTS могут отличаться сигнатуры. Методы, свойства и события с одинаковыми именами (при сравнении идентификаторов) должны отличаться не только возвращаемым типом, за исключением случаев из правила 39 спецификации CLS.
Перегрузка Перегружать можно только свойства и методы. 37 
Перегрузка Свойства и методы могут перегружаться только на основе количества и типов их параметров, за исключением операторов преобразования op_Implicit и op_Explicit, которые также могут перегружаться на основе возвращаемого типа. 38 
Перегрузка Если в типе объявлены несколько CLS-совместимых методов с одним и тем же именем, и они создают набор экземпляров типа с одинаковыми параметрами и возвращаемыми типами, эти методы должны быть семантически эквивалентны в экземплярах типа. 48 
Типы Тип System.Object является CLS-совместимым. Все другие CLS-совместимые классы должны наследоваться от CLS-совместимого класса. 23 
Свойства Методы, которые реализуют получение и задание значения, должны быть отмечены в метаданных атрибутом SpecialName. 24 
Свойства Все методы доступа свойства должны быть либо одновременно статическими, либо виртуальными, либо экземплярами. 26 
Свойства Тип свойства, возвращаемый тип метода получения значения и тип последнего аргумента метода задания значения должны совпадать. Типы параметров свойства, типы параметров метода получения значения и типы параметров метода задания значения (за исключением его последнего параметра) должны совпадать. Все типы должны быть CLS-совместимыми и не могут быть управляемыми указателями (т. е. не могут передаваться по ссылке). 27 
Свойства Свойства должны следовать определенному шаблону именования. Атрибут SpecialName, упоминаемый в правиле 24 спецификации CLS, должен игнорироваться в соответствующих сравнениях имен и соответствовать правилам в отношении идентификаторов. Свойство должно иметь метод получения и/или задания значения. 28 
Преобразование типов При наличии оператора преобразования op_Implicit или op_Explicit необходимо предоставить альтернативный способ приведения. 39 
Типы Упакованные типы значений не являются CLS-совместимыми.
Типы Все типы сигнатуры должны быть CLS-совместимыми. Все типы, составляющие экземпляры универсального типа, должны быть CLS-совместимыми. 11 
Типы Типизированные ссылки несовместимы с CLS. 14 
Типы Типы неуправляемых указателей не являются CLS-совместимыми. 17 
Типы CLS-совместимые классы, типы значений и интерфейсы должны реализовываться без членов, не соответствующих правилам CLS-совместимости. 20 

CLS-совместимые средства

CLS-средства для пользователей

Средства для пользователей — это языки, с помощью которых разработчики получают доступ ко всем возможностям, предоставляемым CLS-совместимыми библиотеками. Разработчики, использующие эти языки, не всегда имеют возможность расширять CLS-совместимые библиотеки, создавая новые типы, но могут использовать любые типы, определенные в совместимой библиотеке. Этот уровень совместимости используется при необходимости получить доступ к библиотеке классов .NET Framework, не создавая новых объектов, например при использовании Windows Forms на странице ASP.NET[Источник 7] или при создании пользовательского интерфейса Windows Forms.

CLS-совместимые средства для расширения

Средства для расширения — это языки, в которых разработчики могут как использовать, так и расширять типы, определенные в CLS-совместимых библиотеках. Разработчики могут использовать существующие типы и определять новые. Средства для расширения должны соответствовать всем правилам, определенным для средств для пользователей, а также некоторым дополнительным правилам, которые описаны в спецификации для CLI, раздел I — 0 Архитектура, доступной на веб-сайте Microsoft Developer Network (MSDN).

Атрибут CLSCompliantAttribute

CLS-совместимый атрибут

Атрибут CLSCompliantAttribute[Источник 8] указывает, соответствует ли элемент правилам спецификации CLS. Конструктор CLSCompliantAttribute.CLSCompliantAttribute(Boolean) имеет один обязательный параметр isCompliant, определяющий, является ли элемент программы CLS-совместимым. Компилятор определяет элементы, которые предположительно являются CLS-совместимыми, однако не соответствуют правилам спецификации CLS, и выдает предупреждение. Он пропускает типы и члены, которые явно объявлены как не соответствующие правилам спецификации CLS. Разработчики компонентов могут использовать атрибут CLSCompliantAttribute двумя способами: Определять части открытого интерфейса, предоставляемые компонентом, которые являются или не являются CLS-совместимыми. Если с помощью этого атрибута пометить определенные элементы программы как CLS-совместимые, они будут доступны во всех языках и инструментах, ориентированных на .NET Framework. С его помощью обеспечить, чтобы открытый интерфейс библиотеки компонентов предоставлял только CLS-совместимые элементы программы. Если элементы не являются CLS-совместимыми, компиляторы обычно выдают предупреждение. Атрибут CLSCompliantAttribute отмечен атрибутом AttributeUsageAttribute со значением AttributeTargets.All. Это значение позволяет применять атрибут CLSCompliantAttribute к любым элементам программы: сборкам, модулям, типам (классам, структурам, перечислениям, интерфейсам и делегатам), членам типов (конструкторам, методам, свойствам, полям и событиям), параметрам, универсальным параметрам и возвращаемым значениям. Однако на практике атрибут рекомендуется применять только к сборкам, типам и членам типов. В противном случае компиляторы игнорируют атрибут и создают предупреждения для всех параметров, универсальных параметров и возвращаемых значений открытого интерфейса библиотеки, которые не являются CLS-совместимыми. Значение атрибута CLSCompliantAttribute наследуется вложенными элементами программы. Например, если сборка отмечена как CLS-совместимая, ее типы также являются CLS-совместимыми. Если тип отмечен как CLS-совместимый, его вложенные типы и члены также являются CLS-совместимыми. Можно явно переопределить наследуемую совместимость, применив к вложенному элементу программы атрибут CLSCompliantAttribute. Например, используя атрибут CLSCompliantAttribute с параметром isCompliant равным false, можно определить в совместимой сборке несовместимый тип, а используя его с параметром isCompliant равным true — определить в несовместимой сборке совместимый тип. Кроме того, можно определять несовместимые члены в совместимом типе. Однако несовместимый тип не может иметь совместимые члены, поэтому наследование от несовместимого типа невозможно переопределить с помощью параметра isCompliant со значением true. При разработке компонентов следует всегда указывать, что сборка, ее типы и члены являются CLS-совместимыми с помощью атрибута CLSCompliantAttribute.

Создание CLS-совместимых компонентов

При разработке собственных CLS-совместимых[Источник 9] компонентов рекомендуется пользоваться CLS-совместимыми средствами. Разработка CLS-совместимых компонентов без таких средств более сложна, поскольку в этом случае, возможно, не удастся получить доступ ко всем необходимым функциям CLS. Некоторые компиляторы CLS-совместимых языков, например компилятор C # или Visual Basic, позволяют указывать, разрабатывается ли код как CLS-совместимый. Такие компиляторы могут выполнять проверку на CLS-совместимость и уведомлять разработчика, когда в коде используются возможности, не поддерживаемые CLS. Компиляторы C # и Visual Basic позволяют отмечать элемент программы как CLS-совместимый, что приведет к ошибке времени компиляции, если код несовместим с CLS.
Пометьте сборку как CLS-совместимую с помощью атрибута CLSCompliantAttribute. Пометьте все открытые типы в сборке, которые не являются CLS-совместимыми, как несовместимые. Пометьте все открытые члены в CLS-совместимых типах как несовместимые. Предоставьте CLS-совместимую альтернативу членам, которые не являются CLS-совместимыми. Если все несовместимые типы и члены отмечены, компилятор не выдает предупреждений о несовместимости. Однако следует указать, какие члены не являются CLS-совместимым, и определить CLS-совместимые альтернативы в документации продукта. При разработке приложений (а не библиотек, где предоставляются типы и члены, которые могут использоваться другими разработчиками) вы столкнетесь с вопросами CLS-совместимости программных элементов, которые использует приложение, только если их не поддерживает язык, на котором вы работаете. И если вы попытаетесь использовать элементы, которые не являются CLS-совместимыми, языковой компилятор выдаст предупреждение.


Источники

  1. Microsoft Intermediate Language (MSIL) [Электронный ресурс]: MSDN / Дата обращения: 09.03.2017. Режим доступа: https://msdn.microsoft.com/ru-ru/library/c5tkafs1(v=vs.90).aspx
  2. Общеязыковая инфраструктура (CLI) (пункты 7–11 раздела I) [Электронный ресурс]: Ecma International / Дата обращения: 09.03.2017. Режим доступа: http://www.ecma-international.org/
  3. Система общих типов CTS [Электронный ресурс]: MSDN / Дата обращения: 09.03.2017. Режим доступа: https://msdn.microsoft.com/ru-ru/library/zcx1eb1e(v=vs.110).aspx
  4. Среда CLR [Электронный ресурс]: MSDN / Дата обращения: 09.03.2017. Режим доступа: https://msdn.microsoft.com/ru-ru/library/8bs2ecf4(v=vs.110).aspx
  5. Дословные выдержки из документа Стандарт ECMA-335: общеязыковая инфраструктура (CLI) [Электронный ресурс]: Ecma International / Дата обращения: 09.03.2017. Режим доступа: http://www.ecma-international.org/
  6. Приложение 7 технического отчета 15 стандарта Юникода версии 3.0 [Электронный ресурс]: Code Charts - Unicode / Дата обращения: 09.03.2017. Режим доступа: http://www.unicode.org/unicode/reports/tr15/tr15-18.html
  7. ASP.NET [Электронный ресурс]: ProfessorWeb / Дата обращения: 09.03.2017. Режим доступа: https://professorweb.ru/my/ASP_NET/base/level1/aspnet_info.php
  8. Класс CLSCompliantAttribute [Электронный ресурс]: MSDN / Дата обращения: 09.03.2017. Режим доступа: https://msdn.microsoft.com/ru-ru/library/system.clscompliantattribute(v=vs.110).aspx
  9. Правила CLS-совместимости [Электронный ресурс]: MSDN / Дата обращения: 09.03.2017. Режим доступа: https://msdn.microsoft.com/ru-ru/library/12a7a7h3(v=vs.110).aspx#Правила

Ссылки/Литература

  • Джеффри Рихтер. CLR via C#. Программирование на платформе Microsoft .NET Framework 4.5 на языке C#. — 4-е изд. — СПб.: Питер, 2013. — 896 с. — ISBN 978-5-496-00433-6.
  • Programmingdoc.com [Электронный ресурс]: Common Language Specification (CLS). Режим доступа: http://programmingdoc.com/
  • MSDN Library [Электронный ресурс]: Независимость от языка и независимые от языка компоненты. Режим доступа: https://msdn.microsoft.com/ru-ru/library/12a7a7h3(v=vs.110).aspx#Types