一、 什么是委托 ?
委托代表的是方法,委托是一种数据类型,当调用委托时就是调用了这个方法。
解释:委托是一类行为的抽象,是方法的引用,存储了方法的地址。
委托是一种数据类型【声明了返回类型和参数组成】
委托可以实现对方法的【间接】调用! 灵活=维护性好!
委托代表的是方法 【代表和委托签名一致的任何方法】
签名 含义不同 有时1: 签名=返回类型和参数组成
有时2:签名=方法名和参数组成【隐藏】
有时3:签名=方法名和参数组成,返回类型【重写!】
注意:
委托的使用步骤:三步 1:定义端 2:实例化委托(多种写法) 3:调用端
二、 实例化委托多种写法 :
方式一、基本传统标准的写法,适合于: 委托已有的方法。
步骤1【定义端】:定义委托
delegate 返回值 方法签名;
例如:delegate void Handler(); 习惯命名:方法后加Handler:SelectHandler
步骤2【调用端】:创建实例
【实例化委托:为委托指定{绑定}方法,方法名】
Handler handler = new Handler(Fun);等号右边表示的是委托对象,委托不是方法
步骤3【调用端】:调用委托【和调方法相似,有参数就要写参数,有返回值可以返回】
handler();
public static void Fun() { }
方式二、基本传统标准的简化写法,写法一的简化,适合于: 委托已有的方法
注意:方式一、二一定要先写好方法再绑定委托
下面介绍实例化委托的其他两种常用写法:
方式三、匿名方法,适合于功能简单少量代码可以完成,且该功能不需要在其它地方复用.
匿名方法本质是委托对象,没有名字
方式四、Lambda 表达式
写法一:功能简单少量代码可以完成,且该功能不需要在其它地方复用
Lambda 表达式语法:
委托类型 委托对象名=Lambda 表达式;
写法一 : (参数)=>{语句} => 读作goto
(参数1,参数2)=> 一行代码;注意:方法有返回值的时候return不能写!
简化写法二 :当参数是一个,语句是一句话的时候小括号大括号可以省略:
一个参数=>一行代码;return不能写!
Handler handler = (p) => Console.WriteLine(p + "HAHA");
等号右边 表示的是委托对象=Lambda 表达式=匿名方法
Lambda表达式写法二:功能代码超简单,一行代码可以完成
注意:方式三、四不需要写好方法,心中定义好
三、练习:实例化以下的委托, 使用4种方法来实例化完成
public int Handler(Person p) //从一个对象中选一个属性 Person id或age
public Person Handler(List< Person > list,int id)//从一个集合中选择编号=id的那个对象
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace DemoDelegate444
{
//
class EX4
{
static void Main()
{
//2> 4种写法
//Handler handlerObj = new Handler(Fun);//111
//Handler handlerObj = Fun;//222
//Handler handlerObj = delegate(List<Person> list, int id)
//{
// Person person = null;
// foreach (var p in list)
// {
// if (p.Id == id)
// {
// person = p;
// break;
// }
// }
// return person;
//};
Handler handlerObj = (list, id) =>
{
Person person = null;
foreach (var p in list)
{
if (p.Id == id)
{
person = p;
break;
}
}
return person;
}; //444
//3>
List<Person> arr = new List<Person>
{
new Person(){Id = 1,Name = "aa",Age = 20},
new Person(){Id = 2,Name = "bb",Age = 22}
};
var re = handlerObj(arr, 2);
}
//static Person Fun(List<Person> list, int id)
//{
// Person person = null;
// foreach (var p in list)
// {
// if (p.Id == id)
// {
// person = p;
// break;
// }
// }
// return person;
//}
}
//定义端 1>
public delegate Person Handler(List< Person> list,int id);
//从一个集合中选择编号=id的那个对象
public class Person
{
public int Id { get; set; }
public string Name { get; set; }
public int Age { get; set; }
}
}
四、委托的分类 调用【使用】方式
1单播委托:一个委托对象只关联一个方法
2多播执行:一个委托对象关联多个方法 只返回最后方法的结果
所以:委托有返回值不适合多播执行!适合单播执行。
委托无返回值适合多播执行!
委托是数据类型
五、委托的作用 用途 实际应用!
1》、将方法做为参数传递,可以将一个方法的执行代码注入到另一个方法中。
为什么要注入?
1、定义算法/方法时 :有的语句/步骤能定下来,有的暂时定不下来,可以使用委托表示确定不下来的
2、调用时再确定 把有些功能推迟到客户端【调用端】确定!
2》、实现回调,实现的方式比接口更灵活
回调最早的含义1: 方法或函数由 系统调用 【不是程序员直接调用的】
含义 2 这里的含义 定义方法 有些定义时确定不下来,留给客户端确定
调用时候,从 调用端 到定义端
回到调用端 再到定义端执行 【灵活性】
回到调用端,结束
举个例子: 比如回家紧接着做什么事情。回家是唯一,能确定的 做的什么事情是不确定的【复习,看电视,玩游戏,聊天】
解决方案1:
解决方案2:对于变化的提取出来单独封装【接口】,接口作为参数,也会造成代码的膨胀
解决方案3:使用委托做参数不会造成代码的膨胀
举这个例子想要说明得是:
- 接口可以作为方法的参数!
- 委托可以作为方法的参数!
同样可以作为方法参数;委托可以实现回调,比接口更灵活.