Events, delegates and lambdas in .NET C# part 6: other scenarios

Introduction

So far in this series we’ve seen the basics of events, delegates and lambdas. We’ve looked at examples of how to define these elements and use them in code.

It’s now time for us to look at some other simulated scenarios where you can use these language elements. In particular we’ll look at the following:

  • Mediator pattern with delegates
  • Asynchronous delegate invocation

Communication across components

Imagine a scenario where you have a dynamic GUI of a Windows application. The components – widgets – can be loaded here and there and they are independent of each other to allow for loose coupling. At the same time they should be able to communicate with each other.

This scenario can be generalised: imagine independent objects that don’t know about other objects but still want to communicate with them in case they are present.

This is a perfect scenario for events and delegates and a pattern called the Mediator pattern. If you don’t know what a mediator is then make sure to read that introduction where the pattern is demonstrated without using events and delegates. With independent components we’ll need a Mediator that acts as a glue for those components. They will only know about the Mediator but not the other objects they are indirectly communicating with.

An additional pattern that is useful in this scenario is the Singleton pattern. If you don’t know what it means then skim through that article to get the basics. The purpose of the singleton in this case is to have only one Mediator class in memory. Otherwise the independent components may reference different mediators.

Note that this post concentrates on the role of delegates and events. If you’d like to extend this example so that it better follows SOLID and abstractions then look through blog entries in the Architecture and patterns section.

Open the project we’ve been working on in this series and add a new C# library called ComponentsMediator. Add a new class to it called Mediator which will be responsible for the communication between the independent components.

Add the following elements to adhere to the singleton pattern. We’ll employ a simple version of the pattern. Read the referenced article to see what some of the other possible solutions are.

private static readonly Mediator _instance = new Mediator();

private Mediator() { }
public static Mediator Instance
{
        get
	{
		return _instance;
	}
}

We’ll simulate the scenario where the user selects a product in a drop down list. We want to update the screen accordingly. Add the following Product class to the project:

public class Product
{
	public int Id { get; set; }
	public string Name { get; set; }
	public DateTime Registered { get; set; }
	public int OnStock { get; set; }
}

Return to Mediator.cs and add the following event handler to the Mediator:

public event EventHandler<ProductChangedEventArgs> ProductChanged;

…where ProductChangedEventArgs looks as follows:

public class ProductChangedEventArgs : EventArgs
{
	public Product Product { get; set; }
}

We’ll raise the event in the following method:

public void OnProductChanged(object sender, Product product)
{
	if (ProductChanged != null)
	{
		ProductChanged(sender, new ProductChangedEventArgs() { Product = product });
	}
}

By allowing the sender to be passed in we show that the original event raiser was an object different from the Mediator. Otherwise all products would “think” that the Mediator raised the event which is not entirely true. Keep in mind that the mediator is only an errrm…, well, a mediator. It mediates between independent objects. We need to see if there’s any listener by checking if ProductChanged is null.

Let’s add a component that will initiate the product selection change. You can think of this object as a combo box where the users can select products:

public class ProductChangeInitiator
{
	public ProductChangeInitiator(int selectedProductId)
	{
		SelectedProductId = selectedProductId;			
	}

	public int SelectedProductId { get; set; }

}

Add another class to the library called ProductChangeSimulation and a method called SimulateProductChange:

public class ProductChangeSimulation
{
        private List<Product> _allProducts = new List<Product>()
	{
		new Product(){Name = "FirstProduct", Id = 1, Registered = DateTime.Now.AddDays(-1), OnStock = 456}
		, new Product(){Name = "SecondProduct", Id = 2, Registered = DateTime.Now.AddDays(-2), OnStock = 123}
		, new Product(){Name = "ThirdProduct", Id = 3, Registered = DateTime.Now.AddDays(-3), OnStock = 987}
		, new Product(){Name = "FourthProduct", Id = 4, Registered = DateTime.Now.AddDays(-4), OnStock = 432}
		, new Product(){Name = "FifthProduct", Id = 5, Registered = DateTime.Now.AddDays(-5), OnStock = 745}
		, new Product(){Name = "SixthProduct", Id = 6, Registered = DateTime.Now.AddDays(-6), OnStock = 456}
	};

	public void SimulateProductChange(ProductChangeInitiator changeInitiator)
	{
		Product selectedProduct = (from p in _allProducts where p.Id == changeInitiator.SelectedProductId select p).FirstOrDefault();
		Mediator.Instance.OnProductChanged(changeInitiator, selectedProduct);
	}
}

We maintain a list of products in a private variable. We let the product change initiator to be passed into the method. We then call the OnProductChanged event handler of the mediator by passing the changeInitiator as the original sender and the selected product.

We now have the components ready in order to raise the event and pass in the necessary parameters. We’ll now need a listener. Add a new class called Warehouse:

