Приветствую всех, сегодня начнем разбираться с Linq, урок будет длинным но надеюсь продуктивным и позволит вам разобраться с ними, надеюсь хотя бы вопросов станет при использовании у вас меньше. А так же поймете всю мощь и скорость проектирования с помощью Linq.
Когда не было линков, разработчики использовали в своих приложениях в основном колекци, и это превращало большие проекты в сущий кошмар, для тех кто его поддерживал. При появлении linq сократилось время разработки и код программ мог уменьшиться аж в 10 раз, а понимание и читаемость кода увеличиться, потому сейчас 2018 год и использование linq повсеместно в разработке.
Давайте рассмотрим как создавали код до линков:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
public class Student { public string LastName { get; set; } public string Group { get; set; } } public class Program { public static void Main() { var students = new List<Student> { new Student { LastName="Andrey", Group="ПМТ-1" }, new Student { LastName="Sergey", Group="ПМТ-1" }, new Student { LastName="Alexandr", Group="ПК-1"}, new Student { LastName="Vladimir", Group="ПК-1"} }; var result = new List<string>(); foreach (var s in students) if (s.Group == "ПК-1") result.Add(s.LastName); foreach (var name in result) Console.WriteLine(name); Console.ReadKey(); } } //Alexandr //Vladimir |
В коде ничего сложного, просто мы создали класс студентов и поместили в коллекции самих студентов по группам. И осуществили поиск в коллекции в посоответствию если есть студенты в группе ПК-1, то поместить их в другу коллекцию и вывести их имена.
А теперь давайте рассмотрим тот же код но используем Linq:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
public class Student { public string LastName { get; set; } public string Group { get; set; } } public class Program { public static void Main() { var students = new List<Student> { new Student { LastName="Andrey", Group="ПМТ-1" }, new Student { LastName="Sergey", Group="ПМТ-1" }, new Student { LastName="Alexandr", Group="ПК-1"}, new Student { LastName="Vladimir", Group="ПК-1"} }; var result = students.Where(z => z.Group == "ПК-1").Select(z => z.LastName).ToList(); foreach (var name in result) Console.WriteLine(name); Console.ReadKey(); } } //Alexandr //Vladimir |
Метод ToList будет выполняться первым, вторым Select, а третьим Where. Потому что linq основан на так называемых ленивых методах, с использованием лямбда-выражений. Это означает что метод будет работать не в строке ниже:
1 |
var result =students.Where(z => z.Group == "ПК-1").Select(z => z.LastName).ToList(); |
А когда мы воспользуемся перечислением в foreach и только тогда мы перейдем в метод ToList который является обычным методом, за тем Select, а из него в Where которые являются ленивыми методами, и так будет происходит по каждому элементу пока они не закончатся.
1 2 |
foreach (var name in result) Console.WriteLine(name); |
Суть ленивых методов заключается в том, что один метод по элементно вызывает каждый раз другой, и в такой взаимосвязи они оба отрабатывают по каждому элементу. А вызов методов ленивых начинается с последнего метода, то есть с конца. Стоит запомнить что ленивые методы вызывают только обычные методы, сами они не будут отрабатывать, на то они и ленивые.
Как видите код программы сократился, при том что логика программа не большая, а понимание происходящего в коде программы стало проще, пошутил пока возможно вы еще ничего не поняли, но я объясню каждую команду. А вы сможете применять linq в своих приложениях.
Хочу показать еще пример классической реализации:
1 2 3 4 5 6 7 8 9 10 |
public List<int> GetLet() { var resualt = new List<int>(); for(int i=0; i<let.Length; i++) { if (let[i].IsNew) resualt.Add(let[i].Id); } return resualt; } |
И тот же пример с Linq:
1 2 3 4 |
public IEnumerable<int> GetLet() { return let.Where(l => l.IsNew).Select(l => l.Id); } |
В Linq находиться интерфейс последовательности IEnumerable<T> Последовательность — это абстракция чего-то, что можно начать перечислять и переходить от текущего элемента к следующему пока последовательность не закончится (или не прервется принудительно).
Массивы, List, Dictionary, HashSet — все эти коллекции реализуют интерфейс последовательности IEnumerable<T>.
From так называемое предложение, указывает на источник данных, в лямбда-выражениях не используется.
1 |
from student in faculty |
Where Применяет фильтр, используется для фильтрации перечисляемого. Он принимает в качестве параметра функцию-предикат и возвращает новое перечисляемое, состоящее только из тех элементов исходного перечисляемого, на которых предикат вернул true, так же можно использовать в запросе логические операторы.
1 |
where student.Name == "Andrey" |
1 2 |
.Where(x => x.Length == words.Select(y => y.Length).Max()).First(); //находим максимальную длину массива слов |
orderby Упорядочивание, сортирует или упорядочивает элементы возвращаемой последовательности к примеру по алфавиту:
От А до Я
1 |
orderby student.Name ascending |
1 |
mass = mass.OrderBy(worker => worker.Name).ToArray<Worker>(); |
mass= массив
worker = любое вымышленое название, которое будет использовано внутри выражения.
.Name свойство в классе Worker;
Worker =класс, с полями и методами.
От Я до А
1 |
orderby student.Name descending |
group Группирования на основе ключа. Позволяет группировать, В примере ниже, я поместил всех Андреев в отдельную группу, и вывел их в консоль
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
static void Main() { string[] student = {"Andrey","Sergey,","Alexandr","Andrey","Dasha","Andrey","Kiril" }; var searchStudent = from cust in student group cust by cust.Equals("Andrey"); foreach (var name in searchStudent) { if(name.Key) foreach (var customer in name) Console.WriteLine(" {0}", customer); } Console.ReadKey(); } |
Select Задает тип возвращаемых элементов.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
static void Main() { List<int> Scores = new List<int>() { 97, 92, 81, 60 }; var queryHighScores = from score in Scores where score > 80 select score; foreach (int i in queryHighScores) { Console.Write(i + " "); } Console.ReadKey(); } |
Выражение запроса должно оканчиваться предложением Select или group
Методы Linq:
Take обрезает последовательность после указанного количества элементов.
IEnumerable<T> Take(this IEnumerable<T> items, int count)
Skip обрезает последовательность, пропуская указанное количество элементов с начала.
IEnumerable<T> Skip(this IEnumerable<T> items, int count)
ToArray и ToList используются для преобразования IEnumerable<T> в массив T[] или в List<T>, соответственно.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
static void Main() { int[] num = { 1, 2, 3, 4, 5, 6, 7, 8, 9 }; IEnumerable<int> even = num.Where(x => x % 2 == 0); IEnumerable<int> squares = even.Select(x => x * x); IEnumerable<int> squaresWithoutOne = squares.Skip(1); IEnumerable<int> secondAndThirdSquares = squaresWithoutOne.Take(2); int[] result = secondAndThirdSquares.ToArray(); foreach (var i in result) Console.WriteLine(i); Console.ReadKey(); } |
Ключевые слова синтаксиса запроса:
from — Указание источника данных и переменной диапазона (аналогично переменной итерации).
where — Фильтрация исходных элементов на основе одного или нескольких логических выражений, разделенных операторами AND и OR ( && или || ).
select — Указание типа и формы, которую будут иметь элементы в возвращенной последовательности при выполнении запроса.
group — Группировка результатов запроса по заданному ключевому значению.
into — Предоставление идентификатора, который может служить ссылкой на результаты предложения join, group или select.
orderby — Сортировка результатов запроса по возрастанию или убыванию в компараторе по умолчанию для типа элемента.
join — Соединение двух источников данных на основе вычисления равенства между двумя заданными парными критериями.
let — Ввод переменной диапазона для хранения результатов вложенного выражения в выражении запроса.
in — Контекстно-зависимое ключевое слово в предложении join.
on — Контекстно-зависимое ключевое слово в предложении join.
equals — Контекстно-зависимое ключевое слово в предложении join.
by — Контекстно-зависимое ключевое слово в предложении group.
ascending — Контекстно-зависимое ключевое слово в предложении orderby.
descending — Контекстно-зависимое ключевое слово в предложении orderby.
Ключевые слова синтаксиса методов:
Объединение
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 — Возвращает последовательность, представляющую собой объединение двух других последовательностей.