三分之十的菜鸟C#学习小记(十三)委托和事件

委托(Delegate)

C# 中的委托(Delegate)类似于 C 或 C++ 中函数的指针。

委托(Delegate)特别用于实现事件和回调方法。所有的委托(Delegate)都派生自 System.Delegate 类(委托是一个类!!)

委托的定义:

public delegate int NumberChanger(int n);

委托的实例化:

NumberChanger nc1 = new NumberChanger(AddNum);	  //后面的AddNum是方法名
NumberChanger nc2 = new NumberChanger(MultNum);

注意:委托的定义和方法名一样,比如AddNum的定义是public static int AddNum(int p),注意返回值和参数类型

委托的调用:

int res = nc1(25);

和原方法的调用一样

委托的多播(Multicasting of a Delegate)

委托对象可使用 “+” 运算符进行合并。(注意:!相同类型!才能合并)
“-” 运算符可用于从合并的委托中移除组件委托。

委托的 多播(multicasting):意思就是利用委托的合并性质,把方法A、B、C…的调用组成一个调用列表。

例如:

// 创建委托实例
 NumberChanger nc;
 NumberChanger nc1 = new NumberChanger(AddNum);
 NumberChanger nc2 = new NumberChanger(MultNum);
 nc = nc1;
 nc += nc2;
 
// 调用多播
 nc(5);

其实上面nc(5)相当于MultNum(AddNum(5))
以后我每次调用nc就可以调用一坨。比较方便

事件(Event)

事件(Event) 基本上说是一个用户操作,如按键、点击、鼠标移动等等;或者是一些提示信息,如系统生成的通知。应用程序需要在事件发生时响应事件。例如,中断。
C# 中使用事件机制实现线程间的通信。
在这里插入图片描述
1. 声明事件(Event)
在类的内部声明事件,首先必须声明该事件的委托类型。例如:
public delegate void BoilerLogHandler(string status);

然后,声明事件本身,使用 event 关键字:
public event BoilerLogHandler BoilerEventLog;

上面的代码定义了一个名为 BoilerLogHandler 的委托和一个名为 BoilerEventLog 的事件,该事件在生成的时候会调用委托。

2. 事件实例

using System;

namespace DelegateAndEvent
{
    //定义一个事件类
    public class MyEvent
    {
        //定义一个委托
        public delegate void MyDelegate();
        //定义一个事件
        public event MyDelegate MyDelegateEvent;
        //定义一个触发事件的函数
        public void OnMyDelegateEvent()
        {
            //判断事件是否非空
            if (MyDelegateEvent != null)
            {
                //执行事件
                MyDelegateEvent();
            }
            //MyDelegateEvent?.Invoke(); //简化的判断和执行
        }
    }
    class Program
    {

        //输出一串字符
        public static void putOutChar()
        {
            Console.WriteLine("I was fired");
        }
        //输出第二串字符
        public static void putOutChar2()
        {
            Console.WriteLine("I was fired22222");
        }

        static void Main(string[] args)
        {
            //实例化MyEvent2类
            MyEvent myEvent = new MyEvent();
            //注册一个事件
            myEvent.MyDelegateEvent += new MyEvent.MyDelegate(putOutChar);
            myEvent.MyDelegateEvent += new MyEvent.MyDelegate(putOutChar2);
            //执行触发事件的函数
            Console.WriteLine("执行绑定了两个事件后的函数");
            myEvent.OnMyDelegateEvent();
            //解绑一个事件
            myEvent.MyDelegateEvent -= new MyEvent.MyDelegate(putOutChar);
            //再次执行触发事件的函数
            Console.WriteLine("执行解绑了一个事件后的函数");
            myEvent.OnMyDelegateEvent();
            Console.ReadKey();
        }
    }
}

注意点:

  1. 委托有啥用?
    用来表明事件的调用类型。比如:Exploded("sorry,this car is dead"),那么其委托就是public delegate void CarEngineHandler(string msg);

