Advanced C#. Part 2

Preview:

Citation preview

eleks.com eleks.com

Advanced C#. Part 2Events and Delegates. Anonimous methods. Lamda Expressions. LINQ

Делегати

public abstract class Delegate : ICloneable, ISerializable

Делегати

Делегати – вказівники на методи, які інкапсулюють справжні вказівники і надають

зручні сервіси для роботи з ними.

Делегати є об’єктами типу System.Delegate або System.MulticastDelegate.

System.Delegate (obsolete) - тільки одне посилання на метод

System.MulticastDelegate – кілька посилань на метод, які викликаються по ланцюжку

При описі делегати ми вказуємо прототип методу, на який будуть посилатись

екземпляри даного делегата.

public delegate void MyDelegate (string s);

де MyDelegate – назва делегата (назва типу), void – тип що мають повертати функції,

string – тип аргумента функцій

Сам по собі делегат являється типом і жодних посилань на метод містити не може і,

відповідно, не може використовуватись для звернення до них.

Оголошення делегата

MyDelegate delegate1 = new MyDelegate(MyHandler);

Де MyDelegate – тип делегата, delegate1 – екземпляр делегата, який буде створений

в результаті виконання конструкції, MyHendler – метод, на який буде посилатись

делегат.

Після створення делегата ми можемо звертатись до методів, на які він посилається.

До делегата можна звертатись як до самого метода:

delegate1(“Hello World”);

Створення екземпляра делегата

eleks.com

Демонстрація 1• Найпростіший приклад роботи з делегатами

Методи в .Net діляться на статичні (static) і екземплярні (instance).

Щоб викликати екземплярний метод делегату потрібно знати посилання на об’єкт до

якого прив’язаний конкретний метод. Це посилання зберігається в самому обєкті

делегата і вказується при його створенні.

MyDelegate myDelegate = new MyDelegate(myClass.MyHandler);

Де myClass – посилання на екземпляр обєкта,який повинен використовуватися при

зверненні до методу MyHandler

Делегат і екземплярні методи

eleks.com

Демонстрація 2• Делегат і екземплярний метод

• Коваріантність – дозволяє присвоїти делегату метод, тип результату якого може

бути клас дочірній до класу, вказаного в делегаті.

• Контрваріантність - дозволяє присвоїти делегату метод, тип результату якого

може бути клас батьківський до класу, вказаного в делегаті.

Коваріантність і контрваріантність

Властивості

Щоб викликати екземплярний метод делегату потрібно знати посилання на об’єкт до

якого прив’язаний конкретний метод. Це посилання зберігається в самому обєкті

делегата і вказується при його створенні.

public MethodInfo Method { get; }

public object Target { get; }

MulticastDelegate

Повертає метод, на який посилається делегат

Повертає об’єкт, до якого прив’язаний метод, на який посилається делегат

MulticastDelegate.Method

Якщо делегат мітить більше одного посилання на функцію, то властивість повертатиме

останнє добавлене посилання.

MulticastDelegate.Target

Якщо делегат посилається на статичний метод , то властивість поверне null. Якщо

делегат містить більше одного посилання на функцію, то властивість поверне об’єкт,

пов’язаний з останнім в черзі методом.

MulticastDelegate

eleks.com

Демонстрація 3• Використання властивостей делегата

Equality and Inequality Operators

Оператори рівності ( = = ) і нерівності ( ! = ) дозволяє визначити рівність делегатів, чи

посилаються вони на одну й туж саму функцію. При порівнянні враховується не тільки

метод, на який посилається делегат але й посилання на об’єкт, з яким зв’язаний

метод.

Оператори порівняння делегатів

• Delegate.Combine – обєднує два або більше делегата, створюючи новий делегат,

список викликів якого включає списки обєднуваних делегатів. Вихідні делегати не

модифікуються.

• Delegate.Remove – видаляє список викликів одного делегата з списку викликів

іншого. При цьому створюється новий делегат, список викликів якого являє собою

результат видалення. Вихідні делегати не модифікуються.

Методи делегатів

Ви можете оперувати з делегатами за допомогою звичайних операцій додавання і

віднімання ( +, -, + =, - = ). При цьому компілятор автоматично буде генерувати код, який

звертатиметься до методів Combine i Remove.

• Delegate.DynamicInvoke – дозволяє динамічно звернутись до функцій, повязаних з

делегатом.

Методи делегатів

• MulticastDelegate.GetInvocationList – повертає список делегатів, які знаходяться в

