Home

Delegates

   

C# and Delegates

 

Introduction

A class can contain one or more methods used to perform operations. Such a method must be explicitly called. Here is an example:

using System;
using System.Drawing;
using System.Windows.Forms;

public class Exercise : Form
{
    Button btnShow;

    public Exercise()
    {
        InitializeComponent();
    }

    void InitializeComponent()
    {
        btnShow = new Button();
        btnShow.Text = "Show";
        btnShow.Location = new Point(12, 12);
        btnShow.Click += new EventHandler(btnShowClick);

        Controls.Add(btnShow);

        Text = "Exercise";
        StartPosition = FormStartPosition.CenterScreen;
    }

    private string Welcome()
    {
	return "Welcome to the wonderful world of C#!";
    }

    private void btnShowClick(object sender, EventArgs e)
    {
	MessageBox.Show("Before exiting the application, we say " + Welcome() + " and that's it.",
                        "Exercise",
                        MessageBoxButtons.OK, MessageBoxIcon.Information);
    }

    [STAThread]
    public static int Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        System.Windows.Forms.Application.Run(new Exercise());

        return 0;
    }
}

This would produce:

Delegates

The C and C++ languages (and other languages such as Pascal, Ada, etc) provide the ability to refer to the memory address of a method (for any necessary reason), rather called a function or a procedure (in those languages). This makes it possible to declare a variable that is based on that function. The function is not explicitly defined as done for the method of a class. Instead, the function is only declared and thus considered a type, like any of the data types you are familiar with. Such a function is called a function pointer. The topic of function pointer is too large for us to study here.

Because function pointers are not directly used in the .NET Framework as they are in Win32, Microsoft instead created the concept of delegates. Like a function pointer, a delegate is a technique of using the reference of a class method as a type. The delegate specifies the syntax of a method but then the name of the delegate can be used to declare a variable that references the actual method. As we will see, the concept of delegate has been expanded to solve various types of problems.

Creating a Delegate

The basic formula used to create a delegate is:

[attributes] [modifiers] delegate ReturnType Name ([formal-parameters]);

The attributes can be a normal C# attribute.The modifiers can be one or an appropriate combination of the following keywords: new, public, private, protected, or internal. The delegate keyword is required. The ReturnType can be any of the data types we have used so far. It can also be a type void or the name of a class. The Name must be a valid C# name.

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;

public delegate void Simple();

public class Exercise
{
}

As mentioned already, a delegate is primarily a syntax for an actual method and it is used to refer to an actual method. In order to use a delegate, you must define a method that would carry an assignment to perform. That method must have the same return type and the same (number of) argument(s), if any. For example, the above declared delegate is of type void and it does not take any argument. You can define a corresponding method as follows:

public delegate void Example();

public class Exercise
{
    public void Welcome()
    {
        MessageBox.Show("Welcome to the Wonderful World of C# Programming!",
                        "Exercise",
                        MessageBoxButtons.OK, MessageBoxIcon.Information);
    }
}

With such a method implemented, you can associate it to the name of the delegate. To do that, where you want to use the method, declare a variable of the type of the delegate and assign the method to the delegate variable. Because you are assigning the method to a delegate, one of the rules of delegates is that you must not apply the parentheses to the method. Here is an example:

void btnShowClick(object sender, EventArgs e)
{
    Simple example = Welcome;
}

Accessing a Delegate

Once you have assigned 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;
using System.Drawing;
using System.Windows.Forms;

public class Exercise : Form
{
    Button btnShow;

    public delegate void Simple();

    public Exercise()
    {
        InitializeComponent();
    }

    void InitializeComponent()
    {
        btnShow = new Button();
        btnShow.Text = "Show";
        btnShow.Location = new Point(12, 12);
        btnShow.Click += new EventHandler(btnShowClick);

        Controls.Add(btnShow);

        Text = "Exercise";
        StartPosition = FormStartPosition.CenterScreen;
    }

    private void Welcome()
    {
	MessageBox.Show("Welcome to the wonderful world of C# Programming!",
			"Exercise on Delegates",
			MessageBoxButtons.OK, MessageBoxIcon.Information);
    }

    private void btnShowClick(object sender, EventArgs e)
    {
	Simple example = Welcome;

	example();
    }

    [STAThread]
    public static int Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        System.Windows.Forms.Application.Run(new Exercise());

        return 0;
    }
}

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. In both cases, you would not need to declare the variable first. As a result, you can use this:

private static void Welcome()
{
    MessageBox.Show("Welcome to the wonderful world of C# Programming!",
		    "Exercise on Delegates",
		    MessageBoxButtons.OK, MessageBoxIcon.Information);
}

private void btnShowClick(object sender, EventArgs e)
{
    Simple example = Welcome;

    example();
}

or this:

private static void Welcome()
{
    MessageBox.Show("Welcome to the wonderful world of C# Programming!",
		    "Exercise on Delegates",
		    MessageBoxButtons.OK, MessageBoxIcon.Information);
}

private void btnShowClick(object sender, EventArgs e)
{
    Exercise.Simple example = Welcome;

    example();
}

or this:

private static void Welcome()
{
    MessageBox.Show("Welcome to the wonderful world of C# Programming!",
		    "Exercise on Delegates",
		    MessageBoxButtons.OK, MessageBoxIcon.Information);
}

private void btnShowClick(object sender, EventArgs e)
{
    Exercise.Simple example = Exercise.Welcome;

    example();
}

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 create a delegate. 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.

Before implementing an anonymous method, first declare the delegate you will use, as we did previously. 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:

private void btnShowClick(object sender, EventArgs e)
{
    Simple example = delegate()
    {
	MessageBox.Show("Welcome to the wonderful world of C# Programming!",
			    "Exercise on Delegates",
			    MessageBoxButtons.OK, MessageBoxIcon.Information);
    };
}

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

using System;
using System.Drawing;
using System.Windows.Forms;

public class Exercise : Form
{
    Button btnShow;

    public delegate void Simple();

    public Exercise()
    {
        InitializeComponent();
    }

    void InitializeComponent()
    {
        btnShow = new Button();
        btnShow.Text = "Show";
        btnShow.Location = new Point(12, 12);
        btnShow.Click += new EventHandler(btnShowClick);

        Controls.Add(btnShow);

        Text = "Exercise";
        StartPosition = FormStartPosition.CenterScreen;
    }

    private void btnShowClick(object sender, EventArgs e)
    {
	Simple example = delegate()
	{
	    MessageBox.Show("Welcome to the wonderful world of C# Programming!",
			    "Exercise on Delegates",
			    MessageBoxButtons.OK, MessageBoxIcon.Information);
	};

	example();
    }

    [STAThread]
    public static int Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        System.Windows.Forms.Application.Run(new Exercise());

        return 0;
    }
}

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:

private void btnShowClick(object sender, EventArgs e)
{
    Simple example = () =>
    {
            MessageBox.Show("Welcome to the wonderful world of C# Programming!",
			    "Exercise on Delegates",
			    MessageBoxButtons.OK, MessageBoxIcon.Information);
    };

    example();
}

Delegates Compositions

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

using System;
using System.Drawing;
using System.Windows.Forms;

public class Exercise : Form
{
    Button btnShow;

    public delegate void Simple();

    public Exercise()
    {
        InitializeComponent();
    }

    void InitializeComponent()
    {
        btnShow = new Button();
        btnShow.Text = "Show";
        btnShow.Location = new Point(12, 12);
        btnShow.Click += new EventHandler(btnShowClick);

        Controls.Add(btnShow);

        Text = "Exercise";
        StartPosition = FormStartPosition.CenterScreen;
    }

    private void Welcome()
    {
        MessageBox.Show("Welcome to the wonderful world of C# Programming!",
                "Exercise on Delegates",
                MessageBoxButtons.OK, MessageBoxIcon.Information);
    }

