P19委托
与2021-12-22-《C#基础+WinForms》-内容总结-P11 委托+Lambda配合食用
回溯:2022/01/11/12/13
一、P19内容总结
- 介绍委托
- 委托的声明
- 委托的使用
二、什么是委托delegate
- 委托是函数指针的升级版
1)举例说明:C/C++中的函数指针 - 程序员常提及的概念:一切皆地址
1)变量(数据)是以某个地址为起点的一段内存中所存储的值
解释:数据存储在变量中,变量的本质:以变量名所对应的内存地址为起点的一段内存[存储着变量的数据],内存的大小由数据类型决定
2)函数(算法)是以某个地址为起点的一段内存中所存储的一组机器语言指令
函数的本质:以函数名所对应的内存地址为起点的一段内存,在这段内存中存储的是一组机器语言的指令,CPU按照这组指令一条一条完成 - 直接调用&间接调用
1)直接调用:通过函数名调用函数,CPU通过函数名直接获得函数的地址并开始执行→返回
2)间接调用:通过函数指针调用函数,CPU通过读取函数指针中存储的值获得函数的地址并开始执行→返回 - 委托的简单使用
//C#中已经声明好的委托类型举例
//Action委托与Func委托
class Program
{
static void Main(string[] args)
{
Calculator calculator = new Calculator();
//Action委托指向的是参数列表为空,返回值为void的方法
Action action = new Action(calculator.Report);
//直接调用
calculator.Report();
//间接调用1
action.Invoke();
//间接调用2
action();
/*Func<>委托指向的是有参数、有返回值的方法
Func<参数,参数,返回值>*/
Func<int, int, int> func1 = new Func<int,int,int>(calculator.Add);
Func<int, int, int> func2 = new Func<int, int, int>(calculator.Sub);
int x = 100;
int y = 200;
int z = 0;
//间接调用1
z = func1.Invoke(x, y);
Console.WriteLine(z);
z = func2.Invoke(x, y);
Console.WriteLine(z);
//间接调用2
z = func1(x, y);
Console.WriteLine(z);
z = func2(x, y);
Console.WriteLine(z);
}
}
//有一个Calculator类有三种方法
class Calculator
{
public void Report()
{
Console.WriteLine("I have 3 methods.");
}
public int Add(int a,int b)
{
int result = a + b;
return result;
}
public int Sub(int a, int b)
{
int result = a - b;
return result;
}
}
三、委托的声明[自定义委托]
- 关于委托
1)委托是一种类class,类是数据类型所以委托也是一种数据类型
2)委托声明在名称空间体中 - 委托声明方式与类不同
1)自定义委托举例
//声明返回值为double类型,参数列表为double类型的委托
public delegate double Calc(double x, double y);
class Program
{
static void Main(string[] args)
{
Calculator calculator = new Calculator();
Calc calc1 = new Calc(calculator.Add);
Calc calc2 = new Calc(calculator.Sub);
Calc calc3 = new Calc(calculator.Mul);
Calc calc4 = new Calc(calculator.Div);
double x = 100;
double y = 200;
double z = 0;
//间接调用1
z = calc1.Invoke(x, y);
Console.WriteLine(z);
z = calc2.Invoke(x, y);
Console.WriteLine(z);
z = calc3.Invoke(x, y);
Console.WriteLine(z);
z = calc4.Invoke(x, y);
Console.WriteLine(z);
//间接调用2
z = calc1(x, y);
Console.WriteLine(z);
z = calc2(x, y);
Console.WriteLine(z);
z = calc3(x, y);
Console.WriteLine(z);
z = calc4(x, y);
Console.WriteLine(z);
}
}
class Calculator
{
public double Add(double a,double b)
{
double result = a + b;
return result;
}
public double Sub(double a, double b)
{
double result = a - b;
return result;
}
public double Mul(double a, double b)
{
double result = a * b;
return result;
}
public double Div(double a, double b)
{
double result = a / b;
return result;
}
}
- 委托与所封装的方法必须“类型兼容”
1)返回值数据类型一致
2)参数列表个数、数据类型要一致
四、委托的使用
委托的一般使用
- 实例:把方法当作参数传给另一个方法
1)模板方法,借用指定的外部方法产生结果
class Program
{
static void Main(string[] args)
{
ProductFactory productFactory = new ProductFactory();
WrapFactory wrapFactory = new WrapFactory();
//准备委托类型的参数,传入方法模板
Func<Product> fun1 = new Func<Product>(productFactory.MakePizza);
Func<Product> fun2 = new Func