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

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

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.