Использование многоадресного делегата для объединения функций
Мой вопрос подробно описан в следующем коде - причина, по которой я прошу об этом, заключается в том, что я экспериментирую с делегатами:
//create the delegate
delegate int del(int x);
class Program {
static void Main(string[] args) {
Program p;
p = new Program();
del d = p.a;
d += p.b;
d += p.c;
d += p.d;
d += p.e;
Console.WriteLine(d(10)); //<<was hoping it would be 10+2+3+4+5+6
Console.WriteLine("press [enter] to exit");
Console.ReadLine();
}
private int a(int x) { Console.WriteLine("a is called"); return x + 2; }
private int b(int x) { Console.WriteLine("b is called"); return x + 3; }
private int c(int x) { Console.WriteLine("c is called"); return x + 4; }
private int d(int x) { Console.WriteLine("d is called"); return x + 5; }
private int e(int x) { Console.WriteLine("e is called"); return x + 6; }
}
16 возвращается....
![enter image description here]()
Все функции запускаются, так как различные сообщения "a вызывается" и т.д. все печатаются в console
, но возвращается только сумма, возвращаемая из последней функции e
- я предполагаю, что в фоновом режиме они возвращается, но затем перезаписывается?
Ответы
Ответ 1
Когда в вашем вопросе есть делегат multicast, например d
, возвращаемое значение является возвращаемым значением из метода last списка вызовов d
.
В общем случае для многоадресных делегатов наиболее естественно использовать возвращаемый тип void
.
У компилятора не было возможности догадаться, что вы надеялись на 10+2+3+4+5+6
. Вы не указали его нигде.
Вы можете изменить свой тип делегата на:
delegate void del(int xToAdd, ref int sum);
Тогда ваш метод a
, например, должен выглядеть следующим образом:
private void a(int x, ref int sum) { Console.WriteLine("a is called"); sum += x + 2; }
Затем экземпляр делегата multicast d
вызывается следующим образом:
int sum = 0;
d(10, ref sum);
Console.WriteLine(sum);
Надеюсь, это поможет.
Ответ 2
Это не то, как обратные типы обрабатываются для делегатов. Что произойдет, так это то, что все обработчики будут выполняться независимо друг от друга, и тогда один будет выбран случайным образом (технически это обработчик, который был подписан последним, но вы не должны полагаться на это), чтобы вернуть вызывающему абоненту который вызвал делегата.
Я бы очень отговаривал вас от использования события (вы рассматриваете этот делегат как событие), у которого есть возвращаемое значение. Поведение практически никогда не бывает желательным. Если вы хотите получить возвращаемое значение, имеет смысл убедиться, что ваш делегат всегда сопоставляется с одной функцией, не более, не менее.
Что касается фактического создания желаемого результата, хотя существует ряд подходов, вам лучше будет обслуживаться более традиционная коллекция делегатов:
List<Func<int, int>> functions = new List<Func<int, int>>();
//populate
int result = functions.Aggregate(10, (total, func) => func(total));