Общеязыковая исполняющая среда CLR

Существует ряд средств, которые поддерживаются .NET, но не поддерживаются C#, и, возможно, вас удивит, что есть также средства, поддерживаемые C# и не поддерживаемые .NET (например, некоторые случаи перегрузки операций). Однако поскольку язык C# предназначен для применения на платформе .NET, вам, как разработчику, важно иметь представление о .NET Framework, если вы хотите эффективно разрабатывать приложения на C#. Поэтому давайте заглянем «за кулисы» .NET.
Центральной частью каркаса .NET является его общеязыковая исполняющая среда, известная как Common Language Runtime (CLR) или .NET runtime. Код, выполняемый под управлением CLR, часто называют управляемым кодом. С точки зрения программирования под термином может пониматься коллекция внешних служб, которые требуются для выполнения скомпилированной единицы программного кода. Например, при использовании платформы MFC для создания нового приложения разработчики осознают, что их программе требуется библиотека времени выполнения MFC (т.е. mfc42.dll). Другие популярные языки тоже имеют свою исполняющую среду: программисты, использующие язык VB6, к примеру, вынуждены привязываться к одному или двум модулям исполняющей среды (вроде msvbvm60.dll), а разработчики на Java — к виртуальной машине Java (JVM).
В составе .NET предлагается еще одна исполняющая среда. Главное отличие между исполняющей средой .NET и упомянутыми выше средами, состоит в том, что исполняющая среда .NET обеспечивает единый четко определенный уровень выполнения, который способны использовать все совместимые с .NET языки и платформы.
Однако перед тем как код сможет выполняться CLR, любой исходный текст (на C# или другом языке) должен быть скомпилирован. Компиляция в .NET состоит из двух шагов:
1. Компиляция исходного кода в Microsoft Intermediate Language (IL)
2. Компиляция IL в специфичный для платформы код с помощью CLR
Этот двухшаговый процесс компиляции очень важен, потому что наличие Microsoft Intermediate Language (IL) является ключом ко многим преимуществам .NET. Microsoft Intermediate Language (промежуточный язык Microsoft) разделяет с байт-кодом Java идею низкоуровневого языка с простым синтаксисом (основанным на числовых, а не текстовых кодах), который может быть очень быстро транслирован в родной машинный код.
Основной механизм CLR физически имеет вид библиотеки под названием mscoree.dll (и также называется общим механизмом выполнения исполняемого кода объектов — Common Object Runtime Execution Engine). При добавлении ссылки на сборку для ее использования загрузка библиотеки mscoree.dll осуществляется автоматически и затем, в свою очередь, приводит к загрузке требуемой сборки в память. Механизм исполняющей среды отвечает за выполнение целого ряда задач. Сначала, что наиболее важно, он отвечает за определение места расположения сборки и обнаружение запрашиваемого типа в двоичном файле за счет считывания содержащихся там метаданных. Затем он размещает тип в памяти, преобразует CIL-код в соответствующие платформе инструкции, производит любые необходимые проверки на предмет безопасности и после этого, наконец, непосредственно выполняет сам запрашиваемый программный код.
Помимо загрузки пользовательских сборок и создания пользовательских типов, механизм CLR при необходимости будет взаимодействовать и с типами, содержащимися в библиотеках базовых классов .NET. Хотя вся библиотека базовых классов поделена на ряд отдельных сборок, главной среди них является сборка mscorlib.dll. В этой сборке содержится большое количество базовых типов, охватывающих широкий спектр типичных задач программирования, а также базовых типов данных, применяемых во всех языках .NET. При построении .NET-решений доступ к этой конкретной сборке будет предоставляться автоматически.

На данной схеме наглядно видно, как выглядят взаимоотношения между исходным кодом (предусматривающим использование типов из библиотеки базовых классов), компилятором .NET и механизмом выполнения .NET.
Использование байт-кода с четко определенным универсальным синтаксисом дает ряд существенных преимуществ:
Независимость от платформы
Первым делом, это значит, что файл, содержащий инструкции байт-кода, может быть размещен на любой платформе; во время выполнения может быть легко проведена финальная стадия компиляции, что позволит выполнить код на конкретной платформе. Другими словами, компилируя в IL, вы получаете платформенную независимость .NET — во многом так же, как компиляция в байт-код Java обеспечивает независимость от платформы программам на Java.
Следует отметить, что независимость .NET от платформы в настоящее время является лишь теоретической, поскольку реализация .NET доступна только для ОС Windows. Однако уже существуют частичные реализации для других платформ (например, проект Mono — попытка создать реализацию .NET с открытым кодом).
Повышение производительности
Хотя язык IL выше сравнивался с Java, все же IL на самом деле более гибкий, чем байт-код Java. Код IL всегда компилируется оперативно (Just-In-Time, JIT-компиляция), в то время как байт-код Java часто интерпретируется. Одним из недостатков Java было то, что во время выполнения программ процесс трансляции байт-кода Java в родной машинный код приводил к снижению производительности (за исключением самых последних версий, где Java компилируется оперативно (JIT) на некоторых платформах).
Вместо компиляции всего приложения за один проход (что может привести к задержкам при запуске), JIT-компилятор просто компилирует каждую порцию кода при ее вызове (т.е. оперативно). Если промежуточный код однажды скомпилирован, то результирующий машинный исполняемый код сохраняется до момента завершения работы приложения, поэтому его перекомпиляция при повторных обращениях к нему не требуется. В Microsoft аргументируют, что такой процесс более эффективен, чем компиляция всего приложения при запуске, поскольку высока вероятность того, что крупные фрагменты кода приложения на самом деле не будут выполняться при каждом запуске. При использовании JIT-компилятора такой код никогда не будет скомпилирован.
Это объясняет, почему можно рассчитывать на то, что выполнение управляемого кода IL будет почти настолько же быстрым, как и выполнение родного машинного кода. Однако это не объясняет того, почему Microsoft ожидает повышения производительности. Причина состоит в том, что поскольку финальная стадия компиляции происходит во время выполнения, JIT-компилятор на этот момент уже знает, на каком типе процессора будет запущена программа. А это значит, что он может оптимизировать финальный исполняемый код, используя инструкции конкретного машинного кода, предназначенные для конкретного процессора.
Традиционные компиляторы оптимизируют код, но они могут проводить лишь оптимизацию, не зависящую от конкретного процессора, на котором код будет выполняться. Это происходит потому, что традиционные компиляторы генерируют исполняемый код до того, как он поставляется пользователям. А потому компилятору не известно, на каком типе процессора они будут работать, за исключением самых общих характеристик вроде того, что это будет х86-совместимый процессор либо же процессор Alpha.
COM и COM+
Формально СОМ и СОМ+ не являются технологиями, нацеленными на .NET, поскольку компоненты, основанные на них, не могут компилироваться в IL (хотя в определенной степени это и можно сделать, применяя управляемый С++, если исходный компонент СОМ+ был написан на С++). Однако СОМ+ остается важным инструментом, потому что его средства не дублируют .NET. К тому же компоненты СОМ будут по-прежнему работать, и .NET включает средства взаимодействия с СОМ, позволяющие управляемому коду вызывать компоненты СОМ и наоборот. Тем не менее, скорее всего, вы обнаружите, что в большинстве случаев удобнее кодировать новые компоненты в виде компонентов .NET, чтобы воспользоваться преимуществами базовых классов .NET, а также другими выгодами от запуска управляемого кода.
/clr (Компиляция среды CLR)
Позволяет приложениям и компонентам использовать функции из среды CLR и включает компиляцию C++/CLI.
Синтаксис
/clr [ : параметры]
Аргументы
options
Один или несколько следующих аргументов, разделенных запятыми.
- нет Без параметров /clr создает метаданные для компонента. Метаданные могут использоваться другими приложениями СРЕДЫ CLR и позволяют компоненту использовать типы и данные в метаданных других компонентов СРЕДЫ CLR. Дополнительные сведения см. в статье Смешанные (собственные и управляемые) сборки.
- netcore Доступно начиная с Visual Studio 2019 версии 16.4, /clr:netcore создает метаданные и код для компонента с помощью последней кроссплатформенной платформы .NET Framework, также известной как .NET Core. Метаданные можно использовать другими приложениями .NET Core. И этот параметр позволяет компоненту использовать типы и данные в метаданных других компонентов .NET Core.
- nostdlib Указывает компилятору игнорировать каталог по умолчанию \clr . Компилятор создает ошибки при включении нескольких версий библиотеки DLL, таких как System.dll. Этот параметр позволяет указать конкретную платформу, используемую во время компиляции.
- pure/clr:pure не рекомендуется. Этот параметр удален в Visual Studio 2017 и более поздних версий. Мы рекомендуем перенести код, который должен быть чистым кодом MSIL, на C#.
- safe/clr:safe не рекомендуется. Этот параметр удален в Visual Studio 2017 и более поздних версий. Мы рекомендуем перенести код, который должен быть безопасным кодом MSIL, на C#.
- noAssembly/clr:noAssembly не рекомендуется. Вместо этого используйте /LN (создать модуль MSIL). Сообщает компилятору не вставлять манифест сборки в выходной файл. По умолчанию параметр noAssembly не действует. Управляемая программа, которая не имеет метаданных сборки в манифесте, называется модулем . Этот noAssembly параметр можно использовать только для создания модуля. При компиляции с помощью /c и /clr:noAssembly затем укажите /NOASSEMBLY параметр на этапе компоновщика для создания модуля. Перед Visual Studio 2005 /clr:noAssembly необходимо /LD . /LD теперь подразумевается при указании /clr:noAssembly .
- initialAppDomaininitialAppDomain устарел. Позволяет приложению C++/CLI работать в среде CLR версии 1. Приложение, скомпилированное с помощью initialAppDomain , не должно использоваться приложением, использующим ASP.NET, так как оно не поддерживается в среде CLR версии 1.
Замечания
Управляемый код — это код , который можно проверить и управлять с помощью среды CLR. Управляемый код может обращаться к управляемым объектам. Дополнительные сведения см. в разделе /clr «Ограничения».
Сведения о разработке приложений, которые определяют и используют управляемые типы в C++, см. в разделе «Расширения компонентов для платформ среды выполнения».
Приложение, скомпилированное с помощью может /clr содержать или не содержать управляемые данные.
Сведения о включении отладки в управляемом приложении см. в разделе /ASSEMBLYDEBUG (Add DebuggableAttribute).
На куче, собранной мусором, создаются только типы СРЕДЫ CLR. Дополнительные сведения см. в статье Классы и структуры. Для компиляции функции в машинный код используйте директиву unmanaged pragma. Дополнительные сведения см. в разделе managed , unmanaged .
По умолчанию /clr не действует. Когда /clr он действует, /MD также действует. Дополнительные сведения см. в разделе /MD , /LD /MT (Использование библиотеки времени выполнения). /MD гарантирует, что динамически связанные многопоточные версии подпрограмм среды выполнения выбираются из стандартных файлов заголовков. Многопоточность необходима для управляемого программирования, так как сборщик мусора CLR запускает методы завершения во вспомогательном потоке.
При компиляции с помощью /c можно указать тип СРЕДЫ CLR результирующего выходного файла с помощью /CLRIMAGETYPE параметра компоновщика.
/clr означает /EHa , что для него не поддерживаются /clr другие /EH варианты. Дополнительные сведения см. в разделе /EH (Модель обработки исключений)
Сведения о том, как определить тип образа СРЕДЫ CLR файла, см. в разделе /CLRHEADER .
Все модули, передаваемые заданному вызову компоновщика, должны быть скомпилированы с помощью одного параметра компилятора библиотеки времени выполнения ( /MD или /LD ).
/ASSEMBLYRESOURCE Используйте параметр компоновщика для внедрения ресурса в сборку. /DELAYSIGN , /KEYCONTAINER и /KEYFILE параметры компоновщика также позволяют настроить создание сборки.
При /clr использовании _MANAGED символ определяется как 1. Дополнительные сведения см. в разделе «Предопределенные макросы».
Глобальные переменные в собственном файле объектов инициализированы сначала (во время DllMain выполнения исполняемого файла — dll), а затем глобальные переменные в управляемом разделе инициализированы (перед запуском любого управляемого кода). #pragma init_seg влияет только на порядок инициализации в управляемых и неуправляемых категориях.
Метаданные и неименованные классы
Неименованные классы отображаются в метаданных под именами, такими как $UnnamedClass$$$ , где последовательное число неименованных классов в компиляции. Например, следующий код создает неименованный класс в метаданных.
// clr_unnamed_class.cpp // compile by using: /clr /LD class <> x;
Для просмотра метаданных используйте ildasm.exe.
Установка данного параметра компилятора в среде разработки Visual Studio
- Откройте диалоговое окно Страницы свойств проекта. Подробнее см. в статье Настройка компилятора C++ и свойства сборки в Visual Studio.
- Установите раскрывающийся список «Конфигурация» на все конфигурации и установите раскрывающийся список «Платформа» на все платформы.
- Выберите страницу «Свойства>конфигурации» C/C++>General.
- Измените свойство поддержки среды CLR. Нажмите ОК, чтобы сохранить внесенные изменения.
В интегрированной среде разработки /clr Visual Studio параметр компилятора можно задать отдельно на странице «Свойства>конфигурации C/C++>Общие» диалогового окна «Страницы свойств». Однако мы рекомендуем использовать шаблон СРЕДЫ CLR для создания проекта. Он задает все свойства, необходимые для успешного создания компонента СРЕДЫ CLR. Другой способ задать эти свойства — использовать свойство поддержки среды CLR на странице «Дополнительные свойства>конфигурации» диалогового окна «Страницы свойств». Это свойство задает все остальные параметры инструментов, связанных с CLR, одновременно.
Установка данного параметра компилятора программным способом
- См. раздел CompileAsManaged.
Обзор среды CLR
.NET предоставляет среду выполнения, называемую средой CLR, которая выполняет код и предоставляет службы, упрощающие процесс разработки.
Компиляторы и средства предоставляют функциональные возможности среды CLR и позволяют писать код, который использует управляемую среду выполнения. Код, разработанный с использованием языкового компилятора для среды выполнения, называют управляемым. В нем используются преимущества таких средств, как объединение языков программирования, объединенная обработка исключений, усиленная безопасность, поддержка отслеживания версий и развертывания, упрощенная модель взаимодействия компонентов, а также службы отладки и профилирования.
Компиляторы и средства могут создавать выходные данные, которые может использовать среда CLR, так как система типов, формат метаданных и среда времени выполнения (виртуальная система выполнения) определяются общедоступным стандартом, спецификацией ОБЩЕЯзыковой инфраструктуры ECMA. Дополнительные сведения см. в разделе Спецификации ECMA для C# и инфраструктуры Common Language Infrastructure (CLI).
Чтобы включить в среде выполнения предоставление служб управляемому коду, языковые компиляторы должны предоставлять метаданные с описанием типов, членов и ссылок в коде. Метаданные хранятся вместе с кодом. Они содержатся в каждом загружаемом переносимом исполняемом (PE) файле среды CLR. Метаданные в среде выполнения используются для поиска и загрузки классов, размещения экземпляров в памяти, разрешения имен при вызове методов, создания машинного кода, обеспечения безопасности и установки границ контекста времени выполнения.
Среда выполнения автоматически обрабатывает макет объектов и управляет ссылками на объекты, освобождая их, когда они больше не используются. Объекты, время жизни которых управляется подобным образом, называются управляемыми данными. Сборка мусора устраняет утечки памяти и некоторые другие распространенные ошибки программирования. Если ваш код является управляемым, в приложении .NET можно использовать управляемые, неуправляемые или как управляемые, так и неуправляемые данные. Поскольку компиляторы языка предоставляют собственные типы, такие как примитивные типы, возможно, вам не всегда нужно знать, управляются ли ваши данные.
Среда CLR упрощает разработку компонентов и приложений, объекты которых могут работать в разных языках. Объекты, написанные на разных языках, могут взаимодействовать друг с другом, а их поведение может быть тесно интегрировано. Например, разработчик может определить класс, а затем на другом языке создать производный от него класс или вызвать метод из исходного класса. Можно также передать экземпляр класса в метод класса, написанного на другом языке. Такая межязыковая интеграция возможна, так как языковые компиляторы и средства, предназначенные для среды выполнения, используют систему общих типов, определенную средой выполнения. Они следуют правилам среды выполнения для определения новых типов, а также для создания, использования, сохранения и привязки к типам.
В составе своих метаданных все управляемые компоненты содержат сведения о компонентах и ресурсах, на базе которых они построены. Среда выполнения использует эти сведения, чтобы обеспечить наличие всех необходимых ресурсов для компонента или приложения. Это снижает вероятность сбоев кода из-за каких-либо неудовлетворенных зависимостей. Сведения о регистрации и данные о состоянии больше не хранятся в реестре, где их может быть трудно установить и поддерживать. Вместо этого сведения об определяемых типах и их зависимостях хранятся в коде в виде метаданных. Таким образом, задача репликации и удаления компонентов будет менее сложной.
Языковые компиляторы и программы предоставляют функции среды выполнения так, чтобы они были полезны и интуитивно понятны для разработчиков. Некоторые функции среды выполнения могут быть более заметными в одной среде, чем в другой. Характеристики среды выполнения зависят от используемых языковых компиляторов и программ. Например, если вы разработчик Visual Basic, вы можете заметить, что в среде CLR язык Visual Basic имеет больше объектно-ориентированных функций, чем раньше. Среда выполнения предоставляет следующие преимущества:
- повышение производительности;
- возможность легко использовать компоненты, разработанные на других языках;
- расширяемые типы, предоставляемые библиотекой классов;
- языковые возможности (например, наследование, интерфейсы и перегрузку) для объектно-ориентированного программирования;
- Поддержка явного свободного потока, которая позволяет создавать многопоточные и масштабируемые приложения.
- поддержку структурированной обработки исключений;
- поддержку настраиваемых атрибутов;
- сборка мусора;
- использование делегатов вместо указателей на функции для повышения типобезопасности и уровня защиты. Подробнее о делегатах см. в разделе Система общих типов CTS.
Версии CLR
Выпуски .NET Core и .NET 5+ имеют одну версию продукта, то есть не существует отдельной версии среды CLR. Список версий .NET Core см. в разделе Загрузка .NET Core.
Однако номер версии платформы .NET Framework не всегда соответствует номеру версии среды CLR, которую он содержит. Список версий .NET Framework и соответствующих версий среды CLR см. в разделе Версии и зависимости платформы .NET Framework.
Связанные статьи
| Заголовок | Описание |
|---|---|
| Процесс управляемого выполнения | Описание шагов, необходимых для использования преимуществ общеязыковой среды выполнения. |
| Автоматическое управление памятью | Описание выделения и освобождения памяти сборщиком мусора. |
| Общие сведения о платформе .NET | Описание ключевых понятий платформы .NET Framework: системы общих типов CTS, межъязыкового взаимодействия, управляемого выполнения, доменов приложений и сборок. |
| Система общих типов CTS | Описание того, как типы объявляются, используются и контролируются в среде выполнения в рамках поддержки межъязыковой интеграции. |
Clr c что это
Microsoft .NET – платформа или среда, обеспечивающая выполнение программного кода.
.NET Framework – инфраструктура платформы Microsoft .NET, определяющая особенности разработки и выполнения программного кода на данной платформе. Предполагает наличие средств организации взаимодействия с операционной системой и прикладными программами. Включает следующие основные компоненты: Common Language Runtime (CLR) и .NET Framework Class Library (.NET FCL).
CLS (Common Language Specification) – общая спецификация языков программирования. Это набор конструкций и ограничений, которые являются руководством для создателей библиотек и компиляторов в среде .NET Framework. Библиотеки, построенные в соответствии с CLS, могут быть использованы из любого языка программирования, поддерживающего CLS. Языки, соответствующие CLS (к их числу относятся языки Visual C#, Visual Basic, Visual C++), могут интегрироваться друг с другом. CLS – это основа межъязыкового взаимодействия в рамках платформы Microsoft .NET.
CLR (Common Language Runtime) – Среда Времени Выполнения или Виртуальная Машина. Обеспечивает выполнение сборки. Основной компонент .NET Framework. Под Виртуальной Машиной понимают абстракцию инкапсулированной (обособленной) управляемой операционной системы высокого уровня, которая обеспечивает выполнение (управляемого) программного кода.
Управляемый код – программный код, который при своем выполнении способен использовать службы, предоставляемые CLR. Соответственно, неуправляемый код подобной способностью не обладает. Об особенностях управляемого кода можно судить по перечню задач, решение которых возлагается на CLR:
- Управление кодом (загрузка и выполнение).
- Управление памятью при размещении объектов.
- Изоляция памяти приложений.
- Проверка безопасности кода.
- Преобразование промежуточного языка в машинный код.
- Доступ к метаданным (расширенная информация о типах).
- Обработка исключений, включая межъязыковые исключения.
- Взаимодействие между управляемым и неуправляемым кодами (в том числе и COM-объектами).
- Поддержка сервисов для разработки (профилирование, отладка и т.д.).
Короче, CLR – это набор служб, необходимых для выполнения управляемого кода.
Сама CLR состоит из двух главных компонентов: ядра (mscoree.dll) и библиотеки базовых классов (mscorlib.dll). Наличие этих файлов на диске – верный признак того, что на компьютере, по крайней мере, была предпринята попытка установки платформы .NET.
Ядро среды выполнения реализовано в виде библиотеки mscoree.dll. При компоновке сборки в нее встраивается специальная информация, которая при запуске приложения (EXE) или при загрузке библиотеки (обращение к DLL из неуправляемого модуля – вызов функции LoadLibrary для загрузки управляемой сборки) приводит к загрузке и инициализации CLR. После загрузки CLR в адресное пространство процесса, ядро среды выполнения производит следующие действия:
- находит расположение сборки;
- загружает сборку в память;
- производит анализ содержимого сборки (выявляет классы, структуры, интерфейсы);
- производит анализ метаданных;
- обеспечивает компиляцию кода на промежуточном языке (IL) в платформозависимые инструкции (ассемблерный код);
- выполняет проверки, связанные с обеспечением безопасности;
- используя основной поток приложения, передает управление преобразованному в команды процессора фрагменту кода сборки.
FCL (.NET Framework Class Library) – соответствующая CLS-спецификации объектно-ориентированная библиотека классов, интерфейсов и системы типов (типов-значений), которые включаются в состав платформы Microsoft .NET.
Эта библиотека обеспечивает доступ к функциональным возможностям системы и предназначена служить основой при разработке .NET-приложений, компонент, элементов управления.
.NET библиотека классов является вторым компонентом CLR.
.NET FCL могут использовать все .NET-приложения, независимо от назначения архитектуры используемого при разработке языка программирования, и в частности:
- встроенные (элементарные) типы, представленные в виде классов (на платформе .NET все построено на структурах или классах);
- классы для разработки графического пользовательского интерфейса (Windows Forms);
- классы для разработки web-приложений и web-служб на основе технологии ASP.NET (Web Forms);
- классы для разработки XML и Internet-протоколов (FTP, HTTP, SMTP, SOAP);
- классы для разработки приложений, работающих с базами данных (ADO .NET) и многое другое.
.NET-приложение – приложение, разработанное для выполнения на платформе Microsoft .NET. Реализуется на языках программирования, соответствующих CLS.
MSIL (Microsoft Intermediate Language) – промежуточный язык платформы Microsoft .NET. Исходные тексты программ для .NET-приложений пишутся на языках программирования, соответствующих спецификации CLS. Для таких языков может быть построен преобразователь в MSIL. Таким образом, программы на этих языках могут транслироваться в промежуточный код на MSIL. Благодаря соответствию CLS, в результате трансляции программного кода, написанного на разных языках, получается совместимый IL-код.
Фактически MSIL является ассемблером виртуального процессора.
МЕТАДАННЫЕ – при преобразовании программного кода в MSIL также формируется блок МЕТАДАННЫХ, который содержит информацию о данных, используемых в программе. Фактически это наборы таблиц, которые включают в себя информацию о типах данных, определяемых в модуле (о типах данных, на которые ссылается данный модуль). Ранее такая информация сохранялась отдельно. Например, приложение могло включать информацию об интерфейсах, которая описывалась на Interface Definition Language (IDL). Теперь метаданные являются частью управляемого модуля.
В частности, метаданные используются для:
- сохранения информации о типах. При компиляции теперь не требуются заголовочные и библиотечные файлы. Всю необходимую информацию компилятор читает непосредственно из управляемых модулей;
- верификации кода в процессе выполнения модуля;
- управления динамической памятью (освобождение памяти) в процессе выполнения модуля;
- обеспечения динамической подсказки (IntelliSence) при разработке программы стандартными инструментальными средствами (Microsoft Visual Studio .NET) на основе метаданных.
Языки, для которых реализован перевод на MSIL:
- Visual Basic,
- Visual C++,
- Visual C# 2.0,
и еще много других языков.
Исполняемый модуль – независимо от компилятора (и входного языка) результатом трансляции .NET-приложения является управляемый исполняемый модуль (управляемый модуль). Это стандартный переносимый исполняемый (PE – Portable Executable) файл Windows.
Элементы управляемого модуля представлены в таблице.
| Заголовок PE | Показывает тип файла (например, DLL), содержит временную метку (время сборки файла), содержит сведения о выполняемом коде |
| Заголовок CLR | Содержит информацию для среды выполнения модуля (версию требуемой среды исполнения, характеристики метаданных, ресурсов и т.д.). Собственно, эта информация делает модуль управляемым |
| Метаданные | Таблицы метаданных: 1) типы, определенные в исходном коде; 2) типы, на которые имеются в коде ссылки |
| IL | Собственно код, который создается компилятором при компиляции исходного кода. На основе IL в среде выполнения впоследствии формируется множество команд процессора |
Управляемый модуль содержит управляемый код.
Управляемый код – это код, который выполняется в среде CLR. Код строится на основе объявляемых в исходном модуле структур и классов, содержащих объявления методов. Управляемому коду должен соответствовать определенный уровень информации (метаданных) для среды выполнения. Код C#, Visual Basic, и JScript является управляемым по умолчанию. Код Visual C++ не является управляемым по умолчанию, но компилятор может создавать управляемый код, для этого нужно указать аргумент в командной строке(/CLR). Одной из особенностей управляемого кода является наличие механизмов, которые позволяют работать с управляемыми данными.
Управляемые данные – объекты, которые в ходе выполнения кода модуля размещаются в управляемой памяти (в управляемой куче) и уничтожаются сборщиком мусора CLR. Данные C#, Visual Basic и JScript .NET являются управляемыми по умолчанию. Данные C# также могут быть помечены как неуправляемые.
Сборка (Assembly) – базовый строительный блок приложения в .NET Framework. Управляемые модули объединяются в сборки. Сборка является логической группировкой одного или нескольких управляемых модулей или файлов ресурсов. Управляемые модули в составе сборок исполняются в Среде Времени Выполнения (CLR). Сборка может быть либо исполняемым приложением (при этом она размещается в файле с расширением .exe), либо библиотечным модулем (в файле с расширением .dll). При этом ничего общего с обычными (старого образца!) исполняемыми приложениями и библиотечными модулями сборка не имеет.
Декларация сборки (Manifest) – составная часть сборки. Это еще один набор таблиц метаданных, который:
- идентифицирует сборку в виде текстового имени, ее версию, культуру и цифровую сигнатуру (если сборка распределяется среди приложений);
- определяет входящие в состав файлы (по имени и хэшу);
- указывает типы и ресурсы, существующие в сборке, включая описание тех, которые экспортируются из сборки;
- перечисляет зависимости от других сборок;
- указывает набор прав, необходимых сборке для корректной работы.
Эта информация используется в период выполнения для поддержки корректной работы приложения.
Процессор не может выполнять IL-код. Перевод IL-кода осуществляется JIT-компилятором (Just In Time – в нужный момент), который активизируется CLR по мере необходимости и выполняется процессором. При этом результаты деятельности JIT-компилятора сохраняются в оперативной памяти. Между фрагментом оттранслированного IL-кода и соответствующим блоком памяти устанавливается соответствие, которое в дальнейшем позволяет CLR передавать управление командам процессора, записанным в этом блоке памяти, минуя повторное обращение к JIT-компилятору.
В среде CLR допускается совместная работа и взаимодействие компонентов программного обеспечения, реализованных на различных языках программирования.
На основе ранее сформированного блока метаданных CLR обеспечивает эффективное взаимодействие выполняемых .NET-приложений.
Для CLR все сборки одинаковы, независимо от того, на каких языках программирования они были написаны. Главное – это чтобы они соответствовали CLS. Фактически CLR разрушает границы языков программирования (cross-language interoperability). Таким образом, благодаря CLS и CTS, .NET-приложения оказываются приложениями на MSIL (IL).
CLR берет на себя решение многих проблем, которые традиционно находились в зоне особого внимания разработчиков приложений. К числу функций, выполняемых CLR, относятся:
- Проверка и динамическая (JIT) компиляция MSIL-кода в команды процессора.
- Управление памятью, процессами и потоками.
- Организация взаимодействия процессов.
- Решение проблем безопасности (в рамках существующей в системе политики безопасности).

