This article discusses the basics of delegates in C# and how to take advantage of delegates by implementing them in your applications. A delegate in C# is similar to a FUNCTION POINTER in C or C++. Delegate can be defined as an object, which contains the address of a method. Delegate is a reference type used to encapsulate a method with a specific signature and return type. As written in MSDN "A Delegate is a type that references a method. Once a delegate is assigned a method, it behaves exactly like that method. The Delegate method can be used like any other method with parameter and return value". .Net implements the concept of function pointer using Delegates. Unlike c or C++ function pointer, delegates are 1. Type safe 2. Object Oriented 3. Secure Delegates have following properties 1. 2. 3. 4.
Delegates are similar to C++ function pointer but it is type safe in nature. Delegate allows method to pass as an argument. Delegate can be chained together. Multiple methods can be called on a single event.
Delegate is a type which safely encapsulates a method. The type of the delegate is defined by name of the delegate. A delegate does not care about class of the object that it references. Any object will do, only matter is that the method signature should be the same as of delegate. Any instance of a given delegate can refer to any instance or static method on any object of any type. Only one condition is there that signature of method matches the signature of delegate. Mainly Delegate is used by creating first and then making object of that.
Main Advantage Delegate is effective use of delegate increase performance of application. Syntax of a delegate Step 1: Declaration Delegate is getting declared here. Modifer delegate return_type delegate_name ( [Parameter....]) Step 2: Instantiation Object of delegate is getting created as passing method as argument Delegate_name delg_object_name = new Delegate_name( method_name); Here method_name signature must be same as of signature of delegate. Step 3: Invocation Delegate is getting called here. Delg_object_name([parameter....]); Delegate Example 1 using using using using
System; System.Collections.Generic; System.Linq; System.Text;
namespace DelgateForNotes { class Program { // Declaring A delegate , which will refer function having two parameter and will return integer public delegate int AddDelegate(int num1, int num2);
static void Main(string[] args) { // Creating method of delegate, and passing Function Add as argument. AddDelegate funct1= new AddDelegate(Add); // Invoking Delegate..... int k=funct1(7,2); Console.WriteLine(" Sumation = {0}",k); Console.Read(); } // Static Function Add, which having same signature as of delegate public static int Add(int num1, int num2) { Console.WriteLine("I am called by Delegate"); int sumation; sumation= num1+ num2; return sumation; } } } Output: I am called by Delegate Sumation =9 Purpose of this above code is to calculate a sum of two numbers. Add is a static function to compute sum of two integers. Signature of Add function is same as of signature of delegate. Here delegate is AddDelegate. On Breaking the above code in steps Step 1: Creating Delegate. public delegate int AddDelegate(int num1, int num2);
here AddDelegate is name of delegate. Return type of delegate is int. Delegate is taking two integer as input parameter. Access modifer of delegate is Public. In above signature keyword "delegate" defines signature is of delegate signature. So delegate AddDelegate can refer any method having two integer parameter and returning one integer value. Step 2: Making Object of delegate. AddDelegate funct1= new AddDelegate(Add); Funct1 is name of the object. Note: In case of delegate , object of delegate is also called as delegate. So in this case funct1 can be called as delegate. As constructor of delegate, here a Method (Add) is passed. Signature of Add method and AddDelegate delegate is exactly same. Add is a static method. Step 3: Invoking delegate int k=funct1(7,2); funct1 is getting called . Here 7, 2 are passed as parameter. Delegate Example 2 This is bubble sort example. Here three classes have been created. 1. BubbleSortClass.cs 2. Student.cs 3. Program.cs BubbleSortClass.cs
This class will hold a static function called Sort. The return type of this function is void. As an argument, it is taking an Array, which is to be sort and a method which is comparing two objects. using using using using
System; System.Collections.Generic; System.Linq; System.Text;
namespace DelgateForNotes { public class BubbleSortClass { static public void Sort(object[] sortArray,.CompareDelegate gtMethod) { for (int i = 0; i < sortArray.Length; i++) { for (int j = 0; j < sortArray.Length; j++) { if(gtMethod(sortArray[j],sortArray[i])) { object temp= sortArray[i]; sortArray[i] = sortArray[j]; sortArray[j]=temp; } } } } } } Student.cs The object of this class is going to be sort using the Bubble sort. In this class, the static function RhsIsGreater is performing the function of comparing two Student objects.
using using using using
System; System.Collections.Generic; System.Linq; System.Text;
namespace DelgateForNotes { // Student class class Student { private string name; private int rollno; private int marks; // Constructor to initaliaze object public Student(string name, int rollno, int marks) { this.name = name; this.rollno = rollno; this.marks = marks; } // Overriding string method to display Student details public override string ToString() { return string.Format(" Name => {0}, RollNumber => {1} , Marks => {2} ", name, rollno, marks); } // user defind function which is comparing two object and returning bool value public static bool RhsIsGreater(object lhs, object rhs) { Student stdLhs = (Student)lhs; Student stdRhs = (Student)rhs; return (stdRhs.marks > stdLhs.marks); } }
} The RhsIsGreater function is taking two object as argument. Inside function, first typecasting has been done. Then boolean value is getting returned. Program.cs This is main program. Here delegate is getting created and sorted array is getting display. using using using using
System; System.Collections.Generic; System.Linq; System.Text;
namespace DelgateForNotes { public class Program { // Declaring A delegate , which will refer function having two object parameter and will return boolean value public delegate bool CompareDelegate(object lhs, object rhs); static void Main(string[] args) { // Creating array of Student objects. Student[] students = { new Student("Mark", 1, 799), new Student ("David",2,545), new Student (" Lavish",3,999), new Student ("Voora",4,228), new Student ("Boll",5,768), new Student (" Donna",6,367), new Student ("Adam",7,799), new Student("Steve",8, 867),
new Student (" Ricky",9,978), new Student (" Brett",10,567) }; // Creating Delegate passing static method of Student class as argument CompareDelegate StudentCompareOp = new CompareDelegate(Student.RhsIsGreater); // Now calling static method of BubbleSortClass , passing Stuednt object arraay and delegate as argument BubbleSortClass.Sort(students,StudentCompareOp); for(int i=0; i< students.Length;i++) { Console.WriteLine(students[i].ToString()); } Console.Read(); } } } MultiCast Delegates A delegate which wrap up more than one method is called Multicast Delegates. When a multicast delegate is get called, it will successively call each functions in order. Multicast Delegate allow to chain together several functions. These chain functions can be called together when delegate is invoked. Every Delegate type has a built in support for dealing with multiiple handlers. Delegate gets this support by inheriting from the MultiCastDelegate class. To work with Multicast Delegate , delegate signature should return void. Otherwise only last method result can be fetched. Operators used are += this operator is used to add functions in delegate . -= this operatir is used to remove function from delegate. Delegate classes
System.Delegate The purpose of a single delegate instance is very similar to a method pointer from C++. However, in C# don't use method pointers, rather, it save the "metadata" that identifies the target method to call. System.Delegate contains two critical data elements. Firstly, it contains an instance of System.Reflection.MethodInfo – in other words, the .NET metadata that enables method invocation using reflection. The second aspect of System.Delegate is the object instance on which the method needs to be invoked. Given an unlimited number of objects that could support a method that matches the MethodInfo signature, we also need to be able to identify which objects to notify. The only exception is when the method identified by MethodInfo is static – in which case the object reference stored by System.Delegate is null. System.MulticastDelegate System.MulticastDelegate therefore, adds to delegates the support for notifying multiple subscribers. This is enabled through System.MulticastDelegate's containment of another System.MulticastDelegate instance. On adding a subscriber to a multicast delegate, the MulticastDelegate class creates a new instance of the delegate type, stores the object reference and the method pointer for the added method into the new instance, and adds the new delegate instance as the next item in a list of delegate instances. In effect, the MulticastDelegate class maintains a linked list of delegate objects. Sequential Invocation When invoking the multicast delegate, each delegate instance in the linked list is called sequentially. This sequential invocation, however, leads to problems if the invoked method throws an exception or if the delegate itself returns data. Multicast Delegate Example 1 using using using using
System; System.Collections.Generic; System.Linq; System.Text;
namespace MulticastDelegate1 { class Program { // Decelaring delegate here, which will refer to method having void return type and one string as argument public delegate void showDelegate(string s); static void Main(string[] args) { showDelegate s = Display; s += Show; s("Hello"); s("Scott"); Console.Read(); } // User Defind static function to display public static void Display(string title) { Console.WriteLine(title); } // User defind static function public static void Show(string title) { Console.WriteLine(title); } } } OUTPUT: Hello Hello Scott Scott
In the above example, the showDelegate is a delegate, which can refer any method having return type void and one string as parameter. There are two static user defined functions called Display and Show. Multicast Delegate Example 2 using using using using
System; System.Collections.Generic; System.Linq; System.Text;
namespace MulticastDelegate { // user defined class for math operation. This class contains two static method. one method for squre and another method for double the number. class MathOperation { // Multiply by two method, this method multiply number by 2 public static void MultiplyByTwo(double d) { double res = d*2; Console.WriteLine("Multiply: "+res.ToString()); } // squre number method public static void Squre(double e) { double res = e * e; Console.WriteLine("Square"+res.ToString()); } } class NewProgram { // Decelaring delegate called del public delegate void del(double Qr);
static void Main() { // Creating delegate del d = MathOperation.MultiplyByTwo; // adding method to del delegate using += operator d += MathOperation.Squre; // calling display function. passsing delegate and double value as parameter Display(d, 2.00); Display(d, 9.9); Console.ReadLine(); } // User defined function to display result and call appropirate operation static void Display(del action, double value) { Console.WriteLine("Result = "+ value); action(value); } } The above code is implementing multicast delegate. In above code, there is a MathOperationClass, this class is containing two methods. One to double the input parameter and other to make squre of that. public delegate void del(double Qr); This is delegate decelaration. It will refer method having one double parameter and will return void. Display function is taking delegate and double as parameter. This function is displaying the result and calling the delegate. There is this thing in C# called a delegate, which is going to be crucial to build interactions between our objects. What's a delegate, you ask? Good question. A delegate is a pointer to a method. What's that mean? Just like you can pass
variable by reference, you can pass a reference to a method. Let me give you an example. Let's say we have a class with two methods that have the same signature (same return type and same parameter configuration). public class MyObject { public int Add(int param1, int param2) { return param1 + param2; } public int Multiply(int param1, int param2) { return param1 * param2; } } We can point to either of the methods in our class by using a delegate declared as follows: public delegate int MyMethodDelegate(int param1, int param2); Now, if we have another class and want to execute either of the methods in MyObject, we can do it through the delegate as in the "Do()" method in the class below. As a matter of fact, we can pass any method with the same signature (not JUST the methods in MyObject). Check out the MySecondObject.Subtract() method. public class MySecondObject { MyObject obj; int a, b; public MySecondObject() { a=4; b=5; obj = new MyObject();
} public int Do(string pMethod) { MyMethodDelegate del = null; switch(pMethod) { case"Add": del = new MyMethodDelegate(obj.Add); break; case"Multiply": del = new MyMethodDelegate(obj.Multiply); break; case "Subtract": del = new MyMethodDelegate(this.Subtract); break; } if(null == del) throw new Exception("Not a valid call"); return del(a,b); } public int Subtract(int param1, int param2) { return param1 - param2; } } Hopefully this gives you a better idea of what delegates are and how they are implemented. Happy coding,
C# .Net Delegates and Events The delegate topic seems to be a confusing and tough for most of the developers. In this article I will explain the basics of delegates and Event handling in C# in a simple manner. Delegate is one of the base types in .NET. Delegate is a class, which is used to create delegate at runtime. Delegate in C# is similar to a function pointer in C or C++. It's a new type of object in C#. Delegate is very special type of object as earlier the entire the object we used to defined contained data but delegate just contains the details of a method. Need of delegate There might be situation in which you want to pass methods around to other methods. For this purpose we create delegate. A delegate is a class that encapsulates a method signature. Although it can be used in any context, it often serves as the basis for the event-handling model in C# but can be used in a context removed from event handling (e.g. passing a method to a method through a delegate parameter). One good way of understanding delegates is by thinking of a delegate as something that gives a name to a method signature. Example: public delegate int DelegateMethod(int x, int y); Any method that matches the delegate's signature, which consists of the return type and parameters, can be assigned to the delegate. This makes is possible to programmatically change method calls, and also plug new code into existing classes. As
long as you know the delegate's signature, you can assign your own-delegated method. This ability to refer to a method as a parameter makes delegates ideal for defining callback methods. Delegate magic In class we create its object, which is instance, but in delegate when we create instance that is also referred as delegate (means whatever you do you will get delegate). Delegate does not know or care about the class of the object that it references. Any object will do; all that matters is that the method's argument types and return type match the delegate's. This makes delegates perfectly suited for "anonymous" invocation. Benefit of delegates In simple words delegates are object oriented and type-safe and very secure as they ensure that the signature of the method being called is correct. Delegate helps in code optimization. Types of delegates 1) Singlecast delegates 2) Multiplecast delegates Delegate is a class. Any delegate is inherited from base delegate class of .NET class library when it is declared. This can be from either of the two classes from System.Delegate or System.MulticastDelegate.
Singlecast delegate Singlecast delegate point to single method at a time. In this the delegate is assigned to a single method at a time. They are derived from System.Delegate class. Multicast Delegate When a delegate is wrapped with more than one method that is known as a multicast delegate. In C#, delegates are multicast, which means that they can point to more than one function at a time. They are derived from System.MulticastDelegate class. There are three steps in defining and using delegates: 1. Declaration To create a delegate, you use the delegate keyword. [attributes] [modifiers] delegate ReturnType Name ([formal-parameters]); The attributes factor can be a normal C# attribute. The modifier can be one or an appropriate combination of the following keywords: new, public, private, protected, or internal. The ReturnType can be any of the data types we have used so far. It can also be a type void or the name of a class. The Name must be a valid C# name. Because a delegate is some type of a template for a method, you must use parentheses, required for every method. If this method will not take any argument, leave the parentheses empty.
Example: public delegate void DelegateExample(); The code piece defines a delegate DelegateExample() that has void return type and accept no parameters. 2. Instantiation DelegateExample d1 = new DelegateExample(Display); The above code piece show how the delegate is initiated 3. Invocation d1(); The above code piece invoke the delegate d1(). Program to demonstrate Singlecast delegate using System; namespace ConsoleApplication5 { class Program { public delegate void delmethod(); public class P { public static void display() { Console.WriteLine("Hello!"); } public static void show() { Console.WriteLine("Hi!");
} public void print() { Console.WriteLine("Print"); } } static void Main(string[] args) { // here we have assigned static method show() of class P to delegate delmethod() delmethod del1 = P.show; // here we have assigned static method display() of class P to delegate delmethod() using new operator // you can use both ways to assign the delagate delmethod del2 = new delmethod(P.display); P obj = new P(); // here first we have create instance of class P and assigned the method print() to the delegate i.e. delegate with class delmethod del3 = obj.print; del1(); del2(); del3(); Console.ReadLine(); } }
}
Program to demonstrate Multicast delegate using System; namespace delegate_Example4 { class Program { public delegate void delmethod(int x, int y); public class TestMultipleDelegate { public void plus_Method1(int x, int y) { Console.Write("You are in plus_Method"); Console.WriteLine(x + y); } public void subtract_Method2(int x, int y) { Console.Write("You are in subtract_Method"); Console.WriteLine(x - y); } } static void Main(string[] args) { TestMultipleDelegate obj = new TestMultipleDelegate(); delmethod del = new delmethod(obj.plus_Method1); // Here we have multicast del += new delmethod(obj.subtract_Method2); // plus_Method1 and subtract_Method2 are called del(50, 10); Console.WriteLine(); //Here again we have multicast
del -= new delmethod(obj.plus_Method1); //Only subtract_Method2 is called del(20, 10); Console.ReadLine(); }
}
} Point to remember about Delegates: • • • • • •
•
Delegates are similar to C++ function pointers, but are type safe. Delegate gives a name to a method signature. Delegates allow methods to be passed as parameters. Delegates can be used to define callback methods. Delegates can be chained together; for example, multiple methods can be called on a single event. C# version 2.0 introduces the concept of Anonymous Methods, which permit code blocks to be passed as parameters in place of a separately defined method. Delegate helps in code optimization.
Usage areas of delegates • • •
The most common example of using delegates is in events. They are extensively used in threading Delegates are also used for generic class libraries, which have generic functionality, defined.
An Anonymous Delegate You can create a delegate, but there is no need to declare the method associated with it. You do not have to explicitly define a method prior to using the delegate. Such a method is referred to as anonymous. In other words, if a delegate itself contains its method definition it is known as anonymous method.
Program to show An Anonymous Delegate using System; public delegate void Test(); public class Program { static int Main() { Test Display = delegate() { Console.WriteLine("Anonymous Delegate method"); }; Display(); return 0; }
}
Note: You can also handle event in anonymous method. Events Event and delegate are linked together. Event is a reference of delegate i.e. when event will be raised delegate will be called. In C# terms, events are a special form of delegate. Events are nothing but change of state. Events play an important part in GUI programming. Events and delegates work hand-in-hand to provide a program's functionality. A C# event is a class member that is activated whenever the event it was designed for occurs.
It starts with a class that declares an event. Any class, including the same class that the event is declared in, may register one of its methods for the event. This occurs through a delegate, which specifies the signature of the method that is registered for the event. The event keyword is a delegate modifier. It must always be used in connection with a delegate. The delegate may be one of the pre-defined .NET delegates or one you declare yourself. Whichever is appropriate, you assign the delegate to the event, which effectively registers the method that will be called when the event fires. How to use events? Once an event is declared, it must be associated with one or more event handlers before it can be raised. An event handler is nothing but a method that is called using a delegate. Use the += operator to associate an event with an instance of a delegate that already exists. Example: obj.MyEvent += new MyDelegate(obj.Display); An event has the value null if it has no registered listeners. Although events are mostly used in Windows controls programming, they can also be implemented in console, web and other applications. Program for creating custom Singlecast delegate and event using System; namespace delegate_custom { class Program {
public delegate void MyDelegate(int a); public class XX { public event MyDelegate MyEvent; public void RaiseEvent() { MyEvent(20); Console.WriteLine("Event Raised"); } public void Display(int x) { Console.WriteLine("Display Method {0}",
x); }
}
static void Main(string[] args) { XX obj = new XX(); obj.MyEvent += new MyDelegate(obj.Display);
} }
obj.RaiseEvent(); Console.ReadLine();
}
Program for creating custom Multiplecast delegate and event using using using using
System; System.Collections.Generic; System.Linq; System.Text;
namespace delegate_custom_multicast
{
class Program { public delegate void MyDelegate(int a, int b); public class XX { public event MyDelegate MyEvent; public void RaiseEvent(int a, int b) { MyEvent(a, b); Console.WriteLine("Event Raised"); }
y);
public void Add(int x, int y) { Console.WriteLine("Add Method {0}", x + }
public void Subtract(int x, int y) { Console.WriteLine("Subtract Method {0}", x - y); } } static void Main(string[] args) { XX obj = new XX(); obj.MyEvent += new MyDelegate(obj.Add); obj.MyEvent += new MyDelegate(obj.Subtract); obj.RaiseEvent(20, 10); Console.ReadLine(); } } }
Practical Anonymous Method using delegate and events
using using using using using using using using
System; System.Collections.Generic; System.ComponentModel; System.Data; System.Drawing; System.Linq; System.Text; System.Windows.Forms;
namespace delegate_anonymous { public partial class Form1 : Form { public delegate int MyDelegate(int a, int b); EventHandler d1 = delegate(object sender, EventArgs e) {
};
MessageBox.Show("Anonymous Method");
MyDelegate d2= delegate (int a, int b) { return(a+b); }; public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { d1(sender, e); } private void button2_Click(object sender, EventArgs e) { int i = d2(10, 20); MessageBox.Show(i.ToString()); } } } Output
Conclusion Hope the article would have helped you in understanding delegates and events. They require a serious study and practical understanding. Your feedback and constructive contributions are welcome. Please feel free to contact me for feedback or comments you may have about this article. Events in C# This article discusses the basics of events in C# and how to take advantage of events by implementing them in your applications. Windows based applications are message based. Application is communicating with windows and windows are communicating with application by using predefined messages. .Net wraps up the messages with 'EVENTS'. And .Net reacting a particular message by handling events. Events are the message sent by an object to indicate the occurrence of an event. Event can also be defined as a member that enables an object to provide notification. Events provide a powerful means of inter-process communication. Events are used for communication between Objects. Communication between Objects is done by events. Delegates are used as the means of wiring up the event when the message is received by the application.
Event Receiver The event receiver may be 1. An application 2. An Object 3. A component Event receiver gets modified when something happens. Event Sender The Event sender may be 1. An assembly in an application 2. An object 3. System events like Mouse event or keyboard entry. Event sender's job is to raise the Event. Event sender doesn't know anything about, whom and what the receiver is. To handle the event, there would be some method inside event receiver. This Event handler method will get executed each time when event is registered to be raised. Here DELEGATE comes into action, because Sender has no idea who the receiver will be. The PROCESS of hooking up the event handler is known as WIRING UP an Event. A simple example of wiring up is CLICK EVENT. The EventHandler Delegate This Delegate is defined in .Net framework. It is defined in System namespace. All of the events that are defined in .Net framework will use it. 1. EventHandler cannot return any value, so it should return Void.
2. Parameters are Object and EventArgs 3. The first parameter is an Object that raises the Event. 4. The Second parameter is EventArgs. This contains information about the Event. Example: Private void Button_Click(Object sender, EventArgs e) { } Here first parameter is a Button; this could be any button if there are multiple buttons on form. The Second parameter is EventArags. This mainly contains the property for which Button is used. Example 1: using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; namespace EventExample { public partial class Form1 : Form { public Form1() { InitializeComponent(); // Adding EventHandler to Click event of Buttons btn1.Click +=new EventHandler(Button_Click);
btn2.Click +=new EventHandler(Button_Click); } // Button Click Method , here signature of this is same as of Eventhandler private void Button_Click(Object sender, EventArgs e) { string str; if (sender == btn1) { str = btn1.Text; MessageBox.Show(str+" Clicked "); } if (sender == btn2) { str = btn2.Text; MessageBox.Show(str+ " Clicked "); } } } } In above code Step 1: Create a Windows Application Step 2: Two butttons are dragged on the form. Name of buttons are btn1 and btn2 . Step 3: At the Constructor part of Form , Eventhandlers are getting add in Button . += operartor is being used for adding EventHandlers. Step 4: Button_Click is a method having same signature as of EventHandler. Output:
When button Scott is clicked, in message Box Scott is displaying. In this case Button_Click method is called by btn1_click delegate. In Button_Click() method , checking has been done for which Button object is calling the event. Or in other words which button is event sender. Code snippet which is checking the sender is if (sender == btn1) { str = btn1.Text; MessageBox.Show(str+" Clicked "); } if (sender == btn2) { str = btn2.Text; MessageBox.Show(str+ " Clicked "); }
Publish and Subscribe of Event 1. In Design pattern, the creator of Control (like Button, List etc) "PUBLISHES" the events to which the button will respond (Such as click).
2. Programmer who uses the Button (those who put Button on their Form) may choose to "SUBSCRIBE" to one or more of the Button's event. For example As a programmer any one could choose to subscribe ( or Notify) click event of Button but not Mouse Hover over the Button 3. Mechanism of publishing is "Creating a Delegate". 4. Mechanism of subscribing is to create a "method "with same signature as of delegate. 5. The Subscribing method is called the "Event Handler" 6. In .Net Framework all event handlers return void and take two parameters. The first parameter is "Source" of the event. The Second parameter is object derived from "EventArgs". 7. EventArgs is the base class for all event data. Other than its constructor, this class inherits all method from Object class. It contains a public static field named "Empty". This represents an Event with no state. The EventArgs derived class contains information about the Event. Publish and Subscribe Example using using using using using
System; System.Collections.Generic; System.Linq; System.Text; System.Threading;
namespace EventExampleTime { #region infoOfEvent public class TimeEvent : EventArgs { public readonly int Hour; public readonly int Minute; public readonly int Second; public TimeEvent(int hour, int minute, int second)
{ this.Hour = hour; this.Minute = minute; this.Second = second; } } #endregion #region publishClass public class Clock { private int hour; private int minute; private int second; public delegate void SecondChangeHandlerDelegate(object clock, TimeEvent timeInformation); public SecondChangeHandlerDelegate SecondChanged; protected virtual void OnSecondChanged(TimeEvent e) { if (SecondChanged != null) { SecondChanged(this, e); } } public void Run() { for (; ; ) { Thread.Sleep(10); DateTime dt = DateTime.Now; if(dt.Second!= second) { TimeEvent timeInformation = new TimeEvent(dt.Hour, dt.Minute, dt.Second); OnSecondChanged(timeInformation); } this.second = dt.Second; this.minute = dt.Minute;
this.hour = dt.Hour; } } } #endregion #region observerClass public class DisplayClock { public void Subscribe(Clock theClock) { theClock.SecondChanged += new Clock.SecondChangeHandlerDelegate(timeHasChanged); } public void timeHasChanged(object theClock, TimeEvent ti) { Console.WriteLine("Current Time : {0}:{1}:{2}", ti.Hour.ToString(), ti.Minute.ToString(), ti.Second.ToString()); } } #endregion #region observerClass2 public class LogCurrentTime { public void Subscribe(Clock theClock) { theClock.SecondChanged += new Clock.SecondChangeHandlerDelegate(writelogentry); } public void writelogentry(object theClock, TimeEvent ti) { Console.WriteLine(" Logging to File : {0}:{1}:{2}", ti.Hour.ToString(), ti.Minute.ToString(), ti.Second.ToString()); } }
#endregion class Program { static void Main(string[] args) { Clock theClock = new Clock(); DisplayClock dc = new DisplayClock(); dc.Subscribe(theClock); LogCurrentTime lct = new LogCurrentTime(); lct.Subscribe(theClock); theClock.Run(); Console.Read(); } } }