списку виклику делегатів

Корисність:

Коли в списку більше однієї функції, і вони повертають значення. Через Invoke ми

отримаємо тільки значення останньої.

Якщо якась з функцій впаде, то робота метода Invoke буде перервана і решта

функцій буде не викликана.

Методи делегатів

Нульові делегатиmyDelegate = new MyDelegate(SomeMethod); myDelegate -= new MyDelegate(SomeMethod);

В результаті ми отримаємо не пустий делегат, а null

Тому коли значення делегата невідоме варто влаштовувати перевірку

if (myDelegate != null)myDelegate("Hello, World!");

Вбудовані делегати:

delegate bool Predicate();delegate bool Predicate<T1>(T1 parameter1);delegate bool Predicate<T1, T2>(T1 parameter1, T2 paremter2);delegate bool Predicate<T1, T2, T3>(T2 parameter1, T2 paremter2, T3 parameter3);

delegate T Func<T>(T returnType);delegate T Func<T, T1>(T returnType, T1 parameter1);delegate T Func<T, T1, T2>(T returnType, T1 parameter1, T2 paremter2);delegate T Func<T T1, T2, T3>(T returnType, T1 parameter1, T2 paremter2, T3 parameter3);

delegate void Action();delegate void Action<T1>(T1 parameter1);delegate void Action<T1, T2>(T1 parameter1, T2 paremter2);delegate void Action<T1, T2, T3>(T1 parameter1, T2 paremter2, T3 parameter3);

eleks.com

Демонстрація 4• GetInvocationList

eleks.com

Переривчик 5хв

delegate void Anonim(); // Сигнатура делегата

// використовуємо анонімний методAnonim anonim = delegate{

DirectoryInfo dir = new DirectoryInfo("D:\\");foreach (DirectoryInfo d in dir.GetDirectories())Console.WriteLine(d.Name);

};

anonim(); // запускаємо

Анонімні методи

delegate void Anonim2( int start, int finish); // Сигнатура делегата

// використовуємо анонімний метод з параметрамиAnonim2 anonim2 = delegate(int a, int b) {

for (int i = a; i <= b; i++)Console.Write(«Опрацьовано {0} анкет." +

" Залишилось опрацювати {1}\n", i, b-i);};

anonim2(1, 10);

Анонімні методи з параметрами

• Лямбда вираз – це анонімна функція, яка містить вирази та оператори і може бути

використана для створення делегатів або типів дерева виразів.

Параметри => Виконуваний код

( x, y ) => { return x + y }

( x, y ) – параметри, => - лямбда-оператор, { return x + y } - тіло методу

• Інший спосіб створення анонімних функцій, може бути присвоєний делегату

Лямбда вирази

delegate int LambdaDelegate ( int step ); // сигнатура делегата

LambdaDelegate lambdaDel = a => ++a;// LambdaDelegate lambdaDel = (int a) => ++a;

int step = 1;int finish = 10;

