Fundamentals of Delegates

Introduction

A function is an action whose role can be requested or called anytime, without going through a class as is the case for a method of a class. This concept is supported in the .NET Framework as a delegate and made available to C# (and the other .NET languages).

As you probably know from C#, a class can contain one or more methods used to perform operations. Here is an example:

using System.Web.Mvc;

namespace Exercises.Controllers
{
    public class HomeController : Controller
    {
        // GET: Home
        public ActionResult Index()
        {
            return View();
        }

        public void Create()
        {
            ViewBag.Message = "Actions speak louder than words";
        }
    }
}

Such a method must be explicitly called. Here is an example:

using System.Web.Mvc;

namespace Exercises.Controllers
{
    public class HomeController : Controller
    {
        // GET: Home
        public ActionResult Index()
        {
            Create();
            
            return View();
        }

        public void Create()
        {
            ViewBag.Message = "Actions speak louder than words";
        }
    }
}

Here is an example of accessing the message in the method:

@{
    ViewBag.Title = "Conversations";
}

<p>@ViewBag.Message</p>

This would produce:

Introduction to Delegates

ApplicationPractical Learning: Introducing Delegates

  1. Start Microsoft Visual Studio
  2. On the main menu of Microsoft Visual Studio, click File -> New -> Project...
  3. In the middle frame of the New Object dialog box, make sure ASP.NET Web Application (.NET Framework) is selected.
    Change the project Name to GasUtilityCompany7
  4. Click OK
  5. In the New ASP.NET Web Application dialog box, in the templates list, click the MVC icon and click OK
  6. In the Solution Explorer, right-click GasUtilityCompany7 -> Add -> New Folder
  7. Type Images as the name of the folder and press Enter
  8. Add the following picture to the Images folder:

    Gas Utility Company

  9. In the Solution Explorer, right-click Content -> Style Sheet
  10. Type Utilities as the name of the file, and press Enter
  11. Add the following styles to the file:
    body {
        padding-top: 150px;
        background-color: #EEEEEE;
    }
    
    #top-banner {
        top: 0;
        left: 0;
        right: 0;
        width: 100%;
        bottom: auto;
        height: 5.75em;
        position: absolute;
        background-color: #192E46; }
    
    .centralizer {
        margin: auto;
        width: 700px; }
    
    .navbar-inverse {
        background-color: orange;
        border-color: #080808;
    }
    
    .navbar {
        border-top: 5px solid #faf76f;
        border-bottom: 5px solid navy;
    }
    
    .navbar-fixed-top { top: 80px; }
    
    .navbar-inverse .navbar-nav > li > a,
    .navbar-inverse .navbar-nav > li > a:link {
        color: #faf76f;
        background-color: transparent;
    }
    
    .navbar-inverse .navbar-nav > li > a:hover,
    .navbar-inverse .navbar-nav > li > a:focus {
        color: orange;
        background-color: #faf76f;
    }
    
    .body-holder {
        width: 800px;
        margin: auto; }
    
    .col-md-3 {
        padding-top: 10px;
        border-radius: 6px;
        padding-bottom: 10px;
        background-color: #800000;
        border: 1px solid #000000; }
    
    .jumbotron {
        padding-top: 3px;
        border-radius: 10px;
        background-color: #f1ddca;
    }
    
    .jumbotron h1 {
        color: #800000;
        font-size: 43px;
    }
    
    .lead { margin-bottom: 0; }
    
    #bottom-banner {
        left: 0;
        right: 0;
        bottom: 0;
        top: auto;
        width: 100%;
        height: 4.15em;
        position: absolute;
        background-color: #003366;
        border-top: 5pt solid black; }
    
    #copyright {
        color: orange;
        margin-top: 1em;
        font-weight: 600;
        font-size: 1.15em;
        text-align: center;
        line-height: 1.15em;
        font-family: Garamond, Georgia, 'Times New Roman', serif; }
    
    .topic { float: left }
    
    .topic a:link, .topic a:active, .topic a:visited, .topic a:hover {
        height: 32px;
        font-size: 12pt;
        line-height: 26px;
        margin-left: -10px;
        padding-left: 20px;
        text-decoration: none;
        display: inline-block;
        font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; }
    
    .topic, .topic a:link, .topic a:active,
    .topic a:visited, .topic a:hover { width: 190px }
    
    .topic a:link    { color: #FFFF00 }
    .topic a:active  { color: #CC99FF }
    .topic a:visited { color: #FFCC99 }
    
    .topic a:hover {
        color: #FFCCFF;
        display: inline-block;
        background-color: #ff6a00;
        outline: 1pt solid #CCFF33; }
    
    .small-text      { width: 30px; }
    .left-col        { width: 120px }
    .large           { width: 168px }
    .txtContext      { width: 80px  }
    .left-column     { width: 200px }
    .left-text-boxes { width: 100px }
    .right-label     { width: 145px }
    .horizontal-line { border-bottom: 1px dotted #000000; }
    
    .btnLarge {
        height: 32px;
        width: 400px; }
  12. In the Solution Explorer, right-click Controllers -> Add -> New Scaffolded Item...
  13. In the Add Scaffold dialog box, in the middle frame, click MVC 5 Controller - Empty
  14. Click Add
  15. Type to Employees to get EmployeesController
  16. Click Add
  17. Add a method named AccountCreation that follows the same formula as the existing method:
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.Mvc;
    
    namespace GasUtilityCompany7.Controllers
    {
        public class EmployeesController : Controller
        {
            // GET: Employees
            public ActionResult Index()
            {
                return View();
            }
    
            // GET: ResetPassword
            public ActionResult ResetPassword()
            {
                return View();
            }
        }
    }
  18. In the Solution Explorer, under Views, right-click Employees -> Add -> New Scaffolded Item...
  19. In the Add Scaffold dialog box, click MVC 5 View and click Add
  20. Type ResetPassword as the View Name
  21. Click Add
  22. In the Solution Explorer, under Views, right-click Employees -> Add -> View...
  23. Type Index as the View Name
  24. Click Add
  25. Change the document as follows:
    @{
        ViewBag.Title = "Employees";
    }
    
    <h2>Gas Utility Company - Employees Portal</h2>
    
    <p>@Html.ActionLink("Reset Employee Account Password", "ResetPassword")</p>
  26. In the Solution Explorer, under Views, expand Home and double-click Index.cshtml to open it
  27. Change the document as follows:
    @{
        ViewBag.Title = "GUC Home";
    }
    
    <div class="jumbotron">
        <h1>Your Gas Needs With Us</h1>
        <p class="lead">The Gas Utility Company (GUC) serves the whole Metropolitan
            area and its vicinity. The company serves both residential and business
            needs in terms of natural gas.</p>
    </div>
    
    <div class="row">
        <div class="col-md-4">
            <h2>Employees</h2>
            <p>If you are an employee, make sure you log in in order to sign your
                time sheet and review available internal employment.</p>
            @Html.ActionLink("Employees Portal", "Index", "Employees")
        </div>
        <div class="col-md-4">
            <h2>Customers</h2>
            <p>In order to review or pay your bill, you must first log in. If you
                are not yet a customer, please create an account today.</p>
            @Html.ActionLink("Customers Topics", "Index", "Customers")
        </div>
        <div class="col-md-4">
    
            <h2>Community</h2>
            <p>This section provides much information about GUC's interactions
                with its community and its environment.</p>
            @Html.ActionLink("Community Relations", "Index", "Home")
        </div>
    </div>
  28. In the Solution Explorer, expand Views and expand Shared
  29. Double-click _Layout.cshtml to open it
  30. Change the document as follows:
    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Gas Utility Company :: @ViewBag.Title</title>
    @Styles.Render("~/Content/css")
    @Scripts.Render("~/bundles/modernizr")
    <link rel="stylesheet" type="text/css" href="~/Content/Utilities.css" />
    </head>
    <body>
        <header id="top-banner">
            <p class="text-center"><img src="~/Images/guc.png" alt="Gas Utility Company" width="649" height="74" /></p>
        </header>
    
        <div class="navbar navbar-inverse navbar-fixed-top">
            <div class="centralizer">
                <div class="container">
                    <div class="navbar-header">
                        <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
                            <span class="icon-bar"></span>
                            <span class="icon-bar"></span>
                            <span class="icon-bar"></span>
                        </button>
                    </div>
                    <div class="navbar-collapse collapse">
                        <ul class="nav navbar-nav">
                            <li>@Html.ActionLink("GUC Home", "Index", "Home")</li>
                            <li>@Html.ActionLink("Customers", "Index", "Home")</li>
                            <li>@Html.ActionLink("Community", "Index", "Home")</li>
                            <li>@Html.ActionLink("Careers", "Index", "Home")</li>
                            <li>@Html.ActionLink("About GUC", "About", "Home")</li>
                            <li>@Html.ActionLink("Contact Us", "Contact", "Home")</li>
                        </ul>
                    </div>
                </div>
            </div>
        </div>
    
        <div class="body-holder">
            <div class="col-md-3">
                <div class="topic">@Html.ActionLink("Safety", "Index", "Home")</div>
                <div class="topic">@Html.ActionLink("Outages", "Index", "Home")</div>
                <div class="topic">@Html.ActionLink("Commercial", "Index", "Home")</div>
                <div class="topic">@Html.ActionLink("Residential", "Index", "Home")</div>
                <div class="topic">@Html.ActionLink("Environment", "Index", "Home")</div>
                <div class="topic">@Html.ActionLink("Services/Appliances", "Index", "Home")</div>
                <div class="topic">@Html.ActionLink("Community Relations", "Index", "Home")</div>
            </div>
            <div class="col-md-9">
                @RenderBody()
            </div>
        </div>
    
        <hr />
    
        <footer id="bottom-banner">
            <p id="copyright">&copy; @DateTime.Now.Year - Gas Utility Company</p>
        </footer>
    
        @Scripts.Render("~/bundles/jquery")
        @Scripts.Render("~/bundles/bootstrap")
        @RenderSection("scripts", required: false)
    </body>
    </html>
  31. In the Solution Explorer, under Controllers, double-click HomeController.cs to access it

Introduction to Creating a Delegate

The basic formula to create a delegate is:

[options] [modifier(s)] delegate void delegate-name ([formal-parameters]);

You can start with some opions (such as attributes). The modifiers can be one or an appropriate combination of the following keywords: new, public, private, protected, or internal. The delegate keyword is required. A delegae can be any of the types we have used so far. It can also be a type void. The delegate-name must be a valid C# name. The names of delegates follow the rules and suggestions of named of methods.

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, leave the parentheses empty. Here is an example:

using System.Web;

public delegate string Observation();

public class Sociology
{
}

You can also create a delegate in a file that contains a controller class. Here is an example:

using System.Web.Mvc;

namespace Exercises.Controllers
{
    public delegate void Observation();

    public class HomeController : Controller
    {
    }
}

As mentioned already, a delegate is primarily a syntax for a method and it is used to refer to an actual method. To use a delegate, you must define a method that would carry an assignment. That method must have the same return type and the same (number of) argument(s), if any. Here is an example:

public delegate void Observation();

public class Sociology
{
    public void Create()
    {
        string sentence = "A man with one watch knows what time it is; a man with two watches is never quite sure. - Lee Segall -";
    }
}

Here is an example of the method created in a controller class:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace Exercises.Controllers
{
    public delegate void Observation();

    public class ConversationController : Controller
    {
        public void Create()
        {
            ViewBag.Message = "A man with one watch knows what time it is; a man with two watches is never quite sure. - Lee Segall -";
        }
    }
}

ApplicationPractical Learning: Creating a Delegate

  1. Create a delegate as follows:
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.Mvc;
    
    namespace GasUtilityCompany7.Controllers
    {
        public delegate void AccountReset();
    
        public class EmployeesController : Controller
        {
            // GET: Employees
            public ActionResult Index()
            {
                return View();
            }
    
            // GET: ResetPassword
            public ActionResult ResetPassword()
            {
                return View();
            }
        }
    }

Associating a Method to a Delegate

After creating the method, you can associate it to the name of the desired delegate. To do that, where you want to use the method, declare a variable of the type of the delegate. You have two options:

Practical LearningPractical Learning: Associating a Method to a Delegate

Accessing a Delegate

Once you have associated a method to a delegate variable, you can use the delegate variable as if it were a defined method. That is, you can call it as you would proceed for a normal method. Here is an example:

using System.Web.Mvc;

namespace Exercises.Controllers
{
    public delegate void Observation();

    public class HomeController : Controller
    {
        // GET: Home
        public ActionResult Index()
        {
            Observation quote = new Observation(Hold);

            quote();

            return View();
        }

        public void Hold()
        {
            ViewBag.Message "A man with one watch knows what time it is; a man with two watches is never quite sure. - Lee Segall -";
        }
    }
}

If you are working in a webpage, you can precede the call with @. Here is an example:

@{
    ViewBag.Title = "Conversations";
}

<p>@@ViewBag.Message</p>

ApplicationPractical Learning: Accessing a Delegate

  1. Change the ResetPassword method in the EmployeeController class as follows:
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.Mvc;
    
    namespace GasUtilityCompany7.Controllers
    {
        public delegate void AccountReset*(;
    
        public class EmployeesController : Controller
        {
            // GET: Employees
            public ActionResult Index()
            {
                return View();
            }
    
            // GET: ResetPassword
            public ActionResult ResetPassword()
            {
                AccountReset change = new AccountReset(ChangingCredentials);
    
                change();
    
                return View();
            }
    
            public void ChangingCredentials()
            {
                . . . No Change
            }
        }
    }
  2. Access the ResetPassword.cshtml file and change the document as follows:
    @{
        ViewBag.Title = "Reset Password";
    }
    
    <h2>Gas Utility Company</h2>
    <h3>Reset Password</h3>
    
    <div class="horizontal-line"></div>
    
    <h4>Suggested Password Summary</h4>
    
    <p>The suggested password contains:</p>
    
    <ul>
        <li>@ViewBag.Characters letters and/or symbols</li>
        <li>@ViewBag.Digits digits</li>
        <li>@ViewBag.Symbols symbols</li>
        <li>@ViewBag.Uppercase uppercase letters</li>
        <li>@ViewBag.Lowercase lowercase letters</li>
    </ul>
  3. In the Solution Explorer, under Views and under Home, double-click Index.cshtml to access it
  4. To execute the project, on the main menu, click Debug -> Start Without Debugging:

    Introduction to Characters and Strings

  5. Click the Employees Portal button and click the Reset Employee Account Password link:

    Introduction Delegates

  6. Close the browser and return to your programming environment

Introductory Topics on Delegates

A Static Method for a Delegate

If the class that contains the method is static, you must define the method as static. Even if that class is not static, you can still define the method as static. Here is an example of such a method:

using System.Web.Mvc;

namespace Exercises.Controllers
{
    public delegate void Observation();

    public class HomeController : Controller
    {
        // GET: Home
        public ActionResult Index()
        {
            return View();
        }

        public static void Create()
        {
        }
    }
}

In both cases, you would not need to declare the variable first. Here is an example:

using System.Web.Mvc;

namespace Exercises.Controllers
{
    public delegate void Observation();

    public class HomeController : Controller
    {
        // GET: Home
        public ActionResult Index()
        {
            Observation quote = Create;

            return View();
        }

        public static void Create()
        {
        }
    }
}

An Anonymous Delegate

In the above examples, we had to create a method that would be associated with a delegate. As an alternative, you can first create a delegate. Here is an example:

namespace Exercises.App_Code
{
    public delegate void Observation();
}

Then, when you need to use it, create a type of local implementation of a method and use it. In other words, you donít have to define a formal method that would initialize the delegate. Such a method is referred to as anonymous.

To create an anonymous method, declare a variable for the delegate and assign it the delegate keyword as if it were a method. That is, followed by parentheses and curly brackets that would represent the body of the method. In the body of the anonymous method, do whatever you want. Here is an example:

p@{
    Exercises.Controllers.Observation example = delegate ()
    {
        return "If reality TV has taught us anything, it's that you can't keep people with no shame down. - 30 Rock (NBC) -";
    };
}

Once you have done this, you can then call the delegate variable as if it were a normal method. Here is an example:

@{
    ViewBag.Title = "Conversations";
}

@{ 
    Exercises.Controllers.Observation remark = delegate ()
    {
        ViewBag.Message = "If reality TV has taught us anything, it's that you can't keep people with no shame down. - 30 Rock (NBC) -";
    };
}

@{ 
    remark();
}

ApplicationPractical Learning: Creating and Using an Anonymous Delegate

  1. Access the HomeController.cs file
  2. Delete the ChangingCredentials() method and change the ResetPassword() method as follows:
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.Mvc;
    
    namespace GasUtilityCompany7.Controllers
    {
        public delegate void AccountReset();
    
        public class EmployeesController : Controller
        {
            // GET: Employees
            public ActionResult Index()
            {
                return View();
            }
    
            // GET: ResetPassword
            public ActionResult ResetPassword()
            {
                return View();
            }
        }
    } 
  3. Access the ResetPassword.cshtml file and change the document as follows:
    @{
        ViewBag.Title = "Reset Password";
    }
    
    <h2>Gas Utility Company</h2>
    <h3>Reset Password</h3>
    
    <div class="horizontal-line"></div>
    
    @{
        GasUtilityCompany7.Controllers.AccountReset change = delegate ()
        {
            int digits = 0;
            int symbols = 0;
            int lowercase = 0;
            int uppercase = 0;
            string strNewPassword = "N@t0ralS3creT#48";
            int length = strNewPassword.Length;
    
            for (int i = 0; i < length; i++)
            {
                if (Char.IsDigit(strNewPassword[i]))
                {
                    digits++;
                }
    
                if (Char.IsSymbol(strNewPassword[i]) || Char.IsPunctuation(strNewPassword[i]))
                {
                    symbols++;
                }
    
                if (Char.IsLower(strNewPassword[i]))
                {
                    lowercase++;
                }
    
                if (Char.IsUpper(strNewPassword[i]))
                {
                    uppercase++;
                }
            }
    
            ViewBag.Digits     = digits;
            ViewBag.Characters = length;
            ViewBag.Symbols    = symbols;
            ViewBag.Lowercase  = lowercase;
            ViewBag.Uppercase  = uppercase;
            ViewBag.Password   = strNewPassword;
        };
    }
    
    <div class="horizontal-line"></div>
    
    @{ 
        change();
    }
    
    @using (Html.BeginForm())
    {
        <table>
            <tr>
                <td class="left-col">New Password:</td>
                <td><input type="text" name="txtNewPassword" value=@ViewBag.Password /></td>
                <td><input type="text" name="txtCharacters" class="small-text" value=@ViewBag.Characters /> Characters</td>
            </tr>
            <tr>
                <td>Confirm Password:</td>
                <td><input type="text" name="txtConfirmPassword" , value="" /></td>
                <td>&nbsp;</td>
            </tr>
        </table>
        <table>
            <tr>
                <td class="left-col">&nbsp;</td>
                <td class="large"><input type="text" name="txtLowercase" class="small-text" , value=@ViewBag.Lowercase /> Lowercase Letters</td>
                <td><input type="text" class="small-text" name="txtUppercase" value=@ViewBag.Uppercase /> Uppercase Letters</td>
            </tr>
            <tr>
                <td class="left-col">&nbsp;</td>
                <td><input type="text" name="txtDigits" , class="small-text" value=@ViewBag.Digits /> Digits</td>
                <td><input type="text" name="txtSymbols" value=@ViewBag.Symbols class="small-text" /> Symbols</td>
            </tr>
        </table>
        <div class="horizontal-line"></div>
        <p class="text-center"><input type="submit" name="btnSubmit" value="Submit" class="btnLarge" /></p>
    }
  4. To execute the project, on the main menu, click Debug -> Start Without Debugging

    Introduction Delegates

  5. Close the browser and return to your programming environment
  6. Change the ResetPassword.cshtml file as follows:
    @{
        ViewBag.Title = "Reset Password";
    }
    
    <h2>Gas Utility Company</h2>
    <h3>Reset Password</h3>
    
    <div class="horizontal-line"></div>
    
    @{
        GasUtilityCompany7.Controllers.AccountReset change = delegate ()
        {
            int length = 0;
            int digits = 0;
            int symbols = 0;
            int lowercase = 0;
            int uppercase = 0;
            string strNewPassword = string.Empty;
    
            strNewPassword = Request["txtNewPassword"];
            length = strNewPassword.Length;
    
            for (int i = 0; i < length; i++)
            {
                if (Char.IsDigit(strNewPassword[i]))
                {
                    digits++;
                }
    
                if (Char.IsSymbol(strNewPassword[i]) || Char.IsPunctuation(strNewPassword[i]))
                {
                    symbols++;
                }
    
                if (Char.IsLower(strNewPassword[i]))
                {
                    lowercase++;
                }
    
                if (Char.IsUpper(strNewPassword[i]))
                {
                    uppercase++;
                }
            }
    
            ViewBag.Digits = digits;
            ViewBag.Characters = length;
            ViewBag.Symbols = symbols;
            ViewBag.Lowercase = lowercase;
            ViewBag.Uppercase = uppercase;
            ViewBag.Password = strNewPassword;
        };
    }
    
    <div class="horizontal-line"></div>
    
    @{
        if (IsPost)
        {
            change();
        }
    }
    
    @using (Html.BeginForm())
    {
        <table>
            <tr>
                <td class="left-col">New Password:</td>
                <td><input type="text" name="txtNewPassword" value=@ViewBag.Password /></td>
                <td><input type="text" name="txtCharacters" class="small-text" value=@ViewBag.Characters /> Characters</td>
            </tr>
            <tr>
                <td>Confirm Password:</td>
                <td><input type="text" name="txtConfirmPassword" , value="" /></td>
                <td>&nbsp;</td>
            </tr>
        </table>
        <table>
            <tr>
                <td class="left-col">&nbsp;</td>
                <td class="large"><input type="text" name="txtLowercase" class="small-text" , value=@ViewBag.Lowercase /> Lowercase Letters</td>
                <td><input type="text" class="small-text" name="txtUppercase" value=@ViewBag.Uppercase /> Uppercase Letters</td>
            </tr>
            <tr>
                <td class="left-col">&nbsp;</td>
                <td><input type="text" name="txtDigits" , class="small-text" value=@ViewBag.Digits /> Digits</td>
                <td><input type="text" name="txtSymbols" value=@ViewBag.Symbols class="small-text" /> Symbols</td>
            </tr>
        </table>
        <div class="horizontal-line"></div>
        <p class="text-center"><input type="submit" name="btnSubmit" value="Submit" class="btnLarge" /></p>
    }
  7. To execute the project, on the main menu, click Debug -> Start Without Debugging
  8. In the top text box, type a password, such as Password1

    Introduction Delegates

  9. Click the button:

    Introduction Delegates

  10. Close the browser and return to your programming environment

The Lambda Operator

You can also create an anonymous method using an operator called lambda and represented by =>. From our example above, to use the lambda operator to create an anonymous method, omit the delegate keyword and follow the parentheses by the operator. Here is an example:

@{
    ViewBag.Title = "Conversations";
}

@{
    Exercises.App_Code.Quote example = () =>
    {
        return "I feel like I've got a guest come to my house, unexpected, stayed three weeks uninvited, and then they start complaining about the food. - Robert Blasier - Attorney at Law -";
    };
}

<p>@example()</p>

ApplicationPractical Learning: Creating and Using a Lambda Expression

  1. On the code of the webpage, delete the delegate keyword and, on the right side of the parentheses, type =>
    @{
        ViewBag.Title = "Reset Password";
    }
    
    <h2>Gas Utility Company</h2>
    <h3>Reset Password</h3>
    
    <div class="horizontal-line"></div>
    
    @{
        GasUtilityCompany7.Controllers.AccountReset change = () =>
        {
            . . . No Change
            
        };
    }
    
    <div class="horizontal-line"></div>
    
    @{ 
        if (IsPost)
        {
            change();
        }
    }
    
    @using (Html.BeginForm())
    {
        . . . No Change
    }
  2. To test the project, on the main menu, click Debug -> Start Without Debugging
  3. Close the browser and return to your programming environment

Delegates Compositions

Adding Delegates

A delegate can be added to another delegate using the + operation. This is referred to as composition. This is done by adding one delegate variable to another as in result = a + b. After doing this, to access the action produced, call the variable as if it were a method, as in result(). In the same way, you can add many delegates as in result = a + b + c. or more. You can call the variable like a method as in result().

ApplicationPractical Learning: Adding Delegates

  1. Change the document as follows:
    @{
        ViewBag.Title = "Reset Password";
    }
    
    <h2>Gas Utility Company</h2>
    <h3>Reset Password</h3>
    
    <div class="horizontal-line"></div>
    
    @{
        string[] recentPasswords = new string[5] { "Password1", "Password2", "Password3", "Password4", "Password5" };
    
        GasUtilityCompany7.Controllers.AccountReset change = () =>
        {
            int length = 0;
            int digits = 0;
            int symbols = 0;
            int lowercase = 0;
            int uppercase = 0;
            string strNewPassword = string.Empty;
    
            strNewPassword = Request["txtNewPassword"];
            length = strNewPassword.Length;
    
            for (int i = 0; i < length; i++)
            {
                if (Char.IsDigit(strNewPassword[i]))
                {
                    digits++;
                }
    
                if (Char.IsSymbol(strNewPassword[i]) || Char.IsPunctuation(strNewPassword[i]))
                {
                    symbols++;
                }
    
                if (Char.IsLower(strNewPassword[i]))
                {
                    lowercase++;
                }
    
                if (Char.IsUpper(strNewPassword[i]))
                {
                    uppercase++;
                }
            }
    
            ViewBag.Digits = digits;
            ViewBag.Symbols = symbols;
            ViewBag.Characters = length;
            ViewBag.Lowercase = lowercase;
            ViewBag.Uppercase = uppercase;
            ViewBag.Password = strNewPassword;
        };
    
        GasUtilityCompany7.Controllers.AccountReset comparison = () =>
        {
            bool pwdFound = false;
            string strNewPassword = string.Empty;
            string strConfirmPassword = string.Empty;
    
            strNewPassword = Request["txtNewPassword"];
    
            for (int i = 0; i < recentPasswords.Length; i++)
            {
                if(recentPasswords[i] == strNewPassword)
                {
                    pwdFound = true;
                }
            }
    
            if(pwdFound == true)
            {
                ViewBag.ErrorMessage = "That password was previously used. Please try another password.";
            }
        };
    }
    
    <div class="horizontal-line"></div>
    
    @{
        if (IsPost)
        {
            GasUtilityCompany7.Controllers.AccountReset combination = change + comparison;
    
            combination();
        }
    }
    
    @using (Html.BeginForm())
    {
        <table>
            <tr>
                <td class="left-col">New Password:</td>
                <td><input type="text" name="txtNewPassword" value=@ViewBag.Password /></td>
                <td><input type="text" name="txtCharacters" class="small-text" value=@ViewBag.Characters /> Characters</td>
            </tr>
            <tr>
                <td>Confirm Password:</td>
                <td><input type="text" name="txtConfirmPassword" , value="" /></td>
                <td>&nbsp;</td>
            </tr>
        </table>
        <table>
            <tr>
                <td class="left-col">&nbsp;</td>
                <td class="large"><input type="text" name="txtLowercase" class="small-text" , value=@ViewBag.Lowercase /> Lowercase Letters</td>
                <td><input type="text" class="small-text" name="txtUppercase" value=@ViewBag.Uppercase /> Uppercase Letters</td>
            </tr>
            <tr>
                <td class="left-col">&nbsp;</td>
                <td><input type="text" name="txtDigits" , class="small-text" value=@ViewBag.Digits /> Digits</td>
                <td><input type="text" name="txtSymbols" value=@ViewBag.Symbols class="small-text" /> Symbols</td>
            </tr>
        </table>
        <div class="horizontal-line"></div>
        <p class="text-center"><input type="submit" name="btnSubmit" value="Submit" class="btnLarge" /></p>
    
        @ViewBag.ErrorMessage
    }
  2. To execute the application, on the main menu, click Debug -> Start Without Debugging
  3. In the top text box, type a password such as Password3
  4. Click the button:

    Introduction Delegates

  5. Close the browser and return to your programming environment

Delegates and Compound Addition

Besides the regular addition, delegates also support the compound addition performed using the += operator. It works exactly as in C# arithmetic. This means that you can first add a delegate to a variable and assign the result to the variable as follows:

result = first;
result = result + second;

As an alternative, you can use the += operator between the variable and the right operand. This can be done as follows:

result = first;
result += second;

ApplicationPractical Learning: Performing a Compound Addition on Delegates

  1. Change the document as follows:
    @{
        ViewBag.Title = "Reset Password";
    }
    
    <h2>Gas Utility Company</h2>
    <h3>Reset Password</h3>
    
    <div class="horizontal-line"></div>
    
    @{
        string[] recentPasswords = new string[5] { "P@ssw0rdAgent#1", "P@ssw0rdAgent#2", "P@ssw0rdAgent#3", "P@ssw0rdAgent#4", "P@ssw0rdAgent#5" };
    
        GasUtilityCompany7.Controllers.AccountReset change = () =>
        {
            int length = 0;
            int digits = 0;
            int symbols = 0;
            int lowercase = 0;
            int uppercase = 0;
            string strNewPassword = string.Empty;
    
            strNewPassword = Request["txtNewPassword"];
            length = strNewPassword.Length;
    
            for (int i = 0; i < length; i++)
            {
                if (Char.IsDigit(strNewPassword[i]))
                {
                    digits++;
                }
    
                if (Char.IsSymbol(strNewPassword[i]) || Char.IsPunctuation(strNewPassword[i]))
                {
                    symbols++;
                }
    
                if (Char.IsLower(strNewPassword[i]))
                {
                    lowercase++;
                }
    
                if (Char.IsUpper(strNewPassword[i]))
                {
                    uppercase++;
                }
            }
    
            ViewBag.Digits = digits;
            ViewBag.Symbols = symbols;
            ViewBag.Characters = length;
            ViewBag.Lowercase = lowercase;
            ViewBag.Uppercase = uppercase;
            ViewBag.Password = strNewPassword;
        };
    
        GasUtilityCompany7.Controllers.AccountReset comparison = () =>
        {
            bool pwdFound = false;
            string strNewPassword = string.Empty;
            string strConfirmPassword = string.Empty;
    
            strNewPassword = Request["txtNewPassword"];
    
            for (int i = 0; i < recentPasswords.Length; i++)
            {
                if (recentPasswords[i] == strNewPassword)
                {
                    pwdFound = true;
                }
            }
    
            if (pwdFound == true)
            {
                ViewBag.ErrorMessage = "That password was previously used. Please try another password.";
            }
        };
    
        GasUtilityCompany7.Controllers.AccountReset validation = () =>
        {
            int digits = 0;
            int symbols = 0;
            int lowercase = 0;
            int uppercase = 0;
            string strNewPassword = Request["txtNewPassword"];
            int length = strNewPassword.Length;
    
            for (int i = 0; i < length - 1; i++)
            {
                if (Char.IsDigit(strNewPassword[i]))
                {
                    digits++;
                }
    
                if (Char.IsSymbol(strNewPassword[i]) || Char.IsPunctuation(strNewPassword[i]))
                {
                    symbols++;
                }
    
                if (Char.IsLower(strNewPassword[i]))
                {
                    lowercase++;
                }
    
                if (Char.IsUpper(strNewPassword[i]))
                {
                    uppercase++;
                }
            }
    
            if( length < 8 )
            {
                ViewBag.ErrorMessage = "Your password does not meet the requirements (a password must have at least 8 characters).";
            }
            else if( lowercase < 2 )
            {
                ViewBag.ErrorMessage = "The password you provided is not valid (the password must include at least 2 lowercase letters).";
            }
            else if( uppercase < 2 )
            {
                ViewBag.ErrorMessage = "The password you typed doesn't meet the requirement rules (a password must include at least 2 uppercase letters).";
            }
            else if( digits < 2 )
            {
                ViewBag.ErrorMessage = "Your password is not meeting the credential rules (the password must have at least 2 digits).";
            }
            else if (symbols < 2)
            {
                ViewBag.ErrorMessage = "Your password doesn't meet the required rules (a password must have at least 2 non-alphabetical symbols).";
            }
        };
    }
    
    <div class="horizontal-line"></div>
    
    @{
        if (IsPost)
        {
            GasUtilityCompany7.Controllers.AccountReset combination = change;
    
            combination += comparison;
            combination += validation;
    
            combination();
        }
    }
    
    @using (Html.BeginForm())
    {
        <table>
            <tr>
                <td class="left-col">New Password:</td>
                <td><input type="text" name="txtNewPassword" value=@ViewBag.Password /></td>
                <td><input type="text" name="txtCharacters" class="small-text" value=@ViewBag.Characters /> Characters</td>
            </tr>
            <tr>
                <td>Confirm Password:</td>
                <td><input type="text" name="txtConfirmPassword" , value="" /></td>
                <td>&nbsp;</td>
            </tr>
        </table>
        <table>
            <tr>
                <td class="left-col">&nbsp;</td>
                <td class="large"><input type="text" name="txtLowercase" class="small-text" , value=@ViewBag.Lowercase /> Lowercase Letters</td>
                <td><input type="text" class="small-text" name="txtUppercase" value=@ViewBag.Uppercase /> Uppercase Letters</td>
            </tr>
            <tr>
                <td class="left-col">&nbsp;</td>
                <td><input type="text" name="txtDigits" , class="small-text" value=@ViewBag.Digits /> Digits</td>
                <td><input type="text" name="txtSymbols" value=@ViewBag.Symbols class="small-text" /> Symbols</td>
            </tr>
        </table>
        <div class="horizontal-line"></div>
        <p class="text-center"><input type="submit" name="btnSubmit" value="Submit" class="btnLarge" /></p>
    
        @ViewBag.ErrorMessage
    }
  2. To execute the application, on the main menu, click Debug -> Start Without Debugging
  3. Type a password in the top text box and click the button
  4. Close the browser and return to your programming environment

Delegates and Parameters

A Delegate that Uses a Parameter

If you want to use a method that takes arguments and associate it to a delegate, when creating the delegate, provide the necessary parameter(s) in its parentheses. Here is an example of a delegate that takes a parameter:

delegate void Observation(string arg);

When defining the associated method, make it take the same number and type(s) of parameters. Here is an example:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace Exercises.Controllers
{
    public delegate void Observation(string msg);

    public class HomeController : Controller
    {
        // GET: Home
        public ActionResult Index()
        {
            return View();
        }

        public void Create(string say)
        {
        }
    }
}

To associate the method to the delegate, declare a variable for the delegate and initialize it with the method. Here is an example:

using System.Web.Mvc;

namespace Exercises.Controllers
{
    public delegate void Observation(string msg);

    public class HomeController : Controller
    {
        // GET: Home
        public ActionResult Index()
        {
            Observation quote = new Observation(Create);

            return View();
        }

        public void Create(string say)
        {
            ViewBag.Message = say;
        }
    }
}

To use the variable, when calling it, pass an argument. Here is an example:

using System;
using System.Web.Mvc;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters;

namespace Exercises.Controllers
{
    public delegate void Observation(string msg);

    public class HomeController : Controller
    {
        // GET: Home
        public ActionResult Index()
        {
            Observation conference = Create;

            Observation quote = new Observation(Create);

            quote("Les dances ŗ la gloire de la fornication.");

            return View();
        }

        public void Create(string say)
        {
            ViewBag.Message = say;
        }
    }
}

Here is an example of accessing the value of the operation from a webpage:

@{
    ViewBag.Title = "Conversations";
}

<p>@@ViewBag.Message</p>

In the same way, you can declare various variables of the same delegate. Here are two examples:

using System.Web.Mvc;

namespace Exercises.Controllers
{
    public delegate void Observation(string msg);

    public class HomeController : Controller
    {
        // GET: Home
        public ActionResult Index()
        {
            Observation conference = Create;

            Observation quote = new Observation(Create);

            return View();
        }

        public void Create(string say)
        {
            ViewBag.Message = say;
        }
    }
}

Notice that only the name of the method is used. No parentheses are added and the arguments are not passed. To actually use the delegate, when calling it, add the parentheses to it and in the parentheses, provide a value for each argument. Here is an example:

using System.Web.Mvc;

namespace Exercises.Controllers
{
    public delegate void Observation(string msg);

    public class HomeController : Controller
    {
        // GET: Home
        public ActionResult Index()
        {
            string strMessage = "A man with one watch knows what time it is; a man with two watches is never quite sure. - Lee Segall -";
            Observation conference = Create;

            Observation description = new Observation(Create);

            conference(strMessage);

            description("Chemistry is the study of matter. Matter is the " +
                        "building block of anything in the environment, that is, anything that " +
                        "occupies any form of space, anything that can be seen or is hidden to " +
                        "the human eye.");

            return View();
        }

        public void Create(string say)
        {
            ViewBag.Message = say;
        }
    }
} 

In the same way, you can use any type of parameter.

A Delegate with Many Parameters

A delegate can use more than one parameter. Remember that, when creating the delegate, pass the same number and type(s) of parameter(s). Here is an example:

using System.Web.Mvc;

namespace Exercises.Controllers
{
    public delegate void Operation(string n, double x, char c, double y);

    public class HomeController : Controller
    {
        // GET: Home
        public ActionResult Index()
        {
            return View();
        }
    }
}

Remember that a method that will be associated to the delegate must take the same types and order of parameters. Here is an example:

using System.Web.Mvc;

namespace Exercises.Controllers
{
    public delegate void Operation(string n, double x, char c, double y);

    public class HomeController : Controller
    {
        // GET: Home
        public ActionResult Index()
        {
            return View();
        }

        public void Add(string name, double first, char oper, double second)
        {
            double result = first + second;

            ViewBag.Addition = result.ToString();
        }
    }
}

When calling the delegate from a variable, pass the appropriate number and type(s) of argument(s):

using System.Web.Mvc;

namespace Exercises.Controllers
{
    public delegate void Operation(string n, double x, char c, double y);

    public class HomeController : Controller
    {
        // GET: Home
        public ActionResult Index()
        {
            Operation Number = Add;
            Operation Times = new Operation(Multiply);

            Number("Addition", 2946.24, '+', 8253.44);
            Times("Multiplication", 208.73, '*', 95.86);

            return View();
        }

        public void Add(string name, double first, char oper, double second)
        {
            double result = first + second;

            ViewBag.Addition = result.ToString();
        }

        public void Multiply(string identification, double number, char symbol, double factor)
        {
            double result = number * factor;

            ViewBag.Multiplication = result.ToString();
        }
    }
}

Parameterized Delegates and Lambda Expressions

You can create an anonymous method for a delegate that takes one or more parameters. Of course, you must first create a delegate. Here is an example:

using System.Web.Mvc;

namespace Exercises.Controllers
{
    public delegate void Description(string n, int s);

    public class HomeController : Controller
    {
        // GET: Home
        public ActionResult Index()
        {
            return View();
        }
    }
}

Remember that, to create an anonymous delegate, you can use the delegate keyword. Here is an example:

@{ 
    Exercises.Controllers.Description sayit = delegate (string strName, string units, int items)
    {
        ViewBag.Message = "A " + strName + " uses " + items + " " + units;
    };
}

When calling the delegate variable, in its parentheses, pass each argument as the same type and order as a parameter of the delegate. Here are examples:

@{
    ViewBag.Title = "Descriptions";
}

@{ 
    Exercises.Controllers.Description sayit = delegate (string strName, string units, int items)
    {
        ViewBag.Message = "A " + strName + " uses " + items + " " + units;
    };
}

@{ 
    sayit("square", "sides", 4);
}

<p>@ViewBag.Message</p>

@{
    sayit("water molecule", "atoms", 3);

    <p>@ViewBag.Message</p>
}

Instead of the delegate keyword, you can define an anonymous method using the lambda operator. In this case, in the parentheses of the lambda expression, enter the data type of the argument followed by its name. In the body of the anonymous method, use the argument or ignore it as you see fit. After defining the method, you can call it like a normal method. Here is an example:

@{
    ViewBag.Title = "Conversations";
}

@{ 
    Exercises.Controllers.Description sayit = (string strName, string units, int items) =>
    {
        ViewBag.Message = "A " + strName + " uses " + items + " " + units;
    };
}

@{ 
    sayit("square", "sides", 4);
}

<p>@ViewBag.Message</p>

@{
    sayit("water molecule", "atoms", 3);

    <p>@ViewBag.Message</p>
}

In our example, we specified the type of the parameter. If you want, you can let the compiler figure out the type of argument. In this case, pass only the name of the parameter and not its type. Here is an example:

@{
    ViewBag.Title = "Conversations";
}

@{ 
    Exercises.Controllers.Description sayit = (strName, units, items) =>
    {
        ViewBag.Message = "A " + strName + " uses " + items + " " + units;
    };
}

@{ 
    sayit("square", "sides", 4);
}

<p>@ViewBag.Message</p>

@{
    sayit("water molecule", "atoms", 3);

    <p>@ViewBag.Message</p>
}

A Delegate as a Type

Returning a Delegate from a Method

Because a delegate is a type, you can create a method that returns it. Here is an example:

using System.Web.Mvc;

namespace Exercises.Controllers
{
    public delegate void Observation();

    public class HomeController : Controller
    {
        // GET: Home
        public ActionResult Index()
        {
            return View();
        }

        public Observation Produce()
        {
        }
    }
}

In the body of the method, do what you want. At the end of the method, make sure you return a value or object that is the type of the delegate. For example, or at a minimum, you can declare a variable of the delegate and initialize it as we have done so far, then return that variable. Here is an example:

using System.Web.Mvc;

namespace Exercises.Controllers
{
    public delegate void Observation();

    public class HomeController : Controller
    {
        // GET: Home
        public ActionResult Index()
        {
            return View();
        }

        public void Hold()
        {
        }

        public Observation Produce()
        {
            Observation quote = new Observation(Hold);

            return quote;
        }
    }
}

To use the method, you can declare a variable of the type of the delegate and you can initialize it with a call to the method that returns the delegate. You can then call the new variable as a method. Here ia an example:

using System;
using System.Web.Mvc;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters;

namespace Exercises.Controllers
{
    public delegate void Observation();

    public class HomeController : Controller
    {
        // GET: Home
        public ActionResult Index()
        {
            Observation obs = Produce();

            obs();
            
            return View();
        }

        public void Hold()
        {
            ViewBag.Message = "A man with one watch knows what time it is; a man with two watches is never quite sure. - Lee Segall -";
        }

        public Observation Produce()
        {
            Observation quote = new Observation(Hold);

            return quote;
        }
    }
}

Once again, you can access the value that was processed in the class from a webpage:

@{
    ViewBag.Title = "Conversations";
}

<p>@@ViewBag.Message</p>

Passing a Delegate (Method) as Parameter

Most languages don't allow pass a method (called function) as argument. Delegates provide an alternative. Because a delegate is an object, or rather treated as such, it can be used as a parameter.

To start, you must have or create a delegate that has the syntax of the method you want to use. Here is an example of a delegate for a method that simply adds two numbers:

using System.Web.Mvc;

namespace Exercises.Controllers
{
    public delegate void Observation();

    public class HomeController : Controller
    {
        // GET: Home
        public ActionResult Index()
        {
            return View();
        }
    }
}

Once you have the delegate, you can create a method with the same syntax but that performs the action you want. Here is an example:

using System.Web.Mvc;

namespace Exercises.Controllers
{
    public delegate void Observation();

    public class HomeController : Controller
    {
        // GET: Home
        public ActionResult Index()
        {
            return View();
        }

        public void Hold()
        {   
        }
    }
}

After doing this, you can create a method to which you would pass the delegate as parameter. Here is an example:

using System.Web.Mvc;

namespace Exercises.Controllers
{
    public delegate void Observation();

    public class HomeController : Controller
    {
        // GET: Home
        public ActionResult Index()
        {
            return View();
        }

        public void Hold()
        {
            
        }

        public void Create(Observation speech)
        {
        }
    }
}

In the body of the method, call the delegate as a mehod. Here is an example:

using System.Web.Mvc;

namespace Exercises.Controllers
{
    public delegate void Observation();

    public class HomeController : Controller
    {
        // GET: Home
        public ActionResult Index()
        {
            return View();
        }

        public void Hold()
        {
        }

        public void Create(Observation speech)
        {
            speech();
        }
    }
}

When you call the method that takes a delegate as parameter, pass the name of the method that is associated to the delegate. This can be done in a class as follows:

Alternative, you can keep one backslash in each placeholder but precede the value of the string with the @ symbol. Here is an example:

using System.Web.Mvc;

namespace Exercises.Controllers
{
    public delegate void Observation();

    public class HomeController : Controller
    {
        // GET: Home
        public ActionResult Index()
        {
            Create(Hold);

            return View();
        }

        public void Hold()
        {
            ViewBag.Message = "A man with one watch knows what time it is; a man with two watches is never quite sure. - Lee Segall -";
        }

        public void Create(Observation speech)
        {
            speech();
        }
    }
}

Here is an example of accessing the value of the above scenario in a webpage:

@{
    ViewBag.Title = "Conversations";
}

<p>@ViewBag.Message</p>

A Method as Parameter in a Lambda Expression

Instead of creating a formal method that would be associated with a delegate passed as parameter, you can define a lambda expression in the place where the delegate variable is passed as argument.

Delegates and Classes

So far, we involved only primitive types with delegates, especially when it came to parameters. Indeed, any type of value can be passed to a delegate and subsequently to its associated method(s). You can use any appropriate class. For example, you can create your own class, but as you know it already, the .NET Framework provide a large library of classes you can use.


Previous Copyright © 2008-2019, FunctionX Next