net framework и С#, весна 2015: linq

39
Толстиков Никита [email protected] LINQ 05.07.2022 1 Generics

Upload: cs-center

Post on 15-Apr-2017

418 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Net Framework и С#, весна 2015: LINQ

Толстиков Никита[email protected]

LINQ

02.05.2023 1Generics

Page 2: Net Framework и С#, весна 2015: LINQ

План лекции

• Введение• Средства реализации • Структура и методы LINQ• Ленивые вычисления

02.05.2023 Толстиков Никита 2LINQ

Page 3: Net Framework и С#, весна 2015: LINQ

Пример• Дано :

• Найти:– Из 10 самых здоровых монстров с четными Id cтроку максимальной длинны состоящую из имени монстра и его здоровья

02.05.2023 Толстиков Никита 3LINQ

var monsters = new MonsterGenerator().Take(50).ToList();

Page 4: Net Framework и С#, весна 2015: LINQ

Итеративный подход

02.05.2023 Толстиков Никита 4LINQ

static string IterativeMaxNameLength(List<Monster> monsters) { var filteredMonster = new List<Monster>(); foreach (var monster in monsters) { if (monster.Id % 2 == 0) { filteredMonster.Add(monster); } } filteredMonster.Sort(new MonstersHealthComparer()); int max = int.MinValue; string resultString = ""; for (int i = Math.Max(0, filteredMonster.Count - 10); i < filteredMonster.Count; i++) { string currentString =

String.Format("{0} {1}", filteredMonster[i].Name, filteredMonster[i].Health); var currentCoef = currentString.Length; if (currentCoef > max) { max = currentCoef; resultString = currentString; } } return resultString; }

Page 5: Net Framework и С#, весна 2015: LINQ

LINQ

02.05.2023 Толстиков Никита 5LINQ

private static string LinqMaxNameLength(IEnumerable<Monster> monsters) { return monsters.Where(monster => monster.Id % 2 == 0) .OrderByDescending(monster => monster.Health) .Take(10) .Select(monster => String.Format("{0} {1}", monster.Name, monster.Health)) .OrderByDescending(s => s.Length) .First(); }

Page 6: Net Framework и С#, весна 2015: LINQ

Почему работает?• Неявно типизированные

локальные переменные• Синтаксис инициализации

объектов• Lambda-функции• Extension-методы• Анонимные типы

02.05.2023 Толстиков Никита 6LINQ

Page 7: Net Framework и С#, весна 2015: LINQ

Почему работает?• Синтаксис инициализации

объектов• Extension-методы• Неявно типизированные

локальные переменные• Анонимные типы• Lambda-функции

02.05.2023 Толстиков Никита 7LINQ

Page 8: Net Framework и С#, весна 2015: LINQ

Неявная типизация

– Компилятор сам выводит тип и подставляет его во время компиляции

– Позволяет сократить кол-во написанного кода

– Неявно типизировать можно только локальные переменные или типовые параметры

02.05.2023 Толстиков Никита 8LINQ

var dict = new Dictionary<string, List<Tuple<Monster, string, int>>>();

Page 9: Net Framework и С#, весна 2015: LINQ

Анонимные типы

– Компилятор может вывести поля типа только внутри метода

– Не стоит передавать в методы– Нельзя реализовывать интерфейсы– Нельзя создавать методы–Можно использовать как ключи в

словаре02.05.2023 Толстиков Никита 9LINQ

var nameFamily = new {Name = "Иван", Family = "Иванов"};Console.WriteLine(nameFamily.GetType()); //<>f__AnonymousType0`2[System.String, System.String]Console.WriteLine("{0} {1}", nameFamily.Name, nameFamily.Family);

Page 10: Net Framework и С#, весна 2015: LINQ

Lambda-функции• Функции которыми можно

манипулировать как переменными• Для введени используется символ

‘=>’• Синтаксис:

(<arguments>) => { <code> }

– все скобки могут быть опущены02.05.2023 Толстиков Никита 10LINQ

Page 11: Net Framework и С#, весна 2015: LINQ

