Делегати — Delegates атрибутиopt модифікатори opt delegate тип
Делегати - Delegates атрибутиopt модифікатори opt delegate тип результату ідентифікатор (список формальних параметрів) Делегат – спеціалізований тип-посилання: виклик через його об’єкти методів, які мають задану сигнатуру неявно оголошений як sealed (не допускає утворення похідних класів) може бути компонентою типів-агрегатів ініціалізують як статичними (через тип), так і нестатичними методами об’єднання делегатів (тип результату -void, жоден з параметрів-не out) використання з подіями
public delegate string inform(); class Program{ .... static void Main(string[] args) { ..... Point pn=new Point(100,200); inform pi=new inform(pn.ToString); Console.WriteLine( pi() ); Pixel px = new Pixel(10, 30, Color.Blue); pi = new inform(px.ToString); Console.WriteLine( pi() ); } }
.NET Framework використовує делегати для забезпечення зворотнього виклику (callbacks) Оголошення визначає сигнатуру методу об”єкт делегата зберігає адресу об”єкта і метод, що пов”язаний з ним Події вимагають реєстрацію і зворотній виклик
дані передаються через делегат
delegate void StudentCallback(double gpa); class Parent { public void Report(double gpa) { ... } } class Student { public StudentCallback GpaChanged; public void Record(int grade) { // update gpa ... GpaChanged(gpa); } } Student ann = new Student("Ann"); Parent mom = new Parent(); ann.GpaChanged = new StudentCallback(mom.Report); ann.Record(4); define delegate caller stores delegate caller invokes delegate target method create and install delegate
class Student { public StudentCallback GpaChanged; public void Record(int grade) { // update gpa ... if (GpaChanged != null) GpaChanged(gpa); } test before call Null reference
class Registrar { public static void Log(double gpa) { ... } } void Run() { Student ann = new Student("Ann"); ann.GpaChanged = new StudentCallback(Registrar.Log); ... } Static methods static method register
Multiple Можна комбінувати делегати використовуючи operator+= або operator+ Parent mom = new Parent(); Parent dad = new Parent(); Student ann = new Student("Ann"); ann.GpaChanged += new StudentCallback(mom.Report); ann.GpaChanged += new StudentCallback(dad.Report); ... targets first second
Parent mom = new Parent(); Parent dad = new Parent(); Student ann = new Student("Ann"); ann.GpaChanged += new StudentCallback(mom.Report); ann.GpaChanged += new StudentCallback(dad.Report); ... ann.GpaChanged -= new StudentCallback(dad.Report); ... remove add Remove delegate Можна видаляти делегати зі списку - використовуючи operator -= або operato r-
public delegate MulticastDelegate
delegate void inform_dist(Point p, Point q); public delegate void inform_dist(Point p, Point q); class Program { static void test(inform_dist f, Point [] arr){ Point orr= new Point(3,0); foreach(Point p in arr) f(orr,p); } static void Main(string[] args) { Point pn=new Point(0,4); inform_dist pi=new inform_dist(pn.print_dist); pi(new Point(),pn); Pixel px = new Pixel(1, 30, Color.Blue); pi = new inform_dist(px.print_dist); pi(new Point(1,5), px); Point[] parr ={ pn, px }; test(pi, parr); test(px.print_dist, parr); } } dist=4 dist=25 dist=5 dist=30.07
Події - Events атрибутиopt модифікаториopt event тип делегата ідент. події ; event & delegate – елементи реалізації патерну Observer Основа – підтримка списку зареєстрованих делегатів EventHandler : стандартний системний делегат узагальнений системний делегат, аргумент -тип даних події суфікс назви делегата, визначеного користувачем EventArgs : стандартний системний тип даних події (без даних) суфікс назви типу даних події, похідного від EventArgs Тип, який реагує на подію, надає метод для обробки події Обробник події реєструється через делегат
Приклад реалізації патерну Observer private void ListChanged (object sender, EventArgs e) {...} ListWithChangedEvent list = new ListWithChangedEvent(); EventListener listener = new EventListener(list); list.Add("item 1"); list.Add("item 2"); list[1]="item 20"; list.Clear(); listener.Detach();
Події - Events атрибутиopt модифікаториopt event тип делегата ідентифікатор події Сценарій механізму подій: Оголосити делегат Створити клас з подією на основі делегата з методами, які генерують подію (декларатор з аргументами) Створити один або кілька класів-прослуховувачів події для прив’язки методів до події: асоціацію операторами += ( -= ) методів-обробітників з подією визначення методів-обробітників Створення об’єкта першого класу Створення об’єкта класу-прослуховувача з використанням першого об’єкта як аргумента Робота з першим об’єктом
Системні делегати подій Стандартний системний делегат [SerializableAttribute] [ComVisibleAttribute(true)] public delegate void EventHandler ( Object sender, EventArgs e ) Узагальнений системний делегат, аргумент -тип даних події [SerializableAttribute] public delegate void EventHandler
Типи даних для подій EventArgs [Serializable] public class EventArgs { public static readonly EventArgs Empty = new EventArgs(); public EventArgs() { } }
Компілювання подій // код програми до компіляції public event EventHandler
delegate void StudentCallback(double gpa); class Parent { public void Report(double gpa) { ... } } class Student { public StudentCallback GpaChanged; public void Record(int grade) { // update gpa ... GpaChanged(gpa); } } Student ann = new Student("Ann"); Parent mom = new Parent(); ann.GpaChanged = new StudentCallback(mom.Report); ann.Record(4); // 4 == 'A' define delegate caller stores delegate caller invokes delegate target method create and install delegate
Events in C# are implemented with delegates. The publishing class defines a delegate. The subscribing class does two things: first, it creates a method that matches the signature of the delegate, and then it creates an instance of that delegate type encapsulating that method. When the event is raised, the subscribing class's methods are invoked through the delegate. A method that handles an event is called an event handler. You can declare your event handlers as you would any other delegate. By convention, event handlers in the .NET Framework always return void and take two parameters. The first parameter is the "source" of the event (that is, the publishing object). The second parameter is an object derived from EventArgs. Your event handlers will need to follow this design pattern.
Suppose you want to create a Clock class that uses delegates to notify potential subscribers whenever the local time changes its value by one second. Call this delegate SecondChangeHandler. The declaration for the SecondChangeHandler delegate is: public delegate void SecondChangeHandler( object clock, TimeInfoEventArgs timeInformation); public class TimeInfoEventArgs : EventArgs { public int hour; public int minute; public int second; public TimeInfoEventArgs(int hour, int minute, int second) { this.hour = hour; this.minute = minute; this.second = second; } }
// The publisher: the class that other classes // will observe. This class publishes one delegate: // SecondChangeHandler. public class Clock { private int hour; private int minute; private int second; // the delegate the subscribers must implement public delegate void SecondChangeHandler(object clock, TimeInfoEventArgs timeInformation); // an instance of the delegate public event SecondChangeHandler SecondChanged; // set the clock running // it will raise an event for each new second public void Run( )
public void Run( ) { for (; ; ) { // sleep 100 milliseconds Thread.Sleep(100); // get the current time System.DateTime dt = System.DateTime.Now; // if the second has changed // notify the subscribers if (dt.Second != second) { // create the TimeInfoEventArgs object // to pass to the subscriber TimeInfoEventArgs timeInformation = new TimeInfoEventArgs(dt.Hour, dt.Minute, dt.Second); // if anyone has subscribed, notify them if (SecondChanged != null) { SecondChanged(this, timeInformation); } } // update the state this.second = dt.Second; this.minute = dt.Minute; this.hour = dt.Hour; } }
// A subscriber: DisplayClock subscribes to the // clock's events. The job of DisplayClock is // to display the current time public class DisplayClock { public void Subscribe(Clock theClock) { theClock.SecondChanged += new Clock.SecondChangeHandler(TimeHasChanged); } public void TimeHasChanged(object theClock, TimeInfoEventArgs ti) { Console.WriteLine("Current Time: {0}:{1}:{2}", ti.hour.ToString( ), ti.minute.ToString( ), ti.second.ToString( )); } }
public class Tester { public void Run( ) { // create a new clock Clock theClock = new Clock( ); // create the display and tell it to // subscribe to the clock just created DisplayClock dc = new DisplayClock( ); dc.Subscribe(theClock); // create a Log object and tell it // to subscribe to the clock LogCurrentTime lct = new LogCurrentTime( ); lct.Subscribe(theClock); // Get the clock started theClock.Run( ); } } Current Time: 14:53:56 Logging to file: 14:53:56 Current Time: 14:53:57 Logging to file: 14:53:57 Current Time: 14:53:58 Logging to file: 14:53:58 Current Time: 14:53:59 Logging to file: 14:53:59 Current Time: 14:54:0 Logging to file: 14:54:0
lektsiya7_del_ev.ppt
- Количество слайдов: 25