public class Warehouse
{
	public Warehouse()
	{
		Mediator.Instance.ProductChanged += (s, e) => { SaveChangesInRepository(e.Product); };
	}

	private void SaveChangesInRepository(Product product)
	{
		Console.WriteLine("About to save the changes for product {0}", product.Name);
	}
}

We subscribe to the ProductChanged event of the mediator where the initiator of the event is unknown to Warehouse. It could be any component in reality: a customer, an e-commerce site, a physical shop, whatever. The Warehouse object won’t care. It only wants to know if there was a change so that it can go on with its job. As you see we declared the event subscription with a lambda.

Add a reference from the main project to the ComponentsMediator library. We can connect the pieces from Program.Main as follows:

ProductChangeInitiator initiator = new ProductChangeInitiator(2);
Warehouse warehouse = new Warehouse();
ProductChangeSimulation simulation = new ProductChangeSimulation();
simulation.SimulateProductChange(initiator);

We simulate the product id #2 was selected and start the simulation. You’ll see that Warehouse correctly displays the message in the console.

Let’s add another listener to the library project. Let’s say that the company CEO is a control freak and wants to be notified of all product changes:

public class CEO
{
	public CEO()
	{
		Mediator.Instance.ProductChanged += (s, e) => 
		{ 
			Console.WriteLine("This is the CEO speaking. Well done for selling {0}", e.Product.Name); 
		};
	}
}

Extend the code in Main as follows:

ProductChangeInitiator initiator = new ProductChangeInitiator(2);
Warehouse warehouse = new Warehouse();
CEO ceo = new CEO();
ProductChangeSimulation simulation = new ProductChangeSimulation();
simulation.SimulateProductChange(initiator);

You’ll see that the CEO is very happy now. We effortlessly added another listener to the product change. The CEO, Warehouse and ProductChangeInitiator objects don’t know about each other. This ensures that the components remain loosely coupled. The listeners won’t care where the notification is coming from, they are only connected to the mediator.

Asynchronous delegates

Let’s look at how asynchronous operations can be applied to delegates. Insert a new C# library to the project called AsyncDelegates. Insert a new class called AsynchronousProcessSimulation. Imagine that we start a long process and want to be notified of the progress made. Insert the following method that represents our lengthy process:

private void DoProgress(int maxValue)
{
	for (int i = 0; i <= maxValue; i++)
	{
		Console.WriteLine("Time : {0}", i);
		Thread.Sleep(50);
	}
}

We want to use a delegate to wire the information to the DoProgress method. We’ll do it with a private delegate:

private delegate void ShowProgressDelegate(int status);

Insert the following public entry point that initiates the delegate:

public void StartReporting()
{
	ShowProgressDelegate progressDelegate = new ShowProgressDelegate(DoProgress);
}

Let’s say that we want to invoke this delegate asynchronously. Delegates have a built-in method called BeginInvoke which comes in very handy. It will spin up a separate thread that will call into DoProgress. We can pass in the value for the maxValue parameter, a callback function and an additional object input which will be null in this example. We don’t need a callback either. Add the following async call to StartReporting:

progressDelegate.BeginInvoke(500, null, null);
Console.WriteLine("Finishing the StartReporting method.");

Insert a reference to this project from the main project. You can test the async delegate as follows:

AsynchronousProcessSimulation asyncSimulation = new AsynchronousProcessSimulation();
asyncSimulation.StartReporting();

You’ll see that “Finishing the StartReporting method.” is printed in the console after the delegate has been invoked on a different thread proving the point that BeginInvoke did in fact spawn up a new thread. The lengthy operation just keeps running in the background.

This post finishes this series on delegates and events. I hope you have learned some new stuff that you can use in your own project.

Events, delegates and lambdas in .NET C# part 4: subscribing to events

Introduction

We saw in the previous post how to add delegates, events and event handlers to our SuperHero class. We also discussed that the standard signature for a delegate in .NET accepts the sender as an objects and another object that inherits from the EventArgs class. You may of course define your delegate as you like but consumers of your class will be expecting the standard signature.

The missing piece now is to wire up those elements. The key is to understand how to add an element to the invocation list. Then as the event fires the elements – methods – will be called one after the other in that list.

Demo

Open the project we’ve been working on in this series. The goal is to create a SuperHero object and subscribe to its events. You can imagine that Program.cs is the police chief who sends out a hero to save the world but wants him/her to report the progress and outcome of the work done.

In Main declare a new SuperHero:

SuperHero superman = new SuperHero();

There’s a number of ways you can subscribe to the events of the superhero. Start typing “superman.” in the editor and IntelliSense will list the available events denoted by a lightning bolt. You add elements to the invocation list with the “+=” operator. So type…

superman.WorldSaved +=

…in the editor and you’ll see that IntelliSense is trying to help you by automatically suggesting a method that will be created for you and which matches the delegate signature. Press TAB twice in order for this to happen. You should have the following method in Program.cs:

