Язык программирования C#9 и платформа .NET5
Запустите
в отношенииildasm.exe, используя следующую команду (на уровне каталога решения):RoundTrip.dllildasm /all /METADATA /out=.\RoundTrip\RoundTrip.il.\RoundTrip\bin\Debug\net5.0\RoundTrip.dllНа заметку! При сбрасывании содержимого сборки в файл утилита
также генерирует файлildasm.exe. Такие ресурсные файлы можно игнорировать (и удалять), поскольку в текущей главе они не применяются. В них содержится низкоуровневая информация, касающаяся безопасности CLR (помимо прочих данных).*.resТеперь можете просмотреть файл
в любом текстовом редакторе. Вот его содержимое (для удобства оно слегка переформатировано и снабжено комментариями):RoundTrip.il<b>// Ссылаемые сборки.</b>.assembly extern System.Runtime{.publickeytoken = (B0 3F 5F 7F 11 D5 0A 3A).ver 5:0:0:0}.assembly extern System.Console{.publickeytoken = (B0 3F 5F 7F 11 D5 0A 3A ).ver 5:0:0:0}<b>// Наша сборка.</b>.assembly RoundTrip{....hash algorithm 0x00008004.ver 1:0:0:0}.module RoundTrip.dll.imagebase 0x00400000.file alignment 0x00000200.stackreserve 0x00100000.subsystem 0x0003.corflags 0x00000001<b>// Определение класса Program.</b>.class private abstract auto ansi beforefieldinit '<Program>$'extends [System.Runtime]System.Object{.custom instance void [System.Runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor()= ( 01 00 00 00 ).method private hidebysig static void '<Main>$'(string[] args) cil managed{<b> // Помечает этот метод как точку входа исполняемой сборки.</b>.entrypoint.maxstack 8IL_0000: ldstr "Hello CIL code!"IL_0005: call void [System.Console]System.Console::WriteLine(string)IL_000a: nopIL_000b: call string [System.Console]System.Console::ReadLine()IL_0010: popIL_0011: ret} // end of method '<Program>$'::'<Main>$'} // end of class '<Program>$'Обратите внимание, что файл
начинается с объявления всех внешних сборок, на которые ссылается текущая скомпилированная сборка. Если бы в вашей библиотеке классов использовались дополнительные типы из других ссылаемых сборок (помимо*.ilиSystem.Runtime), тогда вы обнаружили бы дополнительные директивыSystem.Console..assembly externДалее следует формальное определение сборки
, описанное с применением разнообразных директив CIL (RoundTrip.dll,.moduleи т.д.)..imagebaseПосле документирования внешних ссылаемых сборок и определения текущей сборки находится определение типа
, созданное из операторов верхнего уровня. Обратите внимание, что директиваProgramимеет различные атрибуты (многие из которых необязательны) вроде приведенного ниже атрибута.class, который указывает базовый класс для типа:extends.class private abstract auto ansi beforefieldinit '<Program>$'extends [System.Runtime]System.Object{ ... }Основной объем кода CIL представляет реализацию стандартного конструктора класса и автоматически сгенерированного метода
, которые оба определены (частично) посредством директивыMain(). После того, как эти члены были определены с использованием корректных директив и атрибутов, они реализуются с применением разнообразных кодов операций..methodВажно понимать, что при взаимодействии с типами .NET Core (такими как System.Console) в CIL всегда необходимо использовать полностью заданное имя типа. Более того, полностью заданное имя типа всегда должно предваряться префиксом в форме дружественного имени сборки, где определен тип (в квадратных скобках). Взгляните на следующую реализацию метода
в CIL:Main().method private hidebysig static void '<Main>$'(string[] args) cil managed{<b> // Помечает этот метод как точку входа исполняемой сборки.</b>.entrypoint.maxstack 8IL_0000: ldstr "Hello CIL code!"IL_0005: call void [System.Console]System.Console::WriteLine(string)IL_000a: nopIL_000b: call string [System.Console]System.Console::ReadLine()IL_0010: pop