Реализация базовых конструкций в CIL
86C# --- Сборки .NET --- Реализация базовых конструкций в CIL
Определение и реализация интерфейсов в CIL
Как ни странно, но типы интерфейсов в CIL тоже определяются с использованием директивы .class. Однако за счет ее сопровождения атрибутом interface тип реализуется как один из типов интерфейсов CTS. После определения интерфейс может привязываться к какому-нибудь типу класса или структуры с применением атрибута implements.
.namespace MyUI
{
// Объявление интерфейса
.class public interface IMyInterface {}
.class public MyClass { }
// Класс MyUserInfo наследуется от класса MyClass
// и реализует интерфейс IMyInterface
.class public MyUserInfo
extends MyUI.MyClass
implements MyUI.IMyInterface{}
}
Интерфейсы могут выступать в роли базовых для других типов интерфейсов, позволяя строить иерархии интерфейсов. Вопреки возможным ожиданиям, однако, использовать атрибут extends для наследования интерфейса А от интерфейса В в CIL нельзя. Этот атрибут разрешено применять только для указания базового класса типа. Для расширения интерфейса должен использоваться атрибут implements.
Определение структур в CIL
Директива .class может использоваться для определения любой структуры CTS при условии расширения ее типом System.ValueType. В этом случае она должна обязательно сопровождаться атрибутом sealed (поскольку структуры никогда не могут выступать в роли базовых для других типов-значений). В случае несоблюдения этого требования ilasm.exe будет сообщать об ошибке на этапе компиляции.
// При определении структуры должен быть указан атрибут sealed
.class public sealed MyStruct
extends [mscorlib]System.ValueType{}
В CIL также предусмотрен сокращенный вариант синтаксиса для определения типа структуры. В случае использования атрибута value новый тип будет автоматически наследоваться от типа [mscorlib]System.ValueType. Следовательно, тип MyStruct можно было бы определить и так:
// Сокращенный вариант объявления структуры
.class public value MyStruct{}
Определение перечислений в CIL
Перечисления .NET унаследованы от класса System.Enum, который, в свою очередь, наследуется от System.ValueType (и потому должен обязательно сопровождаться атрибутом sealed). Чтобы определить перечисление в CIL, необходимо расширить [mscorlib]System.Enum показанным ниже образом:
// Определение перечисления
.class public sealed MyEnum
extends [mscorlib]System.Enum{}
Как и для структур, для перечислений тоже поддерживается сокращенный синтаксис определения, предусматривающий использование атрибута enum:
// Сокращенный вариант определения перечисления.
.class public sealed enum MyEnum{}
Делегаты, которые являются еще одним фундаментальным типом в .NET, тоже имеют свое специфическое представление в CIL.
Определение обобщений в CIL
Обобщенные типы также имеют свое представление в синтаксисе CIL. Вспомните, что каждый обобщенный тип или член может иметь один и более параметров типа. Например, тип List<T> обладает одним единственным параметром, а Dictionary<TKey, TValue> — двумя. В CIL количество параметров типа указывается с использованием символа обратной одиночной кавычки (`) со следующим за ним числом. Как и в C#, сами значения параметров типа заключаются в квадратные скобки.
Например, предположим, что необходимо создать переменную List<T>, где на месте T должно находиться значение типа System.Int32. В CIL это делается следующим образом (в области действия любого метода CIL):
// В C#: List<int> myInts = new List<int>();
newobj instance void class [mscorlib]
System.Collections.Generic.List`1<int32>::.ctor()
Обратите внимание, что данный обобщенный класс определен как List`1<int32>, поскольку List<T> имеет только один параметр типа.
Компиляция файла program.il
Итак, разрабатываемый файл program.il на данном этапе содержит следующий код:
.assembly extern mscorlib
{
.publickeytoken = (B7 7A 5C 56 19 34 E0 89)
.ver 4:0:0:0
}
// Определение сборки
.assembly UserInfoCIL
{
.ver 1:0:0:1
}
.module UserInfoCIL.dll
// Пространство имен
.namespace MyUI
{
// Объявление интерфейса
.class public interface IMyInterface {}
.class public MyClass { }
// Класс MyUserInfo наследуется от класса MyClass
// и реализует интерфейс IMyInterface
.class public MyUserInfo
extends MyUI.MyClass
implements MyUI.IMyInterface{}
}
Несмотря на то что ни члены, ни код реализации в определенные ранее типы не добавлялись, данный файл *.il уже можно компилировать в .NET-сборку с расширением .dll (это является единственным доступным вариантом, поскольку метод Main() не был определен). Для этого необходимо открыть окно командной строки и ввести следующую команду для запуска утилиты ilasm.ехе:
ilasm /dll program.il
После выполнения этой команды можно загрузить полученный двоичный файл в ildasm.exe и просмотреть его:
Просмотрев содержимое сборки, можно запустить в отношении нее утилиту peverify.ехе. Обратите внимание, что это приведет к выдаче ряда сообщений об ошибках, так как все типы совершенно пусты.