【问题标题】:Event handlers, existing class to new interface事件处理程序,现有类到新接口
【发布时间】:2011-11-11 04:16:24
【问题描述】:

我正在为一个程序增加一些灵活性,因为它的目的现在已经改变了。我想添加一个现有类将实现的接口。

现有类

public class ClassA
{
    #region Events
    public delegate void DataReceivedHandler(object sender, EventArgs e);
    public delegate void DataSentHandler(object sender, EventArgs e);
    public delegate void StatusUpdatedHandler(object sender, EventArgs e);
    public event DataReceivedHandler DataReceived;
    public event DataSentHandler DataSent;
    public event StatusUpdatedHandler StatusUpdated;
    #endregion

    //rest of code here...
 }

新界面

public interface IClassA
{
    event EventHandler DataReceived;
    event EventHandler DataSent;
    event EventHandler StatusUpdated;

    //rest of code here...
}

我的三个问题如下。

第一季度。我首先在类中声明我自己的委托是正确的,即public delegate void DataReceivedHandler,还是应该删除这些委托并将事件替换为普通的EventHandler。即public event EventHandler DataReceived。鉴于这些事件没有通过事件传递数据,只是通知任何订阅的东西发生了变化。

第二季度。与上述问题密切相关。鉴于我正在更改类的属性,即状态(StatusUpdated)。将新状态作为自定义 EventArgs 传递是否是最佳做法,因此需要像原始代码中一样的自定义委托?由于它当前工作,事件被触发,并且订阅的类可以只使用发送者值,即(发送者作为 ClassA).Status。是否有最佳做法,还是仅取决于开发人员?

第三季度。现在这已经不可能了。关于接口的部分。我是否在接口中正确声明了 DataReceived 和其他事件,以匹配将被标记为实现它的类。

【问题讨论】:

    标签: c# .net events interface delegates


    【解决方案1】:

    如果您需要接口方法的自定义委托,您应该单独声明它们(在类之外),因为它们不绑定到特定的实现。委托声明可以位于接口内部,就像类一样。您的代表的问题是他们都有相同的签名EventHandler),因此是多余的。

    如果您在引发这些事件时不需要传递任何数据,则可以使用普通的 EventHandler 委托。但是,我希望通过 DataReceived 事件获得一些数据,因此您应该检查这是否有意义,并可能使用接受一些数据作为参数的委托。

    第三,你的接口事件签名必须匹配类签名。您不能在接口中使用 EventHandler 委托类型,并更改类内的签名。

    请注意,您还可以避免显式声明委托类型,并使用 BCL 提供的通用 Action 委托(从 .NET 3.5 开始)。在这种情况下,您可能会遇到以下情况:

    public interface IClassA
    {
       event Action<IClassA, Data> DataReceived;
       event Action<IClassA, Data> DataSent;
       event Action<IClassA, Status> StatusUpdated;
    }
    

    后一种方法为您提供了具有强类型 sender 参数的好处(与 EventHandler 中的 object 相对)。

    【讨论】:

    • 我已经尝试了这两种方法,你的和 Jamiecs 的方法,感谢你们的回答。我更喜欢使用 Action ,因为我已经看到它也用于 GUI 调用,所以我习惯了它是个好主意。我看到这种方法的唯一缺点是缺乏自动完成功能。如果我输入 myClassA.StatusUpdated += ...,则使用我以前的事件。 += 将自动创建处理事件的方法,即使使用自定义事件参数也是如此。使用Actions就不是这样了,必须自己写方法。
    • 偏好的另一个原因是强类型的发件人,尽管这似乎可以通过委托来实现。
    • @Jon:你确定吗?我从来没有遇到过这样的问题,不管委托签名(输入+=,点击Tab两次,应该生成方法存根)。
    • 刚重新打开VS2008又试了一次,效果很好。很奇怪。
    【解决方案2】:

    在回答你的问题时,当然这些都是见仁见智的问题,所以我会给出我的:

    A1) 不,您不正确地重新声明自己的 XXXHandler 代表,框架中有一个 (EventHandler) 与您的完全匹配 - 这很好地表明您正在“重新发明轮子” .

    A2) 我相信名为StatusChanged 的事件应该将新的(也可能是旧的)状态传递给任何订阅者。但是,这仍然不是实现您自己的委托的理由,因为框架为此目的定义了一个通用委托 (EventHandler&lt;TEventArgs&gt;)。

    A3) 目前你所在班级的事件与接口不匹配,这意味着如果不改变它就无法实现。

    文档:EventHandler&lt;TEventArgs&gt;

    【讨论】:

    • 比 Groo 更简洁的答案,但我喜欢使用 Action。除了对他的回答的评论中的一个缺点。
    猜你喜欢
    • 1970-01-01
    • 2015-02-13
    • 2013-10-20
    • 1970-01-01
    • 1970-01-01
    • 2012-09-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多