static void superman_WorldSaved(object sender, WorldSavedEventArgs e)
{
	throw new NotImplementedException();
}

This is called delegate inference. You didn’t have to new up a delegate yourself. The compiler will do it for you in the background.

Another way to get to the same result is to new up a WorldSavedHandler delegate and pass in the method that will be added to the invocation list:

superman.WorldSaved += new DelegatesIntro.WorldSavedHandler(superman_WorldSaved);

You can test to pass in a method that does not match the delegate signature: Visual Studio will complain immediately.

You can do it either way, it doesn’t make any difference to the outcome. The first option is probably more convenient as Visual Studio is guaranteed to create a method with the correct signature and you can save some code and time.

Modify the method to show some message on the console window:

static void superman_WorldSaved(object sender, WorldSavedEventArgs e)
{
	StringBuilder superHeroMessageBuilder = new StringBuilder();
	superHeroMessageBuilder.Append("Superhero reporting progress! Name: ")
		.Append(e.SaviourName).Append(", has been working for ").Append(e.WorkHasBeenOngoingHs)
		.Append(" hours, ").Append(" date of next occasion: ").Append(e.DateOfNextCatastrophy);
	Console.WriteLine(superHeroMessageBuilder.ToString());
}

The next step is to call on the superhero to finally start working:

superman.SaveTheWorld("Superman", DateTime.UtcNow.AddMonths(3));

Run the code and you’ll see that Superman reports the progress as expected. So you can see that this is kind of a nice way to get multiple values returned by a void method.

Let’s also subscribe to the other event of the superhero:

superman.WorldSavingCompleted += superman_WorldSavingCompleted;

…where superman_WorldSavingCompleted looks like this:

static void superman_WorldSavingCompleted(object sender, WorldSavingCompletedEventArgs e)
{
	StringBuilder superHeroMessageBuilder = new StringBuilder();
	superHeroMessageBuilder.Append("Superhero has saved the world! Name: ").Append(e.Saviour)
		.Append(", time spent saving the world: ").Append(e.HoursItTookToSaveWorld).Append(", message from the superhero: ")
		.Append(e.MessageFromSaviour);
	Console.WriteLine(superHeroMessageBuilder.ToString());
}

Run the code and you’ll see that the correct methods are called when the events fire.

If you want to remove a method from the invocation list then you can use the “-=” operator. If you insert the following – admittedly senseless – code, then you won’t see when the superhero has finished saving the world:

superman.WorldSavingCompleted += superman_WorldSavingCompleted;
superman.WorldSavingCompleted -= superman_WorldSavingCompleted;

Anonymous methods

So far we have declared the elements that react to events as standalone methods. There’s nothing wrong with that at all, but it’s not the only way. As an alternative you can embed the actions in something called an anonymous method which can only be used at the source of the subscription, i.e. where the “+=” operator is used. An anonymous method has no name and may look quite strange at first. You may have heard of “lambdas” before, but they are not the same thing as anonymous methods. They are similar features but still not quite the same. We’ll be looking into lambdas in a later post.

Anonymous methods are defined by the “delegate” keyword. It is followed by the input parameter declarations and finally the method body in curly braces. You close the whole statement with a semi-colon ‘;’.

So we can rewrite…

superman.WorldSavingCompleted += superman_WorldSavingCompleted;


static void superman_WorldSavingCompleted(object sender, WorldSavingCompletedEventArgs e)
{
	StringBuilder superHeroMessageBuilder = new StringBuilder();
	superHeroMessageBuilder.Append("Superhero has saved the world! Name: ").Append(e.Saviour)
		.Append(", time spent saving the world: ").Append(e.HoursItTookToSaveWorld).Append(", message from the superhero: ")
		.Append(e.MessageFromSaviour);
	Console.WriteLine(superHeroMessageBuilder.ToString());
}

…as follows:

superman.WorldSavingCompleted += delegate(object sender, WorldSavingCompletedEventArgs e)
{
	StringBuilder superHeroMessageBuilder = new StringBuilder();
	superHeroMessageBuilder.Append("Superhero has saved the world! Name: ").Append(e.Saviour)
		.Append(", time spent saving the world: ").Append(e.HoursItTookToSaveWorld).Append(", message from the superhero: ")
		.Append(e.MessageFromSaviour);
	Console.WriteLine(superHeroMessageBuilder.ToString());
};

We declare that whatever happens in case the event is fired, it is done right at the source. Note that this method can only be used “here and now” and not be called from anywhere else: it cannot be reused in other words. You may take this approach in case the method body is very simple and don’t want to write a dedicated method for it. In case the method body gets too long then you might want to break it out into a separate method.

We’ll start discussing lambdas, Func of T and Action of T in the next post.

Events, delegates and lambdas in .NET C# part 3: delegates with events in action

Introduction

