Вы можете рассматривать делегатов как нечто среднее между типами значений (например, int
или double
) и массивами адресов методов.
Вы знаете, что если вы напишите этот код:
var x = 5;
var y = x + 2;
y += 3;
Затем впоследствии x == 5
& y == 10
, хотя y
имел промежуточное значение 7
, оно было "выброшено", когда произошло окончательное присвоение.
Совершенно ясно, окончательное значениеy
не 3
.
В своем коде вы написали это:
calc c = new calc(Add);
c += new calc(Multiply);
Как и в случае y
, окончательное значение c
не Multiply
.Это действительно так:
c == { Add, Multiply }
Когда вы затем вызываете что-то вроде c(4, 2)
, вы фактически вызываете обоих Add
& Multiply
, и потому что делегат возвращает значение, которое вывернуть только окончательное значение делегата - в данном случае от Multiply
- и вот почему создается впечатление, что «указатель» изменился на метод Multiply
.
Вы можете попробовать добавить этот код перед тем, каквызовите c
:
c -= new calc(Multiply);
, и это фактически вернет c
к этому:
c == { Add }
И именно поэтому делегаты ведут себя как массивы адресов методов.
Теперь, если вы измените методы Add
& Multiply
, чтобы они выглядели так:
public static int Add(int a, int b)
{
Console.WriteLine("Add({0}, {1})", a, b);
return (a + b);
}
public static int Multiply(int a, int b)
{
Console.WriteLine("Multiply({0}, {1})", a, b);
return (a * b);
}
, вы сможете наблюдать за звонками по мере их возникновения.Ваш оригинальный код работает так:
Add(4, 2)
Multiply(4, 2)
Add(3, 8)
Multiply(3, 8)
24
Надеюсь, это поможет.