
- •Сборки (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. Создание и использование итераторов.
- •Общие сведения о итераторах
Обобщения и другие члены
В C# у свойств, индексаторов, событий, методов операторов, конструкторов и деструкторов не может быть параметров-типов. Но их можно определить в обобщенном типе с тем, чтобы в коде этих членов использовать параметры-типы этого типа.
С# не поддерживает задание собственных обобщенных параметров-типов у этих членов, поскольку создатели C# считают, что разработчикам вряд ли потребуется использовать эти члены в качестве обобщенных. Вдобавок, чтобы эти члены могли применяться как обобщенные, дляC# пришлось бы разработать специальный синтаксис, что довольно затратно. Например, при использовании в коде оператора «+» компилятор вызывает метод перегрузки оператора. В коде, где есть оператор «+», нельзя указать никакие аргументы-типы.
Верификация и ограничения
В процессе компиляции обобщенного кода компилятор C# анализирует его, убеждаясь, что он будет работать с любыми типами данных — существующими и теми, которые будут определены в будущем. Рассмотрим следующий метод.
private static Boolean MethodTakingAnyType<T>(T o)
{
T temp = o;
Console.WriteLine(o.ToString());
Boolean b = temp.Equals(o);
return b;
}
Здесь объявляется временная переменная (temp) типа Т, а затем выполняется несколько операций присвоения переменных и несколько вызовов методов. Он работает с любым типом T— ссылочным, значимым, перечислимым, типом-интерфейсом или типом-делегатом, существующим типом или типом, который определят в будущем, — потому что любой тип поддерживает присвоения и вызовы методов, определенных в Object (например, ToString и Equals).
Вот еще метод:
private static T Min<T>(T o1, T o2)
{
if (o1.CompareTo(o2) < 0)
return o1;
return o2;
}
Метод Min пытается через переменную o1 вызвать методCompareTo. Но многие типы не поддерживают методCompareTo, поэтому компиляторC# не в состоянии скомпилировать этот код и обеспечить, чтобы после компиляции метод смог работать со всеми типами. При попытке скомпилировать приведенный выше код появится сообщение об ошибке:
«Error CS0117: "T does not contain a definition for ' CompareTo »
«ошибка CS0117: T не содержит определение метода CompareTo»
Поэтому может показаться, что при использовании обобщений можно лишь объявлять переменные обобщенного типа, назначать переменные, вызывать методы, определенные Object, и все! Но ведь в таком случае от обобщений пользы мало. К счастью, компиляторы и CLR поддерживают механизм под названием ограничения (constraints), благодаря которому обобщения успешно «реабилитируются».
Ограничение позволяет сузить перечень типов, которые можно передать в обобщенном аргументе, и расширяет возможности по работе с этими типами. Вот новый вариант метода Min, который задает ограничение (выделено серым):
private static T Min<T>(T o1, T o2) where T : IComparable<T>
{
if (o1.CompareTo(o2) < 0)
return o1;
return o2;
}
Маркер where в C# сообщает компилятору, что указанный вTтип должен реализовывать обобщенный интерфейс IComparable того же типа (T). Благодаря этому ограничению компилятор разрешает методу вызвать метод CompareTo, потому что последний определен в интерфейсе IComparable<T>.
Теперь, когда код ссылается на обобщенный тип или метод, компилятор должен убедиться, что в коде указан аргумент-тип, удовлетворяющий этим ограничениям. Например, при компиляции следующего кода появляется сообщение:
«Error CS0309: The type 'object' must be convertible to 'System.IComparable<object>' in order to use it as a parameter T in the generic type or method 'Program.Min<T>(T, T)'|»
«Ошибка CS0309: тип object необходимо преобразовать в System.IComparable<object>, чтобы его можно было использовать в качестве параметра T в обобщенном типе или методе Program.Min<T>(T, T)».
private static void CallMin()
{
Object o1 = "Jeff", o2 = "Richter";
Object oMin = Min<Object>(o1, o2); // Ошибка CS0309.
}
Компилятор выдает эту ошибку, потому что System.Object не реализует интерфейс IComparable<Object>. Честно говоря, System.Object вообще не реализует никаких интерфейсов.
Вы получили общее представление об ограничениях и их работе. Познакомимся с ними поближе. Ограничения можно применять к параметрам-типам как обобщенных типов, так и обобщенных методов (как показано в методе Min). CLR не поддерживает перегрузку по именам параметров-типов или ограничений. Перегрузка типов и методов выполняется только по арности. Покажу это на примере.
// Можно определить следующие типы:
internal sealed class AType { }
internal sealed class AType<T> { }
internal sealed class AType<T1, T2> { }
// Ошибка: конфликт с AType<T>, у которого нет ограничений,
internal sealed class АТуре<Т> where T : IComparable<T> {}
// Ошибка: конфликт с АТуре<Т1, Т2>.
internal sealed class АТуре<ТЗ, Т4> {}
internal sealed class AnotherType
{
// Можно определить следующие методы:
private static void M() {}
private static void М<Т>() { }
private static void M<T1, T2>() { }
// Ошибка: конфликт с M<T>, у которого нет ограничений.
private static void М<Т>() where T : IComparable<T> {}
// Ошибка: конфликт с М<Т1, Т2>.
private static void М<ТЗ, Т4>() {}
}
При переопределении виртуального обобщенного метода в переопределяющем методе нужно задавать то же число параметров-типов, а они, в свою очередь, наследуют ограничения, заданные для них методом базового класса. Честно говоря, переопределяемый метод вообще не вправе задавать ограничения для своих параметров-типов, но может переименовывать параметры-типы. Аналогично, при реализации интерфейсного метода в нем должно задаваться то же число параметров-типов, что и в интерфейсном методе, причем эти параметры-типы наследуют ограничения, заданные для них методом интерфейса. Следующий пример демонстрирует это правило с помощью виртуальных методов.
internal class Base
{
public virtual void M<T1, T2>()
where T1 : struct
where T2 : class { }
}
internal sealed class Derived : Base
{
public override void M<T3, T4>()
where T3 : EventArgs // Ошибка.
where T4 : class { } // Ошибка.
}
При компиляции этого кода появится сообщение об ошибке:
«Error CS0460: Constraints for override and explicit interface implementation methods are inherited from the base method so cannot be specified directly»
«Ошибка CS0460: ограничения для методов интерфейсов с переопределением и явной реализацией наследуются от базового метода и поэтому не могут быть заданы явно».
Если из метода М<ТЗ, Т4> класса Derived убрать две строки where, код успешно скомпилируется. Заметьте: разрешается переименовывать параметры-типы (в этом примере 77 изменено на ТЗ, а 72 на Т4), но изменять (и даже задавать) ограничения нельзя.
Теперь поговорим о различных типах ограничений, которые компилятор и CLR позволяют применять к параметрам-типам. К параметру-типу могут применяться следующие ограничения: основное, дополнительное и/или ограничение конструктора. Речь о них пойдет в следующих трех разделах.