    private void ShowName()
    {
        MessageBox.Show("We remember your name as Jonathan Swanson.",
                "Exercise on Delegates",
                MessageBoxButtons.OK, MessageBoxIcon.Information);
    }
    private void btnShowClick(object sender, EventArgs e)
    {
        Simple name = ShowName;
        Simple well = Welcome;
        Simple example = name + well;

        example();
    }

    [STAThread]
    public static int Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        System.Windows.Forms.Application.Run(new Exercise());

        return 0;
    }
}

Delegates and Parameters

 

Introduction

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

delegate void Simple(string arg);

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

private void Welcome(string strMessage)
{
    MessageBox.Show(strMessage,
		    "Exercise on Delegates",
		    MessageBoxButtons.OK, MessageBoxIcon.Information);
}

To associate the method to the delegate, declare a variable for the delegate and assign the name of the method to it. Here is an example:

private void btnShowClick(object sender, EventArgs e)
{
    Simple example = Welcome;
}

Notice that only the name of the method is passed to the delegate. 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 the argument(s). Here is an example:

using System;
using System.Drawing;
using System.Windows.Forms;

public class Exercise : Form
{
    Button btnShow;

    public delegate void Simple(string arg);

    public Exercise()
    {
        InitializeComponent();
    }

    void InitializeComponent()
    {
        btnShow = new Button();
        btnShow.Text = "Show";
        btnShow.Location = new Point(12, 12);
        btnShow.Click += new EventHandler(btnShowClick);

        Controls.Add(btnShow);

        Text = "Exercise";
        StartPosition = FormStartPosition.CenterScreen;
    }

    private void Welcome(string strMessage)
    {
	MessageBox.Show(strMessage,
			"Exercise on Delegates",
			MessageBoxButtons.OK, MessageBoxIcon.Information);
    }

    private void btnShowClick(object sender, EventArgs e)
    {
	Simple example = Welcome;

	example("Welcome to the wonderful world of C# Programming!");
    }

    [STAThread]
    public static int Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        System.Windows.Forms.Application.Run(new Exercise());

        return 0;
    }
}

A Lambda Expression

You can create an anonymous method for a delegate that takes one or more arguments. You can do this using the delegate keyword. In its parentheses, pass an argument that is the same type as the argument of the delegate. Then, in the body of the method, you can use or ignore the argument. When calling the variable of the delegate, use the same rules we have applied so far. Here is an example:

using System;
using System.Drawing;
using System.Windows.Forms;

public class Exercise : Form
{
    Button btnShow;
    public delegate void Simple(string arg);

    public Exercise()
    {
        InitializeComponent();
    }

    void InitializeComponent()
    {
        btnShow = new Button();
        btnShow.Text = "Show";
        btnShow.Location = new Point(12, 12);
        btnShow.Click += new EventHandler(btnShowClick);

        Controls.Add(btnShow);

        Text = "Exercise";
        StartPosition = FormStartPosition.CenterScreen;
    }

    private void btnShowClick(object sender, EventArgs e)
    {
        Simple example = delegate(string strName)
        {
    MessageBox.Show(strName + ", welcome to the wonderful world of C# Programming!",
                            "Exercise on Delegates",
                            MessageBoxButtons.OK, MessageBoxIcon.Information);
        };

        example("Jonathan Simms");
    }

    [STAThread]
    public static int Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        System.Windows.Forms.Application.Run(new Exercise());

        return 0;
    }
}

This would produce:

Delegates

This technique of using the delegate keyword was introduced in C# 2.0 and has been updated with the lambda operator. 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. Here is an example:

private void btnShowClick(object sender, EventArgs e)
{
    Simple example = (string strName)
    {
     MessageBox.Show(strName + ", welcome to the wonderful world of C# Programming!",
                        "Exercise on Delegates",
                        MessageBoxButtons.OK, MessageBoxIcon.Information);
    };
}

After defining the method, you can call it like a normal method. Here is an example:

private void btnShowClick(object sender, EventArgs e)
{
    Simple example = (string strName)
    {
     MessageBox.Show(strName + ", welcome to the wonderful world of C# Programming!",
                        "Exercise on Delegates",
                        MessageBoxButtons.OK, MessageBoxIcon.Information);
    };
    
    example("Jonathan Simms");
}

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

using System;
using System.Drawing;
using System.Windows.Forms;

public class Exercise : Form
{
    Button btnShow;
    public delegate void Simple(string arg);

    public Exercise()
    {
        InitializeComponent();
    }

    void InitializeComponent()
    {
        btnShow = new Button();
        btnShow.Text = "Show";
        btnShow.Location = new Point(12, 12);
        btnShow.Click += new EventHandler(btnShowClick);

        Controls.Add(btnShow);

        Text = "Exercise";
        StartPosition = FormStartPosition.CenterScreen;
    }

    private void btnShowClick(object sender, EventArgs e)
    {
        Simple example = (strName) =>
        {
     MessageBox.Show(strName + ", welcome to the wonderful world of C# Programming!",
                            "Exercise on Delegates",
                            MessageBoxButtons.OK, MessageBoxIcon.Information);
        };

        example("Jonathan Simms");
    }

    [STAThread]
    public static int Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        System.Windows.Forms.Application.Run(new Exercise());

        return 0;
    }
}

A Delegate With Many Arguments

A delegate can take more than one argument. Remember that, when creating the delegate, pass the same number of arguments. When calling the delegate from your variable, pass the appropriate number of arguments:

using System;
using System.Drawing;
using System.Windows.Forms;

public class Exercise : Form
{
    Button btnShow;

    public delegate void Operation(double x, string op, double y);

    public Exercise()
    {
        InitializeComponent();
    }

    void InitializeComponent()
    {
        btnShow = new Button();
        btnShow.Text = "Show";
        btnShow.Location = new Point(12, 12);
        btnShow.Click += new EventHandler(btnShowClick);

        Controls.Add(btnShow);

        Text = "Exercise";
        StartPosition = FormStartPosition.CenterScreen;
    }

    private void Calculate(double number1, string oper, double number2)
    {
	double result = 0;

	switch(oper)
	{
	    case "+":
		result = number1 + number2;
		break;

	    case "-":
		result = number1 - number2;
		break;

	    case "*":
		result = number1 * number2;
		break;

	    case "/":
		if( number2 != 0 )
		    result = number1 / number2;
		break;
	}

	MessageBox.Show(number1.ToString() + " " + oper + " " + number2.ToString() +
			" = " + result.ToString(),
			"Exercise on Delegates",
			MessageBoxButtons.OK, MessageBoxIcon.Information);
    }

    private void btnShowClick(object sender, EventArgs e)
    {
	Operation example = Calculate;

	example(20486, "+", 947);
	example(20486, "*", 947);
	example(20486, "-", 947);
	example(20486, "/", 947);
    }

    [STAThread]
    public static int Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        System.Windows.Forms.Application.Run(new Exercise());

        return 0;
    }
}

If you want to use a lambda expression to create an anonymous method, in its parentheses, pass the right number of arguments. In the body of the anonymous method, use the arguments as you see fit. To use the delegate, call it as you would a normal method. Here is an example:

using System;
using System.Drawing;
using System.Windows.Forms;

public class Exercise : Form
{
    Button btnShow;

    public delegate void Operation(double x, string op, double y);

    public Exercise()
    {
        InitializeComponent();
    }

    void InitializeComponent()
    {
        btnShow = new Button();
        btnShow.Text = "Show";
        btnShow.Location = new Point(12, 12);
        btnShow.Click += new EventHandler(btnShowClick);

        Controls.Add(btnShow);

        Text = "Exercise";
        StartPosition = FormStartPosition.CenterScreen;
    }

