对代表们的更好理解,一些解释

问题描述 投票:2回答:2

我知道您何时使用委托,委托的工作方式,以及可以使用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

您有一个方法,并将方法作为参数传递给它。因此,似乎您做了一些封装。但这是代表的真正好处吗?封装函数。

当然,您不必再次遍历员工列表。因为这当然较短:

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

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

对我来说,这似乎也像对特定对象的过滤器一样工作。因为在这种情况下,您有一个对象Employee。而且您想与该员工做一些事情。因此,提高薪水或将他们分组。

因此,最后不必重复代码了吗?这也正确吗?

c# delegates
2个回答
2
投票

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

假设您有这个简单的课程:

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

但是现在的真正好处是,您也可以轻松地将计算器与其他类一起重用,例如您拥有此类:

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

您可以这样做

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

1
投票

对,委托的好处之一是您可以将它作为参数传递给函数,但这不是唯一的一个

您可以将委托视为可以包含功能列表的变量,可以分配

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)

0
投票

我建议考虑一种非常常见的更新记录的方案。流程会像这样]

public class EmployeeRepo
{
    public void Process(Employee emp) 
    {
    /// get model
    /// check if null
    /// process model
    /// check if mode is valid
    /// save 
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.