1、委托
通过定义委托和事件可以方便方法重用,并提高程序的编写效率。基于委托,开发事件驱动程序变得非常简单,C# 中的委托类似于 C 或 C++ 中函数的指针。委托是存有对某个方法的引用的一种引用类型变量。引用可在运行时被改变。委托是一种引用类型,虽然在定义委托时与方法有些相似,但不能将其称为方法,可以把其看成一种数据类型,可以定义变量,但是定义的是一种特殊变量。委托相当于把方法当做变量来使用,并且委托定义的变量能接受的数值只能是一个方法(函数),也以把委托理解成方法的指针。
一共可分为三步:定义声明委托、实例化委托以及调用委托。
委托分为命名方法委托、多播委托、匿名委托。
1、命名方法委托
:实例化委托时同时传递方法,然后调用委托执行时传递参数。
/*命名方法委托:
定义声明委托:修饰符 delegate 返回值类型 委托名 ( 参数列表 );*/
public delegate void MyDelegate();
/*实例化:委托名 委托对象名 = new 委托名 ( 方法名 );
调用:委托对象名 ( 参数列表 );*/
MyDelegate myDelegate = new MyDelegate(Test.SayHello);//静态的
MyDelegate myDelegate = new MyDelegate(new Test().SayHello);//非静态的
myDelegate(); //调用
2、多播委托
指在一个委托中注册多个方法,在注册方法时可在委托中使用加号运算符或者减号运算符来实现添加或撤销方法。
//实例化委托
OrderDelegate orderDelegate = new OrderDelegate(Order.BuyFood);
//向委托中注册方法
orderDelegate += Order.BuyCake;
orderDelegate += Order.BuyFlower;
//调用委托
orderDelegate();
orderDelegate -= Order.BuyFlower;//撤销购买鲜花操作
(1)主窗体传值到子窗体
下面我们通过一个例子具体讲解一下委托如何在不同间窗体传参的例子首先创建4个窗体,首先来看主窗体多播到3个从窗体的例子
//【1】声明委托
public delegate void ShowCounter(string counter);
public partial class FrmMain : Form
{
//根据委托创建委托对象
public ShowCounter msgSender;
public FrmMain()
{
InitializeComponent();
FrmOther01 objFrm01 = new FrmOther01();
FrmOther02 objFrm02 = new FrmOther02();
FrmOther03 objFrm03 = new FrmOther03();
//将委托变量和具体方法关联
this.msgSender += objFrm01.Receiver;
this.msgSender += objFrm02.Receiver;
this.msgSender += objFrm03.Receiver;
objFrm01.Show();
objFrm02.Show();
objFrm03.Show();
}
private int counter = 0;
//点击按钮,三个子窗体上的值会加一
private void btnClick_Click(object sender, EventArgs e)
{
counter++;
//同时对三个从窗体发消息
this.msgSender.Invoke(counter.ToString());
}
//复位按钮,子窗体的label置零
private void btnReset_Click(object sender, EventArgs e)
{
counter = 0;
this.msgSender("0");
}
}
三个一样的子窗体里面放下面同一个接收值的方法
public void Receiver(string counter)
{
this.lblCount.Text = counter;
}
(2)子窗体传值到主窗体
首先主窗体里面的内容
//【1】声明委托
public delegate void ShowCounter(string counter);
public partial class FrmMain : Form
{
public FrmMain()
{
InitializeComponent();
FrmOther objFrm = new FrmOther();
//将从窗体的委托变量和主窗体的对应方法关联
objFrm.msgSender = this.Receiver;
objFrm.Show();
}
/// <summary>
/// 接收委托传递的信息
/// </summary>
/// <param name="counter"></param>
private void Receiver(string counter)
{
this.lblCount.Text = counter;
}
子窗体里面的内容
//根据委托创建委托对象
public ShowCounter msgSender;
//计数
private int counter = 0;
private void btnClick_Click(object sender, EventArgs e)
{
counter++;
if (msgSender != null)
{
msgSender(counter.ToString());
}
}
3、匿名委托
是指使用匿名方法注册在委托上,实际上是在委托中通过定义代码块来实现委托的作用。
public delegate void AreaDelegate(double length, double width);//定义委托
static void Main(string[] args)
{
Console.WriteLine("请输入长方形的长:");
double length = double.Parse(Console.ReadLine());
Console.WriteLine("请输入长方形的宽:");
double width = double.Parse(Console.ReadLine());
AreaDelegate areaDelegate = delegate //定义匿名委托
{
Console.WriteLine("长方形的面积为:" + length * width);
};
areaDelegate(length, width);
}
2、事件
事件基本上说是一个用户操作,如按键、点击、鼠标移动等等,或者是一些出现,如系统生成的通知等。事件是一种引用类型,实际上也是一种特殊的委托。每一个事件的发生都会产生发送方和接收方,发送方是指引发事件的对象,接收方则是指获取、处理事件。事件要与委托一起使用。
事件:是一种引用类型的,特殊的委托 public event SayDelegate SayEvent;
发送方:引发事件的对象
接收方:获取处理对象
定义:访问修饰符 event 委托名 事件名 ;
public void SayHello()
{
Console.WriteLine("Hello Event!");
}
//创建触发事件的方法
public void SayEventTrigger()
{
//触发事件,必须与事件是同名方法
SayEvent();
}
//创建Program类的实例
Program program = new Program();
//实例化事件,使用委托指向处理方法
program.SayEvent = new SayDelegate(program.SayHello);
//调用触发事件的方法
program.SayEventTrigger();
MyEvent myEvent = new MyEvent();
//实例化事件,使用委托指向处理方法
myEvent.BuyEvent += new MyEvent.BuyDelegate(MyEvent.BuyFood);
在定义事件后需要定义事件所使用的方法,并通过事件来调用委托。
下面Demo中以基本方法讲解了委托和事件,如果能完全理解,应该能对委托和事件进行简单的使用。
using System;
using System.Threading;
namespace Delegate
{
class Program
{
//定义声明委托
public delegate void MyDelegate(); // 1、命名方法委托
public delegate void BookDelegate(Book[] books);
public delegate void KillerCompany(); // 2、多播委托
public delegate void KillerPeo(string name, int age); // 3、匿名委托
//定义事件,通过事件的方法调用委托,so在事件前需要定义委托
public static event KillerCompany KillEvent; // 4、事件
//定义委托中调用的方法
public void KillMethod()
{
Console.WriteLine("敌人已被干掉!");
}
//触发事件的方法
public static void KillEventTrigger()
{
//触发事件,必须与事件是同名方法
KillEvent();
}
static void Main(string[] args)
{
// 1、命名方法委托,实例化委托
MyDelegate myDelegate = new MyDelegate(Test.SayHello);
myDelegate(); //调用委托
//BookDelegate bookDelegate = new BookDelegate(Book.BookSort);
//Book[] book = new Book[3];
//book[0] = new Book("高等数学", 44);
//book[1] = new Book("英语", 23);
//book[2] = new Book("操作系统", 88);
//bookDelegate(book);
//foreach (Book bk in book)
//{
// Console.WriteLine(bk);
//}
// 2、多播委托
KillerCompany killer = new KillerCompany(new Kill().BeKilled); //通过类的实例调用方法new 类名().方法名
killer += Kill.BeKillBoss; //向委托中注册方法
killer += Kill.CancelKill; //向委托中注册方法
killer(); //调用委托
// 3、匿名方法
Console.Write("选择被暗杀的人:");
string name = Convert.ToString(Console.ReadLine());
Console.Write("选择暗杀人的年龄:");
int age = Convert.ToInt32(Console.ReadLine());
//定义匿名委托
KillerPeo killerPeo = delegate
{
Console.WriteLine("{0}年龄{1}已被匿名悬赏", name, age);
};
killerPeo(name, age); //调用匿名委托
Console.WriteLine("{0}年龄{1}正在被追杀.........", name, age);
Thread.Sleep(1000);
Console.WriteLine("{0}年龄{1}已被暗杀", name, age);
// 4、事件
Program program = new Program(); // 实例化Program类创建的实例
//program.KillEvent = new KillerCompany(program.KillMethod); // 实例化事件,使委托指向处理方法
//program.KillEventTrigger(); //调用触发时间的方法
//多播委托
//创建MyEvent类的实例
MyEvent myEvent = new MyEvent();
//实例化事件,使用委托指向处理方法
myEvent.BuyEvent += new MyEvent.BuyDelegate(MyEvent.BuyFood);
myEvent.BuyEvent += new MyEvent.BuyDelegate(MyEvent.BuyCake);
myEvent.BuyEvent += new MyEvent.BuyDelegate(MyEvent.BuyFlower);
//调用触发事件的方法
myEvent.InvokeEvent();
}
}
class Test
{
public static void SayHello()
{
Console.WriteLine("被委托中的方法");
}
}
class Kill
{
public void BeKilled()
{
Console.WriteLine("杂鱼已被杀手杀死");
}
public static void BeKillBoss()
{
Console.WriteLine("大Boss已被杀掉!");
}
public static void CancelKill()
{
Console.WriteLine("停止暗杀!");
}
}
class MyEvent
{
//定义委托
public delegate void BuyDelegate();
//定义事件
public event BuyDelegate BuyEvent;
//定义委托中使用的方法
public static void BuyFood()
{
Console.WriteLine("购买快餐!");
}
public static void BuyCake()
{
Console.WriteLine("购买蛋糕!");
}
public static void BuyFlower()
{
Console.WriteLine("购买鲜花!");
}
//创建触发事件的方法
public void InvokeEvent()
{
//触发事件,必须和事件是同名方法
BuyEvent();
}
}
}
委托经典例子1:利用委托编写投票计数器