    private void btnShowClick(object sender, EventArgs e)
    {
	Operation example = (a, b, c) =>
	{
	    double result = 0;

	    switch(b)
	    {
	    	case "+":
		    result = a + c;
		    break;

		case "-":
		    result = a - c;
		    break;

		case "*":
		    result = a * c;
		    break;

		case "/":
		    if( c != 0 )
		    	result = a / c;
		    break;
	    }

	    MessageBox.Show(a.ToString() + " " + b + " " + c.ToString() +
			" = " + result.ToString(),
			"Exercise on Delegates",
			MessageBoxButtons.OK, MessageBoxIcon.Information);
	};

	example(20486, "+", 947);
	example(20486, "*", 947);
	example(20486, "-", 947);
	example(20486, "/", 947);
    }

    [STAThread]
    public static int Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        System.Windows.Forms.Application.Run(new Exercise());

        return 0;
    }
}

This would produce:

Delegates Delegates
Delegates Delegates

A Delegate that Returns a Value

 

Introduction

You can create a delegate that returns a value. When creating the delegate, specify the data type to the left side of the name of the delegate. When defining a method that would be associated with the delegate, remember that the method must return the same type of value. To use the method, follow the same approach as we have seen already. Here is an example:

using System;
using System.Drawing;
using System.Windows.Forms;

public class Exercise : Form
{
    private Button btnClose;
    private Button btnSubmit;
    private Label lblUsername;
    private Label lblPassword;
    private TextBox txtUsername;
    private TextBox txtPassword;

    const string strUsername = "mwatson";
    const string strPassword = "$wansonMan15";

    public delegate bool SuccessLoggin();

    public Exercise()
    {
        InitializeComponent();
    }

    void InitializeComponent()
    {
        lblUsername = new Label();
        lblUsername.TabIndex = 0;
        lblUsername.AutoSize = true;
        lblUsername.Text = "Username:";
        lblUsername.Size = new System.Drawing.Size(58, 13);
        lblUsername.Location = new System.Drawing.Point(22, 23);

        txtUsername = new TextBox();
        txtUsername.TabIndex = 1;
        txtUsername.Size = new System.Drawing.Size(100, 20);
        txtUsername.Location = new System.Drawing.Point(86, 20);

        lblPassword = new Label();
        lblPassword.TabIndex = 2;
        lblPassword.AutoSize = true;
        lblPassword.Text = "Password:";
        lblPassword.Size = new System.Drawing.Size(56, 13);
        lblPassword.Location = new System.Drawing.Point(22, 49);

        txtPassword = new TextBox();
        txtPassword.TabIndex = 3;
        txtPassword.PasswordChar = '-';
        txtPassword.Size = new System.Drawing.Size(100, 20);
        txtPassword.Location = new System.Drawing.Point(86, 46);

        btnSubmit = new Button();
        btnSubmit.TabIndex = 4;
        btnSubmit.Text = "Submit";
        btnSubmit.UseVisualStyleBackColor = true;
        btnSubmit.Size = new System.Drawing.Size(75, 23);
        btnSubmit.Location = new System.Drawing.Point(25, 82);
        btnSubmit.Click += new System.EventHandler(btnSubmit_Click);

        btnClose = new Button();
        btnClose.TabIndex = 5;
        btnClose.Text = "Close";
        btnClose.UseVisualStyleBackColor = true;
        btnClose.Size = new System.Drawing.Size(75, 23);
        btnClose.Location = new System.Drawing.Point(111, 82);
        btnClose.Click += new System.EventHandler(btnClose_Click);

        Controls.Add(btnClose);
        Controls.Add(btnSubmit);
        Controls.Add(txtPassword);
        Controls.Add(lblPassword);
        Controls.Add(txtUsername);
        Controls.Add(lblUsername);

        Text = "FunDS - Log In";
        MaximizeBox = false;
        MinimizeBox = false;
        ClientSize = new System.Drawing.Size(207, 123);
        FormBorderStyle = FormBorderStyle.FixedDialog;
        StartPosition = FormStartPosition.CenterScreen;
    }

    private bool GetLogginResult()
    {
        if ((txtUsername.Text  == strUsername) && (txtPassword.Text == strPassword))
            return true;
        else
            return false;
    }

    private void btnSubmit_Click(object sender, EventArgs e)
    {
        SuccessLoggin success = GetLogginResult;

        if( success() == true)
        {
            MessageBox.Show("Welcome to the wonderful world of C# Programming!",
                            "Exercise on Delegates",
                            MessageBoxButtons.OK, MessageBoxIcon.Information);
            Close();
        }
        else
        {
            MessageBox.Show("Unsuccessful Loggin: Your username, your password, or a combination of both, was wrong",
                    "Exercise on Delegates",
                    MessageBoxButtons.OK, MessageBoxIcon.Information);
            Close();
        }
    }

    private void btnClose_Click(object sender, EventArgs e)
    {
        Close();
    }

    [STAThread]
    public static int Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new Exercise());

        return 0;
    }
}

In the same way, you can create an anonymous method that implements the delegate. To do this, follow the same rule we defined earlier. For example, you can use the delegate keyword. Here is an example:

private void btnSubmit_Click(object sender, EventArgs e)
{
    SuccessLoggin success = delegate()
    {
        if ((txtUsername.Text  == strUsername) && (txtPassword.Text == strPassword))
            return true;
        else
            return false;
    };

    if( success() == true)
    {
        MessageBox.Show("Welcome to the wonderful world of C# Programming!",
                        "Exercise on Delegates",
                        MessageBoxButtons.OK, MessageBoxIcon.Information);
        Close();
    }
    else
    {
        MessageBox.Show("Unsuccessful Loggin: Your username, your password, or a combination of both, was wrong",
	                "Exercise on Delegates",
        	            MessageBoxButtons.OK, MessageBoxIcon.Information);
        Close();
    }
}

Or you can use the lambda operator:

private void btnSubmit_Click(object sender, EventArgs e)
{
    SuccessLoggin success = () =>
    {
        if ((txtUsername.Text  == strUsername) && (txtPassword.Text == strPassword))
            return true;
        else
            return false;
    };

    if( success() == true)
    {
        MessageBox.Show("Welcome to the wonderful world of C# Programming!",
                        "Exercise on Delegates",
                        MessageBoxButtons.OK, MessageBoxIcon.Information);
        Close();
    }
    else
    {
        MessageBox.Show("Unsuccessful Loggin: Your username, your password, or a combination of both, was wrong",
	                "Exercise on Delegates",
        	            MessageBoxButtons.OK, MessageBoxIcon.Information);
        Close();
    }
}

A delegate that returns a value can also take one or more arguments. When calling the delegate variable, make sure to pass the appropriate number and type(s) of argument(s). Here is an example:

using System;
using System.Drawing;
using System.Windows.Forms;

public class Exercise : Form
{
    private Button btnClose;
    private Button btnSubmit;
    private Label lblUsername;
    private Label lblPassword;
    private TextBox txtUsername;
    private TextBox txtPassword;

    public delegate bool SuccessLoggin(string arg1, string arg2);

    public Exercise()
    {
        InitializeComponent();
    }

