c#:访问父类的事件不可能?

时间:2011-01-20 00:11:27

标签: c# events inheritance

之前从未遇到过这种情况。这是样本:

using System;

namespace Testing
{
    public class Test
    {
        public event Action ActionRequired;
    }

    public class ChildTest : Test
    {
        public void DoSomething()
        {
            if (this.ActionRequired != null)
                this.ActionRequired();
        }
    }
}

这不起作用,错误是我只能从基类访问该事件。

向左转并不难(向基类添加一个受保护的方法,它既可以检查事件的调用,也可以从子类中调用该方法),但我真的很想知道这个限制背后的想法是什么?

干杯,

塞比

3 个答案:

答案 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();
    }
}