<b>// Этот код не скомпилируете»!</b>
.namespace MyNamespace
{
.class public MyBaseClass {}
.class public MyDerivedClass
<b> extends MyBaseClass {}</b>
}
Чтобы корректно определить родительский класс для
MyDerivedClass
, потребуется указать полностью заданное имя
MyBaseClass
:
<b>// Уже лучше!</b>
.namespace MyNamespace
{
.class public MyBaseClass {}
.class public MyDerivedClass
<b> extends MyNamespace.MyBaseClass {}</b>
}
В дополнение к атрибутам
public
и
extends
определение класса CIL может иметь множество добавочных квалификаторов, которые управляют видимостью типа, компоновкой полей и т.д. В табл. 19.2 описаны избранные атрибуты, которые могут применяться в сочетании с директивой
.class
.
Определение и реализация интерфейсов в CIL
Несколько странно, но типы интерфейсов в CIL определяются с применением директивы
.class
. Тем не менее, когда директива
.class
декорирована атрибутом
interface, тип трактуется как интерфейсный тип CTS. После определения интерфейс можно привязывать к типу класса или структуры с использованием атрибута
implements
:
.namespace MyNamespace
{
<b> // Определение интерфейса.</b>
.class public interface IMyInterface {}
// Простой базовый класс.
.class public MyBaseClass {}
<b> // Теперь MyDerivedClass реализует IMylnterface</b>
<b> // и расширяет MyBaseClass.</b>
.class public MyDerivedClass
extends MyNamespace.MyBaseClass
implements MyNamespace.IMyInterface {}
}
На заметку! Конструкция
extends
должна предшествовать конструкции
implements
. Кроме того, в конструкции
implements
может содержаться список интерфейсов с разделителями-запятыми
Вспомните из главы 8, что интерфейсы могут выступать в роли базовых для других типов интерфейсов, позволяя строить иерархии интерфейсов. Однако вопреки возможным ожиданиям применять атрибут
extends
для порождения интерфейса
А
от интерфейса
В
в CIL нельзя. Атрибут
extends
используется только для указания базового класса типа. Когда интерфейс необходимо расширить, снова будет применяться атрибут
implements
, например:
<b>// Расширение интерфейсов в CIL.</b>
.class public interface IMyInterface {}
.class public interface IMyOtherInterface
implements MyNamespace.IMyInterface {}
Определение структур в CIL
Директива
.class
может использоваться для определения любой структуры CTS, если тип расширяет
System.ValueType
. Кроме того, такая директива
.class
должна уточняться атрибутом
sealed
(учитывая, что структуры никогда не могут выступать в роли базовых для других типов значений). Если попытаться поступить иначе, тогда компилятор
ilasm.exe
выдаст сообщение об ошибке.
<b>// Определение структуры всегда является запечатанным.</b>
.class public sealed MyStruct
extends [System.Runtime]System.ValueType{}
Имейте в виду, что в CIL предусмотрен сокращенный синтаксис для определения типа структуры. В случае применения атрибута
value
новый тип автоматически становится производным от
[System.Runtime]System.ValueType
. Следовательно, тип
MyStruct
можно было бы определить и так:
<b>// Сокращенный синтаксис объявления структуры.</b>
.class public sealed value MyStruct{}
Определение перечислений в CIL
Перечисления .NET Core порождены от класса
System.Enum
, который является
System.ValueType
(и потому также должен быть запечатанным). Чтобы определить перечисление в CIL, необходимо просто расширить
[System.Runtime]System.Enum
:
<b>// Перечисление.</b>
.class public sealed MyEnum
extends [System.Runtime]System.Enum{}
Подобно структурам перечисления могут быть определены с помощью сокращенного синтаксиса, используя атрибут
enum
:
<b>// Сокращенный синтаксис определения перечисления.</b>
.class public sealed enum MyEnum{}
Вскоре вы увидите, как указывать пары "имя-значение" перечисления.
Определение обобщений в CIL
Обобщенные типы также имеют собственное представление в синтаксисе CIL. Вспомните из главы 10, что обобщенный тип или член может иметь один и более параметров типа. Например, в типе
List<T>
определен один параметр типа, а в
Dictionary<TKey,TValue>
— два. В CIL количество параметров типа указывается с применением символа обратной одиночной кавычки (
'
), за которым следует число, представляющее количество параметров типа. Как и в С#, действительные значения параметров типа заключаются в угловые скобки.