# Delegates and Events ![](imgs/11%20Delegates%20and%20Events_0.png) --- # Overview Delegates Multicast Delegates Anonymous Methods Events # Delegates * __Delegates __ are reference type variables that hold a __reference to a method__ or multiple methods * Class objects hold a reference to a class instance, delegate objects hold a reference to a method / methods * Similar to function pointers in C and C++, or how any function in JavaScript works * Allows for methods to be passed as variables, useful for creating, for example, events # Creating a Delegate Declare a delegate using the following syntax: delegate \ \(\); Example: delegate void PrintDelegate(string output); This creates a new delegate of type void, named PrintDelegate and one parameter of type string The referenced method return and parameter types have to match the delegate! # Referencing a Delegate After creating the delegate, it can be instantiated and the method assigned to it with the method name: delegate void PrintDelegate(string output); static void Main(string[] args) { void PrintInLower(string text) { Console.WriteLine(text.ToLower()); } PrintDelegate print = PrintInLower; print("AaaBbbCcc"); // Outputs "aaabbbccc" } # Using Multicast Delegates Delegates can be __composed of__ multiple methods using the "+" operator Using the same PrintDelegate delegate as before, we could do this: delegate void PrintDelegate(string output); static void Main(string[] args) { void PrintInLower(string text) { Console.WriteLine(text.ToLower()); } void PrintInUpper(string text) { Console.WriteLine(text.ToUpper()); } PrintDelegate print = PrintInLower; print += PrintInUpper; print("AaaBbbCcc"); } ![](imgs/11%20Delegates%20and%20Events_1.png) # Using Multicast Delegates (continued) Methods can be removed from the delegate with the "-" operator: delegate void PrintDelegate(string output); static void Main(string[] args) { ... print -= PrintInLower; print("AaaBbbCcc"); // Outputs "AAABBBCCC" ... } # Delegates - Example Let's extend our previous example (without the "-=" part) by creating a new class called DelegateTest, and giving it a constructor that takes a PrintDelegate object as a parameter: public class DelegateTest { public DelegateTest(PrintDelegate printDelegate) { printDelegate("This Method Was Called From Another Class!"); } } # Delegates - Example (continued) Now we can create a new DelegateTest object and pass the delegate to the object constructor: void PrintInLower(string text) { Console.WriteLine(text.ToLower()); } void PrintInUpper(string text) { Console.WriteLine(text.ToUpper()); } // Initialize new delegate which is composed of PrintInLower method PrintDelegate print = PrintInLower; // Add PrintInUpper method to the delegate print += PrintInUpper; // Send the delegate to the class constructor DelegateTest delegateTest = new DelegateTest(print); ![](imgs/11%20Delegates%20and%20Events_2.png) # Anonymous Methods Delegates can be initialized anonymously (without a specified name) Anonymous method in variable declaration: delegate void PrintDelegate(string output); bool printUpper = true; PrintDelegate printCheckUpper = delegate (string text) { if (printUpper) Console.WriteLine(text.ToUpper()); else Console.WriteLine(text); }; printCheckUpper("I'm not angry!"); // Outputs I'M NOT ANGRY! Notice that the actual method that prints the text is not declared anywhere You can use an empty anonymous method to initialize a delegate which does nothing: delegate void SomeDelegate(); class Program { static void Main(string[] args) { // Initialize an empty delegate, add method later... SomeDelegate myDelegate = new SomeDelegate(delegate { }); } } # Events * Consider the following Game class: * class Game * { * Sound gameOverSound; * Window gameOverScreen; * // Some game logic here... * // ... * void OnGameOver() * { * gameOverSound.Play(); // This plays some sound * gameOverScreen.Show(); // This shows some screen * } * } * This raises a couple of problems: * The Game class has to know about the Sound and Window classes * Changes in either of the classes could break the code * = Game is dependent of Sound and Window classes --- Tight coupling # Events (continued) Events are signals that are raised by a __Publisher __ and received by a __Subscriber__ The publisher does not know or care what, if any, object receives the signal Changes in the subscriber classes do not affect the publisher # Events - Example Events are created in two steps: Declare a delegate Declare a variable of the delegate with the event keyword public delegate void GameOver(); class Game { public event GameOver GameOverEventHandler; // Some game logic here... // ... } # Exercise 1: A Rudimentary Event System Create a console application for controlling a plant treatment system, that has three methods which print the following outputs: | void ReleaseWater() | Releasing water... | | :-: | :-: | | void ReleaseFertilizer() | Releasing fertilizer... | | void IncreaseTemperature() | Increasing temperature... | Create a main loop where the user can switch each method on (= add to a delegate) by writing its name. All methods are off by default. (Hint: you can just use switch-case for defining which method should be added to the delegate) If the user types run, all the methods that are on (= added to the delegate), will be executed. ![](imgs/11%20Delegates%20and%20Events_3.png)