    void InitializeComponent()
    {
        lblUsername = new Label();
        lblUsername.TabIndex = 0;
        lblUsername.AutoSize = true;
        lblUsername.Text = "Username:";
        lblUsername.Size = new System.Drawing.Size(58, 13);
        lblUsername.Location = new System.Drawing.Point(22, 23);

        txtUsername = new TextBox();
        txtUsername.TabIndex = 1;
        txtUsername.Size = new System.Drawing.Size(100, 20);
        txtUsername.Location = new System.Drawing.Point(86, 20);

        lblPassword = new Label();
        lblPassword.TabIndex = 2;
        lblPassword.AutoSize = true;
        lblPassword.Text = "Password:";
        lblPassword.Size = new System.Drawing.Size(56, 13);
        lblPassword.Location = new System.Drawing.Point(22, 49);

        txtPassword = new TextBox();
        txtPassword.TabIndex = 3;
        txtPassword.PasswordChar = '*';
        txtPassword.Size = new System.Drawing.Size(100, 20);
        txtPassword.Location = new System.Drawing.Point(86, 46);

        btnSubmit = new Button();
        btnSubmit.TabIndex = 4;
        btnSubmit.Text = "Submit";
        btnSubmit.UseVisualStyleBackColor = true;
        btnSubmit.Size = new System.Drawing.Size(75, 23);
        btnSubmit.Location = new System.Drawing.Point(25, 82);
        btnSubmit.Click += new System.EventHandler(btnSubmit_Click);

        btnClose = new Button();
        btnClose.TabIndex = 5;
        btnClose.Text = "Close";
        btnClose.UseVisualStyleBackColor = true;
        btnClose.Size = new System.Drawing.Size(75, 23);
        btnClose.Location = new System.Drawing.Point(111, 82);
        btnClose.Click += new System.EventHandler(btnClose_Click);

        Controls.Add(btnClose);
        Controls.Add(btnSubmit);
        Controls.Add(txtPassword);
        Controls.Add(lblPassword);
        Controls.Add(txtUsername);
        Controls.Add(lblUsername);

        Text = "FunDS - Log In";
        MaximizeBox = false;
        MinimizeBox = false;
        ClientSize = new System.Drawing.Size(207, 123);
        FormBorderStyle = FormBorderStyle.FixedDialog;
        StartPosition = FormStartPosition.CenterScreen;
    }

    private bool GetLogginResult(string strUsername, string strPassword)
    {
        if ((strUsername == "mwatson") && (strPassword == "$wansonMan15"))
            return true;
        else
            return false;
    }

    private void btnSubmit_Click(object sender, EventArgs e)
    {
        SuccessLoggin success = GetLogginResult;

        if( success(txtUsername.Text, txtPassword.Text) == true)
        {
            MessageBox.Show("Welcome to the wonderful world of C# Programming!",
                            "Exercise on Delegates",
                            MessageBoxButtons.OK, MessageBoxIcon.Information);
            Close();
        }
        else
        {
            MessageBox.Show("Unsuccessful Loggin: Your username, your password, or a combination of both, was wrong",
	                    "Exercise on Delegates",
        	            MessageBoxButtons.OK, MessageBoxIcon.Information);
            Close();
        }
    }

    private void btnClose_Click(object sender, EventArgs e)
    {
        Close();
    }

    [STAThread]
    public static int Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new Exercise());

        return 0;
    }
}

Instead of first creating a formal method, you can use a local lambda expression. Here is an example:

private void btnSubmit_Click(object sender, EventArgs e)
{
        SuccessLoggin success = (string strUsername, string strPassword) =>
        {
            if ((strUsername == "mwatson") && (strPassword == "$wansonMan15"))
                return true;
            else
                return false;
        };

        if( success(txtUsername.Text, txtPassword.Text) == true)
        {
            MessageBox.Show("Welcome to the wonderful world of C# Programming!",
                            "Exercise on Delegates",
                            MessageBoxButtons.OK, MessageBoxIcon.Information);
            Close();
        }
        else
        {
            MessageBox.Show("Unsuccessful Loggin: Your username, your password, or a combination of both, was wrong",
                    "Exercise on Delegates",
                    MessageBoxButtons.OK, MessageBoxIcon.Information);
            Close();
        }
}

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.

A Delegate Passed as Argument

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

public delegate double Squared(double x);

public class Circle
{
    private double _radius;

    public double Radius
    {
        get { return _radius; }
        set { _radius = value; }
    }
}

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

public delegate double Squared(double x);

public class Circle
{
    private double _radius;

    public double Radius
    {
        get { return _radius; }
        set { _radius = value; }
    }

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

After declaring a delegate, remember to define a method that implements the needed behavior of that delegate. You can define the associated method in any class of your choice. Here is an example:

using System;

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

    Public static int Main()
    {
        return 0;
    }
}

You can also define the method in the class where the delegate would be needed. Once the method that implements the delegate is known, you can declare a variable of the type of that delegate and assign it to the variable. Here is an example:

using System;

public delegate double Squared(double x);

public class Circle
{
    private double _radius;

    public double Radius
    {
        get { return _radius; }
        set { _radius = value; }
    }

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

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

    Public static int Main()
    {
        Squared Sq = ValueTimesValue;

        return 0;
    }
}

This declaration gives life to the delegate that can then be used as we have proceeded with delegates so far. Here is an example:

using System;

public delegate double Squared(double x);

public class Circle
{
    private double _radius;

    public double Radius
    {
        get {  return _radius; }
        set { _radius = value; }
    }

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

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

    static int Main()
    {
        Squared Sqr = ValueTimesValue;

        Console.WriteLine("Circle Area: {0}\n", Sqr(24.68));

        return 0;
    }
}

This would produce:

 

In the same way, you can use a lambda expression to implement an anonymous method that would be associated with a delegate. Here is an example:

using System;

public delegate double Squared(double x);

public class Circle
{
    private double _radius;

    public double Radius
    {
        get { return _radius; }
        set { _radius = value; }
    }

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

public class Exercise
{
    static int Main()
    {
        Squared Sqr = (a) =>
        {
            return a * a;
        };

        Console.WriteLine("Circle Area: {0}\n", Sqr(24.68));

        return 0;
    }
}
 
 
 

Delegates and Classes

 

Introduction

Although the method in our previous listing used a primitive type, it can also deal with a class. Here are examples:

using System;
using System.Drawing;
using System.Windows.Forms;
using System.Collections.Generic;

public class Exercise : System.Windows.Forms.Form
{
    private ListView lvwEmployees;
    private ColumnHeader colEmployeeNumber,
				 colFirstName,
				 colLastName,
				 colSalary;

    private List<Employee> employees;

    private delegate void Listing();

    public Exercise()
    {
        InitializeComponent();
    }

    void InitializeComponent()
    {
	colEmployeeNumber = new ColumnHeader();
	colEmployeeNumber.Text = "Empl #";
	colEmployeeNumber.Width = 45;
	colFirstName = new ColumnHeader();
	colFirstName.Text = "First Name";
	colFirstName.Width = 65;
	colLastName  = new ColumnHeader();
	colLastName.Text = "Last Name";
	colLastName.Width = 65;
	colSalary = new ColumnHeader();
	colSalary.Text = "Salary";

	lvwEmployees = new ListView();
	lvwEmployees.GridLines = true;
	lvwEmployees.View = View.Details;
	lvwEmployees.FullRowSelect = true;
	lvwEmployees.Size = new Size(250, 130);
	lvwEmployees.Location = new Point(12, 12);

	lvwEmployees.Columns.AddRange(new ColumnHeader[] { colEmployeeNumber, colFirstName, colLastName, colSalary });

	Controls.Add(lvwEmployees);

	MaximizeBox = false;
        Text = "Delegates - Employees";
	ClientSize = new System.Drawing.Size(276, 160);
        StartPosition = FormStartPosition.CenterScreen;
	Load += new EventHandler(LoadForm);
    }

    private void CreateEmployees()
    {
	employees.Add(new Employee(240580, "James",    "Paulson",  64050));
	employees.Add(new Employee(481004, "Annette",  "Waller",    50888));
	employees.Add(new Employee() { FirstName = "Frank", LastName = "Euler", EmployeeNumber = 303950, Salary = 28905 });
	employees.Add(new Employee(920495, "Jacob",    "Roberts",  105025));
	employees.Add(new Employee(lName : "Ouelett", fName : "Joshua", wage : 55820, emplNbr : 979274));
	employees.Add(new Employee(805813, "Marianne", "Jacobson", 72248));
	employees.Add(new Employee() { Salary = 29095, LastName = "Veuw", FirstName = "Arnold", EmployeeNumber = 830485 });
    }

