私はランバ式を使用してイベントを強く型付けされた方法で接続できるようにすることを検討していましたが、途中でリスナーを使用します。たとえば、次のクラスが与えられました
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)
したがって、割り当てが許可されていないことを訴えているため、これはコンパイラのバグのように見えますが、割り当ては行われておらず、メソッド呼び出しだけです。それとも私は何かを逃していますか...?
編集:
「この動作はコンパイラのバグですか?」という質問があることに注意してください。私が何を求めているのか明確でなかったら申し訳ありません。
編集 2
Inferis の回答を読んだ後、彼は「その時点で += は代入と見なされます」と述べていますが、これはある程度の意味があります。
ただし、明示的なメソッド呼び出しフォームを書くことは許可されていません。
Listener.WireUp<Producer, Consumer>(
(p, c) => p.add_MyEvent(new EventHandler(c.MyHandler)));
与えます:
CS0571: 'Producer.MyEvent.add': 演算子またはアクセサーを明示的に呼び出すことはできません
+=
したがって、問題は、C# イベントのコンテキストで実際に何を意味するのかということになると思います。「このイベントの add メソッドを呼び出す」という意味ですか、それとも「まだ定義されていない方法でこのイベントに追加する」という意味ですか。前者の場合、これはコンパイラのバグのように見えますが、後者の場合、やや直感的ではありませんが、間違いなくバグではありません。考え?