技术开发 频道

深入理解C#的委托和事件:事件的由来

  我们先看看如果把 delegate1 声明为 private会怎样?结果是:这简直就是在搞笑。因为声明委托的目的就是为了把它暴露在类的客户端进行方法的注册,你把它声明为private了,客户端根本就不可见,那它还有什么用?

  再看看把delegate1 声明为 public 会怎样?结果是:在客户端可以对它进行随意的赋值等操作,严重破坏对象的封装性。

  最后,第一个方法注册用"=",是赋值语法,因为要进行实例化,第二个方法注册则用的是"+="。但是,不管是赋值还是注册,都是将方法绑定到委托上,除了调用时先后顺序不同,再没有任何的分别,这样不是让人觉得很别扭么?

  现在我们想想,如果delegate1不是一个委托类型,而是一个string类型,你会怎么做?答案是使用属性对字段进行封装。

  于是,Event出场了,它封装了委托类型的变量,使得:在类的内部,不管你声明它是public还是protected,它总是private的。在类的外部,注册"+="和注销"-="的访问限定符与你在声明事件时使用的访问符相同。

  我们改写GreetingManager类,它变成了这个样子:

public class GreetingManager{
//这一次我们在这里声明一个事件
public event GreetingDelegate MakeGreet;
public void GreetPeople(string name, GreetingDelegate MakeGreeting) {
MakeGreeting(name);
}
}

  很容易注意到:MakeGreet 事件的声明与之前委托变量delegate1的声明唯一的区别是多了一个event关键字。看到这里,在结合上面的讲解,你应该明白到:事件其实没什么不好理解的,声明一个事件不过类似于声明一个进行了封装的委托类型的变量而已。

  为了证明上面的推论,如果我们像下面这样改写Main方法:

static void Main(string[] args) {
GreetingManager gm
= new GreetingManager();
gm.MakeGreet
= EnglishGreeting; // 编译错误1
gm.MakeGreet += ChineseGreeting;
gm.GreetPeople(
"Jimmy Zhang", gm.MakeGreet); //编译错误2
}

  会得到编译错误:事件"Delegate.GreetingManager.MakeGreet"只能出现在 += 或 -= 的左边(从类型"Delegate.GreetingManager"中使用时除外)。

0
相关文章