Что такое CLR? Что такое IL? Что такое CLS?

CLR ("Common Language Runtime", "общеязыковая исполняющая среда") - это компонент .NET Framework, основной задачей которого является управление интерпретацией и исполнением кода IL. CLR отвечает за изоляцию памяти приложений, проверку типов, безопасность кода, преобразование IL в машинный код.

IL (Intermediate Language) - код, содержащий набор инструкций, не зависящих от платформы. Иными словами, после компиляции исходного кода он преобразуется не в код для какой-то определенной платформы, а в промежуточный код на языке IL.

CLS ("Common Language Specification", общеязыковая спецификация) - это набор правил, следуя которым разработчики достигают бесконфликтной работы во всех языках .NET.

Что такое managed code?

Управляемый код (managed code) - это код, работающий в среде CLR. Содержит метаданные, в которых находится информация для среды выполнения - о типах, членах и ссылках, используемых в коде.

Что такое assembly?

Сборка (assembly) - один или несколько файлов, содержащий логический набор функциональности (код и другие данные, связанные с кодом). Бывают статические сборки, хранящиеся на диске, и динамические, которые создаются во время выполнения программы. Сборка - это базовый блок приложения, все ресурсы, относящиеся к ней, доступны или только внутри этого блока, или экспортируются наружу. При выполнении сборка задает область видимости имен и следит за ее соблюдением.

Что такое приватные и совместные сборки?

Сборки (assembly) бывают двух типов - приватные (private), которые использует только само приложение, и совместные (shared), использующиеся набором приложений.
При приватных сборках приложение изолируется от внешнего воздействия программ и операционной системы, отпадает необходимость заботиться об уникальности имен в глобальном пространстве имен.
Чтобы сделать сборку совместной, ее необходимо специальным образом собрать и присвоить ей строгое шифрованное имя.

Что такое assembly manifest?

Манифест сборки (assembly manifest) - это внутренняя часть сборки, которая позволяет ей быть самоописанной. Assembly manifest позволяет идентифицировать сборку, указывает файлы, которые включаются в реализацию сборки, описывает типы и ресурсы, используемые в сборке, указывает зависимости от других сборок, а также набор прав доступа, которые необходимы сборке для корректной работы. Эта информация используется во время выполнения для разрешения ссылок, проверку корректности версий, проверку целостности загруженных сборок.

В чем разница между понятиями namespace и assembly?

Namespace (пространство имен) является логическим соглашением, используемым во время разработки, в то время как assembly (сборка) устанавливает область видимости имени в процессе выполнения.

В чем различие между Value Type и Reference Type?

Value Type находятся в стеке, а Reference Type в куче.

Когда объект удаляется сборщиком мусора?

Объект удаляется сборщиком мусора, когда на него не остается ссылок.

Что такое Code Access Security (CAS)?

CAS - это защитная технология, позволяющая установить ограничение на исполнение управляемого кода. Таким образом можно определить разрешения и установить права доступа к ресурсам компьютера.

Что такое attribute?

Атрибут (attribute) - это универсальное средство связи данных с типами, позволяют добавлять любую текстовую информацию о классах, свойствах, методах и т.д. Атрибуты сохраняются с метаданными и могут быть получены при выполнении программы.

Как обеспечить использование именованных параметров в конструкторе атрибута?

Конструкторы атрибутов могут принимать именованные параметры — поля и свойства атрибутов. При задании именованного параметра в конструктор атрибута передается имя свойства или поля, которое должно принять этот параметр. При чем эти свойства и поля должны быть открытыми.
Если именованные параметры передаются, то они обязательно должны идти следом за позиционными параметрами, которые явно указаны в конструкторе атрибута.
Указание именованных параметров не является обязательным, поэтому при проектировании атрибутов необходимо помнить о том, что некоторые его поля или свойства могут быть не проинициализированы.
Пример использования именованных параметров в конструкторе атрибута:
[DllImport("Kernel32", CharSet=CharSet.Auto, SetLastError=true)]
Здесь передается 1 позиционный параметр — строка "Kernel32" и 2 именованных параметра, которые устанавливают открытые поля CharSet и SetLastError в значения CharSet.Auto и true соответственно.