Структура среды выполнения CLR (основные функциональные элементы среды) представлена на рисунке.
Строгий контроль типов, в частности, предполагает проверку соответствия типа объекта диапазону значений, которые могут быть присвоены данному объекту.
Защита .NET (безопасность) строится поверх системы защиты операционной системы компьютера. Она не дает пользователю или коду делать то, что делать не позволено, и накладывает ограничения на выполнение кода. Например, можно запретить доступ некоторым секциям кода к определенным файлам.
Функциональные блоки CLR Code Manager и Garbage Collector работают совместно: Code Manager обеспечивает размещение объектов в управляемой памяти, Garbage Collector – освобождает управляемую память.
Exception Manager включает следующие компоненты:
- finally handler (обеспечивает передачу управления в блок finally);
- fault handler (включается при возникновении исключения);
- type-filtered handler (обеспечивает выполнение кода соответствующего блока обработки исключения);
- user-filtered handler (выбор альтернативного блока исключения).
Ниже представлена схема выполнения .NET-приложения в среде CLR.

AppDomain (домен приложения) – это логический контейнер сборок, который используется для изоляции приложения в рамках адресного пространства процесса. Код, выполняемый в CLR (CLR-процесс), отделен от других процессов, выполняемых на компьютере в это же самое время. Обычный процесс запускается системой в рамках специально выделяемого процессу адресного пространства. CLR предоставляет возможность выполнения множества управляемых приложений в одном процессе. Каждое управляемое приложение связывается с собственным доменом приложения (сокращенно AppDomain). Все объекты, создаваемые приложением, создаются в рамках определенного домена приложения. Несколько доменов приложений могут существовать в одном процессе операционной системы. CLR изолирует приложения, управляя памятью в рамках домена приложения. В приложении, помимо основного домена, может быть создано несколько дополнительных доменов.
- Домены изолированы друг от друга. Объекты, созданные в рамках одного домена, недоступны из другого домена.
- CLR способна выгружать домены вместе со всеми сборками, связанными с этими доменами.
- Возможна дополнительная конфигурация и защита доменов.
- Для обмена данными между доменами реализован специальный механизм безопасного доступа (маршалинг).
- В .NET Framework разработана собственная компонентная модель, элементами которой являются .NET-сборки (.NET-assembly), а для прямой и обратной совместимости с моделью COM/COM+ в CLR встроены механизмы (COM Interop), обеспечивающие доступ к COM-объектам по правилам .NET и к .NET-сборкам — по правилам COM. При этом для .NET-приложений не требуется регистрации компонентов в системном реестре Windows.
GAC (Global Assembly Cache – Общий кэш сборок). Для выполнения .NET-приложения достаточно разместить относящиеся к данному приложению сборки в одном каталоге. Если при этом сборка может быть использована в нескольких приложениях, то она размещается и регистрируется с помощью специальной утилиты в GAC.
CTS – Common Type System (Стандартная Система Типов). Поддерживается всеми языками платформы. В силу того, что .NET основана на парадигме ООП, речь здесь идет об элементарных типах, классах, структурах, интерфейсах, делегатах и перечислениях. Common Type System является важной частью среды выполнения, определяет структуру синтаксических конструкций, способы объявления, использования и применения общих типов среды выполнения. В CTS сосредоточена основная информация о системе общих предопределенных типов, об их использовании и управлении (правилах преобразования значений). CTS играет важную роль в деле интеграции разноязыких управляемых приложений.
Пространство имен – это способ организации системы типов в единую группу. В рамках .NET существует единая (общеязыковая) библиотека базовых классов. Концепция пространства имен обеспечивает эффективную организацию и навигацию по этой библиотеке. Вне зависимости от языка программирования, доступ к определенным классам обеспечивается за счет их группировки в рамках общих пространств имен.
| System | |
| System.Data | Классы для обращения к базам данных |
| System.Data.Common | |
| System.Data.OleDb | |
| System.Data.SqlClient | |
| System.Collections | Классы для работы с контейнерными объектами |
| System.Diagnostics | Классы для трассировки и отладки кода |
| System.Drawing | Классы графической поддержки |
| System.Drawing.Drawing2D | |
| System.Drawing.Printing | |
| System.IO | Поддержка ввода/вывода |
| System.Net | Поддержка передачи данных по сетям |
| System.Reflection | Работа с пользовательскими типами во время выполнения приложения |
| System.Reflection.Emit | |
| System.Runtime.InteropServices | Поддержка взаимодействия с «обычным кодом» – DLL, COM-серверы, удаленный доступ |
| System.Runtime.Remoting | |
| System.Security | Криптография, разрешения |
| System.Threading | Работа с потоками |
| System.Web | Работа с web-приложениями |
Выполнение неуправляемых исполняемых модулей (обычные Windows-приложения) обеспечивается непосредственно системой Windows. Неуправляемые модули выполняются в среде Windows как «простые» процессы. Процесс характеризуется замкнутым адресным пространством. При этом необходимая для выполнения программы информация (данные) размещается в различных областях адресного пространства процесса, которые называются стеком и кучей. Эти области имеют различное назначение и механизмы управления.
Информация в стеке и куче представляется в виде последовательностей битов с четко определенными свойствами. Такие последовательности называются объектами. Множество неизменяемых свойств, которые могут служить для классификации различных объектов (количество байтов последовательности, формат представления информации в последовательности, операции, определенные над объектом), задают тип объекта.
Таким образом, при выполнении программы в стеке и куче размещаются объекты различных типов.
В стеке размещается информация, необходимая для выполнения программного кода (реализация механизма вызова функций, поддержка операторов управления, сохранение значений локальных переменных). Основным механизмом управления стеком является указатель стека. Освобождение стека происходит в результате перемещения указателя стека, которое связано с выполнением операторов программы.
В куче размещаются используемые в программе данные. Они структурированы и представлены объектами различных типов. Размещение объектов в куче происходит в результате выполнения специального оператора new. Основным механизмом управления кучи является сборщик мусора (Garbage Collector).
Ссылкой (ссылкой на объект) называется объект, который определен на множестве значений, представленных адресами оперативной памяти в рамках процесса. Если значением ссылки является адрес конкретного объекта, ссылка считается определенной. Ссылка на объект не определена, если ее значение не соответствует адресу какого-либо объекта. Неопределенное значение ссылки в программе кодируется специальным обозначением (null). Особых ограничений на месторасположение ссылки не существует. Ссылка может располагаться как в стеке, так и в куче.
Сборка мусора – механизм, позволяющий CLR определить, когда объект становится недоступен в управляемой памяти программы. При сборке мусора управляемая память освобождается. Для разработчика приложения наличие механизма сборки мусора означает, что он больше не должен заботиться об освобождении памяти. Однако это может потребовать изменения в стиле программирования, например, особое внимание следует уделять процедуре освобождения системных ресурсов. Необходимо реализовать методы, освобождающие системные ресурсы, находящиеся под управлением приложения.
Более подробные сведения можно найти на сайте Марченко А.Л. Введение в программирование на C# 2.0