    private void LoadForm(object sender, EventArgs e)
    {
	employees = new List<Employee>();
	
	Listing create = new Listing(CreateEmployees);

	create();
	
	lvwEmployees.Items.Clear();

	foreach(Employee empl in employees)
	{
	    ListViewItem lviEmployee = new ListViewItem(empl.EmployeeNumber.ToString());
	    lviEmployee.SubItems.Add(empl.FirstName);
	    lviEmployee.SubItems.Add(empl.LastName);
	    lviEmployee.SubItems.Add(empl.Salary.ToString());
	    lvwEmployees.Items.Add(lviEmployee);
	}
    }

    public static int Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new Exercise());
        
        return 0;
    }
}

public class Employee
{
    public int    EmployeeNumber { get; set; }
    public string FirstName      { get; set; }
    public string LastName	 { get; set; }
    public double Salary	 { get; set; }

    public Employee()
    {
	EmployeeNumber = 0;
    	FirstName      = "Unknown";
    	LastName       = "Not Available";
    	Salary	       = 0;
    }

    public Employee(int emplNbr, string fName = "John", string lName = "Doe", double wage = 0.00D)
    {
	EmployeeNumber = emplNbr;
    	FirstName      = fName;
    	LastName       = lName ;
    	Salary	       = wage;
    }
}

The Listing delegate takes no argument, but a delegate can receive one, two, or more parameters and even return a value based on how you create it.

A Delegate that Returns an Object

A delegate can be created to return a value that is of a class type. Of course you must know the class you want to use because the compiler would like to know the type of value that the delegate would return. You can use one of the many built-in classes of the .NET Framework or you can create your own class. When creating the delegate, specify the name of the class to its left as the returned type of value. Then, you can create a method that implements the delegate. The method must return the same type of value as the delegate. Here is an example:

using System;
using System.Drawing;
using System.Windows.Forms;
using System.Collections.Generic;

public class Exercise : System.Windows.Forms.Form
{
    private delegate Employee RecordSetup();

    public Exercise()
    {
    }

    private Employee CreateRecord()
    {
        Employee empl = new Employee();

        empl.EmployeeNumber = 240580;
        empl.FirstName = "James";
        empl.LastName = "Paulson";
        empl.Salary = 64050;

        return empl;
    }
}

public class Employee
{
    public int EmployeeNumber { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public double Salary { get; set; }
}

To use the delegate, declare a variable for it and assign the method to it. Here is an example:

public class Exercise : System.Windows.Forms.Form
{
    private delegate Employee RecordSetup();

    public Exercise()
    {
        InitializeComponent();
    }

    void InitializeComponent()
    {
        Load += new EventHandler(LoadForm);
    }

    private Employee CreateRecord()
    {
        Employee empl = new Employee();

        empl.EmployeeNumber = 240580;
        empl.FirstName = "James";
        empl.LastName = "Paulson";
        empl.Salary = 64050;

        return empl;
    }

    private void LoadForm(object sender, EventArgs e)
    {
        RecordSetup Create = CreateRecord;
    }
}

You can then call use the variable as you see fit. Instead of explicitly creating a method that implements the delegate, you can create an anonymous method using a lambda expression. In the body of the anonymous method, make sure you return a value of the type of the delegate. Here is an example:

using System;
using System.Drawing;
using System.Windows.Forms;
using System.Collections.Generic;

public class Exercise : System.Windows.Forms.Form
{
    private delegate Employee RecordSetup();

    public Exercise()
    {
        InitializeComponent();
    }

    void InitializeComponent()
    {
        MaximizeBox = false;
        Text = "Delegates - Employees";
        ClientSize = new System.Drawing.Size(276, 160);
        StartPosition = FormStartPosition.CenterScreen;
        Load += new EventHandler(LoadForm);
    }

    private Employee CreateRecord()
    {
        Employee empl = new Employee();

        empl.EmployeeNumber = 240580;
        empl.FirstName = "James";
        empl.LastName = "Paulson";
        empl.Salary = 64050;

        return empl;
    }

    private void LoadForm(object sender, EventArgs e)
    {
        RecordSetup Create = () =>
        {
            Employee empl = new Employee();

            empl.EmployeeNumber = 240580;
            empl.FirstName = "James";
            empl.LastName = "Paulson";
            empl.Salary = 64050;

            return empl;
        };

        MessageBox.Show("Employee Record\n" +
        "Employee #:\t" + Create().EmployeeNumber.ToString() + Environment.NewLine +
                        "First Name:\t" + Create().FirstName + Environment.NewLine +
                        "Last Name:\t" + Create().LastName + Environment.NewLine +
                        "Salary:\t\t" + Create().Salary.ToString(),
                        "Fun Department Store",
                        MessageBoxButtons.OK, MessageBoxIcon.Information);
    }

    public static int Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new Exercise());
        
        return 0;
    }
}

public class Employee
{
    public int EmployeeNumber { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public double Salary { get; set; }
}

A Delegate that Returns a Collection

As opposed to returning a single value, a delegate can be made to return a collection. Here is an example:

using System;
using System.Drawing;
using System.Windows.Forms;
using System.Collections.Generic;

public class Exercise : System.Windows.Forms.Form
{
    private ListView lvwEmployees;
    private ColumnHeader colEmployeeNumber,
                 colFirstName,
                 colLastName,
                 colSalary;

    private delegate List<Employee> RecordsSetup();

    public Exercise()
    {
        InitializeComponent();
    }

    void InitializeComponent()
    {
        colEmployeeNumber = new ColumnHeader();
        colEmployeeNumber.Text = "Empl #";
        colEmployeeNumber.Width = 45;
        colFirstName = new ColumnHeader();
        colFirstName.Text = "First Name";
        colFirstName.Width = 65;
        colLastName = new ColumnHeader();
        colLastName.Text = "Last Name";
        colLastName.Width = 65;
        colSalary = new ColumnHeader();
        colSalary.Text = "Salary";

        lvwEmployees = new ListView();
        lvwEmployees.GridLines = true;
        lvwEmployees.View = View.Details;
        lvwEmployees.FullRowSelect = true;
        lvwEmployees.Size = new Size(250, 130);
        lvwEmployees.Location = new Point(12, 12);

        lvwEmployees.Columns.AddRange(new ColumnHeader[] { colEmployeeNumber, colFirstName, colLastName, colSalary });

        Controls.Add(lvwEmployees);

        MaximizeBox = false;
        Text = "Delegates - Employees";
        ClientSize = new System.Drawing.Size(276, 160);
        StartPosition = FormStartPosition.CenterScreen;
        Load += new EventHandler(LoadForm);
    }

    private List<Employee> CreateEmployees()
    {
        List<Employee> employees = new List<Employee>();

        employees.Add(new Employee(240580, "James", "Paulson", 64050));
        employees.Add(new Employee(481004, "Annette", "Waller", 50888));
        employees.Add(new Employee() { FirstName = "Frank", LastName = "Euler", EmployeeNumber = 303950, Salary = 28905 });
        employees.Add(new Employee(920495, "Jacob", "Roberts", 105025));
        employees.Add(new Employee(lName: "Ouelett", fName: "Joshua", wage: 55820, emplNbr: 979274));
        employees.Add(new Employee(805813, "Marianne", "Jacobson", 72248));
        employees.Add(new Employee() { Salary = 29095, LastName = "Veuw", FirstName = "Arnold", EmployeeNumber = 830485 });

        return employees;
    }

    private void LoadForm(object sender, EventArgs e)
    {
        RecordsSetup create = CreateEmployees;

        lvwEmployees.Items.Clear();

        foreach (Employee empl in create())
        {
            ListViewItem lviEmployee = new ListViewItem(empl.EmployeeNumber.ToString());
            lviEmployee.SubItems.Add(empl.FirstName);
            lviEmployee.SubItems.Add(empl.LastName);
            lviEmployee.SubItems.Add(empl.Salary.ToString());
            lvwEmployees.Items.Add(lviEmployee);
        }
    }

