- •Сборки (assembly) в среде .Net. Проблема версионности сборок и ее решение.
- •Номер версии в .Net
- •Сведения о версии
- •Номер версии сборки
- •Информационная версия сборки
- •Общая система типов данных в среде .Net. Размерные и ссылочные типы данных. Типы, переменные и значения
- •Пользовательские типы
- •Система общих типов cts
- •Ссылочные типы
- •Типы литеральных значений
- •Неявные типы, анонимные типы и типы, допускающие значение null
- •Упаковка и распаковка размерных типов данных в среде .Net.
- •Производительность
- •Упаковка–преобразование
- •Распаковка-преобразование
- •Ссылочные типы данных. Объектная модель в среде .Net и языке c#.
- •Модели ручной и автоматической утилизации динамической памяти, их сравнительная характеристика. Модель с ручным освобождением памяти
- •Модель с автоматической «сборкой мусора»
- •Модель автоматической утилизации динамической памяти, основанная на сборке мусора. Проблема недетерминизма.
- •Модель автоматической утилизации динамической памяти, основанная на аппаратной поддержке (тегированной памяти).
- •Сборка мусора в среде .Net. Построение графа достижимых объектов.
- •Сборка мусора в среде .Net. Механизм поколений объектов.
- •Модель детерминированного освобождения ресурсов в среде .Net. Интерфейс iDisposable и его совместное использование с завершителем (методом Finalize).
- •«Мягкие ссылки» и кэширование данных в среде .Net.
- •Краткие и длинные слабые ссылки
- •Краткая ссылка
- •Длинная ссылка
- •Правила использования слабых ссылок
- •Динамические массивы в среде .Net и языке c#.
- •Приведение типов в массивах
- •Все массивы неявно реализуют /Enumerable, /Collection и iList
- •Передача и возврат массивов
- •Создание массивов с ненулевой нижней границей
- •Производительность доступа к массиву
- •Небезопасный доступ к массивам и массивы фиксированного размера
- •Делегаты в среде .Net и механизм их работы. Знакомство с делегатами
- •Использование делегатов для обратного вызова статических методов
- •Использование делегатов для обратного вызова экземплярных методов
- •Правда о делегатах
- •Использование делегатов для обратного вызова множественных методов (цепочки делегатов)
- •Поддержка цепочек делегатов в с#
- •Расширенное управление цепочкой делегатов
- •Упрощение синтаксиса работы с делегатами в с#
- •Упрощенный синтаксис № 1: не нужно создавать объект-делегат
- •Упрощенный синтаксис № 2: не нужно определять метод обратного вызова
- •Упрощенный синтаксис № 3: не нужно определять параметры метода обратного вызова
- •Упрощенный синтаксис № 4: не нужно вручную создавать обертку локальных переменных класса для передачи их в метод обратного вызова
- •Делегаты и отражение
- •События в среде .Net; реализация событий посредством делегатов. События
- •Этап 1: определение типа, который будет хранить всю дополнительную информацию, передаваемую получателям уведомления о событии
- •Этап 2: определение члена-события
- •Этап 3: определение метода, ответственного за уведомление зарегистрированных объектов о событии
- •Этап 4: определение метода, транслирующего входную информацию в желаемое событие
- •Как реализуются события
- •Создание типа, отслеживающего событие
- •События и безопасность потоков
- •Явное управление регистрацией событий
- •Конструирование типа с множеством событий
- •Исключительные ситуации и реакция на них в среде .Net. Достоинства
- •Механика обработки исключений
- •Блок try
- •Блок catch
- •Блок finally
- •Генерация исключений
- •Определение собственных классов исключений
- •Исключения в платформе .Net Framework
- •Исключения и традиционные методы обработки ошибок
- •Управление исключениями средой выполнения
- •Фильтрация исключений среды выполнения
- •21 Средства многопоточного программирования в среде .Net. Автономные потоки. Пул потоков.
- •Создание и использование потоков
- •Запуск и остановка потоков
- •Методы управления потоками
- •Безопасные точки
- •Свойства потока
- •Потоки Windows в clr
- •К вопросу об эффективном использовании потоков
- •Пул потоков в clr
- •Ограничение числа потоков в пуле
- •22. Асинхронные операции в среде .Net. Асинхронный вызов делегатов.
- •23. Синхронизация программных потоков в среде .Net. Блокировки.
- •Двойная блокировка
- •Класс ReaderWriterLock
- •Использование объектов ядра Windows в управляемом коде
- •Вызов метода при освобождении одного объекта ядра
- •24. Синхронизация программных потоков в среде .Net. Атомарные (Interlocked-операции). Семейство lnterlocked-методов
- •25. Прерывание программных потоков в среде .Net. Особенности исключительной ситуации класса ThreadAbortException.
- •26. Мониторы в среде .Net. Ожидание выполнения условий с помощью методов Wait и Pulse. Класс Monitor и блоки синхронизации
- •«Отличная» идея
- •Реализация «отличной» идеи
- •Использование класса Monitor для управления блоком синхронизации
- •Способ синхронизации, предлагаемый Microsoft
- •Упрощение кода c# при помощи оператора lock
- •Способ синхронизации статических членов, предлагаемый Microsoft
- •Почему же «отличная» идея оказалась такой неудачной
- •Целостность памяти, временный доступ к памяти и volatile-поля
- •Временная запись и чтение
- •Поддержка volatile-полей в с#
- •27. Асинхронный вызов делегатов.
- •Общие типы (Generics)
- •Инфраструктура обобщений
- •Открытые и закрытые типы
- •Обобщенные типы и наследование
- •Проблемы с идентификацией и тождеством обобщенных типов
- •«Распухание» кода
- •Обобщенные интерфейсы
- •Обобщенные делегаты
- •Обобщенные методы
- •Логический вывод обобщенных методов и типов
- •Обобщения и другие члены
- •Верификация и ограничения
- •Основные ограничения
- •Дополнительные ограничения
- •Ограничения конструктора
- •Другие вопросы верификации
- •Приведение переменной обобщенного типа
- •Присвоение переменной обобщенного типа значения по умолчанию
- •Сравнение переменной обобщенного типа с null
- •Сравнение двух переменных обобщенного типа
- •Использование переменных обобщенного типа в качестве операндов
- •Преимущества использования общих типов
- •29. Итераторы в среде .Net. Создание и использование итераторов.
- •Общие сведения о итераторах
Инфраструктура обобщений
Для обеспечения работы обобщений Microsoft нужно было сделать следующее.
Создать новые IL-команды, работающие с аргументами-типами.
Изменить формат существующих таблиц метаданных для выражения имен типов и методов с обобщенными параметрами.
Обновить многие языки программирования (в том числе С#, Microsoft Visual Basic .NET и другие), чтобы обеспечить поддержку нового синтаксиса и позволить разработчикам определять и ссылаться на новые обобщенные типы и методы.
Изменить компиляторы для генерации новых IL-команд и измененного формата метаданных.
Изменить JIT-компилятор, чтобы он обрабатывал новые IL-команды, работающие с аргументами-типами, и создавал корректный машинный код.
Создать новых членов отражения, для того чтобы разработчики с помощью запроса могли проверять наличие обобщенных параметров у типов и членов. Также пришлось определить новые предоставляющие информацию отражения члены, что позволило разработчикам создавать обобщенные определения типов и методов во время исполнения.
Изменить отладчик, чтобы он отображал и работал с обобщенными типами, членами, полями и локальными переменными.
Изменить механизм IntelliSense в Microsoft Visual Studio для отображения конкретных прототипов членов при использовании обобщенного типа или метода с указанием типа данных.
А теперь обсудим, как работают с обобщениями внутренние механизмы CLR. Эта информация пригодится вам при проектировании и создании обобщенных алгоритмов или выборе готовых обобщенных алгоритмов.
Открытые и закрытые типы
Типы с обобщенными параметрами-типами также считаются типами, причем для каждого из них CLR создает внутренний объект-тип. Это справедливо для ссылочных типов (классов), значимых типов (структур), интерфейсов и делегатов. Но тип с обобщенными параметрами-типами называют открытым типом, а в CLR запрещено конструирование экземпляров открытых типов (как и экземпляров типов-интерфейсов).
При ссылке на обобщенный тип в коде можно определить набор обобщенных аргументов-типов. Если всем аргументам-типам определенного типа передать действительные типы данных, то такой тип будут называть закрытым. CLR разрешает создание экземпляров закрытых типов. Но в коде, ссылающемся на обобщенный тип, можно не определять все обобщенные аргументы-типы. Таким образом, в CLR создается новый объект открытого типа, экземпляры которого создавать нельзя. Следующий код проясняет ситуацию.
using System;
using System.Collections.Generic;
// Частично определенный открытый тип.
internal sealed class DictionaryStringKey<TValue> : Dictionary<String, TValue>
{}
public static class Program
{
public static void Main()
{
Object o = null;
// Dictionary<,> - это открытый тип с двумя параметрами-типами.
Type t = typeof(Dictionary<,>);
// Попытка создания экземпляра этого типа (неудачная),
o = CreateInstance(t);
Console.WriteLine();
// DictionaryStringKey<> - это открытый тип с одним параметром-типом,
t = typeof(DictionaryStringKey<>);
// Попытка создания экземпляра этого типа (неудачная),
o = CreateInstance(t);
Console.WriteLine();
// DictionaryStringKey<Guid> - это закрытый тип.
t = typeof(DictionaryStringKey<Guid>);
// Попытка создания экземпляра этого типа (удачная),
o = CreateInstance(t);
// Проверка успешности попытки.
Console.WriteLine("Object type=" + o.GetType());
Console.ReadKey();
}
private static Object CreateInstance(Type t)
{
Object o = null;
try
{
o = Activator.CreateInstance(t);
Console.Write("Created instance of {0}", t.ToString());
}
catch (ArgumentException e)
{
Console.WriteLine(e.Message);
}
return o;
}
}
Скомпилировав и выполнив этот код, вы увидите:
Cannot create an instance of System.Collections.Generic.
Dictionary'2[TKey,TValue] because Type.ContainsGenericParameters is true.
Cannot create an instance of DictionaryStringKey'1[TValue] because Type.ContainsGenericParameters is true.
Created instance of DictionaryStringKey'1[System.Guid] Object type=DictionaryStringKey'1[System.Guid]
Итак, при попытке создания экземпляра открытого типа метод Createlnstance объекта Activator генерирует исключение ArgumentException. На самом деле, сообщение об исключении означает, что тип все же содержит несколько обобщенных параметров.
В выводимой программой информации видно, что имена типов заканчиваются левой одиночной кавычкой ('), за которой следует число, означающее арность типа, то есть число необходимых для него параметров-типов. Например, арность класса Dictionary равна 2, потому что требуется определить типы ТКеу и TValue. Арность класса DictionaryStringKey — 1, так как требуется указать лишь один тип — TValue.
Также замечу, что CLR размещает статические поля типа в самом объекте-типе - поэтому у каждого закрытого типа есть свои статические поля. Иначе говоря, статические поля, определенные в объекте List<T>, не будут совместно использоваться объектами List<DateTime> и List<String>, потому что у каждого объекта закрытого типа есть свои статические поля. Если же в обобщенном типе определен статический конструктор, то последний выполняется для закрытого типа лишь раз. Иногда разработчики определяют статический конструктор для обобщенного типа, чтобы аргументы-типы соответствовали определенным критериям. Например, так определяется обобщенный тип, используемый только с перечислимыми типами.
internal sealed class GenericTypeThatRequiresAnEnum<T>
{
static GenericTypeThatRequiresAnEnum()
{
if (!typeof(T).IsEnum)
{
throw new ArgumentException("T must be an enumerated type");
}
}
}
В CLR есть функция под названием ограничения — это более удачный способ определения обобщенного типа с указанием допустимых для него аргументов-типов. Но подробнее о них чуть позже. К сожалению, эта функция не позволяет ограничить аргументы-типы только перечислимыми типами. Поэтому в предыдущем примере необходим статический конструктор для проверки того, что используемый тип является перечислимым.