简体   繁体   English

是否可以实现C#接口并扩展事件的参数?

[英]Is it possible to implement a C# Interface and extend the arguments of Events?

Suppose I have the following Interface: 假设我有以下界面:

interface IBook
{
    event EventHandler<EventArgs> PageChanged;
}

which I could implement without difficulty for this class: 我可以在本课程中轻松实现:

class Novel : IBook
{
    public event EventHandler<EventArgs> PageChanged;

    protected void OnPageChanged()
    {
        EventHandler<EventArgs> pageChanged = PageChanged;
        if (pageChanged != null) pageChanged(this, EventArgs.Empty);
    }
}

however, if I now have an object called Encyclopedia defined as: 但是,如果我现在有一个称为Encyclopedia的对象定义为:

class Encyclopedia : IBook
{
    public class EncyclopediaEventArgs : EventArgs
    {
        public int Volume
        {
            get { return volume; }
        }

        private int volume;

        public EncyclopediaEventArgs(int volume)
        {
            this.volume = volume;
        }
    }

    public event EventHandler<EncyclopediaEventArgs> PageChanged;

    protected void OnPageChanged(int volume)
    {
        EventHandler<EncyclopediaEventArgs> pageChanged = PageChanged;
        if (pageChanged != null) pageChanged(this, new EncyclopediaEventArgs(volume));
    }
}

which has all the workings of a Book , but with the added event argument field of Volume . 它具有Book所有功能,但具有Volume的添加的事件参数字段。 When I compile, I get an error (as surmised I would): 当我编译时,我得到一个错误(我猜想是这样):

error CS0738: 'Encyclopedia' does not implement interface member 'IBook.PageChanged'. 错误CS0738:“百科全书库”未实现接口成员“ IBook.PageChanged”。 'Encyclopedia.PageChanged' cannot implement 'IBook.PageChanged' because it does not have the matching return type of 'System.EventHandler' 'Encyclopedia.PageChanged'无法实现'IBook.PageChanged',因为它没有匹配的返回类型'System.EventHandler'

It states that it cannot implement IBook.PageChanged because System.EventHandler<System.EventArgs> is not the return type, even though EncyclopediaEventArgs derives from System.EventArgs . 它声明它不能实现IBook.PageChanged因为System.EventHandler<System.EventArgs>不是返回类型,即使EncyclopediaEventArgs派生自System.EventArgs

My question, therefore, is, would it be possible to derive such a class as Encyclopedia which adds the additional Volume field to its event arguments? 因此,我的问题是,是否有可能派生出诸如Encyclopedia类的类,该类将附加的Volume字段添加到其事件参数中?

(Any discussion is very much welcome as to why this is or is not a poor design/architecture decision!) (关于为什么这是一个糟糕的设计/体系结构决定,任何讨论都非常受欢迎!)

It seems fairly straight forward to do this: 这样做似乎很简单:

interface IBook<T> where T : EventArgs
{
    event EventHandler<T> PageChanged;
}

class Novel : IBook<EventArgs> { ... }

class Encyclopedia : IBook<Encyclopedia.EncyclopediaEventArgs> { ... }

If you still need a plain IBook then you would do this: 如果您仍然需要普通的IBook则可以执行以下操作:

interface IBook { }

interface IBook<T> : IBook where T : EventArgs
{
    event EventHandler<T> PageChanged;
}

It depends a bit on how you are going to use IBook . 这取决于您将如何使用IBook You could create a generic parameter for the EventArgs like so: 您可以像这样为EventArgs创建通用参数:

public interface IBook<TEventArgs> where TEventArgs : EventArgs
{
    event EventHandler<TEventArgs> PageChanged;
}

public class Novel : IBook<EventArgs>
{
    event EventHandler<EventArgs> PageChanged;
}

public class Encyclopedia : IBook<EncyclopediaEventArgs>
{
    event EventHandler<EncyclopediaEventArgs> PageChanged;
}

But then you can't use IBook without the generic type if you need PageChanged for other purposes. 但你不能使用IBook没有泛型类型,如果你需要PageChanged用于其他目的。

Another way is to just keep the event EventHandler<EventArgs> PageChanged; 另一种方法是只保留event EventHandler<EventArgs> PageChanged; have the Encyclopedia implementation pass a EncyclopediaEventArgs and just cast in the event handler. 让Encyclopedia实现传递一个EncyclopediaEventArgs并将其强制转换为事件处理程序。

class Encyclopedia : IBook
{
    public class EncyclopediaEventArgs : EventArgs
    {
    }

    public event EventHandler<EventArgs> PageChanged;

    protected void OnPageChanged(int volume)
    {
        EventHandler<EventArgs> pageChanged = PageChanged;
        if (pageChanged != null) pageChanged(this, new EncyclopediaEventArgs(...));
    }
}

public class BookReader
{
    public void OnPageChanged(object sender, EventArgs e)
    {
        if (sender is Encyclopedia && e is EncyclopediaEventArgs)
        {
            EncyclopediaEventArgs ee = (EncyclopediaEventArgs)e;
        }
        else
        {
        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM