﻿ Lesson 05: Function Delegates

A Delegate as a Function

Introduction

A function is an action that formally produces a value. We say that a function returns a value. In the same way, you can create a delegate that returns a value. To formally support this concept, the .NET Framework provides special built-in delegates.

Introduction to Creating a Function Delegate

The basic formula to create a delegate that returns a value is:

`[attributes] [modifier(s)] delegate return-type Name ([formal-parameters]);`

When creating the delegate, specify the data type to the left side of the name of the delegate. Here is an example:

`public delegate double Evaluation();`

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

```public delegate double Evaluation();

public class Algebra
{
public double Calculate()
{
return 0.00;
}
}```

Using a Function Delegate

To use the method, you can first declare a variable of the type of the delegate and initialize it using its default constructor. In the parentheses of the constructor, pass the name of the method. Here is an example:

```using static System.Console;

public delegate double Evaluation();

public class Algebra
{
public double Calculate()
{
double hSalary = 25.75;
double tWorked = 38.50;

double wSalary = hSalary * tWorked;
return wSalary;
}
}

public class Exercise
{
public static int Main()
{
Algebra oper = new Algebra();
Evaluation eval = new Evaluation(oper.Calculate);

return 0;
}
}```

To use the delegate, you can call the variable as if it were a method. If you need the value returned by the delegate, declare another variable and initialize with a call to the delegate variable. Here is an example:

```using static System.Console;

public delegate double Evaluation();

public class Algebra
{
public double Calculate()
{
double hSalary = 25.75;
double tWorked = 38.50;

double wSalary = hSalary * tWorked;
return wSalary;
}
}

public class Exercise
{
public static int Main()
{
Algebra oper = new Algebra();
Evaluation eval = new Evaluation(oper.Calculate);

WriteLine(eval());

WriteLine("=====================================");
return 0;
}
}```

This would produce:

```991.375
=====================================
Press any key to continue . . .```

When initializing the delegate variable, an alternative is to assign the name of the method to the delegate variable. Here is an example:

```using static System.Console;

public delegate double Evaluation();

public class Algebra
{
public double Calculate()
{
double hSalary = 25.75;
double tWorked = 38.50;

double wSalary = hSalary * tWorked;
return wSalary;
}
}

public class Exercise
{
public static int Main()
{
Algebra oper = new Algebra();
Evaluation eval = oper.Calculate;

WriteLine(eval());

WriteLine("=====================================");
return 0;
}
}```

A Function Delegate with a Parameter

A delegate that returns a value can also use one or more parameters. Here is an example of creating such a delegate:

`public delegate double Operation(double nbr);`

Once again, you must have a method to associate to the delegate. When creating the method, it must have the same syntax as the delegate. In the body of the method, use or ignore the argument. Here is an example:

```public delegate double Operation(double nbr);

public class Algebra
{
public double Calculate(double sal)
{
return 0.00;
}
}```

Once again, before using the delegate, you can declare a variable and initialize it with the method. Here are two examples of doing it:

```
namespace Exercises.Controllers
{
public delegate double Operation(double nbr);

public class HomeController : Controller
{

public ActionResult Index()
{
Operation oper = new Operation(Calculate);
Operation eval = Calculate;

return View();
}

public double Calculate(double sal)
{
const double tWorked = 40.00;

return sal * tWorked;
}
}
}```

When calling the delegate variable, you can declare a variable that is the type of the return value of the delegate. Call the delegate variable as if it were a method. In its parentheses, pass the appropriate number and type(s) of argument(s). Here is an example:

```using static System.Console;

public delegate double Operation(double nbr);

public class Algebra
{
public double Calculate(double sal)
{
const double tWorked = 40.00;

return sal * tWorked;
}
}

public class Exercise
{
public static int Main()
{
Algebra alg = new Algebra();
Operation oper = new Operation(alg.Calculate);
Operation eval = alg.Calculate;

const double hourlySalary = 25.75;

WriteLine("Net Pay: " + eval(17.86));
WriteLine("Net Pay: " + oper(hourlySalary));

WriteLine("=====================================");
return 0;
}
}```

This would produce:

```Net Pay: 714.4
Net Pay: 1030
=====================================
Press any key to continue . . .```

A Function Delegate with Many Parameters

A delegate that returns a value can also use many parameters. The parameters can be of the same or different types. The associated method must use the same number and types of parameters. Here is an example:

```using static System.Console;

public delegate double Operation(double x, double y);

public class Algebra
{
public double Calculate(double sal, double time)
{
return sal * time;
}
}

public class Exercise
{
public static int Main()
{
Algebra alg = new Algebra();
Operation oper = new Operation(alg.Calculate);
Operation eval = alg.Calculate;

const double timeWorked = 37.50;
const double hourlySalary = 25.75;

WriteLine("Net Pay: " + eval(17.86, 42.50));
WriteLine("Net Pay: " + oper(hourlySalary, timeWorked));

WriteLine("=====================================");
return 0;
}
}```

This would produce:

```Net Pay: 759.05
Net Pay: 965.625
=====================================
Press any key to continue . . .```

Function Delegates and Anonymous Methods

Introduction

Function delegates support anonymous methods. You primarily create the method as done for a void delegate. This time, since the method must produce a value, you can (or must) use its last expression to return a value. Here is an example:

```Operation calc = delegate ()
{
return 0.00;
};```

After doing this, you can just call the variable as done for a method, but if you want to get or use the returned value of the mehod, assign the call to another variable. Here is an example:

```using static System.Console;

public delegate double Operation();

public class Exercise
{
public static int Main()
{
Operation calc = delegate ()
{
const double hourlySalary = 25.75;
const double timeWorkedWeek = 38.50;

return hourlySalary * timeWorkedWeek;
};

WriteLine("Net Pay: {0:F}", calc());

WriteLine("=====================================");
return 0;
}
}```

This would produce:

```Net Pay: 991.38
=====================================
Press any key to continue . . .```

Using a Lambda Expression

Instead of first creating a formal method, you can use a local lambda expression. To do this, from the above code, simply omit the delegate keyword. Here is an example:

```using static System.Console;

public delegate double Operation();

public class Exercise
{
public static int Main()
{
Operation calc = () =>
{
const double hourlySalary = 25.75;
const double timeWorkedWeek = 38.50;

return hourlySalary * timeWorkedWeek;
};

WriteLine("Net Pay: {0:F}", calc());

WriteLine("=====================================");
return 0;
}
}```

Remember that you can omit the data types of the arguments. Remember that you don't have to get or use the value from the method.

Anonymous Function Delegates and Parameters

To create an anonymous delegate that uses a parameter, provide the data type and name of the parameter in the parentheses. Here is an example that uses the delegate keyword:

```using static System.Console;

public delegate double Operation();

public class Exercise
{
public static int Main()
{
Operation calc = () =>
{
const double hourlySalary = 25.75;
const double timeWorkedWeek = 38.50;

return hourlySalary * timeWorkedWeek;
};

double salary = calc();

WriteLine("Net Pay: {0:F}", salary);

WriteLine("=====================================");
return 0;
}
}```

Remember that a delegate can use more than one parameter. Here is an example:

`public delegate double Operation(double a, double b);`

When creating the anonymous delegate, pass the same number and types of parameters. Here is an example:

```using static System.Console;

public delegate double Operation(double a, double b);

public class Exercise
{
public static int Main()
{
Operation calc = delegate (double hSalary, double time)
{
const double hourlySalary = 25.75;
const double timeWorkedWeek = 38.50;

return hourlySalary * timeWorkedWeek;
};

double salary = calc(30.25, 44.00);

WriteLine("Net Pay: {0:F}", salary);

WriteLine("=====================================");
return 0;
}
}```

You can omit the delegate keyword, in which case you must add the => operator after the parentheses. Here is an example that uses one parameter:

```using static System.Console;

public delegate double Operation(double a);

public class Exercise
{
public static int Main()
{
Operation times = (double hSalary) =>
{
const double timeWorkedWeek = 38.50;

return hSalary * timeWorkedWeek;
};

double salary = times(32.85);

WriteLine("Net Pay: {0:F}", salary);

WriteLine("=====================================");
return 0;
}
}```

This would produce:

```Net Pay: 1264.73
=====================================
Press any key to continue . . .```

In case you are not using the delegate keyword, you can omit the data type(s) of the parameter(s). Here is an example that uses one parameter:

```using static System.Console;

public delegate double Operation(double a);

public class Exercise
{
public static int Main()
{
Operation times = (hSalary) =>
{
const double timeWorkedWeek = 38.50;

return hSalary * timeWorkedWeek;
};

double salary = times(32.85);

WriteLine("Net Pay: {0:F}", salary);

WriteLine("=====================================");
return 0;
}
}```

Here is an example that uses two parameters:

```using static System.Console;

public delegate double Operation(double a, double b);

public class Exercise
{
public static int Main()
{
Operation times = (salary, time) =>
{
return salary * time;

};

double pay = times(30.25, 44.00);

WriteLine("Net Pay: {0:F}", pay);

WriteLine("=====================================");
return 0;
}
}```

This would produce:

```Net Pay: 1331.00
=====================================
Press any key to continue . . .```

A Delegate as a Parameter

Passing a Parameter-Less Delegate as Parameter

Because a delegate is an object, it can be used as a parameter. Of course, you should start by having a delegate. Then create a method that that uses a parameter of the type of that delegate.Here is an example:

```using static System.Console;

public delegate double Operation();

public class Exercise
{
public double Calculate(Operation oper)
{
return 0.00;
}
}```

In the body of the method, you can use or ignore the parameter. When calling the method, pass to it a method that uses the same syntax as the delegate. Here is an example:

```using static System.Console;

public delegate double Operation();

public class Exercise
{
public static double Calculate(Operation oper)
{
double number = oper();

double result = number * 4.00;
return result;
}

public static double Multiply()
{
const double hourlySalary = 25.75;
const double timeWorkedWeek = 38.50;

return hourlySalary * timeWorkedWeek;
}

public static int Main()
{
Operation eval = new Operation(Multiply);

double triple = Calculate(Multiply);

WriteLine("Monthly Salary: {0:F}", triple);

WriteLine("=====================================");
return 0;
}
}```

Passing a One-Parameter Delegate as Parameter

You can create a method that takes a delegate as parameter and that delegate may take one parameter. Here is an example:

```public delegate double Operation(double a);

public class Exercise
{
public double Calculate(Operation oper)
{
return 0.00;
}
}```

When calling the method, pass a method that uses the same syntax as the delegate. Here is an example:

```using static System.Console;

public delegate double Operation(double a);

public class Exercise
{
private double hourlySalary;

public double Multiply(double hSal)
{
const double timeWorkedWeek = 38.50;

return hSal * timeWorkedWeek;
}

public double Calculate(Operation oper)
{
double number = oper(hourlySalary);

double result = number * 4.00;
return result;
}

public void Process()
{
hourlySalary = 28.55;

double triple = Calculate(Multiply);

WriteLine("Monthly Salary = " + triple);
}

public static int Main()
{

Exercise exo = new Exercise();

exo.Process();

WriteLine("=====================================");
return 0;
}
}```

Passing a Multi-Parameter Delegate as Parameter

You can create a method that takes a multi-parameters delegate as parameter. Here is an example of such a delegate:

```using static System.Console;

public delegate double Operation(double a, double b);

public class Exercise
{
public double Calculate(Operation oper)
{
return 0.00;
}
}```

When calling the method, pass the name of a method that uses the same syntax as the delegate. Here is an example:

```using static System.Console;

public delegate double Operation(double a, double b);

public class Exercise
{
private double timeWorked;
private double hourlySalary;

public double Multiply(double hSal, double work)
{
return hSal * work;
}

public double Calculate(Operation oper)
{
double number = oper(hourlySalary, timeWorked);

double result = number * 4.00;
return result;
}

public void Process()
{
timeWorked = 44.50;
hourlySalary = 28.55;

WriteLine("Monthly Salary = " + quadruple);
}

public static int Main()
{
Exercise exo = new Exercise();

exo.Process();
WriteLine("=====================================");
return 0;
}
}```

In the above examples, we used values that were external to the method to perform the necessary calculations. As an alternative, you can pass (an) additional parameter(s) that the delegate-parameter would use to perform the calculations. Here is an example for a method that uses a delegate of one parameter:

```using static System.Console;

public delegate double Operation(double a);

public class Exercise
{
public double Multiply(double hSal)
{
return hSal * 41.50;
}

public double Calculate(Operation oper, double number)
{
double result = oper(number);

return result;
}

public void Process()
{
double hourlySalary = 28.55;

double triple = Calculate(Multiply, hourlySalary);

WriteLine("Monthly Salary = {0:F}", triple);
}

public static int Main()
{
Exercise exo = new Exercise();

exo.Process();
WriteLine("=====================================");
return 0;
}
}```

This would produce:

```Monthly Salary = 1184.83
=====================================
Press any key to continue . . .```

In the same way, if a multi-parameter delegate is passed to a method, you can pass all the other pamameters that the delegate must process. Here is an example:

```using static System.Console;

public delegate double Operation(double a, double b);

public class Exercise
{
public double Multiply(double hSal)
{
return hSal * 41.50;
}

public double Multiply(double hSal, double time)
{
return hSal * time;
}

public double Calculate(Operation oper, double number, double value)
{
double result = oper(number, value);

return result;
}

public void Process()
{
double timeWorked = 42.00;
double hourlySalary = 28.55;

double triple = Calculate(Multiply, hourlySalary, timeWorked);

WriteLine("Weekly Salary = {0:F}", triple);
}

public static int Main()
{
Exercise exo = new Exercise();

exo.Process();
WriteLine("=====================================");
return 0;
}
}```

This would produce:

```Weekly Salary = 1199.10
=====================================
Press any key to continue . . .```

Using a Lambda Expression

A lambda expression can take a delegate as parameter. Of course, you should (must) have a delegate. You can first create one in the class. Here is an example:

`public delegate double ThreeOperands(double x, double y, bool z);`

As we saw already, you can then create a method that receives such a delegate as argument. We saw that, to call the method, you can pass the name of a method that uses the same syntax as the delegate. Here is an example:

```using static System.Console;

public delegate double Operation();

public class Exercise
{
private double hourlySalary = 12.74;
private double timeWorked = 10.50;

public double Multiply()
{
if (timeWorked <= 8)
{
return hourlySalary * timeWorked;
}
else
{
double overtime = timeWorked - 8.00;
double overtimeRate = hourlySalary * 1.50;

double regularPay = 8.00 * hourlySalary;
double overtimePay = overtime * overtimeRate;
return regularPay + overtimePay;
}
}

public double EvaluateSalary(Operation calc)
{
return calc();
}

public void Process()
{
Operation oper = Multiply;

double dailySalary = EvaluateSalary(oper);

WriteLine("Daily Salary = " + dailySalary.ToString("F"));
}

public static int Main()
{
Exercise exo = new Exercise();

Title = "Salary Evaluation";

exo.Process();
WriteLine("=====================================");
return 0;
}
}```

This would produce:

```Daily Salary = 149.70
=====================================
Press any key to continue . . .```

When calling the method that takes a delegate as parameter, instead of first creating the method that would be associated to the delegate, you can implement a lambda expression directly in the parentheses of the calling method as lamda expression. Here is an example:

```using static System.Console;

public delegate double Operation();

public class Exercise
{
private double hourlySalary = 12.74;
private double timeWorked = 10.50;

public double EvaluateSalary(Operation calc)
{
return calc();
}

public void Process()
{
double dailySalary = EvaluateSalary(() =>
{
if (timeWorked <= 8)
{
return hourlySalary * timeWorked;
}
else
{
double overtime = timeWorked - 8.00;
double overtimeRate = hourlySalary * 1.50;

double regularPay = 8.00 * hourlySalary;
double overtimePay = overtime * overtimeRate;
return regularPay + overtimePay;
}
});

WriteLine("Daily Salary = " + dailySalary.ToString("F"));
}

public static int Main()
{
Exercise exo = new Exercise();

Title = "Salary Evaluation";

exo.Process();
WriteLine("=====================================");
return 0;
}
}```

You can also create a method that takes a delegate that uses one parameter. Here is an example:

```using static System.Console;

public delegate double Operation(double a);

public class Exercise
{
private double hourlySalary = 12.75;

public double Multiply(double timeWorked)
{
if (timeWorked <= 8)
{
return hourlySalary * timeWorked;
}
else
{
double overtime = timeWorked - 8.00;
double overtimeRate = hourlySalary * 1.50;

double regularPay = 8.00 * hourlySalary;
double overtimePay = overtime * overtimeRate;
return regularPay + overtimePay;
}
}

public double EvaluateSalary(Operation calc)
{
return calc(hourlySalary);
}

public void Process()
{
Operation oper = Multiply;

double dailySalary = EvaluateSalary(oper);

WriteLine("DailySalary = " + dailySalary.ToString("F"));
}

public static int Main()
{
Exercise exo = new Exercise();

Title = "Salary Evaluation";

exo.Process();
WriteLine("=====================================");
return 0;
}
}```

This would produce:

```DailySalary = 192.84
=====================================
Press any key to continue . . .```

Instead of first creating a method to associate to the delegate, you can implement the method directly where it is needed. Here is an example:

```using static System.Console;

public delegate double Operation(double a);

public class Exercise
{
private double hourlySalary = 12.75;

public double EvaluateSalary(Operation calc)
{
return calc(hourlySalary);
}

public void Process()
{
double dailySalary = EvaluateSalary((double timeWorked) =>
{
if (timeWorked <= 8)
{
return hourlySalary * timeWorked;
}
else
{
double overtime = timeWorked - 8.00;
double overtimeRate = hourlySalary * 1.50;

double regularPay = 8.00 * hourlySalary;
double overtimePay = overtime * overtimeRate;
return regularPay + overtimePay;
}
});

WriteLine("Daily Salary = " + dailySalary.ToString("F"));
}

public static int Main()
{
Exercise exo = new Exercise();

Title = "Salary Evaluation";

exo.Process();
WriteLine("=====================================");
return 0;
}
}```

Remember that you can omit the data type of the argument in the lambda expression. Here is an example:

```using static System.Console;

public delegate double Operation(double a);

public class Exercise
{
private double hourlySalary = 12.75;

public double EvaluateSalary(Operation calc)
{
return calc(hourlySalary);
}

public void Process()
{
double dailySalary = EvaluateSalary(timeWorked =>
{
if (timeWorked <= 8)
{
return hourlySalary * timeWorked;
}
else
{
double overtime = timeWorked - 8.00;
double overtimeRate = hourlySalary * 1.50;

double regularPay = 8.00 * hourlySalary;
double overtimePay = overtime * overtimeRate;
return regularPay + overtimePay;
}
});

WriteLine("Daily Salary = " + dailySalary.ToString("F"));
}

public static int Main()
{
Exercise exo = new Exercise();

Title = "Salary Evaluation";

exo.Process();
WriteLine("=====================================");
return 0;
}
}```

In most examples above, we first declared some variables and used them when calling the method. Normally, the values may not be available before the method is called. The solution is to pass additional parameters that would accompagny the method that would use them. Here is an example for a regular delegate:

```using static System.Console;

public delegate double Operation(double a, double b);

public class Exercise
{
public double Multiply(double hSalary, double time)
{
if (time <= 8)
{
return hSalary * time;
}
else
{
double overtime = time - 8.00;
double overtimeRate = hSalary * 1.50;

double regularPay = 8.00 * hSalary;
double overtimePay = overtime * overtimeRate;
return regularPay + overtimePay;
}
}

public double EvaluateSalary(double x, double y, Operation calc)
{
return calc(x, y);
}

public void Process()
{
Operation oper = Multiply;

double dailySalary = EvaluateSalary(12.74, 10.50, oper);

WriteLine("Daily Salary = " + dailySalary.ToString("F"));
}

public static int Main()
{
Exercise exo = new Exercise();

Title = "Salary Evaluation";

exo.Process();
WriteLine("=====================================");
return 0;
}
}```

In the same way, if you are creating a lambda expression, you can pass (an) addition parameter(s). Here is an example:

```using static System.Console;

public delegate double Operation(double a, double b);

public class Exercise
{
public double EvaluateSalary(double x, double y, Operation calc)
{
return calc(x, y);
}

public void Process()
{
double dailySalary = EvaluateSalary(12.74, 10.50,
(double hSalary, double time) =>
{
if (time <= 8.00)
{
return hSalary * time;
}
else
{
double overtime = time - 8.00;
double overtimeRate = hSalary * 1.50;

double regularPay = 8.00 * hSalary;
double overtimePay = overtime * overtimeRate;
return regularPay + overtimePay;
}
});

WriteLine("DailySalary = " + dailySalary.ToString("F"));
}

public static int Main()
{
Exercise exo = new Exercise();

Title = "Salary Evaluation";

exo.Process();
WriteLine("=====================================");
return 0;
}
}```

Remember that you can omit the data types of the parameters in the lambda expression.

If the lambda expression is only only one parameter, you can omit the parentheses of the parameter. Here is an example:

```using static System.Console;

public delegate double Operation(double a);

public class Exercise
{
private double hourlySalary = 12.74;

public void Process()
{
double dailySalary = EvaluateSalary(timeWorked =>
{
if (timeWorked <= 8.00)
{
return hourlySalary * timeWorked;
}
else
{
double overtime = timeWorked - 8.00;
double overtimeRate = hourlySalary * 1.50;

double regularPay = 8.00 * hourlySalary;
double overtimePay = overtime * overtimeRate;
return regularPay + overtimePay;
}
});

WriteLine("Daily Salary = " + dailySalary.ToString("F"));
}

public double EvaluateSalary(Operation calc)
{
return calc(hourlySalary);
}

public static int Main()
{
Exercise exo = new Exercise();

Title = "Salary Evaluation";

exo.Process();
WriteLine("=====================================");
return 0;
}
}```

If the lambda expression is using more than one parameter, those parameters must be included in parentheses.