Делегати. Анонімні функції

Содержание

Слайд 2

Делегати

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

Делегати Делегат – об’єкт, який може посилатися на метод. Даний метод можна
допомогою цього посилання.
Один делегат можна використовувати для виклику різних методів, змінюючи посилання на них під час виконання програми.

Слайд 3

Загальна форма оголошення делегату

delegate тип_повернення ім'я(список_параметрів);
Приклади:
delegate void Del();
delegate int Deleg1(int i, double

Загальна форма оголошення делегату delegate тип_повернення ім'я(список_параметрів); Приклади: delegate void Del(); delegate
x, bool b);
delegate bool Deleg1(int i, double x, string s);
delegate bool Deleg2(int i2, double x, string s3);
delegate void Deleg3(int i, double x, string s);

Слайд 4

Виклик методу

Делегат може викликати метод екземпляру класу або статичний метод
//Приклад
using System;
delegate void

Виклик методу Делегат може викликати метод екземпляру класу або статичний метод //Приклад
del();
class Program
{
static void Main()
{
SayHelloWorld(); // викликаємо метод
// створюємо об'єкт делегата dl і задаємо його посилання на метод SayHelloWorld()
del dl = new del(SayHelloWorld);
dl(); // викликаємо метод через делегат
}
static void SayHelloWorld()
{
Console.WriteLine("Hello World!");
}
}

Слайд 5

Приклад 2
using System;
// Оголошуємо делегат
delegate string strMod(string str);
class DelegateTest {
static string

Приклад 2 using System; // Оголошуємо делегат delegate string strMod(string str); class
replaceSpaces(string a)
{
Console.WriteLine("Заміна пробілів дефісами.");
return a.Replace(' ', '-');
}
// Метод видаляє пробіли.
static string removeSpaces(string a)
{
string temp = "";
int i;
Console.WriteLine("Видалення пробілів.");
for (i = 0; i < a.Length; i++)
if (a[i] != ' ') temp += a[i];
return temp;
}
// Метод реверсує рядок.
static string reverse(string a)
{
string temp = "";
int i, j;
Console.WriteLine("Реверсування рядка.");
for (j = 0, i = a.Length - 1; i >= 0; i--, j++)
temp += a[i];
return temp;
}
public static void Main()
{
// Створення делегата.
strMod strOp = new strMod(replaceSpaces);
string str;
// Викликаємо методи через делегат
str = strOp("Це звичайний текст.");
Console.WriteLine("Резуьтуючий рядок: " + str);
Console.WriteLine();
strOp = new strMod(removeSpaces);
str = strOp("Це звичайний текст.");
Console.WriteLine("Резуьтуючий рядок: " + str);
Console.WriteLine();
strOp = new strMod(reverse);
str = strOp("Це звичайний текст.");
Console.WriteLine("Резуьтуючий рядок: " + str);
}
}

Слайд 6

Виклик нестатичного методу

Делегат може викликати метод екземпляру класу або статичний метод
//Приклад
using System;
delegate

Виклик нестатичного методу Делегат може викликати метод екземпляру класу або статичний метод
void del();
class Program
{
static void Main()
{
Program pr = new Program(); // створюємо об'єкт
pr.SayHelloWorld(); // викликаємо метод
// створюємо об'єкт делегата dl і задаємо його посилання на метод SayHelloWorld()
del dl = new del(pr.SayHelloWorld);
dl(); // викликаємо метод через делегат
}
void SayHelloWorld()
{
Console.WriteLine("Hello World!");
}
}

Слайд 7

Багатоадресна передача (multicasting)

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

Багатоадресна передача (multicasting) Multicasting – можливість делегата створювати ланцюжок викликів методів, які
автоматично викликатися при виклику делегата.
Для цього використовується оператор «+=»
Щоб видалити метод з ланцюжка – оператор «-=»
Обмеження – делегат повинен повертати тип даних – void.

Слайд 8

Багатоадресна передача (multicasting). Приклад