In the previous part of this series we looked at some examples of delegates. We also discussed the basics of events in .NET. We’re now ready to see some custom events in action.

Demo

Open the project we’ve been working on in this series. Add a new class to the project called SuperHero. Add the following method stub to SuperHero.cs:

public void SaveTheWorld(string saviourName, DateTime dateForNextCatastrophy)
{

}

Also, add the same delegate as we had before in Program.cs:

public delegate void WorldSavedHandler(string saviourName, DateTime dateForNextCatastrophy);

You can also put this is a separate class, it’s up to you.

Let’s say that an external class, such a police chief calls SuperHero to save the world and wants to monitor the progress. SaveTheWorld is void so we cannot read out anything from this method. However, we can raise events. We now know how to declare events so let’s add one to SuperHero.cs:

public event WorldSavedHandler WorldSaved;

The police chief will want to know when the world has been saved, i.e. the superhero’s work has completed. We can add an event handler for that. Add the following code just below the event declaration:

public event EventHandler WorldSavingCompleted;

EventHandler is the built-in .NET event handler that may look familiar to you from Windows UI programming. It is a delegate that does not return anything, accepts an object – the sender – and an EventArgs argument. So this is just a short-hand solution for a case where we don’t have any specialised event arguments. We only want to notify all listeners that the work has been completed. Note that EventHandler has a generic form as well: EventHandler of type T : EventArgs. Use this version if you want to specify a more specialised EventArgs class than the default empty EventArgs:

public event EventHandler<WorldSavingCompletedEventArgs> WorldSavingCompleted;

Then when you raise this event you’ll have to provide WorldSavingCompletedEventArgs to it instead of just EventArgs. Later on we’ll see an example of this.

We have now declared the events. The next step is to raise them. There are basically two ways to do that. One is to call an event like you would call a method:

if (WorldSaved != null)
{
	WorldSaved(saviourName, dateForNextCatastrophy);				
}

Another way is to extract the delegate from the event and invoke it:

WorldSavedHandler handler = WorldSaved as WorldSavedHandler;
if (handler != null)
{
	handler(saviourName, dateForNextCatastrophy);
}

Why do we check for a null value? It’s because if no other object has signed up with the event, i.e. there’s nothing in the invocation list, then the event will be null and you’ll get a null pointer exception if you try to raise it. It is the same as trying to call a method of an object that has not been initialised.

A common practice is to raise the event in a dedicated method and give that method a special name: ‘On’ + the name of the event, kind of like the familiar “OnClick” and “OnSelectedItemChanged” etc. methods. This is not a must for the event to work, only a possible way to organise your code:

public void SaveTheWorld(string saviourName, DateTime dateForNextCatastrophy)
{
	OnWorldSaved(saviourName, dateForNextCatastrophy);
}

private void OnWorldSaved(string saviourName, DateTime dateForNextCatastrophy)
{
	if (WorldSaved != null)
	{
		WorldSaved(saviourName, dateForNextCatastrophy);
	}
}

Let’s say that the police chief wants to monitor the superhero’s progress every hour. We’ll also hard code the duration of the superhero’s work to 4 hours to make this simple. So we’ll raise a WorldSaved event every hour to report some progress. At the end of the 4 hours we’ll raise a WorldSavingCompleted event to tell the world that the superhero has finished:

public void SaveTheWorld(string saviourName, DateTime dateForNextCatastrophy)
{
	int hoursToSaveTheWorld = 4;
	for (int i = 0; i < hoursToSaveTheWorld; i++)
	{
		OnWorldSaved(i + 1, saviourName, dateForNextCatastrophy);
		Thread.Sleep(1000);
	}
	OnWorldSavingCompleted();
}

private void OnWorldSaved(int hoursPassed, string saviourName, DateTime dateForNextCatastrophy)
{
	if (WorldSaved != null)
	{
		WorldSaved(string.Concat(saviourName, " has been working for ", hoursPassed, " hour(s)"), 
			dateForNextCatastrophy);
	}
}

private void OnWorldSavingCompleted()
{
	if (WorldSavingCompleted != null)
	{
		WorldSavingCompleted(this, EventArgs.Empty);
	}
}

So we report every hour worked by the superhero. In the OnWorldSavingCompleted method we raise the default .NET event which accepts the sender as an object and an EventArgs class. The sender of the event is ‘this’, i.e. the current SuperHero object. We don’t have any data to transmit to the listeners so we use the EventArgs.Empty convenience method. We’ll see later on how to send your data with your custom EventArgs object.

This is quite a nice way of getting sort of multiple return values out of void methods. Indeed, all listeners will be notified of the events raised by the superhero.

Custom event arguments

We’ve seen two ways to create delegates in this post: directly with the ‘delegate’ keyword and by using the built-in EventHandler class that is a wrapper around a delegate. Before we see how to subscribe to these events from the outside we need know how to pass custom event arguments.

