LINQ (Language-Integrated Query) или язык интегрированных запросов - набор функций, который расширяет возможности синтаксиса языков программирования C# и Visual Basic. Проще говоря, LINQ это язык запросов, который возвращает набор объектов, одиночный объект или подмножество полей из объекта, либо набора объектов. В LINQ этот возвращенный набор называется последовательностью (sequence), последовательности LINQ чаще всего используют тип IEnumerable<T>, где Т - тип данных объектов, находящихся в последовательности (например IEnumerable<string>, IEnumerable<[] int>).
LINQ включает в себя около 50 стандартных операций, которые в свою очередь делятся на 2 группы - отложенные операции (выполняются при вызове) и не отложенные операции (выполняются в первую очередь). На Рис. 11.1 представлена схема данных запросов.
(рис 11.1) Схема стандартных операторов используемых LINQ
Полный список методов, которые используются в LINQ-запросах, представлен в Табл. 11.1.
| Оператор | Описание |
|---|---|
| Объединение | |
| Aggregate | Применяет к последовательности пользовательский метод. |
| Average | Вычисляет среднее для числовой последовательности. |
| Count | Возвращает количество элементов в последовательности (целочисленное значение). |
| LongCount | Возвращает количество элементов в последовательности (значение в диапазоне LongInt). |
| Min | Возвращает наименьшее значение для числовой последовательности. |
| Max | Возвращает наибольшее значение для числовой последовательности. |
| Sum | Складывает члены числовой последовательности. |
| Конкатенация | |
| Concat | Соединяет две последовательности в одну. |
| Преобразование | |
| Cast | Преобразует элементы последовательности в элементы указанного типа. |
| OfType | Выбирает из элементов последовательности элементы указанного типа. |
| ToArray | Возвращает массив из элементов последовательности. |
| ToDictionary | Возвращает словарь из элементов последовательности. |
| ToList | Возвращает список из элементов последовательности. |
| ToLookup | Возвращает результаты поиска по последовательности. |
| ToSequence | Возвращает последовательность IEnumerable. |
| Элемент | |
| DefaultIfEmpty | Создает стандартный элемент для пустой последовательности. |
| ElementAt | Возвращает элемент последовательности по указанному индексу. |
| ElementAtOrDefault | Возвращает элемент по указанному индексу или стандартный элемент (если индекс вышел за пределы диапазона). |
| First | Возвращает первый элемент последовательности. |
| FirstOrDefault | Возвращает первый элемент последовательности или стандартный элемент (если нужный элемент не найден). |
| Last | Возвращает последний элемент последовательности. |
| LastOrDefault | Возвращает последний элемент последовательности или стандартный элемент (если нужный элемент не найден). |
| Single | Возвращает единственный элемент последовательности. |
| SingleOrDefault | Возвращает единственный элемент последовательности или стандартный элемент (если нужный элемент не найден). |
| Равенство | |
| SequenceEqual | Проверяет эквивалентность двух последовательностей. |
| Создание | |
| Empty | Создает пустую последовательность. |
| Range | Создает последовательность в соответствии с заданным диапазоном. |
| Repeat | Создает последовательность, повторяя значение заданное количество раз. |
| Группировка | |
| GroupBy | Группирует элементы последовательности указанным образом. |
| Присоединение | |
| GroupJoin | Выполняет группированное соединение двух последовательностей. |
| Join | Выполняет внутреннее соединение двух последовательностей. |
| Упорядочение | |
| OrderBy | Упорядочивает элементы последовательности по заданным значениям в порядке возрастания. |
| OrderByDescending | Упорядочивает элементы последовательности по заданным значениям в порядке убывания. |
| ThenBy | Упорядочивает элементы уже упорядоченной последовательности в порядке возрастания. |
| ThenByDescending | Упорядочивает элементы уже упорядоченной последовательности в порядке убывания. |
| Reverse | Зеркально отображает порядок расположения элементов в последовательности. |
| Разделение на части | |
| Skip | Возвращает последовательность, в которой указанное число элементов пропущено. |
| SkipWhile | Возвращает последовательность, в которой пропущены элементы, не соответствующие указанному условию. |
| Take | Возвращает последовательность, в которую включается указанное число элементов. |
| TakeWhile | Возвращает последовательность, в которую включаются элементы, соответствующие указанному условию. |
| Проекция | |
| Select | Создает проекцию части последовательности. |
| SelectMany | Создает проекцию части последовательности по принципу "один ко многим". |
| Кванторы | |
| All | Определяет соответствие всех элементов последовательности указанным условиям. |
| Any | Определяет, есть ли в последовательность элементы, удовлетворяющие указанным условиям. |
| Contains | Определяет, есть ли в последовательности указанный элемент. |
| Ограничение | |
| Where | Сортирует члены последовательности. |
| Настройка | |
| Distinct | Возвращает последовательность без повторяющихся элементов. |
| Except | Возвращает последовательность, представляющую собой разность двух других последовательностей. |
| Intersect | Возвращает последовательность, представляющую собой пересечение двух других последовательностей. |
| Union | Возвращает последовательность, представляющую собой объединение двух других последовательностей. |
В первом примере, используем LINQ-запрос для того, что бы из заданного массива выбрать диапазон чисел с условием, что элемент массива будет больше 1, но меньше 9 включительно:
static void Main(string[] args)
{
int[] numbers = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
var nums = from i in numbers
where i > 1 i <= 9
select i;
foreach (var n in nums)
{
Console.Write(n + " ");
}
Console.ReadLine();
}
(рис 11.2) Результат выполнения LINQ - запроса по выборке чисел
Рассмотрим подробнее строчку с LINQ-запросом:
var nums = from i in numbers
where i > 1 i <= 9
select i;
nums - это неявный тип переменной, которой присваивается результат выполнения LINQ -запроса; i - это переменная диапазона; numbers - источник данных.
Этот же LINQ - запрос (как и любой другой) можно реализовать с помощью лямбда-выражения:
var nums = numbers.Where(i => i > 1 i <= 9);
Также, в фрагменте кода с оператором select, можно вызывать функцию или реализованный ранее метод, и тогда переменной nums - будет присвоен результат выполнения функции или метода. Как показано в примере ниже переменная nums будет содержать результаты работы функции Math.Sqrt которая вычисляет квадратный корень из массива numbers:
var nums = from i in numbers
where i > 1 i <= 9
select Math.Sqrt(i);
(рис 11.3) Результат выполнения LINQ - запроса с использованием функции Math.Sqrt()
Также, с помощью LINQ - запросов можно обращаться к другим источникам данных, таким как типизированные списки List<T>, объекты, которых содержат простые экземпляры классов. В нашем случае - это объекты класса Employee:
public class Employee
{
public int id {get;set;}
public string firstname { get; set; }
public string lastname {get;set;}
public double salary {get;set;}
public static List<Employee> GetEmployees()
{
List<Employee> emp = new List<Employee>
{
new Employee { id = 1, firstname = "Иван", lastname = "Иванов",salary=3500 },
new Employee { id = 2, firstname = "Сергей", lastname = "Сидоров", salary = 1710 },
new Employee { id = 3, firstname = "Алексей", lastname = "Петренко", salary = 2115.3 },
new Employee { id = 4, firstname = "Александр", lastname = "Иванов", salary = 1411.1 }
};
return (emp);
}
}
static void Main(string[] args)
{
var employees = Employee.GetEmployees();
var employee = from i in employees
where i.lastname=="Иванов"
select i;
foreach (var n in employee)
{
Console.WriteLine(n.id + " " + n.firstname +" "+n.lastname +" "+ n.salary);
}
Console.ReadLine();
}
В методе Main() получаем список сотрудников с помощью метода GetEmployees() который возвращает список сотрудников, содержащийся в типизированной коллекции List<Employee>. LINQ-запрос получает список сотрудников, у которых фамилия "Иванов" (Рис. 11.4)
(рис 11.4) Результат выполнения LINQ - запроса с использованием объектов класса Employee
PLINQ (Параллельный LINQ) - это распараллеленная реализация LINQ. Запросы PLINQ схожи с не параллельными запросами LINQ, основное отличие этих запросов заключается в том, что PLINQ полностью использует возможности всех процессоров в системе. Результаты запросов PLINQ, также как и последовательные запросы LINQ, возвращают тип IEnumerable<T>, данный результат достигается путем разделения источника данных на сегменты и параллельной обработки запроса каждого сегмента в отдельном рабочем потоке на нескольких процессорах.
Благодаря PLINQ в значительной степени увеличивается производительность по сравнению с устаревшим кодом. Однако параллелизм может привести к появлению собственных сложностей, и не все операции запросов выполняются быстрее в PLINQ.
Все основные методы PLINQ содержаться в классе System.Linq.ParallelEnumerable - пространства имен System.Linq компилируются в сборку System.Core.dll. Данный класс включает в себя, реализации всех стандартных операторов запросов, поддерживаемых LINQ to Objects.
Кроме стандартных операторов-запросов класс ParallelEnumerable содержит набор методов, которые обеспечивают поведения, характерные для параллельного выполнения. Эти методы представлены в Табл. 11.2.
| Методы класса ParallelEnumerable | Описание |
|---|---|
AsParallel |
Точка входа для PLINQ. Указывает на необходимость параллелизации остальной части запроса, если это возможно. |
AsSequential<TSource> |
Указывает на необходимость последовательного выполнения остальной части запроса как непараллельного запроса LINQ. |
AsOrdered |
Указывает, что PLINQ должен сохранить порядок исходной последовательности для остальной части запроса или до тех пор, пока порядок не будет изменен. |
AsUnordered<TSource> |
Указывает, что PLINQ не должен сохранять порядок исходной последовательности для остальной части запроса. |
WithCancellation<TSource> |
Указывает, что PLINQ должен периодически отслеживать состояние предоставленного токена отмены и отменять выполнение при запросе. |
WithDegreeOfParallelism<TSource> |
Указывает максимальное количество процессоров, которое должен использовать PLINQ для параллелизации запроса. |
WithMergeOptions<TSource> |
Предоставляет подсказку о том, как PLINQ должен, если это возможно, выполнять слияние параллельных результатов в одну последовательность в потоке-потребителе. |
WithExecutionMode<TSource> |
Указывает, должен ли PLINQ выполнять параллелизацию запроса, даже если согласно поведению по умолчанию он будет выполняться последовательно. |
ForAll<TSource> |
Многопоточный метод перечисления, который в отличие от итерации результатов запроса позволяет обрабатывать результаты параллельно без предварительного слияния в поток-потребитель. |
Перегрузка Aggregate |
Уникальная для PLINQ перегрузка, обеспечивающая промежуточное агрегирование локальных частей потока, и предоставляющая функцию окончательного агрегирования для объединения результатов всех частей. |
Метод AsParallel() - это некая входная точка в использовании запросов PLINQ. Он преобразует последовательность данных в ParallelQuery. Механизм LINQ обнаруживает использование ParallelQuery в качестве источника в запросе и переключается на выполнение PLINQ автоматически. Метод AsParallel() несколько типов перегрузки, которые представлены ниже:
IEnumerable <TSource> и возвращает экземпляр ParallelQuery <TSource>, который может быть использован в качестве основы запроса PLINQ:
public static ParallelQuery<TSource> AsParallel<TSource>( this IEnumerable<TSource> source )
ParallelQuery из IEnumerable и предназначен для поддержки унаследованных коллекций, таких как System.Collections.ArrayList. Объект ParallelQuery не является строго типизированным и не может использоваться в качестве основы запроса PLINQ без преобразования в ParallelQuery:
public static ParallelQuery AsParallel( this IEnumerable source )
Оба типа возвращают исключение вида ArgumentNullException.
Что бы преобразовать LINQ в PLINQ, в запросе LINQ достаточно вызвать метод AsParallel() в LINQ запросе. В следующем примере находятся числа в диапазоне от 1 до 100000, кратные двум с помощью неоптимизированного параллельного алгоритма:
var source = Enumerable.Range(1, 100000);
var parallelQuery = from num in source.AsParallel()
where num % 2 == 0
select num;
foreach (var n in parallelQuery)
{
Console.WriteLine(n);
}
Console.ReadLine();
Этот же запрос можно было записать с использованием лямда-выражения:
var parallelQuery = source.AsParallel().Where(n => n % 2 == 0).Select(n => n);
(рис 11.5) Результаты выполнения запроса PLINQ
Существует ряд причин, по которым, PLINQ не используется по умолчанию. Первое, использование PLINQ целесообразно использовать при наличии значительного количества вычислительных задач, распределенных по рабочим потокам. Многие запросы LINQ выполняются очень быстро, и распараллеливание не только не нужно, но и нецелесообразно, так как накладные расходы на разделение данных, объединения результатов и координацию дополнительных потоков могут, на самом деле, только ухудшить производительность. В следующем списке описаны формы запросов, которые PLINQ по умолчанию будет выполнять в последовательном режиме:
Where, индексированный SelectMany или ElementAt после оператора упорядочивания или фильтрации, который удаляет или переупорядочивает исходные индексы.
Take, TakeWhile, Skip, SkipWhile и в которых индексы в исходной последовательности не находятся в исходном порядке.
Zip или SequenceEquals за исключением, когда один из источников данных содержит изначально упорядоченный индекс, а другие источники данных можно проиндексировать (то есть массив или IList(T)).
Concat, за исключением случая, если они применяются к индексируемым источникам данных.
Reverse, за исключением случая, если они применяются к индексируемым источникам данных. Для получения официальных документов о завершении программы дополнительного профессионального образования (удостоверения о повышении квалификации, дипломов о профессиональной переподготовке и MBA) необходимо предоставить:
Внимание! Вы можете не заказывать доставку бумажной версии официального документы, а скачать его в электронном виде и распечатать самостоятельно. Информация о выданном документе в течение 1 месяца загружается в Федеральную информационную систему «Федеральный реестр сведений о документах об образовании и (или) о квалификации, документах об обучении» - ФИС ФРДО.
Доступ на новый сайт осуществляется с использованием адреса электронной почты, который был указан вами при регистрации на "старом". Мы постарались перенести все ваши данные с прежнего ресурса, однако не исключена вероятность потери части информации.
При возникновении проблемы со входом, воспользуйтесь функцией сброса пароля
Если вы обнаружите несоответствия, пожалуйста, сообщите нам.