Nov 13, 2014
We can think of the concept of delegates in the .NET framework as a type-safe implementation of callback functions. In today’s post, I’ll dig deeper into this definition and the review this important concept. What we mean by a callback function is just the name of an existing function that we pass as an argument to another function. The use of callback functions is pervasive in C/C++ programming and although very useful, they are the source of a lot of trouble because C/C++ compilers will not check if the callback function is used properly inside the function that receives it as an input parameter. The name of the callback function is nothing more than just an address in memory that will be invoked inside the body of some other function. So if we don’t pass to the callback function exactly the type of parameters it is expecting, we will crash our program and we will only know it at run time. In .NET, it’s a whole new story because now the callback function becomes a declared type that will be initialised with the function to be called back. When this initialisation happens, the compiler can check if the declaration of the delegate type matches the signature of the function we want to call back. So we can say that delegates are type-safe and they provide the same functionality of callback functions, aka function pointers, in C/C++ unmanaged code. Now let’s review the syntax to use delegates in C#. We are choosing C# because it’s the most popular language in .NET, but of course VB.NET offers the same functionality. We can declare delegates as a top-level type or inside a class using the delegate keyword:public delegate void MyDelegate1(int a, int b); public delegate string MyDelegate2(int a, string s);In the first example, MyDelegate1 will match any function that accepts 2 integers as input and has no return value, as for example:
public void MyFunction1(int x, int y) { … }In the second example, we will initialise MyDelegate2 with functions receiving an int followed by a string and returning a string:
public string MyFunction2(int x, string msg) { … }The way to initialise the delegate is by declaring a variable with the type of the delegate and then assign to that variable a function with the right signature. MyDelegate1 callback1 = MyFunction1; MyDelegate2 callback2 = MyFunction2; Now, let’s say we have some functions that are expecting input parameters with the types MyDelegate1 and/or MyDelegate2 among other parameters:
void Test1(MyDelegate1 p, int a, int b) { p(a,b); //this line is invoking the delegate and will execute whatever we pass in to p } void Test2(MyDelegate2 p, int a, string s) { string result = p(a,s); //it calls the function assigned to p } void Test3(MyDelegate1 p1, MyDelegate2 p2, … ) { … }We will be able to call those 3 functions passing the variables callback1 and callback2 as appropriate Test1(callback1); Test2(callback2); Test3(callback1, callback2); Note that callback1 is referring to MyFunction1, so inside Test1 we are executing MyFunction1. The same for callback2 in Test2. In Test3, we could use both functions. The flexibility in using delegates comes from the fact that we can decide are runtime what functions we will pass to Test1, Test2 and Test3. If we are always passing the same functions then of course, there would be no reason to be using the delegate as an intermediary. Instead, we would just hardcode the call to MyFunction1 inside Test1, MyFunction2 inside Test2, etc. and simply eliminate the first parameter in Test1 and Test2 or the first 2 parameters in Test3. Also note that the only restriction for the function we use to initialise the delegate is that it has the right signature. So it could be defined anywhere, even in a class located in some external assembly we add as a reference. We can write code that will use the functionality provided by some function even before we have that function available. We declare the delegate with the signature of the function and start using variables with the delegate type everywhere that function is required. Once we get hold of some library that contains the implementation for those required functions we can add a reference to the assembly and initialise the delegate variable with the appropriate functions. The code is prepared to work with whatever external library we choose. To learn more about delegates in .NET we recommend the course 20483: Programming in C#.
How do your Excel skills stack up?
Test NowNext up:
- Charts that aren’t charts
- Control your digital world from your mobile device
- Using SharePoint to create a ‘Team Based Master Calendar’
- Deliver successful organisational transformation
- Removing the background from a picture in Microsoft Office
- The Windows Server 2012 R2 Desktop Experience
- Comparing and combining two lists using VLOOKUPs
- Fabulous, fitting feedback
- Apply permissions on web parts in SharePoint
- Scheduling Rostered Days Off (RDO) in Project 2013
Previously
- More haste, less speed
- Active Directory Administrative Center (ADAC) Updated
- How to create a template in Microsoft Outlook 2010 and 2013
- Wrapping your head around Content Type IDs
- Evolving Office 365 plans
- Killer Fillers
- Duplicate animations with ease using PowerPoint’s Animation Painter
- SQL Server in Microsoft Azure virtual machines
- Doing a VLOOKUP that finds exactly what you want
- Designing business continuity management strategies in SharePoint 2013