Delegates


A delegate is a type that enables you to store references to functions. Although this sounds quite involved, the mechanism is surprisingly simple. The most important purpose of delegates won't become clear until later in this book when you look at events and event handling, but you can get a fair amount of mileage by looking at delegates here. When you come to use them later on, they'll look familiar, which will make some more complicated topics a lot easier to comprehend.

Delegates are declared much like functions, but with no function body and using the delegate keyword. The delegate declaration specifies a function signature consisting of a return type and the parameter list. After defining a delegate, you can declare a variable with the type of that delegate. You can then initialize this variable as a reference to any function that has the same signature as that delegate. Once you have done this, you can call that function by using the delegate variable as if it were a function.

When you have a variable that refers to a function, you can also perform other operations that would be impossible by any other means. For example, you can pass a delegate variable to a function as a parameter, then that function can use the delegate to call whatever function it refers to, without having knowledge as to what function will be called until runtime.

The following Try It Out gives an example of using a delegate to access one of two functions.

Try It Out – Using a Delegate to Call a Function

image from book
  1. Create a new console application called Ch06Ex05 in the directory C:\BegVCSharp\Chapter6.

  2. Add the following code to Program.cs:

    class Program { delegate double ProcessDelegate(double param1, double param2); static double Multiply(double param1, double param2) { return param1 * param2; } static double Divide(double param1, double param2) { return param1 / param2; } static void Main(string[] args)    { ProcessDelegate process; Console.WriteLine("Enter 2 numbers separated with a comma:"); string input = Console.ReadLine(); int commaPos = input.IndexOf(','); double param1 = Convert.ToDouble(input.Substring(0, commaPos)); double param2 = Convert.ToDouble(input.Substring(commaPos + 1, input.Length - commaPos - 1)); Console.WriteLine("Enter M to multiply or D to divide:"); input = Console.ReadLine(); if (input == "M") process = new ProcessDelegate(Multiply); else process = new ProcessDelegate(Divide); Console.WriteLine("Result: {0}", process(param1, param2)); Console.ReadKey();    } }

  3. Execute the code. The result is shown in Figure 6-10.

    image from book
    Figure 6-10

How It Works

This code defines a delegate (ProcessDelegate) whose signature matches that of the two functions (Multiply() and Divide()). The delegate definition is:

delegate double ProcessDelegate(double param1, double param2);

The delegate keyword specifies that the definition is for a delegate, rather than a function (the definition appears in the same place as a function definition might). Next, you have a signature that specifies a double return value and two double parameters. The actual names used are arbitrary, so you can call the delegate type and parameter name whatever you like. Here, you've used a delegate name of ProcessDelegate and double parameters called param1 and param2.

The code in Main() starts by declaring a variable using the new delegate type:

static void Main(string[] args) {    ProcessDelegate process; 

Next, you have some fairly standard C# code that requests two numbers separated by a comma and places these numbers in two double variables:

Console.WriteLine("Enter 2 numbers separated with a comma:"); string input = Console.ReadLine(); int commaPos = input.IndexOf(','); double param1 = Convert.ToDouble(input.Substring(0, commaPos)); double param2 = Convert.ToDouble(input.Substring(commaPos + 1,                                         input.Length - commaPos - 1));

Note

Note that, for demonstration purposes, I've included no user input validation here. If this were "real" code, you'd spend much more time ensuring that you got valid values in the local param1 and param2 variables.

Next, you ask the user whether to multiply or divide these numbers:

Console.WriteLine("Enter M to multiply or D to divide:"); input = Console.ReadLine();

Based on the user's choice you initialize the process delegate variable:

if (input == "M")    process = new ProcessDelegate(Multiply); else    process = new ProcessDelegate(Divide);

To assign a function reference to a delegate variable, you use slightly odd looking syntax. Much like assigning array values, you must use the new keyword to create a new delegate. After this keyword, you specify the delegate type and supply a parameter referring to the function you want to use, namely the Multiply() or Divide() function. Note that this parameter doesn't match the parameters of the delegate type or the target function, it is a syntax unique to delegate assignment. The parameter is simply the name of the function to use, without any parentheses.

Finally, you call the chosen function using the delegate. The same syntax works here, regardless of which function the delegate refers to:

   Console.WriteLine("Result: {0}", process(param1, param2));    Console.ReadKey(); }

Here, you treat the delegate variable just as if it were a function name. Unlike a function, however, you can also perform additional operations on this variable, such as passing it to a function via a parameter. A simple example of such a function is:

 static void ExecuteFunction(ProcessDelegate process) { process(2.2, 3.3); } 

This means that you can control the behavior of functions by passing them function delegates, much like choosing a "snap-in" to use. For example, you might have a function that sorts a string array alphabetically. There are several methods of sorting lists with varying performance, depending on the characteristics of the list being sorted. By using delegates, you can specify the method to use by passing a sorting algorithm function delegate to a sorting function.

There are many such uses for delegates, but, as mentioned earlier, their most prolific use is in event handling. You come to this subject in Chapter 12.

image from book




Beginning Visual C# 2005
Beginning Visual C#supAND#174;/sup 2005
ISBN: B000N7ETVG
EAN: N/A
Year: 2005
Pages: 278

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net