1.委托是什么
个人理解:委托大概就跟现实生活中的委托差不多吧,举个栗子
我想要买水果 (函数的操作),
但是我不想或者不能亲自去买,
所以我找了我弟弟 (委托类的实例),
告诉他去干什么 (函数名给他),
然后给他钱 (函数的参数),
他不乐意的去买了 (函数的操作),
然后他拿回来一颗桃子 (返回值);
1.1 C/C++中的函数指针
- 一个函数在内存中实际上是一组机器语言指令的集合;
- 函数指针是一个指针变量,里面保存了函数这组机器语言指令的入口地址;
- 先声明函数指针类型,参数类型要和函数的参数类型相同;
- 声明函数指针类型的变量,将函数的入口地址赋给它;
- 通过函数指针来调用函数。
实例:
#include <stdio.h>
typedef int (* Calc)(int a, int b); //Calc是返回值为int,参数为(int, int)的函数指针
int Add(int a, int b)
{
return a + b;
}
int Sub(int a, int b)
{
return a - b;
}
int main()
{
int x = 20, y = 30, z = 0;
Calc func1 = &Add; //取Add函数的地址
Calc func2 = ⋐ //取Sub函数的地址
//正常方式调用函数
printf("正常方式调用函数\n");
z = Add(x, y);
printf("%d + %d = %d\n", x, y, z);
z = Sub(x, y);
printf("%d - %d = %d\n", x, y, z);
//函数指针方式调用
z = 0;
printf("函数指针的方式调用函数\n");
z = func1(x, y);
printf("%d + %d = %d\n", x, y, z);
z = func2(x, y);
printf("%d - %d = %d\n", x, y, z);
scanf_s("%d", &z); //为了使程序停在这
return 0;
}
1.2 C#中的委托
- 委托是由C/C++的函数指针升级而来;
- 是把一个函数名交给委托类的实例,通过委托类来调用这个函数;
- 它跟函数指针的用法类似,都是通过传递函数的地址,让CPU通过地址来调用函数;
- 需要的参数也与函数的参数相同
- 与C/C++不同的是:需要声明委托的实例,即new一个委托类的对象Function,把函数名传进去;
- 通过new出来的这个委托的对象调用函数:Function.invoke();
2.委托的分类以及使用
C#已经为我们封装好了几种委托,其中常用的就是Action和Func
2.1 Action委托
- Action是 没有返回值 的委托,它是一个类,可以用来调用 返回值为Void 的函数;
- 使用时new一个Action的实例,将要调用的方法名传递给它;
- 注意:方法名不要加上括号,加括号是函数调用。
using System;
namespace DelegateTest
{
class Program
{
static void Main(string[] args)
{
Calculator calculator = new Calculator();
//Action实例
Action Act1 = new Action(calculator.OutPut);
//通过正常方法调用
calculator.OutPut();
//通过委托的方法调用
Act1.Invoke();
Console.ReadKey();
}
}
class Calculator
{
public void OutPut()
{
Console.WriteLine("I have 3 mathods");
}
}
}
这个程序输出了两行 I have 3 mathods ;
2.2 Func委托
- Func和Action的区别:Func是有返回值的;
- 声明Func的时候需要在Func< >的尖括号中添加函数的参数类型,在最后加上返回值的类型;
- 例程如下:
using System;
namespace DelegateTest
{
class Program
{
static void Main(string[] args)
{
Calculator calculator= new Calculator();
int c = 0;
//前两个int是函数的参数类型,第三个int是函数的返回值类型
Func<int, int, int> Function1 = new Func<int, int, int>(calculator.Add);
Func<int, int, int> Function2 = new Func<int, int, int>(calculator.Sub);
//用委托的方式调用
c = Function1.Invoke(1, 2);
Console.WriteLine(c);
c = Function2.Invoke(1, 2);
Console.WriteLine(c);
//正常方式调用
c = 0;
c = calculator.Add(100, 200);
Console.WriteLine(c);
c = calculator.Sub(100, 200);
Console.WriteLine(c);
Console.ReadKey();
}
}
class Calculator
{
public int Add(int a, int b)
{
return a + b;
}
public int Sub(int a, int b)
{
return a - b;
}
}
}
通过输出的结果来看,两种调用方法的效果是相同的。
2.3 自定义委托 delegate
- 除了使用C#给我们提供的委托,我们还可以自己定义一个delegate类;
- 委托定义的方式与普通的类稍有区别;
- 格式大致如此: public delegate 返回值类型 类名 (参数列表);
- 例如:public delegate double calc(double x, double y);
- 注意:参数和返回值必须与函数的相同;
using System;
namespace DelegateTest
{
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 c = 0;
c = calc1(x, y);
Console.WriteLine(c);
c = calc2(x, y);
Console.WriteLine(c);
c = calc3(x, y);
Console.WriteLine(c);
c = calc4(x, y);
Console.WriteLine(c);
Console.ReadKey();
}
}
class Calculator
{
public double Add(double a, double b)
{
return a + b;
}
public double Sub(double a, double b)
{
return a - b;
}
public double Mul(double a, double b)
{
return a * b;
}
public double Div(double a, double b)
{
return a / b;
}
}
}
3 总结
初步的学习了一下委托是什么,怎么使用;
对于具体的使用场景,为什么使用它,还有使用它的好处,注意事项等等