代理和事件

C#编程实战宝典

代理

C#:代理[代表、委托]是对方法的引用,指向的是方法,c#中以类的形式对代理进行了实现,设置相应关键字

代理类型是某个方法的类型或者方法标识

代理的属性:

  • 代理所指向方法的标识
  • 代理能够指向[某个方法的]代理[的引用]
  • 指向某个实际的方法

方法标识:方法的返回类型和方法的参数类型

使用delegate关键词声明一种类型的代理

代理引用的使用

可以使用|该代理类型的引用|指向[调用]|符合[代理所定义的]标识|的实际方法

具体过程就是将标识相同的方法名作为参数[通过]相应的代理传递给类型代理的引用

//声明使用的命名空间
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace collection
{//定义program类
    class program
    {
        //定义MyDelegate代理:定义了一个新的代理相当于创建了System.Delegate类的一个子类,所以不能某个方法[^2]的内部定义代理
        delegate int MyDelegate(int p,int q);
        //定义符合MyDelegate标识类型的方法,
        //static函数
        static int Add(int a, int b)
        {
            return a + b;
        }
        static void Main()
        {adMyDelegate代理引用指向Add方法1
            MyDelegate adMyDelegate =null;
            adMyDelegate = new MyDelegate(Add);
            int r = adMyDelegate(3, 4);
            //adMyDelegate代理引用指向Add方法2
            MyDelegate adMyDelegate =new MyDelegate(Add);
            //调用
            int r=adMyDelegate(2,3);

        }
    }
}

代理作为方法的参数

通过将代理作为参数传递给方法

 delegate int MyDelegate(int p,int q);
static void PerformOperation(int p,int q, MyDelegate Operation)
{
    int a=Operation(int p,int q); 
}

.NET Framework中的代理

在.NET中代理更多表现为引用,所有代理都继承 System.Delegate 类,一个代理其实是|继承System.Delegate 类后|形成了新的|引用类型,使用该类型的实例可以调用|与代理定义|方法标识|吻合的方法.定义了一个新的代理相当于创建了System.Delegate类的一个子类,所以不能某个方法1的内部定义代理

多重代理

  • 一个代理同时指向多个符合方法标识的方法,多重代理调用后,该代理指向的所有方法都被调用
  • 是.NET代理的特点,使程序在设计时更加方便灵活
  • 是.NET代理的特点,使程序在设计时更加方便灵活
  • 本质:是对System.MulticastDelegate类的继承和实现,也是System.Delegate子类
  • 局限:所定义的方法标识的返回值必为void类型2
  • 事件的处理方法就是通过多重代理实现的

使用

 //定义多重代理
        delegate void MyMulticastDelegate(int p, int q);

多重代理引用多于一个方式时,使用+=添加新方法,使用-=移除方法。【程序设计时可以将功能分解,通过代理调用】

static void Main()
{
            MyMulticastDelegate hhh = null;
            hhh = new MyMulticastDelegate(Add);
            //多重代理引用多于一个方式时,使用+=添加新方法
            hhh += new MyMulticastDelegate(Max);  
}
//声明使用的命名空间
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace collection
{//定义program类
    class program
    {
        //定义多重代理
        delegate void MyMulticastDelegate(int p, int q);

        static void Add(int a, int b)
        {
           Console.WriteLine( a + b);
        }
        static void Max(int a, int b)
        {
            Console.WriteLine(a > b ? a : b);
        }
        static void Main()
        {
            //多重代理
            MyMulticastDelegate hhh = null;
            hhh = new MyMulticastDelegate(Add);
            //多重代理引用多于一个方式时,使用+=添加新方法
            hhh += new MyMulticastDelegate(Max);
            //调用
            hhh(3, 4);
            Console.ReadLine();
        }
    }
}

事件

所有程序需要响应处理的动作。事件机制是以消息为基础的,当特定动作产生后会发出相应的消息,关注该事件的应用程序收到事件发出的消息会执行相应程序。

事件的触发类:产生事件的类

事件的接受类:处理事件的类

事件的处理方法:处理事件的方法

C#中的事件处理

