C#之 委托(Delegate)与事件(Event)

一、委托

1、什么什么使用委托

        比如A类中有aa方法,B类中有bb方法。首先在A中创建一个B对象,去调用bb方法。然后现在有特殊需求,需要在B中调用A中的aa方法。这样出现了对象之间的相互调用,是不被允许的,这样的需求就需要“委托”来解决。

        委托一般用来处理事件多线程对象之间的逆向调用(传值)。

        这部分代码是:类A的AA方法,以及在类A中创建了B的对象,并调用BB方法

public class ClassA
    {
        ClassB classB=new ClassB();
        public void ATest()
        {
            classB.BB();
        }
        public void AA()
        {
            Console.WriteLine("这是A类中的aa方法");
        }
    }

         这部分代码是:类B的BB方法,以及在类B中创建A对象,调用AA方法。

public class ClassB
    {
        ClassA classA = new ClassA();
        public void BTest()
        {
            classA.AA();
        }
        public void BB()
        {
            Console.WriteLine("这是类B的bb方法");
        }
    }

        在调用部分,分别调用对应的的方法 。会发现在类A中创建B的对象时就会出现报错

  static void Main(string[] args)
        {
            ClassA classA=new ClassA();
            classA.ATest();

            ClassB classB=new ClassB();
            classB.BTest();
        }

 

2、委托的概念 

        通俗的理解:委托的本质就是用来代表一个或多个方法的。委托其实规定的是方法的”原型“,根据原型,定义符合要求的方法,委托变量就可以去代表这些方法。也就意味着,以前是直接调用方法,现在改成使用”委托变量“来调用。

        方法的原型:指的是规定了方法的返回值类型,方法参数类型,参数个数。

        现在我们可以通过创建一个委托,让”委托“与AA方法关联。然后类B使用委托调用类A的AA方法。   

        使用委托来实现B类调用AA方法的代码:

        【1】可以看见我们使用”delegate“关键字来声明委托。这个委托只有方法的原型即返回值类型、参数类型。

        【2】然后编写我们想要实现的具体方法。即想要在B类调用的A类的AA方法。

        【4】我们将得到的“委托变量=具体方法”关联起来。(如果有多个具体方法需要关联的话,从第二个开始要使用+=进行关联。)

        【5】使用委托变量调用具体方法。(将委托变量像方法一样使用。)

  public class ClassA
    {
        ClassB classB=new ClassB();
        public void ATest()
        {
            classB.BB();

            //【4】关联委托(委托变量关联具体方法)
            classB.delegateA = AA;

            //【5】使用委托变量调用方法
            classB.delegateA();
        }
        //【2】编写具体方法
        public void AA()
        {
            Console.WriteLine("这是类A的AA方法");
        }
    }
    //【1】声明委托类型
    public delegate void DelegateA();

        【3】接下来定义委托变量。因为委托变量与具体方法不属于同一个类,如果定义成字段则只能定义成公有字段(不建议)。所以最后定义为属性。 

 public class ClassB
    {
        //ClassA classA = new ClassA();
        //public void BTest()
        //{
        //    classA.AA();
        //}
        public void BB()
        {
            Console.WriteLine("这是类B的BB方法");
        }
        //【3】定义委托变量
        public DelegateA delegateA { get; set; }
    }
static void Main(string[] args)
        {
            ClassA classA=new ClassA();
            classA.ATest();

            //ClassB classB=new ClassB();
            //classB.BTest();

            Console.ReadLine();
        }

        最后执行的结果:

这是类B的BB方法
这是类A的AA方法

3、委托使用基本步骤

        从上面的例子中我们可以看出委托的使用的基本步骤有五步。

        【1】声明委托类型。(定义方法的原型。一般委托都声明在类的外面,委托本身也是一种特殊的数据类型。)

        【2】编写具体方法。(符合方法的原型。方法编写在类内。)

        【3】创建委托变量。(字段、属性都可以,根据情况来做。)

        【4】关联委托。(将一个或多个具体的方法与委托变量进行关联。)

        【5】委托变量调用方法。(由于委托变量与具体方法进行了关联,所以调用时不需要再直接调用方法,直接调用委托变量即可。)

        多路委托:一个委托变量关联了若干方法。当调用委托变量的时候,所关联的方法会按照关联的顺序依次执行。

        断开关联:使用”-=“符号。