while (step <= finish){Console.Write(«Оброблено {0} документів." + " залишилось {1}\n", step, finish - step);

step = lambdaDel(step);}

*Що буде якщо замінити ++а на а++ ?

Лямбда вирази (одиночні)

Лямбда – оператори: (input parameters) => {statements;}

delegate int Power ( int change); // сигнатура делегата

Power lambdaDel = change =>{

if (change != 0)return change * change;

return 0;}

Console.WriteLine( Power ( 10 ) );

Лямбда оператори (блокові вирази)

eleks.com

Summary

Подія – автоматичне оповіщення про те, що сталась якась дія.

Події діють по настпному принципу: обєкт, який проявляє цікавіть до події, реєструє обробник цієї події.

Коли подія стається, викликаються всі зареєстровані обробники цієї події.

Обробники зазвичай представлені делегатами.

Події (Events)

delegate void ClickHandler();

class Button

{

public ClickHandler Click;

void OnMsg(...)

{

switch(msg)

{

case WM_LBUTTONDOWN:

if (Click != null)

Click();

}

}

};

Приклад події на основі делегата

event делегат_події ім’я_події;

Це введене в .NET поле-подія, яку автоматично вводить поле-делегат і два додаткових методі, які його обслуговують.

Події (Events)

eleks.com

Демонстрація 5• Events

eleks.com

Демонстрація 6• Екземплярний метод в якості обробника

public event EventHandler<MyEventArgs> SomeEvent;

Середовище .NET надає вбудований узагальнений делегат EventHandler.

Рекомендується використовувати саме такий спосіб, а не визначати власний делегат.

EventHandler<TEventArgs>

public delegate void EventHandler(

object sender, // Посилання на обєкт, що викликав подію

EventArgs e // Параметри, які описують подію

);

EventArgs не містить жодного поля, яке б передавало корисну інформацію.

Щоб передати додаткову інформацію через EventArgs, вводиться новий клас,

дочірний для нього.

Стандартний делегат

eleks.com

Демонстрація 7• Складний приклад обробника подій

• Дозволяють додавати нові методи в вже існуючі типи, без створення власного

класа.

• Метод розширення має доступ тільки до публічних членів класу.

• Якщо є вбудований метод і розширення, пріоритет надається вбудованому методу

• Методи розширення широко використовуються в LINQ.

Extension methods

Examplepublic static class StringExtension{

public static int WordCount(this string str, char c){

int counter = 0;for (int i = 0; i<str.Length; i++){

if (str[i] == c)counter++;

}return counter;

}}

int i = s.WordCount(c);

eleks.com

Демонстрація 8• Extension methods

• LINQ (Language-Integrated Query) – мова інтегрованих запитів, дозволяє

видобувати інформацію з різних джерел даних.

• Працює з XML, SQL, ADO.NET, .NET Collections….

• Робить запит* частиною мови програмування.

• Компонент .NET Framework 3.5

*Запит – вираз, який дістає дані з джерела даних.

LINQ

OthersC# VB.NET

.NET Language Integrated Query (LINQ)

LINQto SQL

LINQto Objects

LINQto XML

LINQto Datasets

LINQto Entities

LINQ data source providers

ADO.NET support for LINQ

• Найпростіше визначення запита LINQ

from змінна in набір-обєктів

select змінна;

Запити LINQ

• Обєкти використовують цикли і умови

foreach(Customer c in customers) if (c.Region == "UK") ...

• Бази даних використовують SQL

SELECT * FROM Customers WHERE Region='UK'

• XML використовую XPath/XQuery

//Customers/Customer[@Region='UK']

Запити без LINQ

Запити з LINQ

var myCustomers = from c in customers

where c.Region == "UK"

select c;

var goodCusts = (from c in db.Customers

where c.PostCode.StartsWith("GY")

orderby c.Sales descending

select c).Skip(10).Take(10);

Оператори LINQТип оператора запиту Оператори запиту

Обмеження Where, OfType

Проекція Select, SelectMany

Обєднання Join, GroupJoin

Конкатинація Concat

Сортування OrderBy, OrderByDescending, ThenBy, ThenByDescending, Reverse

Установка Distinct, Except, Intersect, Union

Групування GroupBy

Перетворення AsEnumerable, Cast, OfType, ToArray, ToDictionary, ToList, ToLookup

Порівняння SequenceEqual

Вибір елемента DefaultIfEmpty, ElementAt, ElementAtOrDefault, First, FirstOrDefault, Last, LastOrDefault, Single,

SingleOrDefault

Утворення Empty, Range, Repeat

Кількісне визначення All, Any, Contains

Агрегація Aggregate, Average, Count, LongCount, Max, Min, Sum

Разметка Skip, SkipWhile, Take, Takewhile

• Крім стандартного синтаксису from .. in .. select для створення запиту

LINQ ми можемо застосовувати спеціальні методи розширення, які

визначені в інтерфейсі IEnumerable.

• Не кожен метод розширення має аналог серед операторів LINQ, в

цьому випадку можна застосовувати обидва підходи.

string[] teams = { "Баварія", "Борусія", "Реал Мадрид", "Манчестер Сіті", "Барселона" };

int number = (from t in teams where t.ToUpper().StartsWith("Б") select t).Count();

Методи розширення LINQ

var contacts =

from c in customers

where c.City == "Hove"

select new { c.Name, c.Phone };

var contacts =

customers

.Where(c => c.City == "Hove")

.Select(c => new { c.Name, c.Phone });

Extension methods

Lambda expressions

Query expressions

Object initializersAnonymous types

Local variable type inference

eleks.com

Демонстрація 10• Робота з LINQ

© Denys Prylutskyi, 2015

Практичне завдання

Рекомендована література

1. R. Sedgewick “Algorithms”

2. A. Troelsen “C# 6.0 and the .NET 4.6 Framework”

3. H. Schildt “C# 4.0 The Complete Reference”

4. J. Richter “CLR via C#”

5. J. Skeet “C# in Depth”

6. Stackoverflow.com

Recommended