Lambda-функции• Функции которыми можно

манипулировать как переменными• Для введени используется символ

‘=>’• Синтаксис:

(<arguments>) => { <code> }

– все скобки могут быть опущены02.05.2023 Толстиков Никита 11LINQ

Page 12: Net Framework и С#, весна 2015: LINQ

Lambda-функции• Пример:

– оператор ‘=>’ может читаться как «goes to»

02.05.2023 Толстиков Никита 12LINQ

List<int> elements = new List<int>() { 10, 20, 31, 40 };// ... Find index of first odd element.int oddIndex = elements.FindIndex(x => x % 2 != 0);Console.WriteLine(oddIndex);

Page 13: Net Framework и С#, весна 2015: LINQ

Lambda-функции

Какой тип у lambda-функции?

02.05.2023 Толстиков Никита 13LINQ

Page 14: Net Framework и С#, весна 2015: LINQ

Делегат• Тип описывающий метод с определенной

сигнатурой:

• Инициализация объекта типа:– через метод

– через lambda-фунцию

02.05.2023 Толстиков Никита 14LINQ

public delegate void WriteLog(string message);

public static void FileWriteLog(string message){

//Write log to file}...WriteLog method = FileWriteLog;

method = log => { Console.WriteLine("log"); };

Page 15: Net Framework и С#, весна 2015: LINQ

Делегат• Исполнить делегат или выполнить

метод на который он указывает:

– лямбда функция запоминает контекст– у типа делегат переопределен оператор ()– аналогично можно вызвать метод Invoke()

02.05.2023 Толстиков Никита 15LINQ

WriteLog method = FileWriteLog;method.Invoke("FileLog"); //Вывести лог в файл

method = log => { Console.WriteLine("log"); };method.Invoke("ConsoleLog"); //Вывести лог на консоль

method("SomeLog"); //Вывести лог на консоль

Page 16: Net Framework и С#, весна 2015: LINQ

Lambda-функции• Типы lambda-функций:– процедуры:

–функции:

02.05.2023 Толстиков Никита 16LINQ

public delegate void Action<in T, in T1 ...>(T obj, T1 obj1 ...);

public delegate TResult Action<in T, in T1 ..., out TResult>

(T obj, T1 obj1 ...);

Page 17: Net Framework и С#, весна 2015: LINQ

Lambda-функции• Пример:

02.05.2023 Толстиков Никита 17LINQ

// Use implicitly typed lambda expression.// ... Assign it to a Func instance.Func<int, int> func1 = x => x + 1;// Use lambda expression with statement body.Func<int, int> func2 = x => { return x + 1; };// Use formal parameters with expression body.Func<int, int> func3 = (int x) => x + 1;// Use parameters with a statement body.Func<int, int> func4 = (int x) => { return x + 1; };// Use multiple parameters.Func<int, int, int> func5 = (x, y) => x * y;// Use no parameters in a lambda expression.Action func6 = () => Console.WriteLine();// Use delegate method expression.Func<int, int> func7 = delegate(int x) { return x + 1; };// Use delegate expression with no parameter list.Func<int> func8 = delegate { return 1 + 1; };

Page 18: Net Framework и С#, весна 2015: LINQ

Почему работает?

02.05.2023 Толстиков Никита 18LINQ

Page 19: Net Framework и С#, весна 2015: LINQ

LINQ

02.05.2023 Толстиков Никита 19LINQ

Page 20: Net Framework и С#, весна 2015: LINQ

Группы операций• Фильтры (Where)• Проекции (Select, SelectMany)• Сортировка (OrderBy)• Групировки (GroupBy)• Оперции над множествами (Distinct, Union, Intersect, Except)

• Преобразования (ToList, ToDictionary)• Элементы (First, FirstOrDefault, Last)• Кванторы (All, Any)• Агрегаторы (Count,Sum,Max/Min, Aggregate)

02.05.2023 Толстиков Никита 20LINQ

Page 21: Net Framework и С#, весна 2015: LINQ

Фильтрыstring[] digits = { "zero", "one", "two",

"three", "four", "five", "six", "seven", "eight", "nine" };

// Фильтр foreachvar oddsDigits = digits.Where(digit => digit.Length % 2 == 0);

// Фильтр foreach c индексомvar shortDigits = digits.Where((digit, index) => digit.Length <

index);

