以苹果手机举例子
设计 --> 生产 --> 销售
生产就可以变成委托:设计 --> 委托 --> 销售
这样的好处就是通过委托会变得更灵活,如果出现比富士康更好的代工厂,可以直接更换富士康。
定义委托
- delegate
- [访问修辞] delegate 返回类型 委托名(参数列表)
实例化委托
- 委托类型 委托变量 = new 委托名(方法名)
- 委托类型 委托变量 = 方法名
使用委托
- 委托引用名(实参列表)
- 委托引用?.Invoke(参数)
//委托的实际运用
//形参为委托类型
static void Test(Cal f)
{
Console.Write("请输入x:");
double x = Convert.ToDouble(Console.ReadLine());
Console.Write("请输入y:");
double y = Convert.ToDouble(Console.ReadLine());
//委托方法工作,怎么工作由具体委托决定
double result = f(x,y);
Console.WriteLine("X:{0}与Y:{1}委托方法计算结果为:{2}",x,y,result);
}
//定义委托 这个委托还可以写入下面的Program类里
public delegate double Cal(double x,double y)
internal class Program
{
static double Add(double x,double y)
{
return x+y;
}
static double Dec(double x,double y)
{
return x-y;
}
static void Main(string[] args)
{
/* 写法1
Cal cal = new Cal(Add); //找到委托对象
doubel result = cal(6,8);
Console.WriteLine($"委托Add计算结果为:{result}");
*/
/* 写法2
Cal cal = Dec;
Test(cal);
*/
/* 写法3
Test(new Cal(Add));
*/
Test(Dec);
Console.ReadKey();
}
}
委托是一种引用类型的变量,用于存储某个方法的引用地址
定义格式
- public delegate 返回值类型 委托类型的名字(参数类型1 参数名字,参数类型2 参数名字,…)
委托存在的意义
- 回调方法:当某个任务执行完毕后或者某事件触发后,调用的方法
// 1 场面上所有的按钮,都是当前Button类实例化的对象
// 2 每个按钮被点击后,发生的事情都不一样
// 3 每个按钮点击后,发生的事情由外界决定
class Button
{
// 1 声明一个点击信息响应的方法类型签名(委托)
public delegate void OnClickDelegat();
// 2 声明(创建)一个OnClickDelegate类型的委托(分配地址)
public OnClickDelegat onclick = null;
// 3 在点击事件触发后,调用onclick委托存储的方法
//模拟点击
public void Click()
{
Console.WriteLine("按钮被点击了");
if (onclick != null)
onclick();
}
}
class Program
{
static void Main(string[] args)
{
Button gameStartButton = new Button();
gameStartButton.onclick = new Button.OnClickDelegat(OnGameStart);
gameStartButton.Click();
Console.ReadKey();
}
//点击了游戏开始按钮触发的方法
static public void OnGameStart()
{
Console.WriteLine("游戏开始");
}
}
用类里的方法(实现结果与上面代码一致)
// 1 场面上所有的按钮,都是当前Button类实例化的对象
// 2 每个按钮被点击后,发生的事情都不一样
// 3 每个按钮点击后,发生的事情由外界决定
class Button
{
// 1 声明一个点击信息响应的方法类型签名(委托)
public delegate void OnClickDelegat();
// 2 声明一个OnClickDelegate类型的委托
public OnClickDelegat onclick = null;
// 3 在点击事件触发后,调用onclick委托存储的方法
//模拟点击
public void Click()
{
Console.WriteLine("按钮被点击了");
if (onclick != null)
onclick();
}
}
class Program
{
static void Main(string[] args)
{
GameController gameController = new GameController();
// 开始游戏按钮
Button gameStartButton = new Button();
gameStartButton.onclick = new Button.OnClickDelegat(gameController.OnGameStart);
gameStartButton.Click();
Button friendButton = new Button();
friendButton.onclick = new Button.OnClickDelegat(gameController.OnFriend);
friendButton.Click();
Console.ReadKey();
}
//点击了游戏开始按钮触发的方法
//static public void OnGameStart()
//{
// Console.WriteLine("游戏开始");
//}
//static public void OnFriend()
//{
// Console.WriteLine("分享给好友");
//}
}
创建了一个类
internal class GameController
{
public GameController() { }
//游戏开始的方法
public void OnGameStart()
{
Console.WriteLine("游戏开始 --- 这是类里的方法");
}
//分享给好友
public void OnFriend()
{
Console.WriteLine("分享给好友 --- 这是类里的方法");
}
}
委托存在的意义二次思考
- 需求:把Button类,写成一个独立的C#文件,然后可以在其他项目中使用
不用Delegate
class StartButton
{
public void OnClick()
{
Game game = new Ganme();
GameMap map = new GameMap();
}
......
}
使用Delegate
class Button
{
public delegate void OnClickDelegate();
......
public OnClickDelegate OnClick = null;
......
public void Click(){ OnClick();}
区别:使用delegate后,代码可以直接给新项目使用。但是不用delegate的代码里面会有Game、GameMap等其他新项目没有的类
委托的多播
- 多播:一个主委托对象可以容纳多个其他的子委托对象,当调用主委托对象,会将所有子委托全部按序运行
class Program
{
public delegate int CalculateDelegate(int a, int b);
public static int Add(int a, int b)
{
System.Console.WriteLine(a + b);
return a + b;
}
public static int Multiply(int a, int b)
{
System.Console.WriteLine(a * b);
return a * b;
}
static void Main(string[] args)
{
CalculateDelegate cal0 = new CalculateDelegate(Add);
CalculateDelegate cal1 = new CalculateDelegate(Multiply);
//多播方式1
//CalculateDelegate cal = cal0 + cal1;
//多播方式2
//CalculateDelegate cal = null;
//cal += cal0;
//cal += cal1;
//cal(1, 3);
cal0 += cal1;
cal0(1, 3);
Console.Read();
}
}
泛型委托的好处:简化委托的使用
委托的使用步骤:
1、定义委托(泛型委托要解决的问题是定义委托,可以不用自己定义委托)
2、实例化委托
3、执行委托
Action委托
- public delegate void Action();
- public degegate void Action(T obj);
Func< TResult>委托
- public delegate TResult Func< out TResult>();
- public delegate TResult Func<in T1,in T2,out TResult>(T1 arg1,T2 arg2);
internal class Program
{
//第一个函数
static void SayHi()
{
Console.WriteLine("你好");
}
//第二个函数
static void SayHi(string msg)
{
Console.WriteLine(msg);
}
//第三个函数
static double Add(double x,double y)
{
return x + y;
}
//第四个函数
static void Mul(demical x,int y)
{
return x * y;
}
static void Main(string[] args)
{
//此时指向第一个函数
Action action = SayHi;
action();
//此时指向第二个函数
Action<string> action = SayHi;
action("世界");
//此时指向第三个函数
Func<double,double,double> func = new func<double,double,double>(Add);
double result = func(1.2,2.2);
Console.WriteLine(result);
//此时指向第四个函数
Func<decimal,int,decimal> func = Mul; //第三个类型是返回值得类型
decimal result = func(1.2m,2.2);
Console.WriteLine(result);
Console.ReadKey();
}
}
自定义泛型委托(泛型的好处是可以更多的选择,例如int,double)
namespace Combine{
class Program{
static void Main(string[] args)
{
MyDele<int> deleAdd = new MyDele<int>(Add);
int res = deleAdd(100,200);
Console.WriteLine(res);
MyDele<double> deleMul = new MyDele<double>(Mul);
double mulRes = deleMul(3.0,4.0);
Console.WriteLine(mulRes);
}
static int Add(int x,int y)
{
return x + y;
}
static double Mul(double x,double y)
{
return x * y;
}
}
delegate T MyDele<T>(T a,T b);
}
总结
- 1、委托其实就是方法的引用,其声明格式为;
- public delegate 返回值类型 委托类型名字 {参数列表…};
- public 委托类型名字 委托名字;
- 2、委托用在某个事务完毕后回调或者响应某个事件
- 3、一个委托可以包含多个子委托,从而实现广播调用
4、具体使用场景:有一个按钮,每次点击执行不同方法(例如变换页面颜色)