The usual and standard way in .NET to create events is by specifying a method signature where the handling method will accept the sender as an object and an EventArgs. You must have seen that before if you did any Windows GUI development. We’ve also seen an example of that in OnWorldSavingCompleted(). However, that is kind of limiting as the default EventArgs is – almost – empty, you cannot supply your own messages to it.

Creating a custom EventArgs is very easy: create a class and inherit from the EventArgs object. You are then free to put an as many properties as you wish. You don’t need to worry about extending a parameter list of some delegate, you can just add new properties to your event args class. Add the following class to the project:

public class WorldSavingCompletedEventArgs : EventArgs
{
	public string Saviour { get; set; }
	public DateTime TimeForNextCatastrophy { get; set; }
	public int HoursItTookToSaveWorld { get; set; }
        public string MessageFromSaviour { get; set; }
}

The naming convention is to take the name of the event and attach ‘EventArgs’ to it. All the data that needs to be wired to the listeners is now encapsulated within this event args object. It is easy to extend and the properties are easily extracted from it.

Let’s clean up the WorldSavedHandler delegate. Add the following custom event args:

public class WorldSavedEventArgs : EventArgs
{
	public string SaviourName { get; set; }
	public DateTime DateOfNextCatastrophy { get; set; }
}

The WorldSavedHandler will take the following form:

public delegate void WorldSavedHandler(object sender, WorldSavedEventArgs e);

You’ll get compiler errors because we’ve changed the signature of the handler, we’ll correct it in a bit. As hinted at above the EventHandler object has a generic form to specify the type of the event handler. An advantage of using the EventHandler class will ensure that you’re sticking to the standard event signature. Modify the WorldSavingCompleted event handler to the following:

public event EventHandler<WorldSavingCompletedEventArgs> WorldSavingCompleted;

We can keep both examples, i.e. the delegate and the EventHandler in this demo project so that you can see both approaches, but in practice it’s more convenient to just stick to EventHandler and EventHandler of T. Using the EventHandler object saves having a separate delegate. Use the delegate-event-pair approach if you need access to the delegate on its own, i.e. without the matching event. Let’s clean up our code so that it compiles:

public delegate void WorldSavedHandler(object sender, WorldSavedEventArgs e);

public class SuperHero
{
	public event WorldSavedHandler WorldSaved;
	public event EventHandler<WorldSavingCompletedEventArgs> WorldSavingCompleted;

	public void SaveTheWorld(string saviourName, DateTime dateForNextCatastrophy)
	{
		int hoursToSaveTheWorld = 4;
		for (int i = 0; i < hoursToSaveTheWorld; i++)
		{
			OnWorldSaved(i + 1, saviourName, dateForNextCatastrophy);
			Thread.Sleep(1000);
		}
		OnWorldSavingCompleted(hoursToSaveTheWorld, "Yaaay!", saviourName, dateForNextCatastrophy);
	}

	private void OnWorldSaved(int hoursPassed, string saviourName, DateTime dateForNextCatastrophy)
	{
		if (WorldSaved != null)
		{
			WorldSavedEventArgs e = new WorldSavedEventArgs()
			{
				DateOfNextCatastrophy = dateForNextCatastrophy
				, SaviourName = saviourName
				, WorkHasBeenOngoingHs = hoursPassed
			};
			WorldSaved(this, e);
		}
	}

	private void OnWorldSavingCompleted(int totalHoursWorked, string message, string saviour, DateTime timeOfNextCatastrophy)
	{
		if (WorldSavingCompleted != null)
		{
			WorldSavingCompletedEventArgs e = new WorldSavingCompletedEventArgs()
			{
				HoursItTookToSaveWorld = totalHoursWorked
				, MessageFromSaviour = message
				, Saviour = saviour
				, TimeForNextCatastrophy = timeOfNextCatastrophy
			};
			WorldSavingCompleted(this, e);
		}
	}
}

You’ll see the revised delegate and event handler definitions. They follow the sender/eventargs convention. You also see how easy it is to wire data through the custom event args to the listeners.

Now the SuperHero class is ready to work and make announcements. But no-one is listening yet to catch those event notifications. We’ll see how to do just that in the next post.

Events, delegates and lambdas in .NET C# part 2: delegates in action

Introduction

In the previous installment of this series we looked at the foundations of delegates, events and event handlers. It’s now time to see them in action.

Demo

Open Visual Studio 2012/2013 and create a new Console application with .NET 4.5 as the underlying framework. I haven’t tested the code with .NET4.0 or .NET 3.5 but I think it should work with those frameworks as well.

In Program.cs add the following delegate declaration just above the Main method:

public delegate void WorldSavedHandler(string saviourName, DateTime dateForNextCatastrophy);

So this is a delegate for when some superhero saves the world for the nth time. It is void, it has a name and accepts two parameters: a string and a date. Note that it’s customary but not mandatory to name delegates with the word ‘Handler’ attached.