    public static int Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new Exercise());
        
        return 0;
    }
}

public class Employee
{
    public int EmployeeNumber { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public double Salary { get; set; }

    public Employee()
    {
        EmployeeNumber = 0;
        FirstName = "Unknown";
        LastName = "Not Available";
        Salary = 0;
    }

    public Employee(int emplNbr, string fName = "John", string lName = "Doe", double wage = 0.00D)
    {
        EmployeeNumber = emplNbr;
        FirstName = fName;
        LastName = lName;
        Salary = wage;
    }
}

A Delegate that Takes an Object as Argument

A delegate can be created to receive a class type as argument. When creating the delegate, in its parentheses, specify the class whose value it takes as argument. To use the delegate, you can first create a method that uses the same syntax as the delegate, then declare a variable for the delegate and assign the method to it. Here is an example:

using System;
using System.Drawing;
using System.Windows.Forms;
using System.Collections.Generic;

public class Exercise : System.Windows.Forms.Form
{
    private delegate Employee RecordSetup();
    private delegate void Present(Employee e);

    public Exercise()
    {
        InitializeComponent();
    }

    void InitializeComponent()
    {
        MaximizeBox = false;
        Text = "Delegates - Employees";
        ClientSize = new System.Drawing.Size(276, 160);
        StartPosition = FormStartPosition.CenterScreen;
        Load += new EventHandler(LoadForm);
    }

    private Employee CreateRecord()
    {
        Employee empl = new Employee();

        empl.EmployeeNumber = 240580;
        empl.FirstName      = "James";
        empl.LastName       = "Paulson";
        empl.Salary         = 64050;

        return empl;
    }

    private void Show(Employee empl)
    {
        MessageBox.Show("Employee Record\n" +
                        "Employee #:\t" + empl.EmployeeNumber.ToString() + Environment.NewLine +
                        "First Name:\t" + empl.FirstName + Environment.NewLine +
                        "Last Name:\t" + empl.LastName + Environment.NewLine +
                        "Salary:\t\t" + empl.Salary.ToString(),
                        "Fun Department Store",
                        MessageBoxButtons.OK, MessageBoxIcon.Information);
    }

    private void LoadForm(object sender, EventArgs e)
    {
        RecordSetup Create = () =>
        {
            Employee empl = new Employee();

            empl.EmployeeNumber = 240580;
            empl.FirstName = "James";
            empl.LastName = "Paulson";
            empl.Salary = 64050;

            return empl;
        };

        Present pres = Show;
        
        pres(Create());
    }

    public static int Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new Exercise());
        
        return 0;
    }
}

public class Employee
{
    public int EmployeeNumber { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public double Salary { get; set; }
}

If you prefer to create an anonymous method using a lambda expression, in the parentheses, enter a name for the argument and use that argument in the body of the method as you see fit. Here is an example:

private void LoadForm(object sender, EventArgs e)
{
        RecordSetup Create = () =>
        {
            Employee empl = new Employee();

            empl.EmployeeNumber = 240580;
            empl.FirstName = "James";
            empl.LastName = "Paulson";
            empl.Salary = 64050;

            return empl;
        };

        Present pres = (Employee empl) =>
        {
            MessageBox.Show("Employee Record\n" +
            "Employee #:\t" + empl.EmployeeNumber.ToString() + Environment.NewLine +
                            "First Name:\t" + empl.FirstName + Environment.NewLine +
                            "Last Name:\t" + empl.LastName + Environment.NewLine +
                            "Salary:\t\t" + empl.Salary.ToString(),
                            "Fun Department Store",
                            MessageBoxButtons.OK, MessageBoxIcon.Information);
        };
        
        pres(Create());
}

In the same way:

  • You can create a delegate that takes a class as argument and returns a class type
  • You can create a delegate that takes more than one argument. One of the arguments could be a class type and the other(s) a class or a primitive type

Delegates and Arrays

 

Introduction

While a regular method can be used to return an array, you can use the features of a delegate to return an array of methods or to take an array of methods as arguments. Of course before proceeding, you must first create the necessary delegate. Here is an example:

using System;

delegate double Measure(double R);

public static class Program
{
    static int Main(string[] args)
    {
        return 0;
    }
}

Before creating the array, you must first know or have the methods you would refer to. These methods must have a similar syntax. This means that they must return the same type of value, they must have the same number of arguments and they must  have the  same type(s) of argument(s), if any. Here are examples of such functions:

using System;

delegate double Measure(double R);

public class Circle
{
    const double PI = 3.14159;

    double Diameter(double Radius)
    {
        return Radius * 2;
    }

    double Circumference(double Radius)
    {
        return Diameter(Radius) * PI;
    }

    double Area(double Radius)
    {
        return Radius * Radius * PI;
    }
}

public static class Program
{
    static int Main(string[] args)
    {
        return 0;
    }
}

An Array of Delegates

To create an array of delegates, declare a normal array as we have done so far. You can initialize each member using its index and calling the corresponding method. This can be done as follows:

using System;

delegate double Measure(double R);

public class Circle
{
    const double PI = 3.14159;

    public double Diameter(double Radius)
    {
        return Radius * 2;
    }

    public double Circumference(double Radius)
    {
        return Diameter(Radius) * PI;
    }

    public double Area(double Radius)
    {
        return Radius * Radius * PI;
    }
}

public static class Program
{
    static int Main(string[] args)
    {
        double R = 12.55;
        Circle circ = new Circle();
        Measure[] Calc = new Measure[3];

        Calc[0] = new Measure(circ.Diameter);
        double D = Calc[0](R);
        Calc[1] = new Measure(circ.Circumference);
        double C = Calc[1](R);
        Calc[2] = new Measure(circ.Area);
        double A = Calc[2](R);

        Console.WriteLine("Circle Characteristics");
        Console.WriteLine("Diameter:      {0}", D);
        Console.WriteLine("Circumference: {0}", C);
        Console.WriteLine("Area:          {0}\n", A);

        return 0;
    }
}

You can also list the members of the array when creating it. After creating the array, you can retrieve its value and store it in a variable. Here is an example:

public static class Program
{
    static void int(string[] args)
    {
        double R = 12.55;
        Circle circ = new Circle();
        Measure[] Calc = new Measure[]
        {
            new Measure(circ.Diameter),
            new Measure(circ.Circumference),
            new Measure(circ.Area)
        };
        
        double D = Calc[0](R);
        double C = Calc[1](R);
        double A = Calc[2](R);

        Console.WriteLine("Circle Characteristics");
        Console.WriteLine("Diameter:      {0}", D);
        Console.WriteLine("Circumference: {0}", C);
        Console.WriteLine("Area:          {0}\n", A);

        return 0;
    }
}

The above code could also be written as follows:

public static class Program
{
    static int Main(string[] args)
    {
        double R = 12.55;
        Circle circ = new Circle();
        Measure[] Calc = new Measure[]
        {
            new Measure(circ.Diameter),
            new Measure(circ.Circumference),
            new Measure(circ.Area)
        };
        
        Console.WriteLine("Circle Characteristics");
        Console.WriteLine("Diameter:      {0}", Calc[0](R));
        Console.WriteLine("Circumference: {0}", Calc[1](R));
        Console.WriteLine("Area:          {0}\n", Calc[2](R));

        return 0;
    }
}

This would produce:

Circle Characteristics
Diameter:      25.1
Circumference: 78.8539
Area:          494.808

Pre-Made Delegates

 

Actions

In most of our examples, we explicitly created a delegate. Because the concepts of delegates are very important, valuable, and useful in Microsoft Windows programming, the .NET Framework provides various pre-built delegates to suit all types of needs. The delegates are created in formula named Action. It is overloaded with various syntaxes. Actually, there 17 versions of the Action delegate ranging from one that doesnít take any argument to one that takes 16 arguments. The Action delegate is created as generic.

To use an action, declare a variable of type Action and initialize it with the method that  implements the behaviour you want. Here is an example:

using System;
using System.Drawing;
using System.Windows.Forms;
using System.Collections.Generic;

public class Exercise : System.Windows.Forms.Form
{
    private ListView lvwEmployees;
    private ColumnHeader colEmployeeNumber,
                         colFirstName,
                         colLastName,
                         colSalary;

