310 likes | 547 Views
Курс по програмиране на C#. Занятие №1 4 Делегати. Събития. Ламбда функции. Съдържание. Функциите като данни Делегати Събития и обработчици Л амбда функции Примери за употреба на делегати и събития. Функциите като данни. Какво е функция - преговор
E N D
Курс по програмиране на C# Занятие №14Делегати. Събития. Ламбда функции
Съдържание • Функциите като данни • Делегати • Събития и обработчици • Ламбда функции • Примери за употреба на делегати и събития
Функциите като данни • Какво е функция - преговор • Подпрограма, която извършва определена дейност и може да бъде извиквана от друга част на програмата • Нула или повече параметри • Тип на параметъра • Вид на параметъра – предаван по стойност, по референция или изходен • Тип на връщания резултат или липса на такъв • Блок от операции (тяло на функцията)
Функциите като данни • Разглеждане на функции като данни • Някои езици за програмиране боравят с типове данни, чиито дефиниционни множества обхващат семейства от функции • На практика това означава, че: • Функция може да бъде присвоена на променлива или член-данна от подходящия тип • Фунцкия може да бъде подадена като аргумент на друга функция (композиция на функции) • Функция може да бъде върната като резултат от изпълнението на друга функция • Механизъм за метапрограмиране: въвеждане в програмата на кратки и лесни за употреба конструкции, които заместват еднотипни фрагменти от код
Функциите като данни • Функционални типове данни • Дефиниционно множество: функциите с определен брой, тип и вид на параметрите и тип на връщания резултат • Предоставят механизъм за извикване на функцията, която се разглежда като данна
Делегати • Какво е „делегат“? • Референтен тип данни • C# еквивалент на функционален тип данни • Наследява класа System.MulticastDelegate • Наименование • Нула или повече параметри • Тип на връщания резултат • Шаблонни делегати – аналогично на другите шаблонни типове
Делегати // Делегат с един целочислен параметър// и целочислен резултатdelegateintUnaryMethod(int x); // Делегат с два целочислени параметъра// и целочислен резултатdelegateintBinaryMethod(int x, int y); // Делегат с два низови параметъра// и без резултатpublicdelegatevoidNameChangedHandler(stringoldName, stringnewName); // Шаблонен делегат с един параметър// от тип, който имплементира интерфейса// IComparable, и същия тип на резултатаdelegateT UnaryMethod<T>(T x)where T : IComparable; Деклариране на делегати Модификатор за достъп (незадължителен) Ключова дума delegate Тип на връщания резултат или ключова дума void Наименование – уникално в рамките на пространството от имена Списък от параметри в кръгли скоби Деклариране на шаблонни делегати Аналогично на декларирането на други шаблонни типове
Деклариране на делегати - демо // Демонстрация
Делегати • Използване на делегати • Делегатите са пълноправни типове данни • Автоматично предоставен конструктор с един параметър • При създаване на делегатен екземпляр, на конструктора се подава като аргумент обръщение към метод без кръгли скоби с аргументи • Методът трябва да има подходящият брой, тип и вид параметри, както и тип на връщания резултат • За изпълнение на метода, съдържащ се в делегатен екземпляр, се поставят кръгли скоби с аргументи след променливата/израза, рефериращ делегатния екземпляр
Делегати staticint Add(int x, int y){returnx + y;} staticdoubleAddPi(double x){returnx + Math.PI;} staticvoid Main(string[] args){// Създаване на делегатен екземплярBinaryMethodbinaryMethod=newBinaryMethod(Add); // Съкратен запис за горнотоBinaryMethodbinaryMethod2 = Add; // Създаване на делегатен екземпляр, // чийто тип е шаблонен екземплярUnaryMethod<double> unaryMethod= AddPi; // Изпълняване на делегатен екземплярinta = binaryMethod(2, 5);Console.WriteLine(a);} Използване на делегати Деклариране на променлива от делегатен тип Създаване на делегатен екземпляр Неявно създаване на делегатен екземпляр – извикването на констурктора може да бъде пропуснато Извикване на метода, към който сочи делегатен екземпляр
Използване на делегати - демо // Демонстрация
Делегати • Приложения на делегатите • Изпълнение на различни операции (определяни по време на изпълнение) върху еднотипни данни • Реализиране на взаимодействия между обекти чрез събития • Функции от по-висок ред – функционално програмиране в C#
Събития • Какво е „събитие“? • Член на клас, структура или интерфейс • Служи за реализиране на взаимодействие между обекти • Тип данни – делегат • Наименование – уникално в рамките на членовете на класа • Към събитието се закачат обработчици – делегатни екземпляри • При предизвикването на събитието се извикват последователно всички закачени обработчици
Събития classPerson{// Частно поле за съхранение //на обработчици на събитиетоprivateNameChangedHandler _nameChanged; // Събитие с явно декларирани блокове // за закачане и откачане на обработчициpubliceventNameChangedHandlerNameChanged{ // Блок за закачане на обработчикadd{ _nameChanged += value; } // Блок за откачане на обработчикremove{ _nameChanged -= value; } } // Съкратен запис на горнотоpubliceventNameChangedHandler NameChanged2;} Деклариране на събития Модификатор за достъп (незадължителен) Ключова дума event Делегатен тип данни Наименование Блокове за закачане и откачане на обработчици (незадължителни) Блок за закачане – предшества се от стандартната дума add Блок за откачане – предшества се от стандартната дума remove Ако блоковете се пропуснат, компилаторът генерира частно поле от същия тип, към което да закача обработчиците (автоматично генерирано събитие)
Деклариране на събития - демо // Демонстрация
Събития // Метод – обработчик на събитиетоstaticvoidPersonNameChanged(stringoldName, stringnewName){Console.WriteLine("The person’s name was changed to '{0}'.",newName);} staticvoid Main(string[] args){Personperson = newPerson("Иван Петров"); // Закачане на обработчик на събитиеperson.NameChanged+= PersonNameChanged; // Изпълняване на код, който би предизвикал // събитиетоperson.Name= "Георги Георгиев"; // Откачане на обработчик на събитиеperson.NameChanged-= PersonNameChanged;} Закачане и откачане на обработчици на събития Не се допуска директно присвояване на стойност на събитие Обработчик на събитие се закача с оператора += Обработчик на събитие се откача с оператора -=
Закачане и откачане на обработчици на събития - демо // Демонстрация
Събития classPerson{// ... privatestring _name; publicPerson(string name){ _name = name;} publicstringName{ get{ return _name; } set{ if(_name == value)return; stringoldName = _name; _name = value; if (_nameChanged!= null) _nameChanged(oldName, _name);}}} Предизвикване на събития Автоматично генерираните събития се предизвикват по същия начин, както се изпълняват делегатни екземпляри Останалите събития не се предизвикват пряко, а трябва да бъде изпълнен делегатният екземпляр, към който addблокът на събитието закача обработчиците Ако няма закачени обработчици, събитието има стойност null; при опит за предизвикването му се предизвиква изключение от тип System.NullReferenceException
Предизвикване на събития - демо // Демонстрация
Събития • Приложения на събитията • Реализиране на взаимодействия между обекти • Разширяване и модифициране на поведението на обекти без пряк достъп до реализацията им и без наследяване • Програмиране, базирано на събития • Приложения с графичен потребителски интерфейс
Ламбда функции • Какво е „ламбда функция“? • Специален синтаксис за създаване на делегатен екземпляр • Може да се декларира директно в тялото на друг метод или дори друга ламбда функция • Параметри – типовете им може да бъдат пропуснати • Тяло • Тип на връщания резултат – не се посочва явно • В тялото на ламбда функцията могат да се използват локалните променливи на метода, в който е декларирана
Ламбда функции // Деклариране на ламбда функция с изразBinaryMethodadd = (int x, int y) => x + y; // Ламбда функция без явно декларирани типове// на параметритеBinaryMethodsubtract = (x, y) => x - y; // Ламбда функция с един параметърUnaryMethod<double> addPi= x => x + Math.PI; // Деклариране на ламбда фунцкия със съжденияPersonperson = newPerson("Иван Петров");person.NameChanged += (oldName, newName) =>{Console.WriteLine("The person’s name changed to '{0}'.",newName);}; Деклариране на ламбда функции Списък от параметри в кръгли скоби Посочването на типовете на параметрите не е задължително Ако параметърът е един, скобите не са задължителни Оператор => Тяло Израз – резултат от изпълнението на ламбда функцията (ламбда функция с израз) Блок от операции, който може да връща, а може и да не връща резултат (ламбда функция със съждения)
Деклариране на ламбда функции - демо // Демонстрация
Ламбда функции // Използване на локалнa променливa//в ламбда функцияint n = 15;UnaryMethodaddN = x => x + n;Console.WriteLine(addN(10)); // Промените в стойността на променливата// след декларацията на функцията се// отразяват на поведението ѝn = 20;Console.WriteLine(addN(10)); Използване на локални променливи в ламбда функции В тялото на ламбда функция може да се използват локалните променливи от метода, в който е декларирана Стойностите на локалните променливи на метода не се копират при декларирането на ламбда функцията и промените в тях след декларацията ѝ се отразяват на нейното поведение Това може да доведе до трудно откриваеми грешки
Използване на локални променливи в ламбда функции - демо // Демонстрация
Ламбда функции • Приложения на ламбда функциите • Кратък синтаксис за създаване на делегатни екземпляри • Подходящи, когато делегатният екземпляр ще бъде използван на едниствено място в програмата • Необходими, когато делегатният екземпляр трябва да използва локални променливи на друг метод • Доближават синтаксиса на C# до функционалното програмиране • Правят кода по-четим, премахвайки излишната пунктуация и декларации
Примери за употреба на делегати и събития - демо // Демонстрация
Задачи за упражнение • Създайте конзолно приложение – калкулатор, като използвате подходящи делегати и делегатни екземпляри за реализиране на различните аритметични операции • Преработете конзолния калкулатор в приложение с графичен потребителски интерфейс и поведение, което е сходно на вградения в Windows калкулатор
Задачи за упражнение • Преработете програмата „ролева игра“, като реализирате събития за важни ситуации в играта и походящи обработчици, които да извършват промени в поведението на програмата или да извеждат на екрана подходящи съобщения; примери за такива ситуации са: • Раняване на чудовище • Раняване на играч • Смърт на чудовище • Смърт на играч • Опит за придвижване в неразрешена посока • Попадане в капан и т.н.
Благодаря! • Александър Далемски • sasho@david.bg • Skype: musasho • https://facebook.com/adalemski • ДАВИД академия • acad@david.bg • http://acad.david.bg/ • @david_academy • https://facebook.com/DavidAcademy