СДЕЛАЙТЕ СВОИ УРОКИ ЕЩЁ ЭФФЕКТИВНЕЕ, А ЖИЗНЬ СВОБОДНЕЕ

Благодаря готовым учебным материалам для работы в классе и дистанционно

Скидки до 50 % на комплекты
только до

Готовые ключевые этапы урока всегда будут у вас под рукой

Организационный момент

Проверка знаний

Объяснение материала

Закрепление изученного

Итоги урока

Применение LINQ

Категория: Информатика

Нажмите, чтобы узнать подробности

Просмотр содержимого документа
«Применение LINQ»

Применение LINQ

Применение LINQ

  Соединение коллекций. Метод Join, GroupJoin и Zip  Соединение в LINQ используется для объединения двух разнотипных наборов в один. Для соединения используется оператор join или метод Join(). Как правило, данная операция применяется к двум наборам, которые имеют один общий критерий. Например, у нас есть два класса:

Соединение коллекций. Метод Join, GroupJoin и Zip

  • Соединение в LINQ используется для объединения двух разнотипных наборов в один. Для соединения используется оператор join или метод Join(). Как правило, данная операция применяется к двум наборам, которые имеют один общий критерий. Например, у нас есть два класса:
 Объекты обоих классов будет иметь один общий критерий - название команды. Соединим по этому критерию два набора этих классов:
  • Объекты обоих классов будет иметь один общий критерий - название команды. Соединим по этому критерию два набора этих классов:
 С помощью выражения join t in teams on pl.Team equals t.Name объект pl из списка players соединяется с объектом t из списка teams, если значение свойства pl.Team совпадает со значением свойства t.Name. Результатом соединения будет объект анонимного типа, который будет содержать три свойства. В итоге мы получим следующий вывод:
  • С помощью выражения join t in teams on pl.Team equals t.Name объект pl из списка players соединяется с объектом t из списка teams, если значение свойства pl.Team совпадает со значением свойства t.Name. Результатом соединения будет объект анонимного типа, который будет содержать три свойства. В итоге мы получим следующий вывод:
 То же самое действие можно было бы выполнить с помощью метода Join():
  • То же самое действие можно было бы выполнить с помощью метода Join():
Метод Join() принимает четыре параметра: второй список, который соединяем с текущим  свойство объекта из текущего списка, по которому идет соединение  свойство объекта из второго списка, по которому идет соединение  новый объект, который получается в результате соединения
  • Метод Join() принимает четыре параметра:
  • второй список, который соединяем с текущим
  •  свойство объекта из текущего списка, по которому идет соединение
  •  свойство объекта из второго списка, по которому идет соединение
  •  новый объект, который получается в результате соединения
GroupJoin Метод GroupJoin кроме соединения последовательностей также выполняет и группировку. Например, возьмем вышеопределенные списки teams и players и сгуппируем всех игроков по командам:

GroupJoin

  • Метод GroupJoin кроме соединения последовательностей также выполняет и группировку. Например, возьмем вышеопределенные списки teams и players и сгуппируем всех игроков по командам:
Результатом выполнения программы будет следующий вывод:

Результатом выполнения программы будет следующий вывод:

Метод GroupJoin, также как и метод Join, принимает все те же параметры. Только теперь во последний параметр - делегат передаются объект команды и набор игроков этой команды.
  • Метод GroupJoin, также как и метод Join, принимает все те же параметры. Только теперь во последний параметр - делегат передаются объект команды и набор игроков этой команды.
Метод Zip Метод Zip позволяет объединять две последовательности таким образом, что первый элемент из первой последовательности объединяется с первым элементом из второй последовательности, второй элемент из первой последовательности соединяется со вторым элементом из второй последовательности и так далее:

Метод Zip

  • Метод Zip позволяет объединять две последовательности таким образом, что первый элемент из первой последовательности объединяется с первым элементом из второй последовательности, второй элемент из первой последовательности соединяется со вторым элементом из второй последовательности и так далее:
Метод Zip в качестве первого параметра принимает вторую последовательность, с которой надо соединяться, а в качестве второго параметра - делегат для создания нового объекта.
  • Метод Zip в качестве первого параметра принимает вторую последовательность, с которой надо соединяться, а в качестве второго параметра - делегат для создания нового объекта.
Консольный вывод программы:

Консольный вывод программы:

Методы All и Any Методы All, Any и Contains позволяют определить, соответствует ли коллекция определенному условию, и в зависимости от результата они возвращают true или false.

