C# 有了委托(delegate)为什么还需要事件(event)?

 相信很多很多人对C#的delegate和event很迷惑,为什么有了delegate还需要event?

网上有一个非常好的教学视频,是刘铁猛老师精心制作,讲的非常好,欢迎去看。分享链接:

事件详解_3

视频整个比较长。不想看视频的,也可以看下这个例子。

using System;
using System.Threading;

delegate void dowork(); // 委托申明
class Baby{
    public event dowork CryEvent; // 事件成员(fild like)
    public void Play()
    {
        System.Console.WriteLine("孩子在玩耍...");
        Thread.Sleep(2000);
        System.Console.WriteLine("孩子摔了一跤.导致孩子哭的事件发生...");
        if(CryEvent!=null)
            CryEvent();
        System.Console.WriteLine("孩子不哭了.");
    }
}

class Dad{
    public void MakeBabyNotCry() // 事件处理器
    {
        System.Console.WriteLine("爸爸开始哄孩子.");
        Thread.Sleep(4000);
    }
}

class Program
{
    public static void Main()
    {
        Baby baby = new Baby(); // 事件拥有者
        Dad dad = new Dad();    // 事件响应者
        baby.CryEvent += dad.MakeBabyNotCry; // 订阅
        baby.Play();
        Console.Read(); 
    }
}

 如果你删除了第6行的event关键字,重新运行,我们会发现代码仍然可以正确运行。

那么为什么要加event?  我们有一种既生瑜(delegate)何生亮(event)的感觉。

做个试验,假设保持上面的代码不变,也就是第6行定义中包含event关键字,然后在32行后添加一句:

baby.CryEvent();

我们会发现编译提示出错。编译器会告诉我们event只能出现在"+="或"-="左边。

如果去掉第6行的event关键字,然后同样在32行后添加baby.CryEvent(),编译器不会有任何错误提示,表示CryEvent()这个方法是可以被显示调用的。

这就是两者的区别。有了event关键字,暴露的事件我们只能增加或者减少事件处理器,而仅仅是delegate时,我们可以显示调用这个方法。如果方法可以被显示调用,那么这个方法和普通方法显得没啥区别,就会存在不安全的情况,事件详解_3中称这种不安全的调用为"借刀杀人",这个比喻非常形象。

因为我们event的处理逻辑包含在事件拥有者内部,如果不想把事件的调用权限给别人随意使用,我们就应当用event。

发布了108 篇原创文章 · 获赞 126 · 访问量 15万+

猜你喜欢

转载自blog.csdn.net/qq_16587307/article/details/104321409