我正在尝试编写EventHandler
的扩展方法,如下所示:
public static class MyExtensions
{
public static void Add(this EventHandler handler, EventHandler next)
{
//Do something
}
}
它适用于我的活动,例如:
public event EventHandler MyEvent
我可以毫无问题地使用我的扩展程序:
MyEvent.Add((x, y) => { /* do something */ });
但是当我想将它应用于TextBox的Click事件时,我收到一个编译错误:
错误CS0079:
事件System.Windows.Forms.TextBoxBase.Click只能出现在
的左侧+=
或-=
让我感到困惑的是,Click事件与MyEvent
没有任何不同,那么为什么它会有约束?
答案 0 :(得分:4)
如果Add
方法是在同一个类中的调用MyEvent
,那么它可能正常工作。
但是,Click
方法是在不同的类中定义的,而不是从您调用Add
的方法。这就是为什么它不起作用。
.NET框架不允许在定义它的类之外直接修改事件,否则一些胭脂代码可能会删除任何类的所有事件处理程序。
这是我能提出的最好的扩展方法,可以帮助你做你想做的事情:
public static Action Add<TDelegate>(
this TDelegate handler,
Action<TDelegate> addHandler,
Action<TDelegate> removeHandler)
{
addHandler(handler);
return () => removeHandler(handler);
}
你可以像这样使用它:
var bar = new Bar();
EventHandler handler = (s, e) =>
{
Console.WriteLine("MyEvent!");
};
var cleanup = handler.Add(h => bar.MyEvent +=h, h => bar.MyEvent -=h);
bar.Raise();
bar.Raise();
cleanup();
cleanup
操作用于在不需要时删除事件处理程序。
为简单起见,我遗漏了所有必需的空检查代码。你必须把它们放在适当的地方。
答案 1 :(得分:1)
两者之间存在差异。一个简单的例子可以证明它:
private EventHandler foodel;
public event EventHandler foo {
add { foodel += value; }
remove { foodel -= value; }
}
public event EventHandler bar;
...
foo.Add((s, e) => { }); // CS0079
bar.Add((s, e) => { }); // No error
删除访问者,代码编译干净。
我将继续说你无意中利用编译器错误。它应该拒绝对没有访问器声明的事件使用扩展方法。微软将修复这个漏洞的几率非常低,这已经持续了很长时间。但最好的解决方法是删除扩展方法。