为什么公共事件不能直接在外部调用?

9

Consider we have a class with event declared:

public class FooBar
{
    public event EventHandler FooBarEvent;
}

虽然这个事件是公开的,但我们不能从外部调用 FooBarEvent.Invoke

通过以下方法修改一个类可以解决这个问题:

public class FooBar
{
    public event EventHandler FooBarEvent;

    public void RaiseFooBarEvent(object sender, EventArgs eventArguments)
    {
        FooBarEvent.Invoke(sender, eventArguments);
    }
}

为什么只能通过添加和移除监听器来限制访问外部公共事件?

+1,好问题,考虑到观察者模式确实有一个公共的notifyObservers方法。 - Heinzi
6个回答

7
定义一个公共事件只是使消费者能够订阅和取消订阅该事件。而引发事件的能力仅限于声明事件的类型层次结构。
允许所有订阅者也能够引发事件将会有点混乱。例如,假设我有一个TextBox类,它有一个Focused事件。如果任何旧的消费者都可以引发事件,那么当TextBox类实际上没有被聚焦时,Focused事件很容易被触发。这将使得在事件期间维护任何类型的不变量几乎不可能。

2
“有点混乱”是本月的轻描淡写之词 :) - Alex

3

我个人认为这是为了恰当地传达整个事件架构背后的设计原则。

事件的目的在于通知监听器给定对象中发生的事件。

对于不属于您的类引发事件有什么意义?


2
这就是事件的作用。如果您想公开调用它,您可能需要使用“委托”而不是“事件”。
事件提供了封装:
1. 防止其他类对其进行任何赋值 2. 防止将其作为参数传递给方法 3. 防止将其分配给任何变量 4. 防止从其他类中调用它(甚至派生类也无法访问它) 5. 等等
“public”可访问性表示可以从任何地方订阅它,而不是从任何地方调用它。

2
您的问题的答案是:
在C#中,事件是一种类向该类的客户端提供通知的方式,当对象发生某些有趣的事情时。因此,不允许从外部调用事件,这是没有意义的。

1
我认为你应该改变对事件的看法。其他类不应该“拥有”事件并触发它。那些通过“订阅”事件来“监听”它并在事件发生时执行某些操作的类需要处理该事件。

0

这就是语言的定义方式 - 事件只能由拥有它的类触发。如果你必须从另一个类中触发它,那么请让拥有它的类定义一个公共方法来触发该事件:

public FireFooBarEvent (object sender, EventArgs args)
{
   if(FooBarEvent != null)
      FooBarEvent(sender, args);
}

并且可以从任何类中调用此方法。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接