    private List<Employee> employees;

    private delegate void Listing();

    public Exercise()
    {
        InitializeComponent();
    }

    void InitializeComponent()
    {
        colEmployeeNumber = new ColumnHeader();
        colEmployeeNumber.Text = "Empl #";
        colEmployeeNumber.Width = 45;
        colFirstName = new ColumnHeader();
        colFirstName.Text = "First Name";
        colFirstName.Width = 65;
        colLastName = new ColumnHeader();
        colLastName.Text = "Last Name";
        colLastName.Width = 65;
        colSalary = new ColumnHeader();
        colSalary.Text = "Salary";
        colSalary.TextAlign = HorizontalAlignment.Right;

        lvwEmployees = new ListView();
        lvwEmployees.GridLines = true;
        lvwEmployees.View = View.Details;
        lvwEmployees.FullRowSelect = true;
        lvwEmployees.Size = new Size(250, 140);
        lvwEmployees.Location = new Point(12, 12);

        lvwEmployees.Columns.AddRange(new ColumnHeader[] { colEmployeeNumber, colFirstName, colLastName, colSalary });

        Controls.Add(lvwEmployees);

        MaximizeBox = false;
        Text = "Delegates - Employees";
        ClientSize = new System.Drawing.Size(276, 166);
        StartPosition = FormStartPosition.CenterScreen;
        Load += new EventHandler(LoadForm);
    }

    private void CreateEmployees()
    {
        employees.Add(new Employee(240580, "James", "Paulson", 64050));
        employees.Add(new Employee(481004, "Annette", "Waller", 50888));
        employees.Add(new Employee() { FirstName = "Frank", LastName = "Euler", EmployeeNumber = 303950, Salary = 28905 });
        employees.Add(new Employee(920495, "Jacob", "Roberts", 105025));
        employees.Add(new Employee(lName: "Ouelett", fName: "Joshua", wage: 55820, emplNbr: 979274));
        employees.Add(new Employee(805813, "Marianne", "Jacobson", 72248));
        employees.Add(new Employee() { Salary = 29095, LastName = "Veuw", FirstName = "Arnold", EmployeeNumber = 830485 });
    }

    private void ShowEmployees()
    {
        lvwEmployees.Items.Clear();

        foreach (Employee empl in employees)
        {
            ListViewItem lviEmployee = new ListViewItem(empl.EmployeeNumber.ToString());
            lviEmployee.SubItems.Add(empl.FirstName);
            lviEmployee.SubItems.Add(empl.LastName);
            lviEmployee.SubItems.Add(empl.Salary.ToString());
            lvwEmployees.Items.Add(lviEmployee);
        }
    }

    private void LoadForm(object sender, EventArgs e)
    {
        employees = new List<Employee>();

        Listing create = new Listing(CreateEmployees);
        create();

        Action show = ShowEmployees;
        show();
    }

    public static int Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new Exercise());

        return 0;
    }
}

public class Employee
{
    public int EmployeeNumber { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public double Salary { get; set; }

    public Employee()
    {
        EmployeeNumber = 0;
        FirstName = "Unknown";
        LastName = "Not Available";
        Salary = 0;
    }

    public Employee(int emplNbr, string fName = "John", string lName = "Doe", double wage = 0.00D)
    {
        EmployeeNumber = emplNbr;
        FirstName = fName;
        LastName = lName;
        Salary = wage;
    }
}

Instead of first creating a method, you can use a lambda expression to locally define the desired behavior. Here is an example:

using System;
using System.Drawing;
using System.Windows.Forms;
using System.Collections.Generic;

public class Exercise : System.Windows.Forms.Form
{
    private ListView lvwEmployees;
    private ColumnHeader colEmployeeNumber,
                         colFirstName,
                         colLastName,
                         colSalary;

    private List<Employee> employees;

    public Exercise()
    {
        InitializeComponent();
    }

    void InitializeComponent()
    {
        colEmployeeNumber = new ColumnHeader();
        colEmployeeNumber.Text = "Empl #";
        colEmployeeNumber.Width = 45;
        colFirstName = new ColumnHeader();
        colFirstName.Text = "First Name";
        colFirstName.Width = 65;
        colLastName = new ColumnHeader();
        colLastName.Text = "Last Name";
        colLastName.Width = 65;
        colSalary = new ColumnHeader();
        colSalary.Text = "Salary";
        colSalary.TextAlign = HorizontalAlignment.Right;

        lvwEmployees = new ListView();
        lvwEmployees.GridLines = true;
        lvwEmployees.View = View.Details;
        lvwEmployees.FullRowSelect = true;
        lvwEmployees.Size = new Size(250, 140);
        lvwEmployees.Location = new Point(12, 12);

        lvwEmployees.Columns.AddRange(new ColumnHeader[] { colEmployeeNumber, colFirstName, colLastName, colSalary });

        Controls.Add(lvwEmployees);

        MaximizeBox = false;
        Text = "Delegates - Employees";
        ClientSize = new System.Drawing.Size(276, 166);
        StartPosition = FormStartPosition.CenterScreen;
        Load += new EventHandler(LoadForm);
    }

    private void ShowEmployees()
    {
        lvwEmployees.Items.Clear();

        foreach (Employee empl in employees)
        {
            ListViewItem lviEmployee = new ListViewItem(empl.EmployeeNumber.ToString());
            lviEmployee.SubItems.Add(empl.FirstName);
            lviEmployee.SubItems.Add(empl.LastName);
            lviEmployee.SubItems.Add(empl.Salary.ToString());
            lvwEmployees.Items.Add(lviEmployee);
        }
    }

    private void LoadForm(object sender, EventArgs e)
    {
        employees = new List<Employee>();

        Action create = () =>
        {
            employees.Add(new Employee(240580, "James", "Paulson", 64050));
            employees.Add(new Employee(481004, "Annette", "Waller", 50888));
            employees.Add(new Employee() { FirstName = "Frank", LastName = "Euler", EmployeeNumber = 303950, Salary = 28905 });
            employees.Add(new Employee(920495, "Jacob", "Roberts", 105025));
            employees.Add(new Employee(lName: "Ouelett", fName: "Joshua", wage: 55820, emplNbr: 979274));
            employees.Add(new Employee(805813, "Marianne", "Jacobson", 72248));
            employees.Add(new Employee() { Salary = 29095, LastName = "Veuw", FirstName = "Arnold", EmployeeNumber = 830485 });
        };
        create();

        Action show = ShowEmployees;
        show();
    }

    public static int Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new Exercise());

        return 0;
    }
}

public class Employee
{
    public int EmployeeNumber { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public double Salary { get; set; }

    public Employee()
    {
        EmployeeNumber = 0;
        FirstName = "Unknown";
        LastName = "Not Available";
        Salary = 0;
    }

    public Employee(int emplNbr, string fName = "John", string lName = "Doe", double wage = 0.00D)
    {
        EmployeeNumber = emplNbr;
        FirstName = fName;
        LastName = lName;
        Salary = wage;
    }
}

If you want to use a delegate that takes one or more arguments, declare the appropriate Action variable but specify the types of variables as for a generic type. You must initialize the variable with a method that takes the same number and type(s) of argument(s). Here are examples:

using System;
using System.Drawing;
using System.Windows.Forms;
using System.Collections.Generic;

public class Exercise : System.Windows.Forms.Form
{
    private ListView lvwEmployees;
    private ColumnHeader colEmployeeNumber,
			 colFirstName,
			 colLastName,
			 colSalary;