委托多播的实例代码:
委托多播

using System;

delegate int NumberChanger(int n);
namespace DelegateAppl
{
   class TestDelegate
   {
      static int num = 10;
      public static int AddNum(int p)
      {
         num += p;
         return num;
      }

      public static int MultNum(int q)
      {
         num *= q;
         return num;
      }
      public static int getNum()
      {
         return num;
      }

      static void Main(string[] args)
      {
         // 创建委托实例
         NumberChanger nc;
         NumberChanger nc1 = new NumberChanger(AddNum);
         NumberChanger nc2 = new NumberChanger(MultNum);
         nc = nc1;
         nc += nc2;
         // 调用多播
         nc(5);
         Console.WriteLine("Value of Num: {0}", getNum());
         Console.ReadKey();
      }
   }
}

事件的实例代码:
C#事件代码

using System;
namespace CarEvent
{
    public class Car
    {
        // 申明委托
        public delegate void CarEngineHandler(string msg);
        // 创建委托实例Exploded和AboutToBlow事件
        public event CarEngineHandler Exploded;
        public event CarEngineHandler AboutToBlow;
        //设置属性
        public int CurrentSpeed { get; set; }
        public int MaxSpeed { get; set; }
        public string PetName { get; set; }
        public bool CarIsDead;//用于判断是否超速
        
        public Car()//构造函数
        {
            MaxSpeed = 100;
        }
        public Car(string name, int maxSp, int currSp)//构造函数重载

        {
            CurrentSpeed = currSp;
            MaxSpeed = maxSp;
            PetName = name;
        }

        public void Accelerate(int delta)//用于触发Exploded和AboutToBlow事件
        {            
            CurrentSpeed += delta;//"踩油门"加速
            if (CurrentSpeed >= MaxSpeed)//判断时速  
                CarIsDead = true;    
            else
                CarIsDead = false;
            if (CarIsDead)// 如果Car超速了,触发Exploded事件
            {
                if (Exploded != null)//判断是否被委托联系起来
                {
                    Exploded("sorry,this car is dead");//调用CarDead事件
                }
            }
            else
            {    //如果没有超速,则提示快要超速并显示实时车速
                if ((MaxSpeed - CurrentSpeed) > 0 && (MaxSpeed - CurrentSpeed) <= 10 && AboutToBlow != null)//判断是否被委托联系起来且速度是否接近临界值
                {
                    AboutToBlow("careful buddy ! gonna blow !");//调用NearDead事件 
                    Console.WriteLine("CurrentSpeed={0}",CurrentSpeed);//显示实时车速
                }
            }
        }
    }

    //订阅类书写举例
    public class Answer
    {
        public void CarDead(string msg)//汽车已爆缸事件
        {
            Console.WriteLine("sorry,this car is dead");
        }

        public void NearDead(string msg)//汽车快要爆缸事件
        {
            Console.WriteLine("careful buddy ! gonna blow !");
        }
    }

    //主函数书写
    public class test
    { 
        static void Main(string[] args)
        { 
            Car c = new Car("奔驰",100,93);//创建实例并初始化,初始速度为93
            Answer an = new Answer();
            c.Exploded += new Car.CarEngineHandler(an.CarDead);//Exploded"绑定"CarDead
            c.AboutToBlow += new Car.CarEngineHandler(an.NearDead);//AboutToBlow"绑定"NearDead
            c.Accelerate(6);//第一次加速,时速小于100,引发的事件为"快要爆缸"并显示实时车速为99
            Console.ReadLine();//等待回车键已启动第二次加速
            c.Accelerate(2);//第二次加速,时速超过100,引发的事件为"已爆缸",不显示车速
            Console.ReadKey();
        }
    }
}

结果为:

"careful buddy ! gonna blow !"
"CurrentSpeed=99"
(空行)(一定要记得敲一下回车键,不然不会显示下面字符串)
"sorry,this car is dead"

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值