Многоадресные делегаты: различное поведение при добавлении ссылок метода к делегату в других методах

У меня есть код ниже, который объявляет делегат:

delegate void EmployeeSalaryCalculated(int idEmp);

У меня эти простые классы:

class Employee { public void CalculateSalary(int idEmp){} } class Payroll { public void EmpSalNotification(int idEmp) { } public void SetMethod(ref EmployeeSalaryCalculated esc) { esc += this.EmpSalNotification; } } class HR { public void EmpSalNotification(int idEmp) { } public void SetMethod(ref EmployeeSalaryCalculated esc) { esc = this.EmpSalNotification; } }

Следующий обработчик кнопки использует вышеуказанные классы:

private void btnStart_Click(object sender, EventArgs e) { Payroll payroll = new Payroll(); HR hr = new HR(); EmployeeSalaryCalculated empSalCalculated = null; empSalCalculated += payroll.EmpSalNotification; empSalCalculated += hr.EmpSalNotification; // This invokes both methods - fine. // empSalCalculated.GetInvocationList() returns 2 empSalCalculated.Invoke(108); EmployeeSalaryCalculated empSalCalculated2 = null; payroll.SetMethod(ref empSalCalculated2); hr.SetMethod(ref empSalCalculated2); // This however, invokes only one method! // empSalCalculated2.GetInvocationList() returns 1 empSalCalculated2.Invoke(108); }

Несмотря на передачу объекта-делегата empSalCalculated2 по ref, он просто выполняет только одну функцию, в отличие от объекта-делегата empSalCalculated который выполняет обе функции.

Есть предположения?

3 ответа

Проблема заключается в этой строке класса HR.SetMethod:

esc = this.EmpSalNotification;

Эта строка переопределяет любое значение esc ранее. Итак, учитывая порядок, в котором вы вызываете SetMethod из объектов, empSalCalculated2 содержит только метод из экземпляра HR, который выполняется.

Чтобы исправить это, вы можете либо переписать HR.SetMethod:

esc += this.EmpSalNotification;

или отменить порядок, в котором SetMethod:

hr.SetMethod(ref empSalCalculated2);
payroll.SetMethod(ref empSalCalculated2);


Просто опечатка в вашем коде:

esc += this.EmpSalNotification;

против

esc = this.EmpSalNotification;


Я думаю, что это опечатка в вашем классе HR

class HR { public void EmpSalNotification(int idEmp) { } public void SetMethod(ref EmployeeSalaryCalculated esc) { // this is =, not +=, so only one ref is held at a time esc = this.EmpSalNotification; } }

licensed under cc by-sa 3.0 with attribution.