Better understanding of delegates, some explanation

Viewed 85

I know when you are using delegates, how they work, and that you can use built in types like Action or Func for using delagates.

But I think the real meaning I still don't understand. Because I have this sample:

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    // A method that processes an employee.
    // private delegate void EmployeeProcessor(Employee employee);

    // The employees.
    //  Employee employee;
    private List<Employee> Employees = new List<Employee>();

    private void Form1_Load(object sender, EventArgs e)
    {
        // Make some employees.
        MakeEmployees();

        // Show the employees.
        ShowEmployees();
    }

    // Add a single employee to the form's ListBox.
    private void ListEmployee(Employee employee)
    {
        employeesListBox.Items.Add(
            employee.Name + ", " +
            employee.Title + ", " +
            employee.Salary.ToString("C"));
    }

    // Do something for all employees.
    private void ProcessEmployees(Action<Employee> process)
    {
        foreach (Employee employee in Employees)
            process(employee);
    }

    // Display all employees in the form's ListBox.
    private void ShowEmployees()
    {
        employeesListBox.Items.Clear();
        ProcessEmployees(ListEmployee);
    }

    // Make some employees.
    private void MakeEmployees()
    {
        Employees.Add(new Employee()
        {
            Name = "Alice Archer",
            Title = "Programmer",
            Salary = 60000m,
        });
        Employees.Add(new Employee()
        {
            Name = "Bob Baker",
            Title = "Engineer",
            Salary = 70000m,
        });
        Employees.Add(new Employee()
        {
            Name = "Cindy Carter",
            Title = "Manager",
            Salary = 80000m,
        });
    }

    // Give a single employee a raise.
    private void GiveRaise(Employee employee)
    {
        employee.Salary *= 1.1m;
    }

    private void GiveRaise2()
    {
        foreach (var employee2 in Employees)
        {
            employee2.Salary *= 1.1m;
        }
    }

    // Give all employees a raise.
    private void giveRaisesButton_Click(object sender, EventArgs e)
    {
        GiveRaise2();// Without Delegate
        ProcessEmployees(GiveRaise); //With delegate
        ShowEmployees();
    }
}

So I made two examples. ONe is using the delegate. And one is not uising the delegate. And then you have to iterate over the list Employees.

And of course this:

ProcessEmployees(GiveRaise); //With delegate

There you have a method and pass a method as a parameter to it. So it seems that you do some encapsualtion. But is this the real benefit of a delegate? That you encapsulate functions.

And of course that you don't have to iterate again of the the list of Employees. Because this is of course shorter:

private void GiveRaise(Employee employee)
{
    employee.Salary *= 1.1m;
}

Hope to get some feedback what I misunderstand.

For me it seems also that is works like a filter for a specific object. Because in this case you have an object Employee. And you want to do some things with that Employee. So raise the salary or group them together.

So at the end you don't have to repeat code? Is that also correct?

2 Answers

In your example the use of delegates doesn't make too much sense because everything is within on class (Form1 here). They make more sense if the delegate and its consumer are in different classes, especially in combination with generics.

Let's say you have this simple class:

public class Calculator<T>
{
   public decimal Average(List<T> items, Func<T, decimal> getValue)
   {
        decimal sum = 0;

        foreach (var item in items)
            sum += getValue(item);

        return sum / items.Count();
   }
}

In your Form1 you can then make a method

private decimal GetSalary(Employee employee)
{
    return employee.Salary;
}

and use that like

var calc = new Calculator<Employee>();
var avg = calc.Average(Employees, GetSalary);

Or you can simplify this by doing without the GetSalary method and use a lambda expression:

var avg = calc.Average(Employees, e => e.Salary);

But the real benefit now is that you can easily reuse your calculator with other classes as well, say you have this class:

public class Product
{
    public decimal Weight { get; set; }
}

you can then do

var calc = new Calculator<Product>();
var avgWeight = calc.Average(listOfProducts, p => p.Weight);

Right, one of the benefits of delegate is that you can pass it as argument to the function, but that is not the only one

You can assume delegate as a variable that can contain list of functions, you can assign

Action a = MyFunction;

Add new function to the list

a+= MyFunction1

Remove function from the list

a-= MyFunction1

Call all functions in the list

a();

Iterate over all functions in list

foreach (var myHandler in a.GetInvocationList()) {
    // Call single myHandler() if you want
}

And pass it as an argument to another method, which can call it when nessesary

Foo(a); // where Foo(Action d)
Related