using System;
namespace Testing
{
public class Test
{
public event Action ActionRequired;
}
public class ChildTest : Test
{
public void DoSomething()
{
if (this.ActionRequired != null)
this.ActionRequired();
}
}
}
这不起作用,错误是我只能从基类访问该事件。
向左转并不难(向基类添加一个受保护的方法,它既可以检查事件的调用,也可以从子类中调用该方法),但我真的很想知道这个限制背后的想法是什么?
干杯,
塞比
答案 0 :(得分:14)
您无法从定义它们的类外部调用事件。但是,你不需要;只需遵循惯用的模式,同时声明一个受保护的方法来触发所述事件。
class Whatever
{
public event EventHandler Foo;
protected virtual void OnFoo( EventArgs e )
{
EventHandler del = Foo;
if( del != null )
{
del( this, e );
}
}
}
现在,类“Whatever”的后代可以通过调用OnFoo()并传入适当的EventArgs对象来触发事件。
编辑:关于为什么这是行为,Jon Skeet在另一个帖子中解释得很好(这也意味着这个问题是重复的,所以投票结束):
当您声明类似公共字段的事件时,编译器会创建一个公共事件和一个私有字段。在同一个类(或嵌套类)中,您可以直接进入该字段,例如调用所有处理程序。从其他类中,您只能看到该事件,该事件仅允许订阅和取消订阅。
答案 1 :(得分:3)
您在示例中用于声明事件的语法实际上是语法糖,如下所示:
private Action _actionRequired;
public event Action ActionRequired
{
add { _actionRequired += value; }
remove { _actionRequired -= value }
}
(实际代码当然要复杂一点)
这里的重要部分是_actionRequired
字段是私有的。只有事件本身是公开的,但它只是一对添加/删除方法(类似于属性)。因此,您可以对事件做的唯一事情是订阅或取消订阅。保存实际委托的字段是私有的,因此只能从声明它的类中访问它。在声明它的类中使用ActionRequired
时,它会引用委托字段或事件本身,具体取决于上下文。
但是从任何其他类来看,只有事件可以访问,而不是字段。这就是为什么你不能从另一个类调用委托,甚至是派生类。
答案 2 :(得分:1)
根据@ThomasLevesque先前的回答 https://stackoverflow.com/a/4742280/3926461
你可以在不使用这种语法糖的情况下宣布你的行动如下所示:
public class Test
{
protected Action _actionRequired;
public event Action ActionRequired {
add {
_actionRequired += value;
}
remove {
_actionRequired += value;
}
}
}
public class ChildTest : Test
{
public void DoSomething()
{
if (this._actionRequired != null)
this._actionRequired();
}
}