Хотя такой код действительно определяет новую сборку .NET Core, обычно внутрь объявления будут помещаться дополнительные директивы. В рассматриваемом примере определение сборки необходимо снабдить номером версии 1.0.0.0 посредством директивы .ver
// Наша сборка.
.assembly CILTypes
{
.ver 1:0:0:0
}
Из-за того, что сборка CILTypes
.module, которая обозначает официальное имя двоичного файла .NET Core, т.е. CILTypes.dll:// Наша сборка
.assembly CILTypes
{
.ver 1:0:0:0
}
// Модуль нашей однофайловой сборки.
.module CILTypes.dll
Кроме .assembly
.module существуют директивы CIL, которые позволяют дополнительно уточнять общую структуру создаваемого двоичного файла .NET Core. В табл. 19.1 перечислены некоторые наиболее распространенные директивы уровня сборки.Определение пространств имен в CIL
Определив внешний вид и поведение сборки (а также обязательные внешние ссылки), вы можете создать пространство имен .NET Core (MyNamespace
.namespace:// Наша сборка имеет единственное пространство имен.
.namespace MyNamespace {}
Подобно C# определения пространств имен CIL могут быть вложены в другие пространства имен. Хотя здесь нет нужды определять корневое пространство имен, ради интереса посмотрим, как создать корневое пространство имен MyCompany
.namespace MyCompany
{
.namespace MyNamespace {}
}
Как и С#, язык CIL позволяет определить вложенное пространство имен следующим образом:
// Определение вложенного пространства имен.
.namespace MyCompany.MyNamespace {}
Определение типов классов в CIL
Пустые пространства имен не особо интересны, поэтому давайте рассмотрим процесс определения типов классов в CIL. Для определения нового типа класса предназначена директива .class
MyBaseClass. Как и в С#, если базовый класс явно не указан, то тип автоматически становится производным от System.Object:.namespace MyNamespace
{
// Предполагается базовый класс System.Object.
.class public MyBaseClass {}
}
При построении типа, производного не от класса System.Object
extends. Для ссылки на тип, определенный внутри той же самой сборки, язык CIL требует использования полностью заданного имени (однако если базовый тип находится внутри той же самой сборки, то префикс в виде дружественного имени сборки можно не указывать). Следовательно, демонстрируемая ниже попытка расширения MyBaseClass в результате дает ошибку на этапе компиляции:// Этот код не скомпилируете»!
.namespace MyNamespace
{
.class public MyBaseClass {}
.class public MyDerivedClass
extends MyBaseClass {}
}
Чтобы корректно определить родительский класс для MyDerivedClass
MyBaseClass:// Уже лучше!
.namespace MyNamespace
{
.class public MyBaseClass {}
.class public MyDerivedClass
extends MyNamespace.MyBaseClass {}
}
В дополнение к атрибутам public
extends определение класса CIL может иметь множество добавочных квалификаторов, которые управляют видимостью типа, компоновкой полей и т.д. В табл. 19.2 описаны избранные атрибуты, которые могут применяться в сочетании с директивой .class.Определение и реализация интерфейсов в CIL
Несколько странно, но типы интерфейсов в CIL определяются с применением директивы .class
.class декорирована атрибутом implements:.namespace MyNamespace
{
// Определение интерфейса.
.class public interface IMyInterface {}