using System;
delegate void del();
class Program
{
static void Main()
{

Багатоадресна передача (multicasting). Приклад using System; delegate void del(); class Program {
Program pr = new Program(); // створюємо об'єкт
// створюємо об'єкт делегата dl і задаємо його посилання на метод SayHelloWorld()
del dl = new del(pr.SayHelloWorld);
// додаємо до ланцюжка виклику методів ще 2 методи
dl += new del(pr.SayHelloPNK);
dl += new del(pr.SayHelloKN);
dl(); // викликаємо 3 методи через делегат
}
void SayHelloWorld()
{
Console.WriteLine("Hello World!");
}
void SayHelloPNK()
{
Console.WriteLine("Hello PNK-31!");
}
void SayHelloKN()
{
Console.WriteLine("Hello KN-31!");
}
}

Слайд 9

Клас System.Delegate

Всі делегати являють собою класи, похідні від System.Delegate. Зазвичай члени цього

Клас System.Delegate Всі делегати являють собою класи, похідні від System.Delegate. Зазвичай члени
класу не використовуються напряму.

Слайд 10

Навіщо потрібні делегати?

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

Навіщо потрібні делегати? Підтримують функціонування подій Під час виконання програми дозволяють виконати
точно невідомий в період компіляції.
Наприклад потрібно створити оболонку до якої могли б підключатися програмні компоненти. Уявіть графічну програму (на зразок стандартної утиліти Windows Paint). Використовуючи делегат, можна було б дозволити користувачеві підключати спеціальні кольорові світлофільтри або аналізатори зображень. Більш того, користувач міг би створювати "свої" послідовності цих фільтрів або аналізаторів. За допомогою делегатів організувати такий алгоритм дуже легко.

Слайд 11

Приклад застосування делегата

1. Оголошуємо делегат в класі або за його межами з

Приклад застосування делегата 1. Оголошуємо делегат в класі або за його межами
певною сигнатурою:
delegate void del();
2. Створюємо один (або декілька методів), сигнатура якого така сама, як в оголошеному делегаті
static void SayHelloWorld()
{
Console.WriteLine("Hello World!");
}

Слайд 12

Приклад застосування делегата

3. Створюємо об'єкт делегата dl і задаємо його посилання на

Приклад застосування делегата 3. Створюємо об'єкт делегата dl і задаємо його посилання
метод SayHelloWorld():
del dl = new del(SayHelloWorld);
4. Викликаємо метод через делегат:
dl();

Слайд 13

Приклад застосування делегата

using System;
delegate void del();
class Program
{
static void Main()
{
// створюємо

Приклад застосування делегата using System; delegate void del(); class Program { static
об'єкт делегата dl і задаємо його посилання на метод SayHelloWorld()
del dl = new del(SayHelloWorld); // або del dl = SayHelloWorld;
dl(); // викликаємо метод через делегат
}
static void SayHelloWorld()
{
Console.WriteLine("Hello World!");
}
}

Слайд 14

Анонімні функції

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

Анонімні функції Метод, на який посилається делегат, нерідко використовується тільки для цієї
Іншими словами, єдиною підставою для існування методу є та обставина, що він може бути викликаний за допомогою делегата, але сам по собі він не викликається взагалі. 
У подібних випадках можна скористатися анонімною функцією, щоб не створювати окремий метод.
Анонімна функція, по суті, являє собою безіменний кодовий блок, який передається конструктору делегата. Перевага анонімної функції полягає, зокрема, в її простоті. Завдяки їй відпадає необхідність оголошувати окремий метод, єдине призначення якого полягає в тому, що він передається делегату.
Починаючи з версії 3.0, в C# передбачено два різновиди анонімних функцій - анонімні методи і лямбда-вирази

Слайд 15

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

Анонімні методи почали застосовуватися в C# ще у версії 2.0, а

Анонімні методи Анонімні методи почали застосовуватися в C# ще у версії 2.0,
лямбда-вирази - у версії 3.0.
В цілому лямбда-вираз удосконалює принцип дії анонімного методу і в даний час вважається кращим для створення анонімної функції. Але анонімні методи широко застосовуються в існуючому коді C# і тому як і раніше є важливою складовою частиною C#. А оскільки анонімні методи передували появі лямбда-виразів, то чітке уявлення про них дозволяє краще зрозуміти особливості лямбда-виразів. До того ж анонімні методи можуть бути використані в цілому ряді випадків, де застосування лямбда-виразів виявляється неможливим.
Анонімний метод – один із способів створення безіменного блоку коду, пов'язаного з конкретним екземпляром делегата. Для створення анонімного методу досить вказати кодовий блок після ключового слова delegate. Покажемо, як це робиться, на конкретному прикладі:

Слайд 16

Анонімні методи (приклад)

using System;
delegate void del();
class Program
{
static void Main()
{
del

Анонімні методи (приклад) using System; delegate void del(); class Program { static
dl = delegate()
{
Console.WriteLine("Hello World!");
};
dl(); // викликаємо анонімний метод через делегат
}
static void SayHelloWorld()
{
Console.WriteLine("Hello World!");
}
}

Слайд 17

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

Починаючи з C# 3.0, доступний новий синтаксис для призначення реалізації коду делегатам,

Лямбда-вирази Починаючи з C# 3.0, доступний новий синтаксис для призначення реалізації коду
що називається лямбда-виразами (lambda expression). Лямбда-вирази можуть використовуватися скрізь, де є параметр типу делегата.
Синтаксис лямбда-виразів простіший синтаксису анонімних методів.
У всіх лямбда-виразах застосовується новий лямбда-оператор =>, який розділяє лямбда-вираз на дві частини. У лівій його частині вказується вхідний параметр (або кілька параметрів), а в правій частині - тіло лямбда-виразу. Оператор => іноді описується такими словами, як "переходить" або "стає".

Слайд 18

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

У C# підтримуються два різновиди лямбда-виразів в залежності від тіла самого лямбда-виразу.
Так,

Лямбда-вирази У C# підтримуються два різновиди лямбда-виразів в залежності від тіла самого
якщо тіло лямбда-виразу складається з одного виразу, то утворюється одиночний лямбда-вираз. У цьому випадку тіло виразу не заключається в фігурні дужки.
Якщо ж тіло лямбда-виразу складається з блоку операторів, укладених у фігурні дужки, то утворюється блочний лямбда-вираз. При цьому блочний лямбда-вираз може містити цілий ряд операторів, в тому числі цикли, виклики методів і умовні оператори if. Обидва різновиди лямбда-виразів розглядаються далі окремо.

Слайд 19

Одиночні лямбда-вирази

В одиночному лямбда-виразі частина, яка перебуває праворуч від оператора =>, впливає

Одиночні лямбда-вирази В одиночному лямбда-виразі частина, яка перебуває праворуч від оператора =>,
на параметр (або ряд параметрів), що вказується зліва. Поверненим результатом обчислення такого виразу є результат виконання лямбда-оператора. Нижче наведена загальна форма одиночного лямбда-виразу, що приймає єдиний параметр:
параметр => вираз
Якщо ж потрібно вказати кілька параметрів, то використовується наступна форма:
(список_параметров) => вираз
Таким чином, коли потрібно вказати два параметра або більше, їх слід помістити в дужки. Якщо ж вираз не вимагає параметрів, то слід використовувати порожні дужки.
Лямбда-вираз застосовується в два етапи. Спочатку оголошується тип делегата, сумісний з лямбда-виразом, а потім екземпляр делегата, якому присвоюється лямбда-вираз. Після цього лямбда-вираз обчислюється при зверненні до примірника делегата. Результатом його обчислення стає повернене значення.

Слайд 20

Одиночні лямбда-вирази (приклад)

using System;
delegate void del(int i);
class Program
{
static void Main()
{

Одиночні лямбда-вирази (приклад) using System; delegate void del(int i); class Program {
// лямбда-вираз
del dl = () => Console.WriteLine("Hello World!");
dl(); // викликаємо через делегат
}
static void SayHelloWorld()
{
Console.WriteLine("Hello World!");
}
}

Слайд 21

Одиночні лямбда-вирази (приклад 2)

using System;
delegate int del(int i1, int i2);
class Program
{
static

Одиночні лямбда-вирази (приклад 2) using System; delegate int del(int i1, int i2);
void Main()
{
// лямбда-вираз
del dl = (i1, i2) => i1+i2;
dl(3, 5); // викликаємо через делегат
}
static int Sum(int i1, int i2)
{
return i1 + i2;
}
}

Слайд 22

Блокові лямбда-вирази

Другим різновидом лямбда-виразів є блоковий лямбда-вираз. Для такого лямбда-виразу характерні розширені можливості виконання

Блокові лямбда-вирази Другим різновидом лямбда-виразів є блоковий лямбда-вираз. Для такого лямбда-виразу характерні
різних операцій, оскільки в його тілі допускається вказувати кілька операторів. Наприклад, в блочному лямбда-виразі можна використовувати цикли і умовні оператори if, оголошувати змінні і т.д. Створити блоковий лямбда-вираз неважко. Для цього досить помістити тіло виразу в фігурні дужки. Крім можливості використовувати кілька операторів, в іншому блочний лямбда-вираз, практично нічим не відрізняється від щойно розглянутого одиночного лямбда-виразу.

Слайд 23

Блокові лямбда-вирази (приклад)
using System;
delegate int del(int i1, int i2);
class Program
{
static void

Блокові лямбда-вирази (приклад) using System; delegate int del(int i1, int i2); class
Main()
{
// блоковий лямбда-вираз
del dl = (i1, i2) =>
{
int i3 = i1 + i2;
if (i1>0) return i3;
else return i1;
};
dl(3, 5); // викликаємо через делегат
}
static int Sum(int i1, int i2)
{
int i3 = i1 + i2;
if (i1 > 0) return i3;
else return i1;
}
}

Слайд 24

Завдання для перевірки засвоєння знань

Дано метод:
static int Method1(string s, int i)

Завдання для перевірки засвоєння знань Дано метод: static int Method1(string s, int
{
int i2 = s.Length * 3;
Console.WriteLine(i2);
return i2;
}
Перетворіть цей метод в анонімний метод і викличте за допомогою делегата.
Перетворіть цей метод в лямбда-вираз і викличте за допомогою делегата.

Слайд 25

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

Методи розширення (extension methods) дозволяють додавати нові методи в уже існуючі

Методи розширення Методи розширення (extension methods) дозволяють додавати нові методи в уже
типи без створення нового похідного класу. Ця функціональність буває особливо корисна, коли нам хочеться додати в певний тип новий метод, але сам тип (клас або структуру) ми змінити не можемо.
Наприклад, нам треба додати для типу string новий метод:

Слайд 26

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

using System;
class Program
{
static void Main(string[] args)
{
string s =

Методи розширення using System; class Program { static void Main(string[] args) {
"Привіт світ";
char c = 'і';
// виклик методу розширення
int i = s.SymbolCount('і');
Console.WriteLine(i);
Console.ReadLine();
}
}
public static class StringExtension
{
// метод розширення
// визначає кількість символів в рядку
public static int SymbolCount(this string str, char c)
{
int counter = 0;
for (int i = 0; i < str.Length; i++)
{
if (str[i] == c) counter++;
}
return counter;
}
}

Слайд 27

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

Для того, щоб створити метод розширення, спочатку треба створити статичний клас,

Методи розширення Для того, щоб створити метод розширення, спочатку треба створити статичний
який і буде містити цей метод. В даному випадку це клас StringExtension. Потім оголошуємо статичний метод. У прикладі це SymbolCount(). Суть нашого методу розширення – підрахунок кількості певних символів в рядку.

Слайд 28

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

Власне метод розширення – це звичайний статичний метод, який в якості

Методи розширення Власне метод розширення – це звичайний статичний метод, який в
першого параметра завжди приймає таку конструкцію: this імя_типу назва_параметра, тобто в нашому випадку this string str. Так як наш метод буде відноситися до типу string, то ми і використовуємо даний тип.

Слайд 29

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

Потім у всіх рядків ми можемо викликати даний метод:
int i =

Методи розширення Потім у всіх рядків ми можемо викликати даний метод: int
s.SymbolCount('і');
Причому нам вже не треба вказувати перший параметр. Значення для інших параметрів передаються в звичайному порядку.
Имя файла: Делегати.-Анонімні-функції.pptx
Количество просмотров: 21
Количество скачиваний: 0