C#中的委托(Delegate)和事件 (Event)详解与使用范例

一.委托(Delegate)

1.委托(Delegate)简介

最近天气晴雨不定,你因为害怕打游戏时忘记在下雨时收衣服或者在天晴时把衣服挂出去,于是你委托好友小明在天气发生变化时打电话通知你,这就是一种委托.

下面是这种委托的实例代码

//定义一个继承自Delegate类的子类小明,这之后小明就具备被委托的属性
//public为公开,void为返回类型,XiaoMing为类名,(string msg)为传递给注册的方法的参数
public delegate void XiaoMing(string msg);
class Me
{
    //public代表聆听小明的信号是公开的方法,以便小明访问
    //static是为了固定ListenToXiaoMing在内存中的入口以便小明能够找到该方法的入口
    public static void ListenToXiaoMing(string msg)
    {
        if(msg == "Rain")
        {
            Console.WriteLine("下雨了!小明收衣服了!");
        }
        else if(msg == "Sunny")
        {
            Console.WriteLine("天晴了!小明晒衣服了!");

        }
    }
}


class Program
{
    static void Main(string[] args)
    {
        //初始化一个XiaoMing类的实体xiaoMing
        //将我的ListenToXiaoMing注册在xiaoMing上
        //相当于我与小明约定下雨后小明就通知我做出行动(调用ListenToXiaoMing)
        XiaoMing xiaoMing = Me.ListenToXiaoMing;



        //假设今天下雨
        string weather = "Rain";
        
        //小明观察天气
        //将weather参数传递给Me.ListenToXiaoMing方法
        xiaoMing.Invoke(weather);

    }
}

以上代码的输出为

下雨了!小明收衣服了!

值得一提的是,如下代码为创建一个继承自Delegate类的名为XiaoMing的子类,该子类实例只接收void类型方法并且参数类型为(string)的注册,如:void foo(string test){}

public delegate void XiaoMing(string msg);

2.组播委托

你感觉小明的提醒十分靠谱,于是将这件事告诉了同样喜欢玩游戏的小刚,于是小刚也决定请小明在天气发生变化时提醒他,这就是组播委托.

当执行delegate.Invoke()时,将会执行所有注册在该delegate上的方法

以下是这种委托的代码:

public delegate void XiaoMing(string msg);


//你的类
class Me
{
    //public代表聆听小明的信号是公开的方法,以便小明访问
    //static是为了固定ListenToXiaoMing在内存中的入口以便小明能够找到该方法的入口
    public static void MeListenToXiaoMing(string msg)
    {
        if(msg == "Rain")
        {
            Console.WriteLine("下雨了!小明收衣服了!");
        }
        else if(msg == "Sunny")
        {
            Console.WriteLine("天晴了!小明晒衣服了!");

        }
    }
}


//小刚的类
class XiaoGang
{
    
    public static void XiaoGangListenToXiaoMing(string msg)
    {
        if (msg == "Rain")
        {
            Console.WriteLine("下雨了!小刚收衣服了!");
        }
        else if (msg == "Sunny")
        {
            Console.WriteLine("天晴了!小刚晒衣服了!");

        }
    }
}

class Program
{
    static void Main(string[] args)
    {
        //初始化一个XiaoMing类的实体xiaoMing
        //将我的ListenToXiaoMing注册在xiaoMing上
        //相当于我与小明约定下雨后小明就通知我做出行动(调用ListenToXiaoMing)
        XiaoMing xiaoMing = Me.MeListenToXiaoMing;

        //小刚也将自己的XiaoGangListenToXiaoMing注册到被委托人小明身上
        xiaoMing += XiaoGang.XiaoGangListenToXiaoMing;



        //假设今天下雨
        string weather = "Rain";

        //小明观察天气
        //将weather参数传递给Me.ListenToXiaoMing方法
        //和XiaoGang.XiaoGangListenToXiaoMing方法
        xiaoMing.Invoke(weather);

    }
}

运行结果为

下雨了!小明收衣服了!
下雨了!小刚收衣服了!

注意事项:

在使用Delegate子类时,需要用如下代码进行初始化

//方法一 
XiaoMing xiaoMing; 
xiaoMing=Me.MeListenToXiaoMing;
//方法二
XiaoMing xiaoMing=Me.MeListenToXiaoMing;

//错误示范
XiaoMing xiaoMing;
xiaoMing+=Me.MeListenToXiaoMing;

3.事件(event)与委托配合

当你和小刚为小明的靠谱感叹时,天气变化无常的季节结束了,你们不再需要小明通知你们收放衣服了.

你们又有了新的需求----你喜欢在阴天运动,但是小刚喜欢在晴天运动,于是你们请小明吃了一顿饭,请求他在阴天通知你运动,在晴天通知小刚运动,这样的话你们就不用在收到阴天和晴天的消息时花费精力自行判断要不要运动了.

以下是这次委托的代码,小明将会根据不同情况通知不同的人

//好朋友小明类
class XiaoMing
{
    //定义一个继承自Delegate类的委托子类,就像是呼叫是人们通讯的方法
    //而小明的呼叫是继承自呼叫的子类
    public delegate void CallTFirends();


    //以下是事件,是一个用于触发不同委托的字段
    //这是委托你去运动的字段
    public  event CallTFirends CallMe;

    //这是委托小刚去运动的字段
    public event CallTFirends CallXiaoGang;
    
    
    
    //好心的小明用下面的方法时时关注天气
    public void LookForWeather(string weather)
    {
        if (weather == "Cloudy")
        {
            //与下方的CallXiaoMing?.Invoke();具有相同功能
            //即防止小明小刚还没通知喜欢哪种运动天气时进行提醒
            //防止在event还没注册时就被调用
            if (CallMe != null)
            {
                CallMe.Invoke();
            }
        }
        else if(weather == "Sunny")
        {
            CallXiaoGang?.Invoke();
        }

    }

}


//你的类
class Me
{
    //你收到小明的信号会调用以下方法去运动
    public static void MeListenToXiaoMing()
    {
       Console.WriteLine("小明运动啦!");
    }
}


//小刚的类
class XiaoGang
{

    //小刚收到小明的信号会调用以下方法去运动
    public static void XiaoGangListenToXiaoMing()
    {
        Console.WriteLine("小刚运动啦!");
    }
}

class Program
{
    static void Main(string[] args)
    {

        XiaoMing xiaoMing = new XiaoMing();
        //天气为阴天
        string weather = "Cloudy";

        //你注册了callMe的事件,意味通知小明在阴天通知你去运动
        xiaoMing.CallMe += Me.MeListenToXiaoMing;
        //小刚注册了XiaoGang.XiaoGangListenToXiaoMing事件,意味通知小明在晴天通知小刚去运动
        xiaoMing.CallXiaoGang += XiaoGang.XiaoGangListenToXiaoMing;

        //小明观察天气并且提醒对应的人去运动
        xiaoMing.LookForWeather(weather);
       

    }
}

运行结果为

小明运动啦!

细节提示:

1.事件只能在声明它的类中被触发(即例子中在XiaoMing类种才能触发),在声明它的类之外只能订阅和取消订阅。

2.事件的一大作用是方便由声明Delegate的类集中管理而不用每个类自行判断传输过来的信号,如你和小刚不用自行判断传来的天气适合做什么只需要在收到消息后去运动即可.

  • 21
    点赞
  • 57
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值