- •1. Жизненный цикл объекта.
- •2.Делегаты. Назначение, синтаксис объявления, использование делегата. Событийная модель.
- •3. События. Объявление события. Шаблон проектирования события в классе. Свойство для безопасной работы с событиями. Безопасный вызов события в многопоточном программировании.
- •4. Обобщенные классы. Объявление и детализация класса типами пользователя.
- •5. Обобщенные методы. Объявление и детализация методов типами пользователя.
- •6. Ограничения на параметры в обобщенных классах и функциях.
- •7. Типы, допускающие значение null
- •8. Коллекции и итераторы. Оператор yield
- •9.Потоки ввода/вывода в c#. Создание объекта потока и работа с ним. Текстовые, бинарные потоки, потоки со сжатием данных.
- •11. Исключения. Создание класса пользовательского исключения. Генерация и перехват исключения.
- •12. Рефлексия типов. Класс типа Type. Методы и свойства класса.
- •13. Сборки. Статическое и динамическое связывание сборок. Класс сборки Assembly.
- •14. Позднее связывание. Класс System.Activator. Создание экземпляра объекта путем позднего связывания. Вызов методов объекта путем позднего связывания.
- •15. Атрибуты. Назначение атрибутов. Базовый класс атрибута. Аннотирование класса атрибутами.
- •16. Расширяющие методы.
- •17. Анонимные методы. Объявление и использование.
- •18. Захват переменных анонимными методами. Цепочка вызовов.
- •20. Захват переменных в лямбда-выражениях. Рекурсивный вызов в лямбда-выражениях. Анонимная рекурсия.
- •21. Выражения и деревья выражений. Стандартные делегаты, используемые с выражениями и деревьями выражений.
- •22. Комбинирование выражений посредством класса InvocatedExpression.
- •23. Язык интегрированных запросов linq. Назначение, технические средства для реализации языка. Группы языка linq.
- •24. Linq to Objects. Вид запроса. Вызов цепочек расширяющих методов. Языковые конструкции для кодирования запроса. Отложенное и неотложенное выполнение запроса.
- •25. Конструкция from…select… Разделы конструкции. Условия. Проекция. Анонимные типы данных.
- •26. Конструкция from…group… Разделы конструкции. Условия. Ключи группировки. Получение ключа в результате-выборке.
- •28. Linq to Objects. Расширяющие методы для преобразования типов, операций со множествами, преобразования в один элемент.
- •29. Технология linq to sql. Назначение технологии. Класс контекста данных и основные атрибуты для создания контекста данных.
- •30. Создание и подключение класса контекста данных к базе данных. Шаблон программирования при добавлении данных в объект контекста данных.
18. Захват переменных анонимными методами. Цепочка вызовов.
При объявлении анонимных методов любые переменные, объявленные вне контекста анонимного метода, но доступные внутри него, включая ссылку this, рассматриваются как внешние переменные. И если тело анонимного метода ссылается на эти переменные, то говорят, что анонимный метод "захватил" переменную.
Public static void Search(list <string> list, string substr)
{
return list.Find(delegate(string x) {return x.Starts with (substr);});
}
Здесь в метод Search передается параметр substr. Этот параметр используется в анонимном методе (вместо него может использовать другая любая локальная переменная, но интересны те локальные переменные, которые хранятся в стеке). Далее из анонимного метода создается делегат, но он может быть передан в другие точки программы, т.е. возможна ситуация, когда делегат вызывается после того, как локальная переменная вышла из зоны видимости.
Локальные переменные или параметры, использованные в теле анонимного метода подчиняются другим правилам жизненного цикла и они говорят, что анонимный метод захватил переменную.
Для захвата переменных, которые являются типами значений, создаются анонимные объекты соответствующих типов, в которых с помощью операций установки присваиваются нужные значения, т.е. анонимный метод работает не с самой переменной, а с ее копией расположенной в куче.
19. Лямбда-выражения и лямбда-операторы. Синтаксис, назначение и простейшие формы.
Используя λ-выражения, можно кратко определять функциональные объекты для использования в любое время. C# всегда поддерживал эту возможность через делегаты, посредством которых создается функциональный объект (в форме делегата) и к нему привязывается код обратного вызова во время создания. λ-выражения связывают эти два действия – создание и подключение – в один выразительный оператор кода. Вдобавок можно легко ассоциировать среду с функциональными объектами.
λ-выражение – это синтаксис, посредством которого можно объявлять анонимные функции (делегаты) более гладким и выразительным способом.
λ-выражение – особая форма функционального программирования для императивного языка.
λ-выражение позволяет в краткой форме определять функциональные объекты.
В основе λ-выражений лежат делегаты. В обычной форме нужно создать делегат и подключить его к методу для обратного вызова. λ-выражение позволяет соединить два этапа в один. У λ-выражений имеется две формы:
1) пишется некий код, который завершается оператором return. Форма, которая наиболее прямо заменяет анонимные методы, представляет собой блок кода, заключенный в фигурные скобки. Это λ-операторы. Такие λ-операторы – прямая замена анонимных методов.
2) λ-выражения предоставляют еще более сокращенный способ объявлять анонимный метод и не требуют ни кода в фигурных скобках, ни оператора return.
Оба типа λ-выражений могут быть преобразованы в делегаты. Однако λ-выражения без блоков операторов можно преобразовать в деревья выражений с помощью типов из пространства имен System.Linq.Expressions. Другими словами, функция, описанная в коде, превращается в данные.
Синтаксис:
<(список операторов)> => λ-выражение
Например, следующее λ-выражение может быть использовано в качестве делегата, принимающего один параметр и возвращающего результат выполнения операции над параметром: х => х/2, где х - атрибут, а х/2 - λ-выражение. Это говорит следующее: “взять x в качестве параметра и вернуть результат следующей операции в x”.
λ-выражение лишено информации о типе. Это не значит, что выражение не имеет типа. Вместо этого компилятор выводит тип аргумента и тип результата из контекста его использования, и отсюда следует, что если вы присваиваете λ-выражение делегату, типы определения делегата используются для определения типов внутри λ-выражения.
Func<int, double> expr = x => x/2;
Console.WriteLine (expr(5));
Тип Func<> – это новый вспомогательный тип, представленный в пространстве имен System, который используется для объявления простых делегатов, принимающих до четырех аргументов и возвращающих результат.
В данном случае объявляется переменная expr, которая является делегатом, принимающим int и возвращающим double.
Public delegate TResult Func <TSouree; TResult>(TSouree souree);
Func<int, int, int> exp r = (x, y) => x+y;
λ-выражения как и делегаты в состоянии захватывать внешние переменные.
Например, необходимо из списка выбрать элементы удовлетворяющие некоторому условию и высчитать их количество.
public static int GetCount<TItem>(IList <TItem>souree, Predicate<TItem> predicate)
{
int count = 0;
foreach(var x in souree)
if(predicate(x)) count ++;
return count;
}
List <string> list = new List<string>() {};
int c = GetCount(list, x => x.Substr(“Петуш”) >= 0);
Или
List <string> list = new List<int>() {2, 3, 4, 7}
int c = GetCount(list, x => x %2 == 0);
Кроме λ-выражений есть λ-операторы. Отличие состоит в том, что λ-операторы имеют внутри себя оператор return аналогично анонимным методам.
Func <int, int, int> expr = (x, y) =>{return x+y;}
И есть одно главное отличие между λ-выражениями с блоками операторов и простыми λ-выражениями. Первые могут быть преобразованы только в типы делегатов, в то время как вторые – и в делегаты, и в деревья выражений, посредством семейства типов, сосредоточенных вокруг System.Linq.Expressions.Expression<T>.