Add the following methods that match the delegate signature:

static void WorldSaved(string saviour, DateTime nextTime)
{
	Console.WriteLine(string.Concat("World saved by ", saviour, ", get ready again by ", nextTime));
}

static void WorldSavedAgain(string saviour, DateTime nextTime)
{
	Console.WriteLine(string.Concat("World saved this time by ", saviour, ", get ready again by ", nextTime));
}

In Main you can instantiate a delegate and hook up a callback method as follows:

WorldSavedHandler worldSavedHandler = new WorldSavedHandler(WorldSaved);

As you type the declaration in the editor IntelliSense will indicate that the delegate is expecting a void method that accepts a string and a date. If you try to pass in a method that doesn’t match this signature you’ll get a compile error. Add another delegate declaration to Main:

WorldSavedHandler worldSavedAgainHandler = new WorldSavedHandler(WorldSavedAgain);

We have set up two pipelines: worldSavedHandler which sends its data to WorldSaved and worldSavedAgainHandler which sends its data to WorldSavedAgain. We can invoke the delegates the same way as we normally call a method:

worldSavedHandler("Bruce Willis", DateTime.UtcNow.AddYears(2));
worldSavedAgainHandler("Spiderman", DateTime.UtcNow.AddMonths(3));

Console.ReadKey();

I added the call to ReadKey so that the console window doesn’t just close down.

Run the program and you’ll see the appropriate output in the console window.

Why on earth are we bothering with this? Up to now this looks like some funny way of calling methods. Consider the following method which accepts our delegate type:

static void SaveWorld(WorldSavedHandler worldSaved)
{
	worldSaved("Bruce Willis", DateTime.UtcNow.AddMonths(5));
}

In Main comment out the two delegate calls…:

worldSavedHandler("Bruce Willis", DateTime.UtcNow.AddYears(2));
worldSavedAgainHandler("Spiderman", DateTime.UtcNow.AddMonths(3));

…and add the following instead:

SaveWorld(worldSavedHandler);

This is stating that we need to save the world and we have 2 possible delegates to give this work to. We entrust worldSavedHandler with this task so we pass it in. An analogy from the real world is when a boss decides the software development team needs to build the data access layer and appoints a particular team member to do just that. In other words the boss delegates the job to a particular programmer, i.e. a handler.

We know that worldSavedHandler will call WorldSaved. SaveWorld gets the delegate and will invoke whatever was passed to it. SaveWorld does NOT know which handler the delegate will call. From its point of view it could be any method with the correct signature, so it’s quite a dynamic setup. The delegate could have been passed in from whichever external object to the SaveWorld method. SaveWorld passes in Bruce Willis and now + 3 months to some unknown method.

Run the program and you’ll see that WorldSaved was called. Now, without changing SaveWorld directly, you can modify its outcome just by providing a different delegate:

SaveWorld(worldSavedAgainHandler);

Run the program and WorldSavedAgain was called as expected without changing SaveWorld at all.

Let’s look at multicasting quickly. Comment out the call to SaveWorld in Main and instead add a third delegate declaration:

WorldSavedHandler worldSavedOnceMoreHandler = new WorldSavedHandler(WorldSavedOnceMore);

…where WorldSavedOnceMore looks like this:

static void WorldSavedOnceMore(string saviour, DateTime nextTime)
{
	Console.WriteLine(string.Concat("World saved once again by ", saviour, ", get ready again by ", nextTime));
}

There are different way to build an invocation list. The following chains our three delegates together:

worldSavedHandler += worldSavedAgainHandler;
worldSavedHandler += worldSavedOnceMoreHandler;

worldSavedHandler("Superman", DateTime.UtcNow.AddMonths(3));

You’ll see that all three method handlers were called.

The below is equivalent to the above:

worldSavedHandler += worldSavedAgainHandler + worldSavedOnceMoreHandler;
worldSavedHandler("Superman", DateTime.UtcNow.AddMonths(3));

The following will wipe out the first handler:

worldSavedHandler = worldSavedAgainHandler + worldSavedOnceMoreHandler;
worldSavedHandler("Superman", DateTime.UtcNow.AddMonths(3));

This time only WorldSavedAgain and WorldSavedOnceMore are called.

You’ll also see that each handler is called in the order they were added to the invocation list. This way we can invoke multiple handlers by calling just one delegate, in this case worldSavedHandler.

Returning a value from a delegate

Delegates can return values, they don’t need to be void all the time. Add the following delegate to Program.cs:

public delegate string SomeoneJustShoutedHandler(string who, DateTime when);

Add the following handlers:

static string SomeoneShouted(string who, DateTime when)
{
	return string.Concat(who , " has shouted on ", when);
}

static string SomeoneShoutedAgain(string who, DateTime when)
{
	return string.Concat(who, " has shouted on ", when);
}

