最近、C# 拡張メソッドを使用してイベントの呼び出しを簡単にする方法を学び、ますます使用しています。私は最近、理解できない奇妙な問題にぶつかりました.誰かがそれを説明できるかどうか疑問に思っていました.
この問題は、イベント ハンドラ拡張メソッドを別のイベントのイベント ハンドラとして設定しようとすると発生します。これが私がやっていることの例です:
public static class EventHandlerExtensions
{
public static void Raise<TEventArgs>(
this EventHandler<TEventArgs> eventHandler,
object sender, TEventArgs args) where TEventArgs:EventArgs
{
if (eventHandler != null)
{
eventHandler(sender, args);
}
}
}
public class Test
{
private event EventHandler<EventArgs> EventA;
private event EventHandler<EventArgs> EventB;
public Test()
{
Console.WriteLine("::Start");
EventB += EventA.Raise;
EventA += (s, a) => Console.WriteLine("Event A raised");
EventB.Raise(this, EventArgs.Empty);
Console.WriteLine("::End");
}
}
この例では、EventB がトリガーされた結果として、EventA がトリガーされます。ただし、このコードを実行すると、EventB が発生しますが、A の拡張メソッドはそのリスナーを見つけられません。
順序を変更すると、すべて正常に動作します。
Console.WriteLine("::Start");
EventA += (s, a) => Console.WriteLine("Event A raised");
EventB += EventA.Raise;
EventB.Raise(this, EventArgs.Empty);
Console.WriteLine("::End");
また、ラムダから EventA.Raise を呼び出しても問題なく動作します。
Console.WriteLine("::Start");
EventB += (s, a) => EventA.Raise(s, a);
EventA += (s, a) => Console.WriteLine("Event A raised");
EventB.Raise(this, EventArgs.Empty);
Console.WriteLine("::End");
これは単純な例ですが、追加されたイベント ソースのイベントを可能な限りクリーンな方法で再ディスパッチできるクラスを作成しようとしています。同じイベントを再ディスパッチするためだけに名前付きメソッドを作成したくありません。また、後でイベント ハンドラーからフック解除できるラムダ関数のリストを保存したくありません。ほとんどの場合、なぜこれが起こっているのか興味がありますか?
何か案は?