02.05.2023 Толстиков Никита 21LINQ

Page 22: Net Framework и С#, весна 2015: LINQ

Проекции

02.05.2023 Толстиков Никита 22LINQ

• Позволяют получать из одних объектов другие

• SelectMany схлопывает последовательности в одну://return IEnumerable<char>

var digitChars = digits.SelectMany( stringDigit => stringDigit.ToCharArray());

//return IEnumerable<int>var intDigits = digits.Select( stringDigit => ConvertStringDigitToInt(stringDigit));

Page 23: Net Framework и С#, весна 2015: LINQ

Сортировки

02.05.2023 Толстиков Никита 23LINQ

• OrderBy упорядочивает последовательность и возвращает IOrderedEnumerable

• Для сортировки по нескольким значениям лучше использовать ThenBy:monsters.OrderBy(monster => monster.Id)

.ThenBy(monsters => monsters.Health);

var monsters = new MonsterGenerator().Take(50);

monsters.OrderBy(monster => monster.Id);monsters.OrderByDescending(monster => monster.Health);

Page 24: Net Framework и С#, весна 2015: LINQ

Группировки

02.05.2023 Толстиков Никита 24LINQ

• GroupBy групирует элементы по ключу и возвращает:

IEnumerable<IGrouping<TKey, TSource>>

– первый параметр – это функция определяющая ключ

– перегрузки позволяют манипулировать группами (проецировать, фильтровать, выбирать свой компаратор и т.д.)

Page 25: Net Framework и С#, весна 2015: LINQ

Группировки

02.05.2023 Толстиков Никита 25LINQ

var groups = monsters.GroupBy(monster => { if (monster.Health < 10) { return 0; }else if (10 <= monster.Health && monster.Health < 70) { return 10; } else if (70 <= monster.Health && monster.Health < 100) { return 70; } else { return 100; } });

foreach (var group in groups) { Console.WriteLine("{0} : {1}", group.Key, group.Count()); }

Page 26: Net Framework и С#, весна 2015: LINQ

Трансформаторы

02.05.2023 Толстиков Никита 26LINQ

• ToList – трансформирует перечисление в List:

• ToDicitionary трансформирует Ienumerable в словарь:

• OfType элементы IEnumerable к типу параметра:

List<Monster> monsters = new MonsterGenerator().Take(50).ToList();

Dictionary<string, Monster> monstersDicitionary = monsters.ToDictionary(monster =>

monster.Name);

object[] numbers = { null, 1.0, "two", 3, "four", 5, "six", 7.0 };

var doubles = numbers.OfType<double>();

Page 27: Net Framework и С#, весна 2015: LINQ

Элементы

02.05.2023 Толстиков Никита 27LINQ

• First/Last - возвращает первый/последний элемент из последовательности удовлетворяющий условию:

– выбрасывает InvalidOperationException, если таких элементов нет

• FirstOrDefault/LastOrDefault – аналогичны, но если элемент не найден – то возвращается default(T)

monsters.First(monster => monster.Name.Length > 10);

Page 28: Net Framework и С#, весна 2015: LINQ

Кванторы

02.05.2023 Толстиков Никита 28LINQ

• Проверяют, что все (All) или хотя бы один (Any) элемент из последовательности удовлетворяет условию:

monsters.Where(monster => monster.Name.Length > 6) .Any(monster => monster.Health > 75);

Page 29: Net Framework и С#, весна 2015: LINQ

Агрегаторы

02.05.2023 Толстиков Никита 29LINQ

• Сворачивают все элементы последовательности в один, находя максимум, минимум, количество элементов или сумму последовательности:

• Aggregate – применяет функцию агрегатор на последовательности:

monsters.Where(monster => monster.Name.Length > 6) .Count(monster => monster.Health > 75);

monsters.Where(monster => monster.Name.Length > 6) .Max(monster => monster.Health);