二、委托示例

        1、窗体之间的逆向传值

                ①、主窗体同时打开3个子窗体。即主窗体调用子窗体的打开窗体的方法。

                ②、子窗体将信息传递到主窗体。即子窗体调用主窗体的信息展示方法。

                 最终想要到达的效果:

        FrmMain主窗体的代码如下:

  //【1】声明委托变量
    public delegate void ChildDelegateMeathod(string data);

    public partial class FrmMain : Form
    {
        public FrmMain()
        {
            InitializeComponent();
        }
        //【2】编写具体方法
        public void ShowMes(string data)
        {
            this.txt_MainReceiveMes.Text += data+"\r\n";
        }
        private void btn_BuildChild_Click(object sender, EventArgs e)
        {
            for (int i = 1; i < 4; i++)
            {
                FrmChild frmChild = new FrmChild(i);
                frmChild.Show();

                //【4】关联委托变量
                frmChild.ChildDelegate = ShowMes;
            }
        }
    }

        FrmChild子窗体代码如下:

 public partial class FrmChild : Form
    {
        public FrmChild(int num)
        {
            InitializeComponent();

            this.Text += "_" + num;
        }

        //【3】创建委托变量
        public ChildDelegateMeathod ChildDelegate { get; set; }

        private void btn_ChildSendMes_Click(object sender, EventArgs e)
        {
            //【5】使用委托变量
            ChildDelegate(this.txt_ChildSendMes.Text.Trim());
        }
    }

         总结:

        【1】声明委托类型。(一般放在具体方法实现类)

        【2】编写具体方法。(准备逆向调用的方法,和声明在一个类)

        【3】创建委托变量。(在调用类创建)

        【4】关联委托。(在具体方法类,通过对象关联)

        【5】委托变量调用方法。(在调用类使用)

 三、事件(Event)

1、事件的概念:

        事件(Event)是一种用于通知的机制,允许一个类(发布者(pubisher))向另一个类(订阅者(subscriber))发送消息事件基于委托实现,订阅者通过委托订阅发布者的事件,当事件被触发时,所有订阅者的方法都会被调用。

        事件的本质:事件的本质就是对委托的进一步包装。

        发布者(发布器)publisher:是一个包含事件和委托的定义的对象。事件和委托之间的联系也定义在这个对象中。发布者类的对象调用这个事件,并通知其他的对象。

        订阅者(订阅器)subscriber:是一个接受事件并提供事件处理程序的对象。在发布者(publisher)类中的委托调用订阅者(subscriber)类中的方法(事件处理程序)。

2、事件的基本步骤与委托的基本步骤对比 

事件与委托使用基本步骤对比
事件

委托

【1】声明委托类型【1】声明委托类型
【2】声明事件【2】编写具体方法
【3】触发事件【3】创建委托变量
【4】订阅事件【4】关联委托
【5】处理事件【5】委托变量调用方法

        事件的基本步骤

        【1】定义委托类型:声明一个委托类型。(与委托【1】一样)

  //【1】声明委托变量
    public delegate void ChildDelegateMeathod(string data);

        【2】声明事件:在类中声明一个事件,类型为前面的定义的委托类型。(在委托的【3】委托类型前面加上关键字“event”。)

  //【2】声明事件(even关键字)
        public event ChildDelegateMeathod ChildDelegate;

        【3】触发事件:在类的方法中,当某个条件满足时,触发事件。【发布器(pubisher)】(与委托的【5】一样)

 private void btn_ChildSendMes_Click(object sender, EventArgs e)
        {
            //【3】触发事件(发布器)
            ChildDelegate(this.txt_ChildSendMes.Text.Trim());
        }

        【4】订阅事件:在另一个类中,订阅发布者的事件。(与委托的【4】关联委托一样,事件的关联需要“+=”,)

   private void btn_BuildChild_Click(object sender, EventArgs e)
        {
            for (int i = 1; i < 4; i++)
            {
                FrmChild frmChild = new FrmChild(i);
                frmChild.Show();

                //【4】订阅事件(使用+=进行关联)
                frmChild.ChildDelegate += ShowMes;
            }
        }

        【5】处理事件:实现事件处理程序(方法)。【订阅器(subscriber)】(与委托的【2】一样)

 //【2】处理事件(订阅器)
        public void ShowMes(string data)
        {
            this.txt_MainReceiveMes.Text += data+"\r\n";
        }

        最终实现的效果与上面委托实现窗体相互调用传值一样。

3、事件与委托的对比

        【1】事件无法直接在“外面”赋值,比如“对象.事件=null”;会出现编译错误,而委托可以。

        好处:避免用户对事件直接操作,比如Click事件,如果允许Click=null,会把底层代码清除!事件可以起到保护作用,而委托太“开发”。

        【2】、event对象没有invoke()方法。

4、事件与委托的选择

        【1】正常解决问题,使用事件与委托没有区别。所有,一般建议使用委托。

        【2】如果做控件的二次开发,扩展控件的事件,必须使用事件。

       

       

       

       

                

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值