Home

A Review of Delegates

 

Introduction

The C and C++ concept of function pointer was very useful when programming for the Microsoft Windows operating systems because the Win32 library relies on the concept of callback functions to process messages. For this reason and because of their functionality, callback functions were carried out in the .NET Framework but they were defined with the name of delegate.

A delegate is a special type of user-defined variable that is declared globally, like a class. In fact, a delegate is created like an interface but appearing as a method. Based on this, a delegate provides a template for a method, like an interface provides a template for a class. Like an interface, a delegate is not defined. Its role is to show what a useful method would look like. To support this concept, a delegate can provide all the necessary information that would be used on a method. This includes a return type, either no argument or one or more arguments.

 

Declaring a Delegate

To declare a delegate, you use the delegate keyword. The basic formula used to create a delegate is:

[attributes] [modifiers] delegate result-type identifier ([formal-parameters]);

The attributes factor can be a normal C# attribute.

The modifier can be one or an appropriate combination of the following keywords: new, public, private, protected, or internal.

The delegate keyword is required.

The ReturnType can be any of the data types we have used so far. It can also be a type void or the name of a class.

The Name must be a valid name for a method.

Because a delegate is some type of a template for a method, you must use parentheses, required for every method. If this method will not take any argument, you can leave the parentheses empty.

After declaring a delegate, remember that it only provides a template for a method, not an actual method. In order to use it, you must define a method that would carry an assignment the method is supposed to perform. That method must have the same return type and the same (number of) argument(s), if any. For example, the above declared delegate is of  type void and it does not take any argument. After implementing the method, you can associate it to the name of the delegate. To do that, where you want to use the method, first declare a variable of the type of the delegate using the new operator. In the parentheses of the constructor, pass the name of the method. The declaration gives meaning to the delegate. To actually use the method, call the name of the delegate as if it were a defined method.

Here is an example that uses a delegate:

using System;
using System.Windows.Forms;

delegate void dlgSimple();

class Exercise : Form
{
	public Exercise()
	{
		dlgSimple Announce = new dlgSimple(Welcome);

		Announce();

		this.InitializeComponent();
	}

	private static void Welcome()
	{
	
	}

	private void InitializeComponent()
	{
	}

	static void Main()
	{
		Exercise form;

		form = new Exercise();
		Application.Run(form);
	}
}

You can also declare a delegate that returns a value. When defining a method that would be associated with the delegate, remember that that method must return the same type of value. Here is an example:

using System;
using System.Windows.Forms;

delegate double Addition();

class Exercise : Form
{
	public Exercise()
	{
		Addition  Add = new Addition(Plus);

		this.InitializeComponent();

		TextBox txtBox = new TextBox();
		Controls.Add(txtBox);

		txtBox.Text = Add().ToString();
	}

	private static double Plus()
	{
		double a = 248.66, b = 50.28;

		return a + b;
	}

	private void InitializeComponent()
	{
	}

	static void Main()
	{
		Exercise form;

		form = new Exercise();
		Application.Run(form);
	}
}

This would produce:

Delegate

Delegates and Classes

In the above introductions, we associated delegates with only methods of the main class. Because delegates are usually declared globally, that is outside of a class, they can be associated with a method of any class, provided the method has the same return type (and the same (number of) argument(s)) as the delegate. When we created the methods of the main class, we defined them as static, since all methods of the main class must be declared static.

Methods of any class can also be associated to delegates. Here is an example of two methods associated with a common delegate:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace WindowsApplication2
{
    delegate double Multiplication();

    public class Cube
    {
        private double _side;

        public double Side
        {
            get { return _side; }

            set { _side = value; }
        }

        public Cube()
        {
            _side = 0;
        }

        public Cube(double s)
        {
            _side = s;
        }

        public double Area()
        {
            return 6 * Side * Side;
        }

        public double Volume()
        {
            return Side * Side * Side;
        }
    }

    public partial class Form1 : Form
    {
        public Form1()
        {
            Cube SmallBox = new Cube(25.58);

            Multiplication AreaDefinition = new Multiplication(SmallBox.Area);
            Multiplication VolDefinition = new Multiplication(SmallBox.Volume);

            InitializeComponent();

            txtSide.Text = SmallBox.Side.ToString();
            txtArea.Text = AreaDefinition().ToString();
            txtVolume.Text = VolDefinition().ToString();
        }
    }
}

This would produce:

Delegate

Delegates Compositions

One of the characteristics that set delegates apart from C/C++ function pointers is that one delegate can be added to another using the + operation. This is referred to as composition. This is done by adding one delegate variable to another as in a = b + c.

A Delegate That Takes One of More Arguments

If you want to associate a method that takes arguments to a delegate, when declaring the delegate, provide the necessary argument(s) in its parentheses. Here is an example of a delegate that takes two arguments (and returns a value):

delegate double Addition(double x, double y);

When defining the associated method, besides returning the same type of value if not void, make sure that the method takes the same number of arguments. Here is an example:

using System;

delegate double Addition(double x, double y);

class Exercise
{
	private static double Plus(double a, double b)
	{
		return a + b;
	}

	static int Main()
	{
		return 0;
	}
}

Once again, to associate the method, declare a variable of the type of delegate and pass the name of the method to the constructor of the delegate. Here is an example:

Addition Add = new Addition(Plus);

Notice that only the name of the method is passed to the delegate. To actually use the delegate, when calling it, in its parentheses, provide a value for the argument(s) conform to the type specified when declaring the delegate.

A Delegate Passed as Argument

Using delegates, one method can be indirectly passed as argument to another method. To proceed, first declare the necessary delegate. Here is a example of such a delegate:

using System;

namespace GeometricFormulas
{
	public delegate double Squared(double x);

	public class Circle
	{
		private double _radius;

		public double Radius
		{
			get { return _radius; }

			set  { _radius = value; }
		}
	}
}

A delegate can be passed as argument to a method. Such an argument would be used as if it were a method itself. This means that, when accessed in the body of the method, the name of the delegate must be accompanied by parentheses and if the delegate takes an argument or argument, the argument(s) must be provided in the parentheses of the called delegate. Here is an example:

using System;

namespace GeometricFormulas
{
	public delegate double Squared(double x);

	public class Circle
	{
		private double _radius;

		public double Radius
		{
			get { return _radius; }

			set	{ _radius = value; }
		}

		public double Area(Squared sqd)
		{
			return sqd(_radius) * Math.PI;
		}
	}
}

After declaring a delegate, remember to define a method that implements the needed behavior of that delegate. Here is an example:

using System;

namespace GeometricFormulas
{
	public delegate double Squared(double x);

	public class Circle
	{
		private double _radius;

		public static double ValueTimesValue(double Value)
		{
			return Value * Value;
		}
	}
}

You can also define the associated method in another class, not necessarily in the class where the delegate would be needed. Once the method that implements the delegate is known, you can use the delegate as you see fit. To do that, you can declare a variable of the type of that delegate and pass the implementing method to its constructor. Here is an example:

using System;

namespace GeometricFormulas
{
	public delegate double Squared(double x);

	public class Circle
	{
		private double _radius;


		public static double ValueTimesValue(double Value)
		{
			return Value * Value;
		}

		public double Area(Squared sqd)
		{
			return sqd(_radius) * Math.PI;
		}

		public void CircleCharacteristics()
		{
			Squared Sq = new Squared(ValueTimesValue);
		}
	}

}

This declaration gives life to the delegate and can then be used as we have proceed with delegates so far.

 

Home Copyright © 2007 FunctionX, Inc.