Методы All и Any

  • Методы All, Any и Contains позволяют определить, соответствует ли коллекция определенному условию, и в зависимости от результата они возвращают true или false.
Метод All проверяет, соответствуют ли все элементы условию. Например, узнаем, у всех ли пользователей возраст превышает 20 и имя начинается с буквы T:
  • Метод All проверяет, соответствуют ли все элементы условию. Например, узнаем, у всех ли пользователей возраст превышает 20 и имя начинается с буквы T:
Поскольку у всех пользователей возвраст больше 20, то переменная result1 будет равна true. В то же время не у всех пользователей имя начинаяется с буквы T, поэтому вторая переменная result2 будет равна false.
  • Поскольку у всех пользователей возвраст больше 20, то переменная result1 будет равна true. В то же время не у всех пользователей имя начинаяется с буквы T, поэтому вторая переменная result2 будет равна false.
Метод Any действует подобным образом, только позволяет узнать, соответствует ли хотя бы один элемент коллекции определенному условию:
  • Метод Any действует подобным образом, только позволяет узнать, соответствует ли хотя бы один элемент коллекции определенному условию:

Первое выражение вернет false, поскольку у всех пользователей возвраст больше 20. Второе выражение возвратит true, так как у нас есть в коллекции пользователь с именем Tom.
  • Первое выражение вернет false, поскольку у всех пользователей возвраст больше 20. Второе выражение возвратит true, так как у нас есть в коллекции пользователь с именем Tom.
Отложенное и немедленное выполнение LINQ Есть два способа выполнения запроса LINQ: отложенное и немедленное выполнение.

Отложенное и немедленное выполнение LINQ

  • Есть два способа выполнения запроса LINQ: отложенное и немедленное выполнение.
При отложенном выполнении LINQ-выражение не выполняется, пока не будет произведена итерация или перебор по выборке. Рассмотрим отложенное выполнение:
  • При отложенном выполнении LINQ-выражение не выполняется, пока не будет произведена итерация или перебор по выборке. Рассмотрим отложенное выполнение:
То есть фактическое выполнение запроса происходит не в строке определения: var selectedTeams = from t..., а при переборе в цикле foreach.
  • То есть фактическое выполнение запроса происходит не в строке определения: var selectedTeams = from t..., а при переборе в цикле foreach.
Фактически LINQ-запрос разбивается на три этапа: 1. Получение источника данных 2. Создание запроса 3. Выполнение запроса и получение его результатов
  • Фактически LINQ-запрос разбивается на три этапа:
  • 1. Получение источника данных
  • 2. Создание запроса
  • 3. Выполнение запроса и получение его результатов
