Язык программирования C#9 и платформа .NET5
Шрифт:
Кроме того, оба инструмента версии 5.0.0 включены в папку
Хотя и верно утверждение о том, что построением полного приложения .NET Core прямо на CIL занимаются лишь немногие программисты (если вообще такие есть), изучение этого языка все равно является чрезвычайно интересным занятием. Попросту говоря, чем лучше вы понимаете грамматику CIL, тем больше способны погрузиться в мир расширенной разработки приложений .NET Core. Обратившись к конкретным примерам, можно утверждать, что разработчики, разбирающиеся в CIL, обладают следующими навыками.
• Умеют дизассемблировать существующую сборку .NET Core, редактировать код CIL в ней и заново
• Умеют строить динамические сборки с применением пространства имен
• Понимают аспекты CTS, которые не поддерживаются высокоуровневыми управляемыми языками, но существуют на уровне CIL. На самом деле CIL является единственным языком .NET Core, который позволяет получать доступ ко всем аспектам CTS. Например, за счет использования низкоуровневого кода CIL появляется возможность определения членов и полей глобального уровня (которые не разрешены в С#).
Ради полной ясности нужно еще раз подчеркнуть, что овладеть мастерством работы с языком C# и библиотеками базовых классов .NET Core можно и без изучения деталей кода CIL. Во многих отношениях знание CIL аналогично знанию языка ассемблера программистом на С (и C++).Те, кто разбирается в низкоуровневых деталях, способны создавать более совершенные решения поставленных задач и глубже понимают лежащую в основе среду программирования (и выполнения). Словом, если вы готовы принять вызов, тогда давайте приступим к исследованию внутренних деталей CIL.
На заметку! Имейте в виду, что эта глава не планировалась быть всеобъемлющим руководством по синтаксису и семантике CIL.
Директивы, атрибуты и коды операций CIL
Когда вы начинаете изучение низкоуровневых языков, таких как CIL, то гарантированно встретите новые (и часто пугающие) названия для знакомых концепций. Например, к этому моменту приведенный ниже набор элементов вы почти наверняка посчитаете ключевыми словами языка C# (и это правильно):
Тем не менее, внимательнее присмотревшись к элементам набора, вы сможете заметить, что хотя каждый из них действительно является ключевым словом С#, он имеет радикально отличающуюся семантику Скажем, ключевое слово
По разительному контрасту с высокоуровневым языком вроде C# в CIL не просто определен общий набор ключевых слов сам по себе. Напротив, набор лексем, распознаваемых компилятором CIL, подразделяется на следующие три обширные категории, основываясь на их семантике:
• директивы CIL;
• атрибуты CIL;
• коды операций CIL.
Лексемы CIL каждой категории выражаются с применением отдельного синтаксиса и комбинируются для построения допустимой сборки .NET Core.
Роль
директив CILПрежде всего, существует набор хорошо известных лексем CIL, которые используются для описания общей структуры сборки .NET Core. Такие лексемы называются директивами. Директивы CIL позволяют информировать компилятор CIL о том, каким образом определять пространства имен, типы и члены, которые будут заполнять сборку.
Синтаксически директивы представляются с применением префикса в виде точки (
Роль атрибутов CIL
Во многих случаях директивы CIL сами по себе недостаточно описательны для того, чтобы полностью выразить определение заданного типа .NET Core или члена типа. С учетом этого факта многие директивы CIL могут сопровождаться разнообразными атрибутами CIL, которые уточняют способ обработки директивы. Например, директива
На заметку! Не путайте атрибут .NET Core (см. главу 17) и атрибут CIL, которые являются двумя совершенно разными понятиями.
Роль кодов операций СIL
После того как сборка, пространство имен и набор типов .NET Core определены в терминах языка CIL с использованием различных директив и связанных атрибутов, остается только предоставить логику реализации для типов. Это работа кодов операций. В традициях других низкоуровневых языков программирования многие коды операций CIL обычно имеют непонятный и совершенно нечитабельный вид. Например, для загрузки в память переменной типа
Справедливости ради следует отметить, что некоторые коды операций CIL довольно естественно отображаются на свои аналоги в C# (например,
Разница между кодами операций и их мнемоническими эквивалентами в СIL
Как только что объяснялось, для реализации членов отдельно взятого типа применяются коды операций вроде