当前位置:  开发笔记 > 编程语言 > 正文

为什么事件不能在派生类中以与C#中的基类相同的方式使用?

如何解决《为什么事件不能在派生类中以与C#中的基类相同的方式使用?》经验,为你挑选了3个好方法。

在下面的代码中,我想通过派生/子类化它来扩展类的行为,并使用基类的事件:

public class A
{
    public event EventHandler SomeEvent;

    public void someMethod()
    {
        if(SomeEvent != null) SomeEvent(this, someArgs);
    }
}

public class B : A
{
    public void someOtherMethod()
    {
        if(SomeEvent != null) SomeEvent(this, someArgs); // << why is this not possible?
//Error: The event 'SomeEvent' can only appear on the left hand side of += or -= 
//(except when used from within the type 'A')
    }
}

为什么不可能?

这种情况的常见解决方案是什么?



1> Jon Skeet..:

其他人已经解释了如何解决问题,但不是为什么它会出现.

声明类似公共字段的事件时,编译器会创建公共事件和私有字段.在同一个类(或嵌套类)中,您可以直接访问该字段,例如调用所有处理程序.从其他类中,您只能看到该事件,该事件仅允许订阅和取消订阅.



2> Todd White..:

这里的标准做法是在基类上有一个受保护的虚方法OnSomeEvent,然后在派生类中调用该方法.此外,出于线程原因,您需要在检查null并调用它之前保留对处理程序的引用.

有关读取Jon Skeet的答案或C#规范的原因解释,该规范描述了编译器如何自动创建私有字段.

这是一个可能的工作.

public class A
{
    public event EventHandler SomeEvent;

    public void someMethod()
    {
        OnSomeEvent();
    }

    protected void OnSomeEvent()
    {
        EventHandler handler = SomeEvent;
        if(handler != null)
            handler(this, someArgs);
    }
}

public class B : A
{
    public void someOtherMethod()
    {
        OnSomeEvent();
    }
}

编辑:根据框架设计指南第5.4节更新代码,并由其他人提醒.



3> cfeduke..:

托德的回答是正确的.通常,您会在整个.NET框架中看到这种OnXXX(EventArgs)方法作为方法实现:

public class Foo
{
    public event EventHandler Click;

    protected virtual void OnClick(EventArgs e)
    {
        var click = Click;
        if (click != null)
            click(this, e);
    }
}

我强烈建议您在发现自己采取各种方式/ 举办活动之前考虑EventArgs/ EventHandler模式.CustomEventArgsCustomEventHandler

推荐阅读
wangtao
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有