Я искал использование выражения 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: Дерево выражений может не содержать оператор присваивания
Теперь это кажется разумным, особенно после чтения объяснения о том, почему деревья выражений не могут содержать присвоения. Однако, несмотря на синтаксис С#, +=
не является назначением, это вызов метода 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': не может явным образом вызывать оператор или аксессор
Итак, я думаю, вопрос сводится к тому, что +=
на самом деле означает в контексте событий С#. Означает ли это, что "вызывать метод добавления для этого события" или означает "добавить к этому событию все-таки undefined". Если это первое, то мне кажется, что это ошибка компилятора, тогда как если она последняя, то она несколько неинтуитивная, но, возможно, не ошибка. Мысли?