static string SomeoneShoutedOnceMore(string who, DateTime when)
{
	return string.Concat(who, " has shouted once more on ", when);
}

…and 3 delegate declarations with the delegate chain:

SomeoneJustShoutedHandler someoneShoutedHandler = new SomeoneJustShoutedHandler(SomeoneShouted);
SomeoneJustShoutedHandler someoneShoutedAgainHandler = new SomeoneJustShoutedHandler(SomeoneShoutedAgain);
SomeoneJustShoutedHandler someoneShoutedOnceMoreHandler = new SomeoneJustShoutedHandler(SomeoneShoutedOnceMore);

someoneShoutedHandler += someoneShoutedAgainHandler + someoneShoutedOnceMoreHandler;
string finalShout = someoneShoutedHandler("The neighbour", DateTime.UtcNow);
Console.WriteLine("Final shout: " + finalShout);

Run the code and you’ll see that it’s only the third string that’s returned. It’s logical as we cannot have multiple return values in C#. You can get the individual return values by calling the delegates separately. However, with an invocation list the last delegate in the list will win.

Adding events

We’ve seen that using delegates can work fine without adding events to the code. However, delegates coupled with events help us raise those events and propagate the event arguments to all listeners in the invocation list.

An event is declared using the ‘event’ keyword in C#. It is also declared with the type of the delegate that raises the event as an event by itself cannot do much. Events are the standard way of providing notifications to all listeners. The data will be supplied using the delegate declared in conjunction with the event. In .NET programming you’ll probably rarely see delegates used without events although it’s certainly possible as we’ve seen above. You also give a name to the event. Here’s an example of an event declaration:

public event WorldSavedHandler WorldHasBeenSaved;

Listeners will be able to sign up with the event and receive a notification when the event has fired. It is equivalent to building the invocation list we saw above. So an event is really nothing but a wrapper around a delegate.

There’s also a more complex way of defining an event using the add/remove accessors:

private WorldSavedHandler WorldHasBeenSaved;
public event WorldSavedHandler WorldSaved
{
	[MethodImpl(MethodImplOptions.Synchronized)]
	add
	{
		WorldHasBeenSaved = (WorldSavedHandler)Delegate.Combine(WorldHasBeenSaved, value);
	}
	[MethodImpl(MethodImplOptions.Synchronized)]
	remove
	{
		WorldHasBeenSaved = (WorldSavedHandler)Delegate.Remove(WorldHasBeenSaved, value);
	}
}

This provides more control over how listeners are added to and removed from the invocation list. You’ll probably not see this kind of event declaration too often. However, if you see it somewhere then you’ll now know what it means.

We have a private delegate of type WorldSavedHandler. Then we see the event declaration that conforms to the example provided above. The add accessor defines how a listener is added to the invocation list. The remove accessor does the opposite. The actions are synchronised to make sure that if different threads perform the same action we don’t run into concurrency issues. The ‘value’ keyword indicates the listener that’s going to be added to the invocation list. The Delegate.Combine method takes the delegate we already have and adds in the new one. The remove accessor works with the Delegate.Remove method that removes ‘value’ from the invocation list.

You might use this type of event declaration if you have extra logic on who and when is allowed to be listed on the invocation list. The access may be limited to some special objects that fulfil certain rules.

Now that we know more about events than we ever wanted to we can create some custom events in our code. We’ll actually do that in the next part.

Events, delegates and lambdas in .NET C# part 1: delegate basics

Introduction

I believe that learning the basic features of a popular OO language, such as C# or Java is not too difficult. Obviously you’ll need a positive mindset towards programming in general otherwise you’re bound to fail but that’s true for every discipline. The basic structures found in C#, such as classes, properties, constructors, methods, functions, interfaces and the like are quite straightforward and simple to use even after a couple of months’ worth of training. If you have a Java or C++ background then you can start to be productive with C# after some weeks even.

However, there are some language features that stick out a little as they are slightly more cryptic: events, delegates and lambda expressions. You can certainly come up with others, but my personal experience is that learning these features thoroughly takes more time than the ones listed above.

This series of posts will be dedicated to these language elements of C#.

The building blocks

If you’ve ever done any Windows app development then you must have seen examples of events and event handlers: button click event, list selection changed event, on mouse over event etc. You added an event and an event handler to a button just by double-clicking on it in the visual editor and the following elements were wired together for you in the background:

  • Event: notifications originating from objects. These notifications can be used to notify other elements – objects – in the application that may be interested in the event, such as when a new order was placed or a party is about to start. Then the objects listening to those events can perform some work dedicated to them: serve the drinks, order the pizzas, let in the guests etc.
  • Event raiser, a.k.a. the Sender: the object that raises the event. They typically don’t know anything about the objects listening to the events raised by themselves
  • Event handler: the handler that ‘caught’ the event raised by the button
  • Delegate: the glue between the button and the event handler. This is usually hidden in the designer cs file of the Form created by Visual Studio, so you may not even have come across it. Without delegates the event raised would not get to the listening objects and their event handlers
  • Event arguments, or EventArgs: the arguments that the Sender is sending to the event handler with the event raised. This can include anything important for the handler, such as the selected item index, the venue for the party, the items that were ordered etc.

