Приветствую всех, сегодня начнем разбираться с Linq, урок будет длинным но надеюсь продуктивным и позволит вам разобраться с ними, надеюсь хотя бы вопросов станет при использовании у вас меньше. А так же поймете всю мощь и скорость проектирования с помощью Linq.
Когда не было линков, разработчики использовали в своих приложениях в основном колекци, и это превращало большие проекты в сущий кошмар, для тех кто его поддерживал. При появлении linq сократилось время разработки и код программ мог уменьшиться аж в 10 раз, а понимание и читаемость кода увеличиться, потому сейчас 2018 год и использование linq повсеместно в разработке.
Давайте рассмотрим как создавали код до линков:
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:
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 основан на так называемых ленивых методах, с использованием лямбда-выражений. Это означает что метод будет работать не в строке ниже:
var result =students.Where(z => z.Group == "ПК-1").Select(z => z.LastName).ToList();
А когда мы воспользуемся перечислением в foreach и только тогда мы перейдем в метод ToList который является обычным методом, за тем Select, а из него в Where которые являются ленивыми методами, и так будет происходит по каждому элементу пока они не закончатся.
foreach (var name in result) Console.WriteLine(name);
Суть ленивых методов заключается в том, что один метод по элементно вызывает каждый раз другой, и в такой взаимосвязи они оба отрабатывают по каждому элементу. А вызов методов ленивых начинается с последнего метода, то есть с конца. Стоит запомнить что ленивые методы вызывают только обычные методы, сами они не будут отрабатывать, на то они и ленивые.
Как видите код программы сократился, при том что логика программа не большая, а понимание происходящего в коде программы стало проще, пошутил пока возможно вы еще ничего не поняли, но я объясню каждую команду. А вы сможете применять linq в своих приложениях.
Хочу показать еще пример классической реализации:
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:
public IEnumerable<int> GetLet()
{
return let.Where(l => l.IsNew).Select(l => l.Id);
}
В Linq находиться интерфейс последовательности IEnumerable<T> Последовательность — это абстракция чего-то, что можно начать перечислять и переходить от текущего элемента к следующему пока последовательность не закончится (или не прервется принудительно).
Массивы, List, Dictionary, HashSet — все эти коллекции реализуют интерфейс последовательности IEnumerable<T>.
From так называемое предложение, указывает на источник данных, в лямбда-выражениях не используется.
from student in faculty
Where Применяет фильтр, используется для фильтрации перечисляемого. Он принимает в качестве параметра функцию-предикат и возвращает новое перечисляемое, состоящее только из тех элементов исходного перечисляемого, на которых предикат вернул true, так же можно использовать в запросе логические операторы.
where student.Name == "Andrey"
.Where(x => x.Length == words.Select(y => y.Length).Max()).First(); //находим максимальную длину массива слов
orderby Упорядочивание, сортирует или упорядочивает элементы возвращаемой последовательности к примеру по алфавиту:
От А до Я
orderby student.Name ascending
mass = mass.OrderBy(worker => worker.Name).ToArray<Worker>();
mass= массив
worker = любое вымышленое название, которое будет использовано внутри выражения.
.Name свойство в классе Worker;
Worker =класс, с полями и методами.
От Я до А
orderby student.Name descending
group Группирования на основе ключа. Позволяет группировать, В примере ниже, я поместил всех Андреев в отдельную группу, и вывел их в консоль
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 Задает тип возвращаемых элементов.
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>, соответственно.
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 — Возвращает последовательность, представляющую собой объединение двух других последовательностей.