В чем различие между Finalize и Dispose?

Dispose - обеспечивает явный контроль над ресурсами, используемыми объектом, а Finalize - неявный, используемый сборщиком мусора.

Что такое Reflection?

Отражение (reflection) — это механизм, предоставляющий исполняемому коду информацию о самом себе. Отражение позволяет методу изучать чужой код и изменять свою работу в соответствии с полученными данными. Также отражение может применяться, когда метод должен выполнять разные действия в зависимости от того, откуда он запущен.
Рассмотрим простой пример:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class Animal
{
    public void Eat() 
    {
       Console.WriteLine("The animal eats."); 
    }
}
 
Animal an = new Animal();
an.Eat();
 
 
Type animalType = typeof(Animal);
 
if(animalType != null)
{
	ConstructorInfo ci = animalType.GetConstructor(new Type[]{});
	object animalReflected = ci.Invoke(new object[]{});
}
В этом примере объявляется класс Animal с одним методом — Eat.
Далее создается экземпляр класса и вызывается метод Eat.
После этого делается попытка получить метаданные, описывающие класс Animal. Эти данные заносятся в переменную animalType.
Если данные получены, переменной ci мы присваиваем ссылку на конструктор.
Далее, используя отражение, вызывается конструктор, который возвращает ссылку на созданный объект.
Теперь мы можем привести переменную animalReflected к типу Animal и пользоваться методами этого класса напрямую.

Что такое Boxing и Unboxing?

Упаковка (boxing) позволяет преобразовать размерный тип в ссылочный. При упаковке объекта размерного типа происходят следующие действия:
1. Выделяется память в управляемой куче.
2. Совершается копирование полей размерного типа в память, которая была выделена в куче.
3. Возвращается адрес объекта.
Некоторые компиляторы автоматически создают IL-код, необходимый для упаковки объекта размерного типа.
Процесс извлечения адреса полей из упакованного объекта называется распаковкой (unboxing). Распаковка не является полной противоположностью упаковке. В отличие от упаковки при распаковке не происходит никакого копирования. Однако обычно вслед за распаковкой следует копирование полей, поэтому обе операции (распаковка и копирование) являются противоположностью операции упаковки.
Приведем пример использования упаковки и распаковки.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// Объявляем размерный тип.
struct Point {
public Int32 x, у;
}
 
class App {
static void Main() {
ArrayList a = new ArrayList();
Point p; 		 	// Выделяется память для Point (не в куче).
for (Int32 i = 0 ; i < 10; i++) {
p.x = p. у = i; 	// Инициализация членов в нашем размерном типе.
a.Add(p); 	 	// Упаковка размерного типа и добавление ссылки в ArrayList.
	}
 
	Point р1 = (Point) a[0]; 	// распаковка и копирование полей
}

Упаковка и распаковка/копирование снижают производительность приложения как в плане замедления, так и в расходе дополнительной памяти, поэтому нужно стараться минимизировать создание кода, в котором происходят операции упаковки и распаковки/копирования.

Что такое GAC?

GAC — это глобальный кэш сборок. В нем хранятся совместно используемые сборки. Обычно это каталог С:\Windows\Assembly\GAC. Этот каталог имеет определенную структуру, в котором хранятся подкаталоги, имена которых сгенерированы по определенному алгоритму.
В GAC можно поместить только сборки со строгими именами. Для того, чтобы поместить сборку в GAC, используют специальный инструмент GACUtil.exe, который знает всю внутреннюю структуру GAC и может генерировать имена подкаталогов надлежащим образом.
Регистрировать в GAC сборки необходимо для того, чтобы избежать конфликтов имен сборок.
Приведем пример: две компании выпустили сборку и назвали ее одним именем Calculus. Если мы скопируем эту сборку в каталог, в котором уже находится сборка с таким же именем, то мы затрем сборку, которая ранее могла использоваться каким-то приложением.
Это приложение с новой сборкой теперь работать не сможет.
Решением этой проблемы будет регистрация этих двух сборок в GAC, в котором для каждой будет создан отдельный каталог.