рис. 1.6.
.Разные.языки.поддерживают.подмножество.CLR/CTS.и.надмножество.CLS.
(возможно,.разные.подмножества)
Как видно из рис. 1.6, CLR/CTS определяет набор функциональных возмож-
ностей. Некоторые языки реализуют более широкое подмножество CLR/CTS.
Например, программист, пожелавший работать на языке ассемблера IL, сможет
использовать все возможности CLR/CTS. Большинство других языков (C#, Visual
Basic, Fortran и т. д.) предоставляют в распоряжение программиста подмножество
возможностей CLR/CTS. CLS определяет минимальный набор возможностей,
которые должны поддерживаться всеми языками. Если вы проектируете тип на
одном языке и собираетесь использовать его в другом языке, не размещайте никакие
возможности, выходящие за пределы CLS, в его открытых и защищенных членах.
В этом случае члены вашего типа могут стать недоступными для программистов,
пишущих код на других языках программирования.
В следующем коде CLS-совместимый тип определяется в коде C#. Однако при
этом тип содержит несколько CLS-несовместимых конструкций, из-за которых
компилятор C# выдает предупреждения.
using System;
// Приказываем компилятору проверять код
// на совместимость с CLS
[assembly: CLSCompliant(true)]
namespace SomeLibrary {
// Предупреждения выводятся, потому что класс является открытым
public sealed class SomeLibraryType {
// Предупреждение: возвращаемый тип 'SomeLibrary.SomeLibraryType.Abc()'
// не является CLS-совместимым
public UInt32 Abc() { return 0; }
продолжение
54
Глава.1 .Модель.выполнения.кода.в.среде.CLR
// Предупреждение: идентификаторы 'SomeLibrary.SomeLibraryType.abc()',
// отличающиеся только регистром символов, не являются
// CLS-совместимыми
public void abc() { }
// Предупреждения нет: закрытый метод
private UInt32 ABC() { return 0; }
}
}
В этом коде атрибут
[assembly:CLSCompliant(true)]
применяется к сборке.
Этот атрибут приказывает компилятору следить за тем, чтобы тип с открытым
уровнем доступа не содержал конструкций, препятствующих его использованию
в другом языке программирования. При компиляции этого кода компилятор C#
выдает два предупреждения. Первое выдается из-за того, что метод
Abc
возвращает
целое без знака; некоторые языки программирования не умеют работать с беззна-
ковыми целыми числами. Второе предупреждение выдается из-за того, что тип
содержит два открытых метода, различающихся только регистром и типом воз-
вращаемого значения:
Abc
и
abc
. В Visual Basic и некоторых других языках вызов
обоих методов невозможен.
Если удалить ключевое слово
public
перед
sealed class
SomeLibraryType
и перекомпилировать код, оба предупреждения пропадают. Дело в том, что тип
SomeLibraryType
по умолчанию рассматривается как
internal
, а следовательно,
становится недоступным за пределами сборки. Полный список правил CLS при-
веден в разделе «Cross-Language Interoperability» документации .NET Framework
SDK (
http://msdn microsoft com/en-us/library/730f1wy3 aspx
).
Позвольте мне изложить правила CLS в предельно упрощенном виде. В CLR
каждый член типа является либо полем (данные), либо методом (поведение). Это
означает, что каждый язык программирования должен уметь обращаться к полям
и вызывать методы. Некоторые поля и некоторые методы используются специ-
альным образом. Для упрощения программирования языки обычно предостав-
ляют дополнительные абстракции, упрощающие реализацию этих стандартных
паттернов — перечисления, массивы, свойства, индексаторы, делегаты, события,
конструкторы, финализаторы, перегрузки операторов, операторы преобразования
и т. д. Когда компилятор встречает эти абстракции в исходном коде, он должен пре-
образовать их в поля и методы, чтобы сделать их доступными для CLR и любых
других языков программирования.
Следующее определение типа содержит конструктор, финализатор, перегру-
женные операторы, свойство, индексатор и событие. Учтите, что приведенный
код написан всего лишь для того, чтобы он компилировался, и не демонстрирует
правильного способа реализации типа.
using System;
internal sealed class Test {
55
CLS
// Конструктор
public Test() {}
// Финализатор
~Test() {}
// Перегрузка оператора
public static Boolean operator == (Test t1, Test t2) {
return true;
}
public static Boolean operator != (Test t1, Test t2) {
return false;
}
// Перегрузка оператора
public static Test operator + (Test t1, Test t2) { return null; }
// Свойство
public String AProperty {
get { return null; }
set { }
}
// Индексатор
public String this[Int32 x] {
get { return null; }
set { }
}
// Событие
public event EventHandler AnEvent;
}
Результатом компиляции этого кода является тип, содержащий набор полей
и методов. В этом можно легко убедиться, просмотрев полученный управляемый
модуль в программе IL Disassembler (
ILDasm exe
), входящей в пакет .NET Framework
SDK (рис. 1.7).
В табл. 1.4 продемонстрировано соответствие между конструкциями языка про-
граммирования и эквивалентными полями/методами CLR.
Дополнительные узлы типа
Test
, не упомянутые в табл. 1.4 —
.class
,
.custom
,
AnEvent
,
AProperty
и
Item
, — содержат дополнительные метаданные типа. Они
не отображаются на поля или методы, а только предоставляют дополнительную
информацию о типе, которая может использоваться CLR, языками программи-
рования или инструментами. Например, программа может узнать, что тип
Test
поддерживает событие
AnEvent
, для работы с которым используются два метода
(
add_AnEvent
и
remove_AnEvent
).
Do'stlaringiz bilan baham: |