//вернет все имена монстров в одной строке разделенные пробеломmonsters.Aggregate("Monsters: ", (seed, monster) => seed + " " + monster.Name);

Page 30: Net Framework и С#, весна 2015: LINQ

Подитог

02.05.2023 Толстиков Никита 30LINQ

• LINQ – привносит функциональный стиль в ООП

• Позволяет писать запросы к различным источникам с удобным синтаксисом

• Имеет множество функций и их перегрузок

• Поддерживает ленивые вычисления

Page 31: Net Framework и С#, весна 2015: LINQ

Ленивые вычисления• Вычисления откладываются до тех

пор пока не понадобится их результаты

• Достаточно описать зависимости функций друг от друга и не следить за тем, чтобы не осуществлялось «лишних вычислений»

02.05.2023 Толстиков Никита 31LINQ

Page 32: Net Framework и С#, весна 2015: LINQ

Пример

02.05.2023 Толстиков Никита 32LINQ

monsters = new List<Monster> { new Monster(1), new Monster(50), new Monster(51) };

var monsterIdMoreThan50 = monsters.Where(monster => monster.Id >= 50);

monsters.Add(new Monster(100));

Console.WriteLine(monsterIdMoreThan50.Count()); //Output: 3

Page 33: Net Framework и С#, весна 2015: LINQ

yield return• Ставит метод на «паузу»

возвращая значение• При следующем вызове, метод

продолжит исполнение с последнего yield return

02.05.2023 Толстиков Никита 33LINQ

Page 34: Net Framework и С#, весна 2015: LINQ

yield return

02.05.2023 Толстиков Никита 34LINQ

public class YieldingClass { public IEnumerable<int> GetFibonachiSequence() { yield return 1;

yield return 1; yield return 2; yield return 3; yield return 5; } }

Page 35: Net Framework и С#, весна 2015: LINQ

yield return

02.05.2023 Толстиков Никита 35LINQ

//Output: 1 1 2foreach (var number in fibonachi){

Console.WriteLine(number);count++;if (count == 3) break;

}

//Output: 3 5foreach (var number in fibonachi){

Console.WriteLine(number);}

Page 36: Net Framework и С#, весна 2015: LINQ

yield return

02.05.2023 Толстиков Никита 36LINQ

[CompilerGenerated]private sealed class YieldingEnumerator : IEnumerable<object>, IEnumerator<object>{

// Fieldsprivate int state;private int current;public YieldingClass owner;private int initialThreadId;

// Methods[DebuggerHidden]public YieldingEnumerator(int state);private bool MoveNext();[DebuggerHidden]IEnumerator<int> IEnumerable<int>.GetEnumerator();[DebuggerHidden]IEnumerator IEnumerable.GetEnumerator();[DebuggerHidden]void IEnumerator.Reset();void IDisposable.Dispose();

// Propertiesobject IEnumerator<object>.Current{ [DebuggerHidden] get; }

object IEnumerator.Current{ [DebuggerHidden] get; }

}

Page 37: Net Framework и С#, весна 2015: LINQ

Состояния

02.05.2023 Толстиков Никита 37LINQ

Метод GetFibonachiSequence() просто возвращает YieldingEnumerator, и устанавливает его state в состояние -2

Какждый enumerator поддерживают состояния, как число:

-2:  Инициализирован как Enumerable-1:  Закрыт0:  Инийиализирован как Enumerator1-n:  Индекс yield return оператора в GetFibonachiSequence() методе

Если от объекта YieldingClass, вызвать повторно GetFibonachiSequence(), то вернется новый YieldingEnumerator

Page 38: Net Framework и С#, весна 2015: LINQ

Итог

02.05.2023 Толстиков Никита 38LINQ

• С# предлагает набор инструментов для реализации ленивого вычисления

• Ленивые вычисления дают возможность обрабатывать данные порциями

• LINQ – отличный модуль для написания запросов и составления pipline’ов

Page 39: Net Framework и С#, весна 2015: LINQ

The End

02.05.2023 Толстиков Никита 39LINQ