通过类的形式实现的,且是C#中的一个基础类,可以使用event关键字定义一个事件,事件的实现和处理的步骤如下:

  1. 所有类的外部为事件定义一个公共访问类型的多重代理

    public delegate void EventDelegate(object sender,EventArgs s);
    
  2. 定义一个可以触发类,在内部使用event关键字与之前声明的代理共同定义一个公共访问类型的事件。在内部设计一个事件产生的逻辑(方法)[当特定的|动作发生或消息到达,会触发事件]。事件的第一个参数是触发类,第二个参数是传给事件处理方法的信息。

    public event EventDelegate MyEvent;
    SomeEventArgs someData=newSomeEventArgs(/*必要的参数信息*/);
    MyEvent(this,someData);
    //一个事件发生后,不需要向事件处理方法传递参数,则定义事件的产生如下
    MyEvent(this,null);
    
  3. 定义一个事件的接受类,在其中定义一个事件的处理方法。这个处理方法必须符合1中代理定义的方法标识,通常情况下,会以“On”作为方法名字的起始字符。在接受类中实例化2中定义的类,并将处理方法与其绑定(即将触发类中的代理指向事件的处理方法)。

//声明使用的命名空间
using System;
using System.Threading;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Event
{ 
    //在所有类的外部为事件定义一个公共访问类型的多重代理,定义事件的代理
public delegate void TimerEvent(object sender,EventArgs s);
class Timer
{
    //在内部使用event关键字与之前声明的代理共同定义一个公共访问类型的事件
    public event TimerEvent Timerd;
    public void Start()
    {
        for (int i = 0; i < 5; i++)
        {
            //事件
            Timerd(this,null);
            Thread.Sleep(1000);
        }
    }
}
class Sample
{ 
    //加静态关键字
    static void Main()
    {
        //实例化2中的定义的类
        Timer clocker = new Timer();
        //将触发类中的代理指向事件的处理方法,执行顺序与添加顺序一致
        clocker.Timerd += new TimerEvent(Onclock);
        clocker.Timerd += new TimerEvent(Onclock2);
        clocker.Start();
        Console.ReadLine();
    }
    //   加静态关键字 定义一个事件的处理方法。这个处理方法**必须符合1中代理定义的方法标识**
    static public void Onclock(object sender, EventArgs s)
    {
        Console.WriteLine("收到时钟事件");
    }
     static public void Onclock2(object sender, EventArgs s)
     {
         Console.WriteLine("Come On");
     }
}
}

利用事件传递数据

  1. 定义一个System.EventArgs类的子类
  2. 在类中封装要传递给方法的数据,可以定义为成员变量或者类的属性
  3. 触发类中实例化该子类,通过事件传递给相应方法
	//声明使用的命名空间
using System;
using System.Threading;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Event
{
    //在所有类的外部为事件定义一个公共访问类型的多重代理
    public delegate void TimerEvent(object sender, ClockEventArgs s);
    class Timer
    {
     //在内部使用event关键字与之前声明的代理共同定义一个公共访问类型的事件
        public event TimerEvent Timerd;
        public void Start()
        {
            for (int i = 0; i < 5; i++)
            {
                //事件
                //实例化子类 new ClockEventArgs(i+1)
                Timerd(this, new ClockEventArgs(i+1));
                Thread.Sleep(1000);
            }
        }
    }
    //定义传递数据的子类
    public class ClockEventArgs : EventArgs
    {
        private int TimerCount;
        public ClockEventArgs(int TimerCount)
        {
            this.TimerCount = TimerCount;
        }
     public int Count
        {
            get 
            {
                return TimerCount;
            }
        }
    }
    class Sample
    {
        //加静态关键字
        static void Main()
        {
            //实例化2中的定义的类
            Timer clocker = new Timer();
            //将触发类中的代理指向事件的处理方法
            clocker.Timerd += new TimerEvent(Onclock);
            clocker.Start();
            Console.ReadLine();
        }
        //   加静态关键字 定义一个事件的处理方法。这个处理方法**必须符合1中代理定义的方法标识**
        static public void Onclock(object sender, ClockEventArgs s)
        {
            Console.WriteLine("第{0}次收到时钟事件",s.Count);
        }
    }
}

  1. C#把Main()看作一个方法 ↩︎

  2. 多重代理可能指向多个方法,若每个方法都有自己的返回值,那么在执行代理后会返回多个值,这与一个代理只能有一个返回值冲突。 ↩︎

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值