    public Exercise()
    {
        InitializeComponent();
    }

    void InitializeComponent()
    {
	. . .
    }

    private void ShowEmployees(List<Employee> empls)
    {
	lvwEmployees.Items.Clear();

	foreach(Employee empl in empls)
	{
	    ListViewItem lviEmployee = new ListViewItem(empl.EmployeeNumber.ToString());
	    lviEmployee.SubItems.Add(empl.FirstName);
	    lviEmployee.SubItems.Add(empl.LastName);
	    lviEmployee.SubItems.Add(empl.Salary.ToString());
	    lvwEmployees.Items.Add(lviEmployee);
	}
    }

    private void LoadForm(object sender, EventArgs e)
    {
	List<Employee> employees = new List<Employee>();
	
	employees.Add(new Employee(240580, "James",    "Paulsons",  64050));
	employees.Add(new Employee(481004, "Annette",  "Waller",    50888));
	employees.Add(new Employee() { FirstName = "Frank", LastName = "Euler", EmployeeNumber = 303950, Salary = 28905 });
	employees.Add(new Employee(920495, "Jacob",    "Roberts",  105025));
	employees.Add(new Employee(lName : "Ouelett", fName : "Joshua", wage : 55820, emplNbr : 979274));
	employees.Add(new Employee(805813, "Marianne", "Jacobson", 72248));
	employees.Add(new Employee() { Salary = 29095, LastName = "Veuw", FirstName = "Arnold", EmployeeNumber = 830485 });
	
	Action<List<Employee>> show = ShowEmployees;
	show(employees);
    }

    public static int Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new Exercise());
        
        return 0;
    }
}

Since Action primarily provides a syntax for a delegate, it abides by all the rules and features we have seen about delegates:

  • The delegate keyword can be used to locally implement. Here is an example:
    using System;
    using System.Drawing;
    using System.Windows.Forms;
    using System.Collections.Generic;
    
    public class Exercise
    {
        public static int Main()
        {
            Action msgBox = delegate()
            {
                MessageBox.Show("Welcome to C# Programming.");
            };
    
            msgBox();
    
            return 0;
        }
    }
  • An Action delegate can be returned from a method. Here is an example:
    using System;
    using System.Drawing;
    using System.Windows.Forms;
    using System.Collections.Generic;
    
    public class Exercise
    {
        private void Present()
        {
            MessageBox.Show("Welcome to C# Programming.");
        }
    
        private Action ShowMessage()
        {
            return Present;
        }
    
        public static int Main()
        {
            Exercise exo = new Exercise();
    
            Action msgBox = exo.ShowMessage();
    
            msgBox();
    
            return 0;
        }
    }
  • A method can return a collection or an array of Action delegates
  • An Action delegate can be passed as argument. Here is an example
    using System;
    using System.Drawing;
    using System.Windows.Forms;
    using System.Collections.Generic;
    
    public class Exercise
    {
        private void Present()
        {
            MessageBox.Show("Welcome to C# Programming.");
        }
    
        private void ShowMessage(Action act)
        {
            Action msgBox = act;
    
            msgBox();
        }
    
        public static int Main()
        {
            Exercise exo = new Exercise();
    
            Action msgBox = exo.Present;
    
            exo.ShowMessage(msgBox);
    
            return 0;
        }
    }

    As opposed to passing it by itself, an Action delegate can be passed as argument along with other arguments

Functions

The Action delegate is used for a method that doesnít return a value. On the other hand, a function in computer programming is an action that produces or returns a value (functions are used in C, C++, Visual Basic, (Object) Pascal (or Delphi), JavaScript, and other languages). To support class methods that return a value, the .NET Framework provides a special delegate named Func. As seen for the Action type, Func is provided in 17 versions that take 0 to 16 arguments. The main difference is that an Action-based delegate is for a method that doesnít return a value and a Func delegate is for a method that returns a value.

Here is an example of using a Func delegate:

using System;
using System.Drawing;
using System.Windows.Forms;
using System.Collections.Generic;

public class Exercise : System.Windows.Forms.Form
{
    private ListView lvwEmployees;
    private ColumnHeader colEmployeeNumber,
			 colFirstName,
			 colLastName,
			 colSalary;

    public Exercise()
    {
        InitializeComponent();
    }

    void InitializeComponent()
    {
	. . .
    }

    private List<Employee> GetEmployees()
    {
	List<Employee> staff = new List<Employee>();
	
	staff.Add(new Employee(240580, "James",    "Paulsons",  64050));
	staff.Add(new Employee(481004, "Annette",  "Waller",    50888));
	staff.Add(new Employee() { FirstName = "Frank", LastName = "Euler", EmployeeNumber = 303950, Salary = 28905 });
	staff.Add(new Employee(920495, "Jacob",    "Roberts",  105025));
	staff.Add(new Employee(lName : "Ouelett", fName : "Joshua", wage : 55820, emplNbr : 979274));
	staff.Add(new Employee(805813, "Marianne", "Jacobson", 72248));
	staff.Add(new Employee() { Salary = 29095, LastName = "Veuw", FirstName = "Arnold", EmployeeNumber = 830485 });

	return staff;
    }

    private void ShowEmployees(List<Employee> empls)
    {
	lvwEmployees.Items.Clear();

	foreach(Employee empl in empls)
	{
	    ListViewItem lviEmployee = new ListViewItem(empl.EmployeeNumber.ToString());
	    lviEmployee.SubItems.Add(empl.FirstName);
	    lviEmployee.SubItems.Add(empl.LastName);
	    lviEmployee.SubItems.Add(empl.Salary.ToString());
	    lvwEmployees.Items.Add(lviEmployee);
	}
    }

    private void LoadForm(object sender, EventArgs e)
    {
	Func<List<Employee>> getThem = GetEmployees;
	getThem();

	Action<List<Employee>> show = ShowEmployees;
	show(getThem());
    }

    public static int Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new Exercise());
        
        return 0;
    }
}

As mentioned Action, the Func delegate:

  • Can be implemented locally using the delegate keyword. Here is an example:
    using System;
    using System.Drawing;
    using System.Windows.Forms;
    using System.Collections.Generic;
    
    public class Exercise
    {
        public static int Main()
        {
            Action msgBox = delegate()
            {
                MessageBox.Show("Welcome to C# Programming.");
            };
    
            msgBox();
    
            return 0;
        }
    }
  • Can be returned from a method. Here is an example:
    using System;
    using System.Drawing;
    using System.Windows.Forms;
    using System.Collections.Generic;
    
    public class Exercise
    {
        private void Present()
        {
            MessageBox.Show("Welcome to C# Programming.");
        }
    
        private Action ShowMessage()
        {
            return Present;
        }
    
        public static int Main()
        {
            Exercise exo = new Exercise();
    
            Action msgBox = exo.ShowMessage();
    
            msgBox();
    
            return 0;
        }
    }
  • Can return a collection or array of values
  • Can be passed as argument. Here is an example:
    using System;
    using System.Drawing;
    using System.Windows.Forms;
    using System.Collections.Generic;
    
    public class Exercise
    {
        private void Present()
        {
            MessageBox.Show("Welcome to C# Programming.");
        }
    
        private void ShowMessage(Action act)
        {
            Action msgBox = act;
    
            msgBox();
        }
    
        public static int Main()
        {
            Exercise exo = new Exercise();
    
            Action msgBox = exo.Present;
    
            exo.ShowMessage(msgBox);
    
            return 0;
        }
    }
  • Can be passed among other arguments
 
 
   
 

Home Copyright © 2008-2014, FunctionX