1 什么是委托
委托(Delegate)类似于 C 或 C++ 中函数的指针。委托(Delegate) 是存有对某个方法的引用的一种引用类型变量。引用可在运行时被改变。调用委托变量时,就是执行该变量指向的方法。
委托与c#中的普通变量【如int i=5】类似,唯一区别在于委托指向方法,普通变量执向整数为5的空间
委托声明决定了可由该委托引用的方法。委托可指向一个与其具有相同标签的方法。
声明委托的语法如下:
delegate <return type> <delegate-name> <parameter list>
关键字 返回类型 委托的名称 参数列表
根据上述语法,可自定定义自己的委托类型【返回类型与参数列表与被执向的方法类型一致】委托一旦声明,允许执向的方法就确定了
delegate string my_delegate_1(int i,int j) ; //允许执向参数为int,返回为string类型的方法
delegate void my_delegate_2; //允许执向无参数,无返回值的方法
2 委托的使用
public class DelegateStudy
{
/// <summary>
/// 扩展方法
/// </summary>
public DelegateStudy() {
}
public void F1() {
Console.WriteLine("我是方法F1");
}
public int F2(int i) {
Console.WriteLine("我是方法F2");
return i + 1;
}
public int F3() {
Console.WriteLine("我是方法F3");
return 10;
}
public int F4(string s)
{
Console.WriteLine("我是方法F4"+s);
return 10;
}
}
class Program
{
//委托的声明
//无返回的委托
delegate void f1();
//有返回的委托
delegate int f2(int i);
//无参数无返回值
static Action action;
//无参数有返回值【int】
static Func<int> func;
//有参数有返回值 输入参数类型为string,返回类型为int
static Func<string, int> func1;
static void Main(string[] args)
{
//避免控制台输出乱码
Console.OutputEncoding = Encoding.Unicode;
DelegateStudy delegateStudy = new DelegateStudy();
//委托的使用
//d1变量指向DelegateStudy中的F1()方法
f1 d1 = delegateStudy.F1;
//委托使用
d1();
//d2变量指向DelegateStudy中的F2()方法
f2 d2 = delegateStudy.F2;
//委托使用
int l= d2(5);
Console.WriteLine("委托2的返回值为:"+l);
//使用new关键字实例化委托
f2 d22 = new f2(delegateStudy.F2);
int ll= d22(10);
Console.WriteLine("委托2-的返回值为:" + ll);
Console.WriteLine("Hello World!");
//系统自定义的委托
action= delegateStudy.F1;
//委托使用
action();
func = delegateStudy.F3;
//委托使用
int lll=func();
Console.WriteLine("func变量执行的方法返回值为:" + lll);
func1 = delegateStudy.F4;
//委托使用
int llll= func1("ssssss");
Console.WriteLine("func1变量执行的方法返回值为:" + llll);
}
}
控制台输出如下:
c#定义了无返回的委托Action以及有返回的泛型委托Func,所以一般不需要自行定义委托
Action具有以下多种重载,可根据实际自行选择无返回的委托(带参数或不带参数)
Func具有以下多种重载,可根据实际自行选择有返回的委托(带参数或不带参数)
3 委托与Lamda表达式的关系
委托除了可以指向一个明确的方法时,通常也可以执行一个匿名方法。而匿名方法通常可以用Lamda表达式来定义。
/// <summary>
/// 委托同样可以指向匿名方法
/// </summary>
Func<int, int, int> fun1 = delegate (int i, int j)
{
Console.WriteLine("fun1指向匿名方法");
return i + j;
};
/// <summary>
/// 匿名方法采用lamda表达式
/// 因为已确定fun2委托变量的参数类型为int,意味着该委托只能指向形如 int functionName(int a,int b)的方法。在匿名表达式的参数类型确定后,可以忽略参数类型
/// </summary>
Func<int, int, int> fun2 = (i, j) => {
Console.WriteLine("fun2指向匿名方法【采用lamda表达式】");
return i + j;
};
/// <summary>
/// 1委托可以指向匿名方法
/// 2匿名方法可以采用lamda表达式
/// 3当匿名表达式有返回值,且只有一行逻辑时,可以省略{}及return
/// </summary>
Func<int, int, int> fun3 = (i, j) => i+j;
/// <summary>
/// 1委托可以指向匿名方法
/// 2匿名方法可以采用lamda表达式
/// 3当匿名表达式无返回值,且只有一行逻辑时,可以省略{}
/// </summary>
Action<int, string> action1 = (age, name) => Console.WriteLine($"年龄:{age},名字:{name}");
/// <summary>
/// 1委托可以指向匿名方法
/// 2匿名方法可以采用lamda表达式
/// 3action2的委托只能指向 void functionName(int i)的方法
/// 3当匿名方法只有一个参数时,可以省略掉参数()
/// </summary>
Action<int> action2 = i=> Console.WriteLine(i*i);