A Delegate as a Function

Introduction

In many programming languages, such as Visual Basic or Pascal, 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.

The basic formula used 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:

using Microsoft.AspNetCore.Mvc.RazorPages;

namespace Exercises.Pages
{
    delegate double Evaluation();

    public class ExerciseModel : PageModel
    {
        public void OnGet()
        {
        }
    }
}

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

using Microsoft.AspNetCore.Mvc.RazorPages;

namespace Exercises.Pages
{
    delegate double Evaluation();

    public class ExerciseModel : PageModel
    {
        public void OnGet()
        {
        }

        public double Calculate()
        {
            return 0.00;
        }
    }
}

Using a Function Delegate

To use the function, you can first declare a variable of the type of the delegate and initialize it using the new operator as done for a class (a record or a structure) with 0 or a default constructor. In the parentheses, pass the name of the function. Here is an example:

@functions{
    delegate double Evaluation();

    double Calculate()
    {
        return 0.00;
    }
}

@{
    Evaluation eval = new Evaluation(Calculate);
}

To use the delegate, you can call the variable as if it were a function. 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:

@functions{
    delegate double Evaluation();

    double Calculate()
    {
        return 0.00;
    }
}

@{
    Evaluation eval = new Evaluation(Calculate);

    double weeklySalary = eval();
}

You can then use the returned value as you see fit. For example, you can present it to the user. This can be done as follows:

@page
@model Exercises.Pages.ExerciseModel
@{
    Evaluation eval = new Evaluation(Calculate);
    
    double wage = eval();

    string strNetPay = "Net Pay: " +  wage.ToString("F");
}

@functions{    
    delegate double Evaluation();

    double Calculate()
    {
        double hSalary = 14.36;
        double tWorked = 32.00;

        double wSalary = hSalary * tWorked;

        return wSalary;
    }
}

<p>@strNetPay</p>

Here is an example of running the program:

Net Pay: 616.86

In the above code, we first declared a variable to store the returned value of the delegate. This can be useful if you are planning to use the value many times. If you are planning to use the value only once, you can call the delegate directly where the value is needed. Here an example:

@page
@model Exercises.Pages.ExerciseModel
@{
    Evaluation eval = new(Calculate);

    string strNetPay = "Net Pay: " +  eval().ToString("F");
}

@functions{    
    delegate double Evaluation();

    double Calculate()
    {
        double hSalary = 17.88;
        double tWorked = 34.50;

        return hSalary * tWorked;
    }
}

<p>@strNetPay</p>

In the above example, we declared a variable for the delegate and initialized it as done for the variable of a class. This can be necessary if you are planning to use the delegate variable many times. If not, you can apply the initialization directly where the function delegate is called. Based on the previous two examples, this can be done as follows:

@page
@model Exercises.Pages.ExerciseModel
@{
    double wage = new Evaluation(Calculate)();

    string strNetPay = "Net Pay: " +  wage.ToString("F");
}

@functions{    
    delegate double Evaluation();

    double Calculate()
    {
        double hSalary = 21.64;
        double tWorked = 36.00;

        return hSalary * tWorked;
    }
}

<p>@strNetPay</p>

Or as follows:

@page
@model Exercises.Pages.ExerciseModel
@{
    string strNetPay = "Net Pay: " +  new Evaluation(Calculate)().ToString("F");
}

@functions{    
    delegate double Evaluation();

    double Calculate()
    {
        double hSalary = 15.73;
        double tWorked = 38.50;

        return hSalary * tWorked;
    }
}

<p>@strNetPay</p>

We saw that, to initialize the delegate variable, we used the new operator, as follows:

@functions{    
    Evaluation eval = new Evaluation(Calculate);
}

As an alternative, you can assign the name of the function to the delegate variable. Here is an example:

@page
@model Exercises.Pages.ExerciseModel
@{
    Evaluation eval = Calculate;

    string strNetPay = "Net Pay: " + eval().ToString("F");
}

@functions{    
    delegate double Evaluation();

    double Calculate()
    {
        double hSalary = 12.96;
        double tWorked = 35.00;

        return hSalary * tWorked;
    }
}

<p>@strNetPay</p>

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:

delegate double Operation(double nbr);

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

@functions{
    delegate double Evaluation(double x);

    double Calculate(double sal)
    {
        return 0.00;
    }
}

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

@functions{
    // A delegate variable initialized with the delegate object
    Operation oper = new Operation(Calculate);
    // A delegate variable initialized with a function (pointer)
    Operation eval = Calculate;
}

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 function. In its parentheses, pass the appropriate number and type(s) of argument(s). Here is an example:

@page
@model Exercises.Pages.ExerciseModel
@{
    double hSalary = 15.65;
    
    Evaluation eval = new Evaluation(Calculate);

    double wage = eval(hSalary);

    string strNetPay = "Net Pay: " + wage.ToString("F");
}

@functions{    
    delegate double Evaluation(double x);

    double Calculate(double sal)
    {        
        double tWorked = 32;

        return sal * tWorked;
    }
}

<pre>================================
Hourly Salary: @hSalary
------------------------------
@strNetPay
================================</pre>

Remember that, if you will use the delegate only one, you don't have to declare a variable for the delegate. Here is an example:

@page
@model Exercises.Pages.ExerciseModel
@{
    double hSalary = 19.36;
    
    double wage = new Evaluation(Calculate)(hSalary);

    string strNetPay = "Net Pay: " + wage.ToString("F");
}

@functions{    
    delegate double Evaluation(double x);

    double Calculate(double sal)
    {
        return sal * 40.00;
    }
}

<pre>================================
Hourly Salary: @hSalary
------------------------------
@strNetPay
================================</pre>

In the same way, you may not need a variable to store the value returned by the function delegate. Here is an example:

@page
@model Exercises.Pages.ExerciseModel
@{
    double hSalary = 22.27;

    string strNetPay = "Net Pay: " + new Evaluation(Calculate)(hSalary).ToString("F");
}

@functions{    
    delegate double Evaluation(double x);

    double Calculate(double sal)
    {
        return sal * 40.00;
    }
}

<pre>================================
Hourly Salary: @hSalary
------------------------------
@strNetPay
================================</pre>

A Function Delegate with Many Parameters

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

@page
@model Exercises.Pages.ExerciseModel
@{
    Evaluation eval = new Evaluation(Calculate);

    double hSalary = 27.27;
    double tWorked = 44.00;
    
    double wage = eval(hSalary, tWorked);

    string strNetPay = "Net Pay: " + wage.ToString("F");
}

@functions{
    // A delegate
    delegate double Evaluation(double x, double y);
    
    // A function for a delegate
    double Calculate(double sal, double time)
    {
        return sal * 40.00;
    }
}

<pre>================================
Hourly Salary: @hSalary
Time Worked: @tWorked
------------------------------
@strNetPay
================================</pre>

Once again, you assign the name of the function to the delegate variable. Here is an example:

@page
@model Exercises.Pages.ExerciseModel
@{
    Evaluation eval = Calculate;

    double hSalary = 23.92;
    double tWorked = 41.50;
    
    double wage = eval(hSalary, tWorked);

    string strNetPay = "Net Pay: " + wage.ToString("F");
}

@functions{    
    delegate double Evaluation(double x, double y);
    
    double Calculate(double sal, double time)
    {
        return sal * 40.00;
    }
}

<pre>================================
Hourly Salary: @hSalary
Time Worked: @tWorked
------------------------------
@strNetPay
================================</pre>

In fact, you may not need a variable for the delegate:

@page
@model Exercises.Pages.ExerciseModel
@{
    Evaluation eval = Calculate;

    double hSalary = 22.82;
    double tWorked = 42.50;
    
    double wage = new Evaluation(Calculate)(hSalary, tWorked);

    string strNetPay = "Net Pay: " + wage.ToString("F");
}

@functions{    
    delegate double Evaluation(double x, double y);
    
    double Calculate(double sal, double time)
    {
        return sal * 40.00;
    }
}

<pre>================================
Hourly Salary: @hSalary
Time Worked: @tWorked
------------------------------
@strNetPay
================================</pre>

In the same way, you may not need a variable to store the value returned by the delegate function, like this:

@page
@model Exercises.Pages.ExerciseModel
@{
    Evaluation eval = Calculate;

    double hSalary = 25.65;
    double tWorked = 40.50;

    string strNetPay = "Net Pay: " + (new Evaluation(Calculate)(hSalary, tWorked)).ToString("F");
}

@functions{    
    delegate double Evaluation(double x, double y);
    
    double Calculate(double sal, double time)
    {
        return sal * 40.00;
    }
}

<pre>================================
Hourly Salary: @hSalary
Time Worked: @tWorked
------------------------------
@strNetPay
================================</pre>

Function Delegates and Anonymous functions

Introduction

Earlier, we learned to create a simple delegate that returns a value and takes no argument. You may already know that you can nest a function in another. Here is an example:

@page
@model Exercises.Pages.ExerciseModel
@{
    Evaluation eval = new Evaluation(Calculate);

    double number = eval();
    string strNetPay = "Net Pay: " + number.ToString("F");
}

@functions{    
    delegate double Evaluation();
    
    double Calculate()
    {
        double hSalary = 21.88;
        double tWorked = 34.50;
        
        return hSalary * tWorked;
    }
}

<pre>================================
@strNetPay
================================</pre>

Here is an example of running the program:

================================
Net Pay: 754.86
================================

Function delegates support anonymous functions. In this case, when declaring a variable for the delegate, replace the combination of the new operator and the name of the delegate by the delegate keyword. Leave the parentheses empty and define the behavior you want, inside the curly brackets. This can be done as follows:

@functions{
    delegate double Evaluation();

    Evaluation eval = delegate()
    {
        double hSalary = 16.47;
        double tWorked = 37.50;

        return hSalary * tWorked;
    };
}

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

@page
@model Exercises.Pages.ExerciseModel
@{
    Evaluation eval = new Evaluation(Calculate);

    double number = eval();

    string strNetPay = "Net Pay: " + number.ToString("F");
}

@functions{    
    delegate double Evaluation();
    
    double Calculate()
    {
        double hSalary = 21.88;
        double tWorked = 34.50;
        
        return hSalary * tWorked;
    }
}

<pre>================================
@strNetPay
================================</pre>

Using a Lambda Expression

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

@page
@model Exercises.Pages.ExerciseModel
@{
    double number = eval();

    string strNetPay = "Net Pay: " + number.ToString("F");
}

@functions{
    delegate double Evaluation();

    Evaluation eval = () =>
    {
        double hSalary = 16.47;
        double tWorked = 37.50;

        return hSalary * tWorked;
    };
}

<pre>================================
@strNetPay
================================</pre>

An Anonymous Function Delegate with a Parameter

To create an anonymous delegate that uses a parameter, declare a variable for the delegate and initialize it with the delegate keyword and parentheses. In the parentheses of delegate(), provide a name for the parameter and its data type. When calling the delegate variable, pass an appropriate argument. Here is an example:

@page
@model Exercises.Pages.ExerciseModel
@{
    double hSalary = 12.68;
    
    double wage = eval(hSalary);

    string strNetPay = "Net Pay: " + wage.ToString("F");
}

@functions{
    delegate double Evaluation(double x);

    Evaluation eval = delegate(double sal)
    {
        return sal * 40.00;    
    };
}

<pre>================================
Hourly Salary: @hSalary
Time Worked: 40.00
------------------------------
@strNetPay
================================</pre>

As an alternative, you can omit the delegate keyword but add the => operator after the parentheses. Here is an example:

@page
@model Exercises.Pages.ExerciseModel
@{
    double hSalary = 17.37;
    
    double wage = eval(hSalary);

    string strNetPay = "Net Pay: " + wage.ToString("F");
}

@functions{
    delegate double Evaluation(double x);

    Evaluation eval = (sal) =>
    {
        return sal * 37.50;    
    };
}

<pre>================================
Hourly Salary: @hSalary
------------------------------
@strNetPay
================================</pre>

An Anonymous Function Delegate with Parameters

Remember that a delegate can use more than one parameter. In fact, you can create its function in the body of the function that will call the delegate. Here is an example:

@page
@model Exercises.Pages.ExerciseModel
@{
    Evaluation eval = new Evaluation(Calculate);

    double hSalary = 26.97;
    double tWorked = 39.00;
    
    double wage = eval(hSalary, tWorked);

    string strNetPay = "Net Pay: " + wage.ToString("F");
}

@functions{
    delegate double Evaluation(double x, double y);
    
    double Calculate(double sal, double time)
    {
        return sal * time;
    }
}

<pre>================================
Hourly Salary: @hSalary
Time Worked: @tWorked
--------------------------------
@strNetPay
================================</pre>

When creating the anonymous delegate, declare a variable for the delegate. Initialize it with delegate(). In the parentheses, pass the same number of parameters. Here is an example:

@page
@model Exercises.Pages.ExerciseModel
@{
    double hSalary = 18.25;
    double tWorked = 37.00;
    
    double wage = eval(hSalary, tWorked);

    string strNetPay = "Net Pay: " + wage.ToString("F");
}

@functions{
    delegate double Evaluation(double x, double y);

    Evaluation eval = delegate(double sal, double time)
    {
        return sal * time;
    };
}

<pre>================================
Hourly Salary: @hSalary
Time Worked: @tWorked
--------------------------------
@strNetPay
================================</pre>

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:

@page
@model Exercises.Pages.ExerciseModel
@{
    double hSalary = 15.85;
    double tWorked = 33.50;
    
    double wage = eval(hSalary, tWorked);

    string strNetPay = "Net Pay: " + wage.ToString("F");
}

@functions{
    delegate double Evaluation(double x, double y);

    Evaluation eval = (double sal, double time) =>
    {
        return sal * time;
    };
}

<pre>================================
Hourly Salary: @hSalary
Time Worked: @tWorked
--------------------------------
@strNetPay
================================</pre>

In the 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:

@page
@model Exercises.Pages.ExerciseModel
@{
    double hSalary = 17.65;
    double tWorked = 36.00;
    
    double wage = eval(hSalary, tWorked);

    string strNetPay = "Net Pay: " + wage.ToString("F");
}

@functions{
    delegate double Evaluation(double x, double y);

    Evaluation eval = (sal, time) =>
    {
        return sal * time;
    };
}

<pre>================================
Hourly Salary: @hSalary
Time Worked: @tWorked
--------------------------------
@strNetPay
================================</pre>

A Delegate as Type

Returning a Delegate from a function

A delegate is a type. As such, it can be used as a type returned from a function. The delegate can be a void type. Therefore, create the delegate and create a function that uses the same syntax as the delegate. Here is an example:

@functions{
    delegate void Observation();

    void Create()
    {
    }
}

Then create a function whose return type is the name of the delegate. The function must return a value that is the type of the delegate. Otherwise, you can return null. Here is an example:

@functions{
    delegate void Observation();

    void Create()
    {
    }

    Observation Produce()
    {
        return null;
    }
}

In the body of the function, you can declare a variable of the type of the delegate and initialize it using the new operator and the name of the delegate. In the parentheses of the initialization, pass the name of the function that uses the same syntax as the delegate. You can then return the variable of the delegate. Here ia an example:

@functions{
    delegate void Observation();

    void Create() { }

    Observation Produce()
    {
        Observation quote = new Observation(Create);

        return quote;
    }
}

By the way, the variable is useful only if you plan to use the value many times. If not, you can just return the initialization of the delegate. Here is an example:

@functions{
    delegate void Observation();

    void Create() { }

    Observation Produce()
    {
        return new Observation(Create);
    }
}

Once the function is ready, to use it, you can declare a variable of the type of the delegate and initialize it with the function that returns it. Here is an example:

@page
@model Exercises.Pages.ExerciseModel
@using static System.Console
@{
    // A variable of a delegate
    Observation obs = Produce();
    
    // Calling the delegate variable
    obs();
}

@functions{
    delegate void Observation();

    void Create()
    {
        WriteLine("Never let your head hang down. Never give up and sit " +
                  "down and grieve. Find another way. And don't pray when " +
                  "it rains if you don't pray when the sun shines. - President Nixon -");
    }

    Observation Produce()
    {
        Observation quote = new Observation(Create);

        return quote;
    }
}

This would produce:

Never let your head hang down. Never give up and sit down and grieve. Find another way. And don't pray when it rains if you don't pray when the sun shines. - President Nixon -

Once again, a variable is necessary only you are planning to use the variable more than once. Otherwise, call the function directly where it is needed. This can be done as follows:

@page
@model Exercises.Pages.ExerciseModel
@using static System.Console
@{
    Produce()();
}

@functions{
    delegate void Observation();

    void Create()
    {
        WriteLine("Never let your head hang down. Never give up and sit " +
                  "down and grieve. Find another way. And don't pray when " +
                  "it rains if you don't pray when the sun shines. - President Nixon -");
    }

    Observation Produce()
    {
        Observation quote = new Observation(Create);

        return quote;
    }
}

Passing a Parameter-Less Delegate as Parameter

In the previous lesson, we saw how to use a void delegate as a parameter. In the same way, if a delegate is returning a value, it can be used as a parameter. Of course, you should start by creating a delegate that returns a value. If necessary, and in most cases, you should have a function that uses the same syntax as the delegate. Here is an example:

@functions{
    delegate double Evaluation();

    double Multiply()
    {
        return 0.00;
    }
}

To use the delegate as parameter, create a function that uses a parameter of the type of that delegate. Here is an example:

@functions{
    delegate double Operation();

    public double Multiply()
    {
        return 0.00;
    }

    double Calculate(Operation oper)
    {
        return 0.00;
    }
}

Create a function that returns the delegate type. In the body of the function, you can declare a variable of the delegate and return it. To use the function that returns the delegate type, you can declare a variable of the delegate and assign the function call to it. After that, the delegate variable holds the value that the original delegate is supposed to produce. This whole description can be implemented as follows:

@page
@model Exercises.Pages.ExerciseModel
@using static System.Console
@{
    Operation eval = Evaluate();

    double netPay = eval();

    string strNetPay = string.Format("{0:f}", netPay);
}

@functions{
    delegate double Operation();

    double Multiply()
    {
        double hSalary = 23.57;
        double tWorked = 30.00;

        return hSalary * tWorked;
    }

    Operation Evaluate()
    {
        Operation oper = new Operation(Multiply);

        return oper;
    }
}

<pre>======================
Net Pay: @strNetPay
======================</pre>

Once again, the variables are useful only if you are planning to use their values many times. Otherwise, you can call a function where it is needed. Here are examples:

@page
@model Exercises.Pages.ExerciseModel
@using static System.Console
@{
    Operation eval = Evaluate();

    string strNetPay = string.Format("{0:f}", eval());
}

@functions{
    delegate double Operation();

    double Multiply()
    {
        double hSalary = 26.36;
        double tWorked = 33.50;

        return hSalary * tWorked;
    }

    Operation Evaluate()
    {
        return new Operation(Multiply);
    }
}

<pre>======================
Net Pay: @strNetPay
======================</pre>

Passing a One-Parameter Delegate as Parameter

Imagine you create a delegate function that takes a parameter. You can create a function that return a value of that delegate type. To start, create a function that uses the same syntax as the delegate. Here is an example:

@functions{
    delegate double Operation(double x);

    // A function
    double Multiply(double time)
    {
        return 0.00;
    }
}

Passing a Multi-Parameter Delegate as Parameter

You can create a function that returns a multi-parameters delegate. The steps to follow are the same as those of the previous sections. Here is an example:

@page
@model Exercises.Pages.ExerciseModel
@using static System.Console
@{
    Operation calc = Evaluate();

    double hSalary = 19.68;
    double tWorked = 39.50;
    
    double result = calc(hSalary, tWorked);

    string strNetPay = string.Format("{0:f}", result);
}

@functions{
    delegate double Operation(double x, double y);

    double Multiply(double sal, double time)
    {
        return sal * time;
    }
    
    Operation Evaluate()
    {
        Operation oper = new Operation(Multiply);

        return oper;
    }
}

<pre>======================
Hourly Salary: @hSalary
Time Worked:   @tWorked
----------------------
Net Pay:       @strNetPay
======================</pre>

Previous Copyright © 2008-2022, FunctionX Friday 04 Mars 2022 Next