C#中的委托与事件实例详解

本文详细介绍了C#中的委托、事件及其与Observer设计模式的关系。通过实例展示了如何将方法作为参数传递,如何使用委托绑定和解除绑定方法,以及事件的封装。还探讨了Observer模式的基本概念,解释了被监视对象和监视者之间的交互,并提供了热水器烧水场景的模拟示例。最后,提到了委托类型的命名规范。
摘要由CSDN通过智能技术生成

本人博客中的代码都是本地测试通过,意思和注释理解了就行

本篇文章引用张子阳博客基本思路,然后根据自己的经验,进行了部分的简化和修改,委托就在于理解,多看几遍就理解了。

委托:本质上讲委托是一种可以将方法作为参数的方法,可以包含参数也可以不包含参数

事件:从本质上将也是委托,只不过是进行了封装的委托。事件可以绑定方法,绑定之后就会监视这些方法,当达到事件的触发条件,就会执行事件绑定的方法

如果比较绕口的话请读10遍就理解了

分五个步骤:

1.委托将方法作为参数传递:将方法作为参数进行传递,当某一个方法作为参数传递时,一起传递的还有这个方法对应的参数

举例:

class Program
{
    //定义委托
    public delegate void GreetDelegate();
    private static void EnglishGreeting(string name)
    {
        Console.WriteLine("Morning,"+name);
    }
    private static void ChaineseGreeting(string name)
    {
        Console.WriteLine("早上好,"+name);
    }
    //定义一个接收GreetingDelegate类型的方法
    private static void GreetPeople(string name,GreetDelegate MakeGreeting)
    {
        MakeGreeting(name);
    }
    
    static void Main(string[] args)
    {
        //将方法作为参数传递,并同时传递方法执行需要的参数
        GreetPeople("cdc",EnglishGreeting);
        GreetPeople("奇点码农",ChineseGreeting);
        Console.ReadKey();
    }
}

2.委托可以通过+=绑定方法,也可以通过-=消除委托对方法的绑定

//将方法绑定到委托
class Program
{
    public delegate void GreetDelegateHandler(string name);
    public static void EnglishGreeting(string name)
    {
        Console.WriteLine("Morning,"+name);
    }
    private static void ChineseGreeting(string name)
    {
        Console.WriteLine("早上好,"+name);
    }

    static void Main(string[] args)
    {
        GreetDelegateHandler delegate1;
        //将方法绑定到委托
        delegate1=EnglishGreeting;
        delegate1+=ChineseGreeting;
        delegate1("cdc");
    }
}

3.事件出马:事件类似于进行了封装的委托类型的变量,事件的参数与与之对应的委托的参数一致

class Program
{
    public delegate void GreetDelegateHandler(string name);
    
    private static void EnglishGreeting(string name)
    {
        Console.WriteLine("Morning,"+name);
    }

    private static void ChineseGreeting(string name)
    {
        Console.WriteLine("早上好,"+name);
    }
    
    public class GreetManager
    {
        public event GreetDelegateHandler GreetDelegate;
        
        public void GreetPeople(string name)
        {
            //事件的参数与与之对应的委托的参数一致
            GreetDelegate(name);
        }
    }

    static void Main(string[] args)
    {
        GreetManager gm=new GreetManager();    
        gm.GreetDelegate+=EnglishGreeting;
        gm.GreetDelegate+=ChineseGreeting;
        gm.GreetPeople("cdc");
        Console.ReadKey();
    }
}

4.Observer设计模式

(1)Subject:被监视对象,包含着其他对象感兴趣的内容

(2)Observer:监视者,监视Subject,当Subject中的某事件发生的时候,会告知Observer,而Observer则会采取相应行动

//注:Observer设计模式是为了定义对象的一种一对多的依赖关系,以便当一个对象的状态改变时,其他依赖于它的对象会自动告知并更新执行