Probably the most confusing element in this list is delegates. They are typically described by adjectives such as ‘odd’, ‘strange’ and ‘unusual’. A delegate, also called a function pointer, is a specialised class that derives from the MulticastDelegate base class. As noted above, it connects the event with the event handler. It’s called a function pointer because the event handler will be a function, i.e. a method, and it points at the event handler from the event and wires the event arguments in between.

An event handler will process the data received from a delegate. It is a method with a special signature that must accept a sender of type ‘object’ and an EventArgs parameter or one that’s derived from the EventArgs class. EventArgs objects are normal C# objects with properties. You can easily define your custom event args by deriving from the EventArgs class. You can put in all sorts of properties into your event args that may be interesting for those waiting for the event. A button click event handler may look like this:

public void btnOrderItems_Click(object sender, EventArgs e)
{
      //do something
}

A custom event handler can have the following form:

public void OrderPlaced(object sender, OrderPlacedEventArgs e)
{
      //do something with the order
}

Delegates

You can create delegates with the ‘delegate’ keyword in C#, example:

public delegate void GraphClicked(GraphType graphType, Point clickCoordinate);

It’s void as nothing is returned, data is only sent one way. In this example the delegate’s name is GraphClicked and it accepts two parameters: a graph type and the click coordinates. This declaration is a blueprint for the method, i.e. the handler, that will receive the data from the delegate. The handler method must match this signature otherwise the code will not compile: it must also receive a graph type and the click coordinates. An example of a matching handler:

public void GraphClicked_Handler(GraphType type, Point coords)
{
     //do something
}

Note that the parameter names don’t necessarily match those in the delegate, but the types must match.

The delegate keyword is special in .NET as the compiler does some magic when it sees it declared. It creates another object that inherits from the MulticastDelegate class behind the scenes which in turns derives from the Delegate base class. Multicast delegate means that a single message can be sent to a range of objects through a range of pipelines. Note that you cannot directly derive from the Delegate or the MulticastDelegate classes. You do it indirectly using the delegate keyword and the compiler will do the inheritance trick for you.

The list of pipelines of a multicast delegate is called the Invokation List. The delegates listed here are invoked sequentially.

Now that we have a delegate you can easily instantiate one:

GraphClicked graphClicked = new GraphClicked(GraphClicked_Handler);

So you see a delegate is a class that you can instantiate using the new keyword. Notice that you must specify the handler in the constructor of the delegate. We say that when the graphClicked delegate is invoked then the GraphClicked_Handler method should be called.

You can invoke the graphClicked delegate as follows:

graphClicked(GraphType.Line, new Point(1,1));

So you invoke it like a method and provide the necessary parameters. This adds one delegate item to the invocation list.

There’s nothing stopping you from instantiating several delegates of the same type:

GraphClicked niceGraphClicked = new GraphClicked(NiceGraphClicked_Handler);
GraphClicked uglyGraphClicked = new GraphClicked(UglyGraphClicked_Handler);

These delegates point to two different handlers: NiceGraphClicked_Handler and UglyGraphClicked_Handler. What if you want niceGraphClicked not only invoke NiceGraphClicked_Handler but UglyGraphClicked_Handler as well? In other words you want to extend the invocation list of niceGraphClicked to two items: NiceGraphClicked_Handler but UglyGraphClicked_Handler. It couldn’t be simpler:

niceGraphClicked += uglyGraphClicked;

So now when niceGraphClicked is raised…:

niceGraphClicked(GraphType.Cylinder, new Point(2, 3));

…then both NiceGraphClicked_Handler but UglyGraphClicked_Handler will be called in the same order as they were added to the invocation list.

This post has given you the absolute basics of delegates, events and event handlers. We’ll look at a couple of examples from scratch in the next post.

ultimatemindsettoday

A great WordPress.com site

Elliot Balynn's Blog

A directory of wonderful thoughts

HarsH ReaLiTy

A Good Blog is Hard to Find

Softwarearchitektur in der Praxis

Wissenswertes zu Webentwicklung, Domain-Driven Design und Microservices

Technology Talks

on Microsoft technologies, Web, Android and others

Software Engineering

Web development

Disparate Opinions

Various tidbits

chsakell's Blog

WEB APPLICATION DEVELOPMENT TUTORIALS WITH OPEN-SOURCE PROJECTS

Once Upon a Camayoc

Bite-size insight on Cyber Security for the not too technical.

Guru N Guns's

OneSolution To dOTnET.

Johnny Zraiby

Measuring programming progress by lines of code is like measuring aircraft building progress by weight.

%d bloggers like this: