tags:

views:

307

answers:

10

Hello,

I'm going take a class on "Delegates and Callbacks" to students who are learning level programmers. They have basic c/c++ & c# background. Instead of directly showing how to use them. I want to show "Why Function Pointers?" first. I want to start with an example situation and ask them "How will you do this"? and make them realize the need for something and then introduce them to FunctionPointers, Delegates & CallBacks.

So, Can any one show me a good example which shows the need for Delegates in C# (or) function pointers in C/C++. Is don't want example of even handling in GUI example and I don't want demonstration of "How to use delegates" with an examples of kind add2numbers etc..

I'm looking for something practical example where they could feel the need of FunctionPointers, Delegates & CallBacks.

If there are any good articles, please post them.

+2  A: 

The Observer-Pattern is an example. The main reason for Callbacks/Delegates is, that you want to reduce coupling and increase flexibility of the architecture for further developments.

Tobias Langner
+6  A: 

I would show how to write/use a generic sort function/method, which takes a callback parameter as a predicate.

Bastien Léonard
This is good, at least if they've already learned the basic sorting algorithms.
caf
+7  A: 

I'm not sure why you don't want to use a GUI example: the concept of "when I click a button, I want X to happen - now how to I express X?" is quite a good one.

Other examples:

  • I want to start a thread: how do I express what I want it to do?
  • I want to filter some data: how do I express the filter?
  • I want to project some data: how do I express the projection?
  • I want to download a file from the web asynchronously: how do I express what I want to happen when it's finished downloading?

Basically each of these is a case of saying, "I want to express some code in a simple way." In each case you could use a single method interface - delegates/function pointers are just a more convenient way of doing that.

Indeed, if some of the students are used to using single method interfaces (e.g. Runnable in Java) then that's probably a good starting point. Imagine if you could implement an interface by saying "just use this method over here..." (And in Java 7 it looks like you'll be able to do just that; they're using single method interfaces and method references in lieu of dedicated delegate types.) From a C# background you can also compare the IComparer<T> interface with the Comparer<T> delegate.

Of course when you've got the idea of delegates, you can then introduce lambda expressions (if it's a C# course) showing them how useful it is to be able to express that bit of logic "inline". Then show them how it's useful to be able to interact with the local environment, using lambdas as closures...

Jon Skeet
Probably because GUI tends to be a distraction when learning. A "pure" code example is more to the point, and doesn't assume as much library functionality
jalf
@jalf: For an actual code example, perhaps - but to explain the *concept* I think it's useful. And in fact, a GUI code sample can still be very small, if hand-written instead of using a designer.
Jon Skeet
+2  A: 

Asyncrhonous calls: you call a method that will execute in background (usually a remote service call), and you want to specify which code will execute when the method finishes (since you indeed need to know when the method finishes). See here for more details: http://msdn.microsoft.com/en-us/magazine/cc301332.aspx

Konamiman
Ding Ding You win the prize! There are many examples (button presses are the most obvious UI operation) including I/O completion routines and etc that need to execute some piece of code(callback) when a method finishes. In the case of the button, it could be merely to re-enable the button after some processing completes so that function is available again. Push Button -> disable button -> start async thread w/callback -> thread completes -> call back entered and button re-enabled. This prevent the dreaded hour-glass during long operations after a button press. TheEruditeTroglodyte
TheEruditeTroglodyte
A: 

You can take the example of how events are implemented in .NET; your students can easily relate to it.

Krishna Kumar
+2  A: 

Delegates allow you to view code as data, so anytime you want something done in a certain way but leave the details to the caller delegates come in handy. Sorting is probably the prime example, but there are many others as illustrated by some of the answers.

E.g. let's say you want to time something. Since you basically want to go through the same timing steps no matter what you're timing, you can let your timing method take a delegate and time that in a consistent way. In pseudo code it could look something like this

TimeThis(method_pointer) {
   setup_timing();
   method_pointer(); // invoke the method
   report_timing();

}

Brian Rasmussen
A: 

To Jon Skeet. Yes, every delegate may be represented as single-method interface, but you may not implement different versions of it in one class. With delegates (function pointers) you may have as many implementations as you want - different names but same signature:

class C
{
  int Add(int a, int b)
  {
    return a + b;
  }
  int Mul(int a, int b)
  {
    return a * b;
  }
};

But you cannot implement the same interface twice (see my class C above). For C++ and C# although we can emulate delegates with interfaces. But for C in is necessary intrument to make callback and runtime polymorphism. In C++ and C# it much for compaitibility and convience.

demi
I don't actually understand your answer. If you have a language which supports both interfaces and delegates, then there is no actual difference between a single method interface and a delegate. You can have many delegates, and you can have many implementations of your interface. You have a bit more work to do when implementing an interface, but you get some stronger encapsulation in interfaces than in delegates (IMHO you can implement delegate in weird ways much easier). Other than that, they can be simply interchanged.
Groo
Yes, I'm aware of the ways in which delegates are far more convenient than single method interfaces... Hence the bit about "Imagine if you could implement an interface by saying "just use this method over here...""
Jon Skeet
+7  A: 

You can show them an example of filtering a list of items in several places in your software.

For example, you might have

public List<Person> GetMale(List<Person> people)
{
   List<Person> results = new List<Person>();
   foreach (Person p in people)
   {
       if (p.IsMale)
          results.Add(p);
   }
   return results;
}

or

public List<Person> GetFemale(List<Person> people)
{
   List<Person> results = new List<Person>();
   foreach (Person p in people)
   {
       if (!p.IsMale)
          results.Add(p);
   }
   return results;
}

To avoid repeating the foreach iteration in every method, you will want to extract the actual condition (i.e. a predicate in this case), and have it implemented somewhere else.

So you will replace these two methods with:

public List<Person> Filter(List<Person> people, Func<bool, Person> match)
{
   List<Person> results = new List<Person>();
   foreach (Person p in people)
   {
       if (match(p))
          results.Add(p);
   }
   return results;
}

and then call it in your code like this:

List<Person> malePersons = Filter(people, p => p.IsMale);
List<Person> femalePersons = Filter(people, p => !p.IsMale);

Note that the actual condition is now extracted outside of the iterating block, and you can reuse the same method to create any custom filtering logic you like. By extracting this logic, you are delegating the problem to someone else, making your code loosely coupled.

Using C# 2.0 anonymous method syntax, calling this method would look like this:

List<Person> malePersons = Filter(people, 
   delegate (Person p) { return p.IsMale; });
List<Person> femalePersons = Filter(people, 
   delegate (Person p) { return !p.IsMale; });

or using actual methods:

List<Person> malePersons = Filter(people, MaleMatch);
List<Person> femalePersons = Filter(people, FemaleMatch);

where predicates are defined as:

private bool MaleMatch(Person p)
{ 
   return p.IsMale;
}

private bool FemaleMatch(Person p)
{ 
   return !p.IsMale;
}

It is important to note that we are not passing the result of these methods, but actual method "pointers", so actual results will be returned when the method is called inside the Filter method.

Note also that LINQ in .Net 3.5 already contains a Where extension method which does the same thing like this example, and many other methods which use delegates for conditions, projecting and other stuff, so you basically only need to pass a delegate with the appropriate signature.

Groo
A: 
namespace WindowsApplication10
{
    /// <summary>
    /// This delegate will be used by the button 
    /// </summary>
    public delegate Point GetCenter();

    public partial class Form1 : Form
    {
        CentralButton central;
        public Form1()
        {
            InitializeComponent();
            central = new CentralButton(this.GetCenter);
            this.Controls.Add(central);
        }

        public Point GetCenter() 
        {
            return new Point(this.Width / 2, this.Height / 2);
        }

        protected override void OnSizeChanged(EventArgs e)
        {
            base.OnSizeChanged(e);
            central.UpdateCenter();
        }
    }

    /// <summary>
    /// This button calculates its location in the center of the parent
    /// </summary>
    public class CentralButton : Button 
    {
        GetCenter myGetCenterMethod;
        public CentralButton(GetCenter findCenterMethod)
        {
            myGetCenterMethod = findCenterMethod;
        }

        public void UpdateCenter()
        {
            // use the delegate for obtain the external information
            this.Location = myGetCenterMethod();
        }
    }
}
serhio
A: 

Checkout the Can your programming language do this? article from Joel.

He has few good examples where there are two functions that are almost doing the same thing, but use different functions to achieve a certain task.

alert("get the lobster");
PutInPot("lobster");
PutInPot("water");

alert("get the chicken");
BoomBoom("chicken");
BoomBoom("coconut");

Refactored with functions passed as arguments:

function Cook( i1, i2, f )
{
    alert("get the " + i1);
    f(i1);
    f(i2);
}

Cook( "lobster", "water", PutInPot );
Cook( "chicken", "coconut", BoomBoom );
hasen j