基础概述
(1)委托是用来封装方法的类型,遵循观察者设计模式,类似于C和C++的函数指针。委托是面向对象的、且类型安全可靠。
(2)委托类型派生自.NET Framework中的System.Delegate类,委托类型是封装的,所以不能被派生。
(3)对委托实例化后,委托会对其进行的方法调用与参数传递到该方法,并且委托会将方法的的返回值返回到调用方,这被称为调用委托。
(4)委托的定义:委托是一种数据类型,和类是同级的,委托和类都 是方法的载体。
(5)委托是方法的抽象,它存储的就是一系列具有相同签名和返回回类型的方法的地址。
(6)调用委托时,委托的所有方法都将被执行。
(7)委托是C#中的特色,通常将委托分为命名方法委托、多播委托、匿名委托。
语法使用
(1)委托的声明:delegate 返回类型 委托名 (参数);
(2)委托的实例化:委托名 实例化名 = new 委托名 (函数名);
(3)匿名方法实例化:委托类型 实例化名 = delegate ( 函数参数 ) { 函数体 };
(4)调用委托:委托名(参数 );
//声明委托
public delegate int MyDelegate(int num);
public static void Method1(int num)
{
Console.WriteLine("Method1被调用了,传入的参数是:" + num);
}
static void Main(string[] args)
{
//1、实例化委托,使用new关键字
MyDelegate del01=new MyDelegate(Method1);
//2、使用匿名方法
MyDelegate del02=delegate(int x, int y)
{
return x + y;
}
//3、使用lambda表达式
MyDelegate del03=(int x, int y) => { return x + y };
//4、调用
del01(25);
}
委托的多播(Multicasting of a Delegate)
(1)多个相同类型的委托对象可以使用“+”进行合并,或使用“-”移除合并的委托
(2)委托可以注册多个函数,这样的委托称之为“多播”或“组播”“委托链”,执行委托时根据注册顺序依次执行注册的函数
class Program
{
//声明委托
public delegate void OrderDelegate();
static void Main(string[] args)
{
//实例化两个委托
OrderDelegate orderDelegate = new OrderDelegate(Order.BuyFood);
OrderDelegate ccDel= new OrderDelegate(Order.BuyFlower);
//向委托中注册方法
orderDelegate += Order.BuyCake;
//合并其它同类型委托
orderDelegate += ccDel;
//调用委托
orderDelegate();
}
}
class Order
{
public static void BuyFood()
{
Console.WriteLine("购买快餐!");
}
public static void BuyCake()
{
Console.WriteLine("购买蛋糕!");
}
public static void BuyFlower()
{
Console.WriteLine("购买鲜花!");
}
}
//最后输出:购买快餐!购买蛋糕!购买鲜花!
事件(EVENT)
(1)事件就是一个狭义的委托,委托是具有相同签名的函数的载体,事件是委托的应用方式之一。
(2)事件是引用类型,事件封装了委托链,所以事件必须配合委托使用
事件和委托的区别
-
通俗来讲,委托可以在客户代码中直接调用从而激发委托指向的函数,而事件的触发只能由服务代码自己触发。
-
也就是说委托你不仅可以安排谁是它的调用函数,还可以直接调用它,而事件不能直接调用,只能通过某些操作触发。
//创建一个委托
public delegate void WaterHeaterDelegate(int Temperature);
class WaterHeater{
//创建一个烧水事件
public event WaterHeaterDelegate WaterDele;
public void Shaoshui() //烧水函数
{
for (int i = 0; i <= 100; i++)
{
if (i > 95)
{
WaterDele.Invoke(i); //当水温达到95度以上,调用事件
}
}
}
public void WaterHot(int temperature) //水温提示函数
{
Console.WriteLine("水已经有{0}C了", temperature);
}
public void WaterBoiling(int temperature) //水烧开函数
{
Console.WriteLine("水已经烧开了"+ temperature);
}
}
class Program
{
static void Main(string[] args)
{
//方法一:绑定外部类中的方法
WaterHeater water = new WaterHeater(); //热水器实例化对象
water.WaterDele += new WaterHeaterDelegate(water.WaterHot); //绑定事件
water.WaterDele += new WaterHeaterDelegate(water.WaterBoiling); //绑定事件
//water.WaterDele += (new WaterHeater()).WaterHot; //绑定事件的 另一种形式
water.Shaoshui();
//方法二:绑定内部类中的方法
//water.WaterDele += Water_WaterDele;
//water.WaterDele += Water_WaterDele1;
//water.Shaoshui();
}
private static void Water_WaterDele1(int Temperature)
{
Console.WriteLine("水已经烧开了" + Temperature);
}
private static void Water_WaterDele(int Temperature)
{
if (Temperature == 100)
{
Console.WriteLine("水已经有{0}C了", Temperature);
}
}
}
Action与Func内置委托
(1)除了自定义命名方法委托之外,系统还提供了内置委托类型→Action和Func。
(2)Action可以定义返回值为void的委托,同时可在泛型列表中定义0到16个函数参数。
(3)Func可以定义具有返回值的委托,同时可在泛型列表中定义0到16个函数参数。
(4)Func的泛型列表中最右一位用来定义返回值类型,若泛型列表只有一个类型,则表示无参带返回值委托。
Action和Func的区别
-
Action用于没有返回值的方法(参数根据自己的需求进行传递)
-
Func相反,它用于有返回值的方法(同样根据自己的需求而定)
-
记住无返回值用action,有返回值用Func
class Program
{
public static void Main()
{
//实例化Action委托
Action<int, int, int> testAction = new Action<int, int, int>(AddNumMethod);
testAction(1, 2, 3);
//实例化一个Func委托(无参返回值为string)
Func<string> testFunc1=new Func<string>(testFuncMethod1);
testFunc2();
//实例化一个Func委托(带参返回值为string)
Func<int, int, string> testFunc2=new Func<int, int, string>(testFuncMethod2);
testFunc2(1, 2);
}
//Action测试方法
private static void AddNumMethod(int num1, int num2, int num3)
{
Console.WriteLine(num1 + num2 + num3);
}
//Func测试方法一
private static string testFuncMethod1()
{
Console.WriteLine("Func委托测试成功!");
}
//Func测试方法二
private static string testFuncMethod2(int num1, int num2)
{
Console.WriteLine("数值的和是:" + (num1 + num2));
}
}