In part two of my series on the C# programming language, I’m going to explain what a delegate and event is. There are a couple different meanings of a delegate in C#. All of the types (delegate, Action, Func, and Predicate) are delegates because they are function pointers to named and anonymous methods. For the purposes of this blog post, delegate refers to the specific data type and not the broader term.

Delegates are not as common as they used to be, mostly because of the introduction of the Action, Func, and Predicate data types in C# v3.0 (some may say it was v2.0, but that was when anonymous methods were introduced and Func/Action weren’t introduced until later). Events are common when you’re working with user interfaces (like Windows Forms and Windows Presentation Foundation). For example, having one or more method called when a button is clicked.

Delegate

Declaring a delegate

A delegate is declared much like a signature for a method inside an interface (but with the delegate keyword). Delegates can be declared at either the namespace or class level. Just like with fields, properties, methods, and others, the visibility modifier can be set. One big difference is delegates cannot be set as static, however, they are set as static automatically (so they can be accessed statically and non-statically). A delegate can have derived return and parameter types so the method assigned to it doesn’t need to match the signature exactly. The following example is a delegate that takes in a string and the return is void:

[highlight lang=”cs”]public delegate void DisplayString(string str):[/highlight]

Calling a delegate

There’s a couple ways to call a delegate. For the purposes of this example, I’m going to use the delegate demonstrated above. Before we can call a delegate, we first must declare a variable that has the delegate name as the data type and assign it to a method. Below I’m assigning a class method called SomeMethod to the delegate variable called delegateVar.

[highlight lang=”cs”]DisplayString delegateVar = SomeMethod;[/highlight]

The first way to call it is just like how you would with any other method, as shown below.

[highlight lang=”cs”]delegateVar(“Hello!”);[/highlight]

You have to remember that delegate data types are nullable so if delegateVar was assigned to null, the example above would throw a NullReferenceException. To circumvent this, you can either check if delegateVar is not null or have a try-catch block.

[highlight lang=”cs”]// Way #1
if (delegateVar != null)
delegateVar(“Hello!”);

// Way #2
try {
delegateVar(“Hello!”);
} catch (NullReferenceException) {

}[/highlight]

If you’re checking if it’s not null (like in way #1), you can have the if statement and method call all in one line of code using a null condition statement and the Invoke method, like so:

[highlight lang=”cs”]delegateVar?.Invoke (“Hello!”);[/highlight]

Delegate vs Action vs Func vs Predicate

C# has relatively new data types included for function pointers. In terms of functionality and performance, there is no real difference between Action, Func, Predicate, or delegate and what it really boils down to is convenience. Instead of writing one line of code to create a delegate and then another to use it as a data type, you can use Action, Func, or Predicate as the data type and skip that extra line of code. Action is where the return data type is void, then there’s the Func data type with the difference being it is for methods with a non-void return data type, and there’s also the Predicate data type where the return type is always a bool. Events are not limited to work with just delegate, Action, Func, or Predicate.

The following is a delegate with a void return type and it’s Action equivalent:

[highlight lang=”cs”]// Namespace or class level
public delegate void ExampleType1(string str);

// Method level
ExampleType1 exampleVar1;[/highlight]

[highlight lang=”cs”]// Method level
Action<string> exampleVar1;[/highlight]

The following is a delegate with a non-void return type and it’s Func equivalent:

[highlight lang=”cs”]// Namespace or class level
public delegate int ExampleType2(string str);

// Method level
ExampleType2 exampleVar2;[/highlight]

[highlight lang=”cs”]// Method level
Func<string, int> exampleVar2;[/highlight]

The following is a delegate with a bool return type and it’s Predicate equivalent:

[highlight lang=”cs”]// Namespace or class level
public delegate bool ExampleType3(int age);

// Method level
ExampleType3 exampleVar3;[/highlight]

[highlight lang=”cs”]// Method level
Predicate<int> exampleVar3;[/highlight]

Event

What is an event?

An event is a sequence that when ran (or fired), other functions attached to it are executed. Think of an event like powering on or off a computer. When you press the button, you are turning on or off the computer but what is really happening is all the components (hard drive, RAM, CPU, video card, etc.) are turned on or off. You can connect or disconnect the components, which may cause the computer to not turn on properly (and shouldn’t be done if it is already turned on). This is essentially the same as an event but instead of components, they’re methods, and instead of adding or removing, it’s attaching and detaching.

Declaring an event

Before an event is declared, you first need to have the delegate that is going to be used with it, or, a Action, Func, or Predicate. Events can only be declared at the class level. C# also has the built-in EventHandler delegate. One difference from a delegate is an event can be declared as static or non-static. If it is non-static, it can only be be accessed from the non-static level and if it’s static, it can be accessed from both the static and non-static level. The access modifier can be set and an event can be set as abstract, sealed, and virtual. Below, I declare a a public non-static event called DisplayEvent that uses the delegate I created before (DisplayString):

[highlight lang=”cs”]public event DisplayString DisplayEvent;[/highlight]

Attaching to an event

Attaching to an event is pretty simple in C# and there are two ways to do it. The first is by assigning a method with the assignment operator. Doing this causes all methods previously attached to the event to be detached before the method is assigned to it. The other way is using the addition assignment operator. Unlike the assignment operator, all previous events aren’t detached (hence, why you use the addition assignment operator). The number of times the same method is attached using the addition assignment operator is the number of times that method is called when the event is fired (in other words, attaching the same method more than once means it’ll be called more than once). I should also note that you can use the addition assignment operator without having it assigned to anything beforehand.

[highlight lang=”cs”]// Assignment operator
DisplayEvent = ExampleMethod;

// Addition assignment operator
DisplayEvent += ExampleMethod;[/highlight]

Detaching from a event

You can probably guess how to detach from an event… It is the same as above except you use the subtraction assignment operator. In some cases when you’re using lambda, the subtraction assignment operator is useless so you may want to use the assignment operator to detach all methods that were previously attached. If one method is attached to an event more than once and you want to detach it, you must use the subtraction assignment as many times as it is attached. If you try to detach a method that wasn’t already attached to the event, no exception occurs.

[highlight lang=”cs”]// Subtraction assignment operator
DisplayEvent -= ExampleMethod;[/highlight]

Firing an event

When an event is fired, the order that the attached methods are called depends on when they were attached. If a method is the first to be attached to the event, it is executed first. The same goes for if it was the last method to be attached, it is executed last. An event can have a return data type (for example, to filter data) which means the event call can be assigned to something. Firing an event is the same as calling a delegate. The first way is just as you would call a method:

[highlight lang=”cs”]DisplayEvent(“Fired”);[/highlight]

Because an event can be set to null (if nothing is attached to it), the following are safer ways to call it and are explained in calling a deleagate:

[highlight lang=”cs”]// Way #1
DisplayEvent?.Invoke(“Fired”);

// Way #2
try {
DisplayEvent(“Fired”);
} catch (NullReferenceException) {

}[/highlight]

Further Reading

If you want to learn more about events, I’d suggest creating a simple user interface with text boxes, buttons, check boxes, etc. and attach to the various events from Windows Forms or Windows Presentation Foundation. Creating a user interface using one of these frameworks is pretty straightforward in Visual Studio and MSDN has a walkthrough on creating a WPF application if you need it. There isn’t much more about delegates but if you’re interested, you may want to go to the MSDN website to learn about lambda expressions. As they say “practice makes perfect”, so you’re best to try it out yourself. Stay tuned for my next blog post on the C# programming language!