Я рассматривал использование выражения lamba, чтобы разрешить передачу событий строго типизированным образом, но с послушателем посередине, например, учитывая следующие классы
class Producer
{
public event EventHandler MyEvent;
}
class Consumer
{
public void MyHandler(object sender, EventArgs e) { /* ... */ }
}
class Listener
{
public static void WireUp<TProducer, TConsumer>(
Expression<Action<TProducer, TConsumer>> expr) { /* ... */ }
}
Событие будет записано как:
Listener.WireUp<Producer, Consumer>((p, c) => p.MyEvent += c.MyHandler);
Однако это дает ошибку компилятора:
CS0832: Дерево выражений может не содержать оператор присваивания
Сначала это кажется разумным, особенно после того, как прочитал объяснение того, почему деревья выражений не могут содержать присваивания . Однако, несмотря на синтаксис C #, +=
не является присваиванием, это вызов метода Producer::add_MyEvent
, как мы видим из CIL, который создается, если мы просто подключаем событие нормально:
L_0001: newobj instance void LambdaEvents.Producer::.ctor()
L_0007: newobj instance void LambdaEvents.Consumer::.ctor()
L_000f: ldftn instance void LambdaEvents.Consumer::MyHandler(object, class [mscorlib]System.EventArgs)
L_0015: newobj instance void [mscorlib]System.EventHandler::.ctor(object, native int)
L_001a: callvirt instance void LambdaEvents.Producer::add_MyEvent(class [mscorlib]System.EventHandler)
Так что мне кажется, что это ошибка компилятора, так как он жалуется на то, что назначения не разрешены, но назначения не происходит, только вызов метода. Или я что-то упустил ...?
Edit:
Обратите внимание, что вопрос «Является ли это поведение ошибкой компилятора?». Извините, если мне неясно, о чем я спрашиваю.
Редактировать 2
После прочтения ответа Inferis, где он говорит, что «в этот момент + = считается присваиванием», это действительно имеет некоторый смысл, потому что в этот момент компилятор, вероятно, не знает, что он будет превращен в CIL .
Однако мне не разрешено писать явную форму вызова метода:
Listener.WireUp<Producer, Consumer>(
(p, c) => p.add_MyEvent(new EventHandler(c.MyHandler)));
Дает:
CS0571: 'Producer.MyEvent.add': невозможно явно вызвать оператор или метод доступа
Итак, я предполагаю, что вопрос сводится к тому, что на самом деле означает +=
в контексте событий C #. Означает ли это «вызвать метод add для этого события» или это означает «добавить к этому событию еще не определенным образом». Если это первое, то мне кажется, что это ошибка компилятора, тогда как если это второе, то это несколько не интуитивно понятно, но, возможно, это не ошибка. Мысли?