私有事件处理程序是否打破了封装?

时间:2013-04-23 07:52:29

标签: c# events delegates encapsulation

每个人都知道私有事件处理程序可以侦听来自其他类的事件。 (文档中的示例始终只使用私有处理程序。)

事件处理程序只不过是另一个类中的私有方法而不是调用事件。因此,从类外部调用处理程序会破坏封装。或者我错过了什么?

示例代码,为了完整性:

 class Caller    {
    public event EventHandler MyEvent;
    public void RaiseMyEvent()
    {
       MyEvent(this, EventArgs.Empty);
    }
}

class Receiver
{
    private void MyPrivateHandler(Object sender, EventArgs e)
    {
        Console.WriteLine("I'm a private method!");
    }

    public void Subscribe(Caller caller)
    {
        caller.MyEvent += this.MyPrivateHandler;
    }
}

在订阅receiver.Subscribe(caller);之后,我们可以从receiver轻松地在caller.RaiseMyEvent();课程中调用私有方法。{/ 1}。

这是一个纯粹的学术问题,甚至是学术问题。而且,我个人觉得这个功能非常方便,实用,而且非常喜欢它。这真的很酷:我们可以明确地授予其他类调用私有方法的权利。 (我们也可以取消订阅,并为代表和活动制作许多引人入胜的内容。)无论如何,它仍然违反了封装的纯度......或者不是?

P.S。:感谢Matthew Watson指出以下细微差别:订阅事件时,私有处理程序可以由此事件专门调用。如果我们公开(或通过公共包装方法调用),它可以被任何人调用。它在可访问性方面有很大差异。

P.P.S:是的 - 我从未在教科书中看到过这个问题。如果您知道,请留下参考。

3 个答案:

答案 0 :(得分:0)

显然,当你从任何一个类的外部做caller.RaiseMyEvent()时,你不必知道谁将会处理这个事件。

事实上,我认为接收方中的订阅方法不应该是公开的,这种方式会失败。如果Receiver有兴趣处理该事件,它应该自己订阅,不应该让其他人订阅它。通过这种方式,您可以保留订阅状态以及隐藏它的方法。

在Receiver-class中没有直接调用这个私有方法,你不应该假设它。接收器类在任何时候都可以取消订阅。

它摆弄了封装,但我不认为它完全违反了它。它基本上是一个广播系统。

如果某个电视台建议人们外出偷苹果而他们实际上是这样做的,谁应该受到指责呢?电视台还是偷的人?我会想到后者。 事件也是如此,提出事件的人不应该担心这些事件。

答案 1 :(得分:0)

私有事件处理程序是私有的,因为您只想为用户提供将其用作事件的选项。

private void MyPrivateHandler(Object sender, EventArgs e)
{
    Console.WriteLine("I'm a private method!");
}

public void Subscribe(Caller caller)
{
    caller.MyEvent += this.MyPrivateHandler;
}

相同
public void Subscribe(Caller caller)
{
    caller.MyEvent += (sender,e)=>{Console.WriteLine("I'm a anonymous method!"); }
}

答案 2 :(得分:0)

虽然有点偏离主题,但它与您的问题有关,您可能会发现它很有趣:a link to a blog post about customizing the adding and removing of C# event handlers。评论值得一读。一篇相关评论引用了MSDN杂志中的answer ("Event Acessors" by Stephen Toub),以及博客文章问题。