更好地理解代表,一些解释

Better understanding of delegates, some explanation

我知道您何时使用委托,它们是如何工作的,并且您可以使用 ActionFunc 等内置类型来使用委托。

但是我觉得真正的意思我还是不明白。因为我有这个样本:

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();
    }
}

所以我举了两个例子。 ONe 正在使用委托。一个是没有使用代表。然后你必须迭代列表 Employees.

当然还有这个:

ProcessEmployees(GiveRaise); //With delegate

你有一个方法并将方法作为参数传递给它。所以看起来你做了一些封装。但这是代表的真正好处吗?你封装函数。

当然,您不必再次迭代 Employees 列表。因为这当然更短了:

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

希望得到一些反馈我的误解。

对我来说,它似乎也像特定对象的过滤器一样工作。因为在这种情况下,您有一个对象 Employee。你想和那个员工一起做一些事情。所以加薪或者组队。

所以最后你不必重复代码?这也对吗?

是的,delegate 的好处之一是你可以将它作为参数传递给函数,但这不是唯一的

你可以假设委托是一个可以包含函数列表的变量,你可以赋值

Action a = MyFunction;

向列表添加新函数

a+= MyFunction1

从列表中删除函数

a-= MyFunction1

调用列表中的所有函数

a();

迭代列表中的所有函数

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

并将其作为参数传递给另一个方法,需要时可以调用它

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

在您的示例中,使用委托没有太大意义,因为所有内容都在 class 内(此处为 Form1)。如果委托及其使用者处于不同的 class 中,尤其是与泛型结合使用时,它们更有意义。

假设你有这个简单的 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();
   }
}

在你的Form1中你可以创建一个方法

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

并像

一样使用它
var calc = new Calculator<Employee>();
var avg = calc.Average(Employees, GetSalary);

或者您可以通过不使用 GetSalary 方法并使用 lambda 表达式来简化此操作:

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

但现在真正的好处是您可以轻松地将您的计算器与其他 classes 重用,假设您有这个 class:

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

然后你可以做

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