Как это происходит в нашем случае: 1. Получение источника данных - определение массива teams: string[] teams = {
  • Как это происходит в нашем случае:
  • 1. Получение источника данных - определение массива teams:
  • string[] teams = {"Бавария", "Боруссия", "Реал Мадрид", "Манчестер Сити", "ПСЖ", "Барселона"};
  • 2. Создание запроса - определение переменной selectedTeams:
  • var selectedTeams = from t in teams where t.ToUpper().StartsWith("Б") orderby t select t;
  • 3. Выполнение запроса и получение его результатов:
  • foreach (string s in selectedTeams)
  • Console.WriteLine(s);
После определения запроса он может выполняться множество раз. И до выполнения запроса источник данных может изменяться. Чтобы более наглядно увидеть это, мы можем изменить какой-либо элемент до перебора выборки:
  • После определения запроса он может выполняться множество раз. И до выполнения запроса источник данных может изменяться. Чтобы более наглядно увидеть это, мы можем изменить какой-либо элемент до перебора выборки:
Теперь выборка будет содержать два элемента, а не три, так как второй элемент после изменения не будет соответствовать условию. Важно понимать, что переменная запроса сама по себе не выполняет никаких действий и не возвращает никаких данных. Она только хранит набор команд, которые необходимы для получения результатов. То есть выполнение запроса после его создания откладывается. Само получение результатов производится при переборе в цикле foreach.
  • Теперь выборка будет содержать два элемента, а не три, так как второй элемент после изменения не будет соответствовать условию.
  • Важно понимать, что переменная запроса сама по себе не выполняет никаких действий и не возвращает никаких данных. Она только хранит набор команд, которые необходимы для получения результатов. То есть выполнение запроса после его создания откладывается. Само получение результатов производится при переборе в цикле foreach.
Немедленное выполнение запроса С помощью ряда методов мы можем применить немедленное выполнение запроса. Это методы, которые возвращают одно атомарное значение или один элемент. Например, Count(), Average(), First() / FirstOrDefault(), Min(), Max() и т.д. Например, метод Count() возвращает числовое значение, которое представляет количество элементов в полученной последовательности. А метод First() возвращает первый элемент последовательности. Но чтобы выполнить эти методы, вначале надо получить саму последовательность, то есть результат запроса, и пройтись по ней циклом foreach, который вызывается неявно внутри структуры запроса.

Немедленное выполнение запроса

  • С помощью ряда методов мы можем применить немедленное выполнение запроса. Это методы, которые возвращают одно атомарное значение или один элемент. Например, Count(), Average(), First() / FirstOrDefault(), Min(), Max() и т.д. Например, метод Count() возвращает числовое значение, которое представляет количество элементов в полученной последовательности. А метод First() возвращает первый элемент последовательности. Но чтобы выполнить эти методы, вначале надо получить саму последовательность, то есть результат запроса, и пройтись по ней циклом foreach, который вызывается неявно внутри структуры запроса.
Рассмотрим пример с методом Count(), который возвращает число элементов последовательности: Результатом метода Count будет объект int, поэтому сработает немедленное выполнение.
  • Рассмотрим пример с методом Count(), который возвращает число элементов последовательности:

Результатом метода Count будет объект int, поэтому сработает немедленное выполнение.

Сначала создается запрос: from t in teams where t.ToUpper().StartsWith(
  • Сначала создается запрос: from t in teams where t.ToUpper().StartsWith("Б") orderby t select t. Далее к нему применяется метод Count(), который выполняет запрос, неявно выполняет перебор по последовательности элементов, генерируемой этим запросом, и возвращает число элементов в этой последовательности.
Также мы можем изменить код таким образом, чтобы метод Count() учитывал изменения и выполнялся отдельно от определения запроса:
  • Также мы можем изменить код таким образом, чтобы метод Count() учитывал изменения и выполнялся отдельно от определения запроса:
Также для немедленного выполнения LINQ-запроса и кэширования его результатов мы можем применять методы преобразования ToArray(), ToList(), ToDictionary() и т.д.. Эти методы получают результат запроса в виде объектов Array, List и Dictionary соответственно. Например:
  • Также для немедленного выполнения LINQ-запроса и кэширования его результатов мы можем применять методы преобразования ToArray(), ToList(), ToDictionary() и т.д.. Эти методы получают результат запроса в виде объектов Array, List и Dictionary соответственно. Например:
Делегаты и анонимные методы в запросах LINQ Хотя, как правило, в качестве параметров в методах расширения LINQ удобно использовать лямбда-выражения. Но лямбда-выражения являются сокращенной нотацией анонимных методов. И если мы обратимся к определению этих методов, то увидим, что в качестве параметра многие из них принимают делегаты типа Func, например, определение метода Where:

Делегаты и анонимные методы в запросах LINQ

  • Хотя, как правило, в качестве параметров в методах расширения LINQ удобно использовать лямбда-выражения. Но лямбда-выражения являются сокращенной нотацией анонимных методов. И если мы обратимся к определению этих методов, то увидим, что в качестве параметра многие из них принимают делегаты типа Func, например, определение метода Where:
Зададим параметры через делегаты:

Зададим параметры через делегаты:

Так как набор элементов, к которому применяется метод Where, содержит объекты int, то в делегат в качестве параметра передается объект этого типа. Возвращаемые тип должен представлять тип bool: если true, то объект int соответствует условию и попадает в выборку.
  • Так как набор элементов, к которому применяется метод Where, содержит объекты int, то в делегат в качестве параметра передается объект этого типа. Возвращаемые тип должен представлять тип bool: если true, то объект int соответствует условию и попадает в выборку.
Альтернативный поход представляет перемещение всей логики в отдельный метод:
  • Альтернативный поход представляет перемещение всей логики в отдельный метод:
Рассмотрим другой пример. Пусть метод Select() добавляет в выборку не текущий элемент-число, а его факториал:
  • Рассмотрим другой пример. Пусть метод Select() добавляет в выборку не текущий элемент-число, а его факториал:
Метод Select в качестве параметра принимает тип Func selector. Так как у нас набор объектов int, то входным параметром делегата также будет объект типа int. В качестве типа выходного параметра выберем int, так как факториал числа - это целочисленное значение.
  • Метод Select в качестве параметра принимает тип Func selector. Так как у нас набор объектов int, то входным параметром делегата также будет объект типа int. В качестве типа выходного параметра выберем int, так как факториал числа - это целочисленное значение.