Чтение онлайн

ЖАНРЫ

Язык программирования C#9 и платформа .NET5
Шрифт:

.method public hidebysig instance int32

Add(int32 addendl, int32 addend2) cil managed

{

// Code size 9(0x9)

// Размер кода 9(0x9)

.maxstack 2

.locals init (int32 V_0)

IL_0000: nop

IL_0001: ldarg.1

IL_0002: ldarg.2

IL_0003: add

IL_0004: stloc.0

IL_0005: br.s IL_0007

IL_0007: ldloc.0

IL 0008: ret

} // end of method Calc::Add

//
конец метода Calc::Add

В качестве финального примера ниже представлена та же самая простая программа

Calc
, разработанная на F# (еще одном языке .NET Core):

// Узнайте больше о языке F# на веб-сайте http://fsharp.org

// Calc.fs

open System

module Calc =

let add addendl addend2 =

addendl + addend2

[<EntryPoint>]

let main argv =

let ans = Calc.add 10 84

printfn "10 + 84 is %d" ans

Console.ReadLine

0

Если вы просмотрите код CIL для метода

Add
, то снова найдете похожие инструкции (слегка скорректированные компилятором F#).

.method public static int32 Add(int32 addendl,

int32 addend2) cil managed

{

.custom instance void [FSharp.Core]Microsoft.FSharp.Core.

CompilationArgumentCountsAttribute::.ctor(int32[]) = ( 01 00 02 00 00

00 01 00 00 00 01 00 00 00 00 00 )

// Code size 4 (0x4)

// Размер кода 4 (0x4)

.maxstack 8

IL_0000: ldarg.0

IL_0001: ldarg.l

IL_0002: add

IL_0003: ret

} // end of method Calc::'add

// конец метода Calc::'add'

Преимущества языка CIL

В этот момент вас может интересовать, какую выгоду приносит компиляция исходного кода в CIL, а не напрямую в специфичный набор инструкций. Одним из преимуществ является языковая интеграция. Как вы уже видели, все компиляторы .NET Core выпускают практически идентичные инструкции CIL. Следовательно, все языки способны взаимодействовать в рамках четко определенной "двоичной арены".

Более того, учитывая независимость от платформы языка CIL, сама инфраструктура .NET Core не зависит от платформы и обеспечивает те же самые преимущества, к которым так привыкли разработчики на Java (например, единую кодовую базу, функционирующую в средах многочисленных операционных систем). В действительности для

языка C# предусмотрен международный стандарт. До выхода .NET Core существовало множество реализаций .NET для платформ, отличающихся от Windows, таких как Mono. Они по-прежнему доступны, хотя благодаря межплатформенной природе .NET Core потребность в них значительно снизилась.

Компиляция кода CIL в инструкции, специфичные для платформы

Поскольку сборки содержат инструкции CIL, а не инструкции, специфичные для платформы, перед применением код CIL должен компилироваться на лету. Компонентом, который транслирует код CIL в содержательные инструкции центрального процессора (ЦП), является оперативный (JIT) компилятор (иногда называемый jitter). Для каждого целевого ЦП исполняющая среда .NET Core задействует JIT-компилятор, который оптимизирован под лежащую в основе платформу.

Скажем, если строится приложение .NET Core, предназначенное для развертывания на карманном устройстве (наподобие смартфона с iOS или Android), то соответствующий JIT-компилятор будет оснащен возможностями запуска в среде с ограниченным объемом памяти. С другой стороны, если сборка развертывается на внутреннем сервере компании (где память редко оказывается проблемой), тогда JIT-компилятор будет оптимизирован для функционирования в среде с большим объемом памяти. Таким образом, разработчики могут писать единственный блок кода, который способен эффективно транслироваться JIT-компилятором и выполняться на машинах с разной архитектурой.

Вдобавок при трансляции инструкций CIL в соответствующий машинный код JIT-компилятор будет кешировать результаты в памяти в манере, подходящей для целевой ОС. В таком случае, если производится вызов метода по имени

PrintDocument
, то инструкции CIL компилируются в специфичные для платформы инструкции при первом вызове и остаются в памяти для более позднего использования. Благодаря этому при вызове метода
PrintDocument
в следующий раз повторная компиляция инструкций CIL не понадобится.

Предварительная компиляция кода CIL в инструкции, специфичные для платформы

В .NET Core имеется утилита под названием

crossgen.exe
, которую вы можете использовать для предварительной компиляции JIT своего кода. К счастью, в .NET Core 3.0 возможность производить "готовые к запуску" сборки встроена в инфраструктуру. Более подробно об этом речь пойдет позже в книге.

Роль метаданных типов .NET Core

В дополнение к инструкциям CIL сборка .NET Core содержит полные и точные метаданные, которые описывают каждый определенный в двоичном модуле тип (например, класс, структуру, перечисление), а также члены каждого типа (скажем, свойства, методы, события). К счастью, за выпуск актуальных метаданных типов всегда отвечает компилятор, а не программист. Из-за того, что метаданные .NET Core настолько основательны, сборки являются целиком самоописательными сущностями.

Чтобы проиллюстрировать формат метаданных типов .NET Core, давайте взглянем на метаданные, которые были сгенерированы для исследуемого ранее метода

Add
класса
Calc
, написанного на C# (метаданные для версии Visual Basic метода
Add
похожи, так что будет исследоваться только версия С#):

TypeDef #2 (02000003)

– -------------------------------------------------------

TypDefName: CalculatorExamples.Calc (02000003)

Поделиться с друзьями: