Upload
eleksdev
View
1.449
Download
1
Embed Size (px)
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