//被监视对象
public class Heater
{
    private int temperature;
    //声明委托
    public delegate void BoilHandler(int param);
    //使用委托声明事件
    public event BoilHandler BoilEvent;
    //烧水
    public void BoilWater()
    {
        for(int i=0;i<=100;i++)
        {
            Thread.Sleep(500);
            temperature=i;
            if(temperature>95)
            {
                if(BoilEvent!=null)
                {
                    BoilEvent(temperature);
                }
            }
        }
    }
}
//监视者:警报器
public class Alarm
{
    public void MakeAlert(int param)
    {
        Console.WriteLine("Alarm:滴滴。。。,水已经{0}度了",param);
    }
}
//监视者:显示器
public class Display
{
    public static void ShowMsg(int param)
    {
        Console.WriteLine("Display:水快烧开了,当前温度:{0}度",param);
    }
}

class Program
{
    static void Main(string[] args)
    {
        Heater heater=new Heater();
        Alarm alarm=new Alarm();
        //注册方法
        heater.BoilEvent+=alarm.MakeAlert;
        //给匿名对象注册方法
        heater.BoilEvent+=(new Alarm()).MakeAlert;
        //注册静态方法
        heater.BoilEvent+=Display.ShowMsg;
        //调用被监视对象执行方法,每当被监视对象的方法中触发一次事件,就会将该事件绑定的所有监视者方法执行一遍
        heater.BoilWater();
        Console.ReadKey();
    }
}

5.委托类型的代码规范

(1)委托类型的名称都应该以Event Handler结束

(2)委托的原型定义有一个void返回值,并接收两个输入参数:一个Object类型,一个EventArgs类型(或者继承自EventArgs)

(3)事件的命名为委托去掉EventHandler之后的剩余部分

(4)继承自EventArgs的类型应该以EventArgs结尾

//热水器
public class Heater
{
    private int temperature;
    //添加型号作为演示
    public string type="RealFire001";
    //添加产地作为演示
    public string area="China Xian";
    //声明委托
    public delegate void BoiledEventHandler(object sender,BoiledEventArgs e);
    //声明事件
    public event BoiledEventHandler Boiled;
    //定义BoiledEventArgs类,传递给Observer所感兴趣的信息
    public class BoiledEventArgs:EventArgs
    {
        public readonly int temperature;
        public BoiledEventArgs(int temperature)
        {
            this.temperature=temperature;
        }
    }
    
    //可以供继承自Heater类的重写,以便继承类拒绝其他对象对它的监视
    protected virtual void OnBoiled(BoiledEventArgs e)
    {
        //如果该事件已经注册方法,则触发对应的方法
        if(Boiled!=null)
        {
            //调用所有注册对象的方法
            Boiled(this,e);
        }
    }
    //烧水
    public void BoilWater()
    {
        for(int i=90;i<=100;i++)
        {
            Thread.Sleep(500);
            temperature=i;
            if(temperature>95)
            {
                //建立Boiled的EventArgs对象
                BoiledEventArgs e=new BoiledEventArgs(temperature);
                OnBoiled(e);
            }
        }   
    }
}

//监视器:警报器
public class Alarm
{
    public void MakeAlert(object sender,Heater.BoiledEventArgs e)
    {
        Heater heater=(Heater)sender;
        //访问sender中的公共字段
        Console.WriteLine("Alarm:{0}-{1}:",heater.area,heater.type);
        Console.WriteLine("Alarm:滴滴,水温{0}度!",e.temperature);
        Console.WriteLine();
    }
}
//监视器:显示器
public class Display
{
    public static void ShowMsg(object sender,Heater.BoiledEventArgs e)
    {
        Heater heater=(Heater)sender;
        Console.WriteLine("Display:{0}-{1}:",heater.area,heater.type);
        Console.WriteLine("Display:显示水温{0}度。",e.temperature);
        Console.WriteLine();
    }
}

class Program
{
    static void Main(string[] args)
    {
        Heater heater=new Heater();
        Alarm alarm=new Alarm();
        //注册方法
        heater.Boiled+=alarm.MakeAlert;
        //给匿名对象注册方法
        heater.Boiled+=(new Alarm()).MakeAlert;
        //注册方法
        heater.Boiled+=new Heater.BoiledEventHandler(alarm.MakeAlert);
        //注册静态方法
        heater.Boiled+=Display.ShowMsg;
        //调用烧水的方法,会自动调用注册的方法
        heater.BoilWater();
        Console.ReadKey();
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值