Deep C# - Delegates
Deep C# - Delegates
Written by Mike James   
Wednesday, 06 January 2016
Article Index
Deep C# - Delegates
Signatures and Methods

Delegates are C#'s original way of allowing you to work with functions as if they were first class objects. The aim may be simple but the need to define a type and then an instance of the type can be confusing. Let's see if we can make it all seem logical.

This is a chapter of our ebook on C# - a work in progress.

 

Deep C#

 coverCsharp

 Chapter List

  1. Value And Reference
    Value and reference are a fundamental division in the way C# treats data. It is important that you understand the differences and most importantly when to use a struct and when to use a class. These aren't just differences in efficiency, they affect the semantics too.

  2. Passing Parameters
    Passing parameters is easy as it always works in the same way but the effects aren't always the same. It can be confusing and even error prone unless you understand how it all works.

  3. Inheritance
    Inheritance is a simple idea, until you try to make use of it.

  4. Casting – the escape from strong typing
    Casting is one of the most confusing aspects of any modern language and it often makes beginners think hard. But if you know why you are doing it then the how makes a lot more sense.

  5. Controlling Inheritance
    Inheritance is a great idea but it is a powerful technique that can be misused. C# provides the tools to keep inheritance under control or to turn it off completely if you want to.

  6. Delegates
    Delegates are C#'s original way of allowing you to work with functions as if they were first class objects. The aim may be simple but the need to define a type and then an instance of the type can be confusing. Let's see if we can make it all seem logical.

  7. Multicast delegates and events
    Multicast delegates are useful in their own right but they also form the basis on which the C# event system is built. We take a close look at how they work and how to use them. For example, did you know you could add and subtract delegates?

  8. Anonymous Methods, Lambdas And Closures
    Anonymous methods aren't particularly new, but they have hidden depths and lead on to lambdas and the idea of a closure. These are all important ideas in modern programming.

  9. Take Exception To Everything

  10. Dangerous Pointers
    In C# pointers have been replaced by references but there is still a need for the raw dangerous original concept. You could say "what's so dangerous about pointers?"
Multicast delegates and events
Tuesday, 25 May 2010
Article Index
Multicast delegates and events
Events
Generic Events

Multicast delegates are useful in their own right but they also form the basis on which the C# event system is built. We take a close look at how they work and how to use them. For example, did you know you could add and subtract delegates?

 

Delegates are at the core of a number of different .NET facilities, events in particular.

It’s long been a truism that the way to get work done is to delegate, but what are C# delegates all about?

First we have to understand what the problem is that delegates are designed to solve.

First Class Functions

In many languages functions are treated in the same way as objects. In JavaScript for example function are objects - this is often expressed by saying the functions are first class objects or they are first class functions. 

Why should this matter?

The simple answer is that sometimes you want to pass a function as an argument to a method call. There are other things you might want to do with a first class function including having a reference to it or having an array of such functions but if we concentrate on the most common usage - passing functions to methods - then we have the key idea. 

For example suppose you have a sorting routine you might want to pass in a function that determines what A>B means, i.e. return true if A is greater than B and false otherwise, where A and B are objects of some type. 

This seems like a reasonable thing to do but notice that in C# and in other object oriented language there are no "disembodied" functions. All functions are methods that belong to some class or instance of a class. This make things a little more complicated because now you cannot simply create a function called myOrder and pass it into a method because myOrder has to be a method of some class or object.

You might think of defining something like:

class Compare{
 public myOrder(){};
}

and now you could try to pass and instance of the object:

Compare myCompare=new Compare();
myData.Sort(myCompare.myOrder);

That is you are trying to pass myCompare.myOrder to the Sort method. 

This is one approach and it could be made to work but C# is strongly typed and every parameter in a method has to have a type.

What type is Compare.myOrder?

Its a method of a type and not a type in its own right and trying to make it a type will quickly become very messy. 

A different alternative is to demand that every time you want to pass a function you have to pass an object that has that function as a method. This is what Java does for example. In this case we don't have a problem with types:

Compare myCompare=new Compare();
myData.Sort(myCompare);

However within the Sort method the myOrder function has to be called as 

myCompare.myOrder();

In other words to pass a function you have to pass an entire object which wraps the function. Of course the one advantage of this method is that in principle you could pass a whole set of functions in one go but this doesn't make up for the inconvenience of the approach when you are trying to pass just one function. 

As any Java programmer will tell you this approach is workable but very verbose. You have to define a class for every function you want to pass and create and instance to pass every time you want to pass it. It is the original method that Java used to implement event handling and over time new facilities such as anonymous classes and eventually lambdas have been added to the language to make this cumbersome method easier to use. 

The C# Approach

The overall C# approach to allowing functions to be first class entities has developed over time as well. Initially delegates were used as a way of wrapping a function in an object in a way that is superficially similar to Java's approach but it also has some special advantages. Over time delegates acquired features that made them easier to use anonymous methods and finally lambdas. 

However it is important that you fully understand the delegate idea and how to use them.

Let’s look at how it works and some of the more interesting ways that you can put it to work.

Delegates and their relationship to events is covered in another chapter.

Delegate basics

What is initially confusing is that to create a delegate you first have to create a type and then create an instance of the type. That is, delegate is a user-defined reference type that encapsulates a method.

Consider, for example, how to encapsulate the simple example method:

public int hello(int param1){
 MessageBox.Show(
  "Hello delegate World"
       +param1.ToString());
 return(++param1);
}

All this does is to display the current value of param1 and then return and incremented value.

First we need to define a delegate type that matches its signature – including, in this case, the return type:

delegate int HelloType(int param);

This delegate type defines the methods that it can encapsulate. Notice that it is only the functions signature and return type that specifies the delegate type. The HelloType delegate can wrap any function that has the specified signature and return. 

Next we have to create an instance of the type and supply it with the hello method to encapsulate:

HelloType HelloInst= new HelloType(hello);

If you prefer you can use the overloaded assignment operator:

HelloType HelloInst = hello;

to create an instance.

Now we can run the original Hello method by calling it directly in the usual way:

int i = hello(2);

or by using the delegate’s invoke method:

int i=HelloInst.Invoke(2);

or by calling the delegate instance as if it was the hello method:

int i=HelloInst(2);

This last form is just a convenience as it implicitly uses the Invoke method.

Notice that the default use of the invoke method makes the delegate instance look like a function object. That is HelloInst is an object but HelloInst(2) looks like a function call. 

Of course there are a few slightly hidden details in these examples which are obvious to experts but often confuse the beginner. The first is that the method being wrapped is still a method belonging to some object and not a "disembodied" function. When the delegate is used to wrap the method the method has to be accessible from where ever the delegate is being declared. In the example above there is the implicit assumption that all of the code is defined within the same class. 

A more elaborate and complete example would create the hello method within a new class:

public class Greetings
{
 public int hello(int param1)
 {
  MessageBox.Show(
    "Hello delegate World"
       + param1.ToString());
  return (++param1);
 }
}

and then within the class that wants to make use of the method:

delegate int HelloType(int param);private void button1_Click(object sender, EventArgs e)
{
 Greetings g = new Greetings();
 HelloType HelloInst = new HelloType(g.hello);
 int i = HelloInst(2);
}

 

Another subtle point is that Invoke uses the same current thread to run the delegate and in this case you need to be aware of any potential “cross threading” problems that might arise.

This also means that the invocation is asynchronous and the calling code will wait until the delegate returns. You can invoke the delegate asynchronously using a thread from the thread pool using BeginInvoke or you could create a thread manually to run the delegate.

To summarise:

To wrap a method belonging to an instance of a class you have to first define a new delegate type with a specific signature and return type, then you wrap the method in and instance of the delegate type. 

 

Banner

<ASIN:1449380344>

<ASIN:1430225378>
<ASIN:0470447613>

<ASIN:1933988924>

<ASIN:3540921443>



Last Updated ( Thursday, 07 January 2016 )
 
 

   
Banner
Banner
RSS feed of all content
I Programmer - full contents
Copyright © 2017 i-programmer.info. All Rights Reserved.
Joomla! is Free Software released under the GNU/GPL License.