1 Action
Action 是框架帮我们声明好的委托,我们可以直接拿来用,它是.NetFramework3.0时代出现的。
这是最简单的无参无返回值的委托
public delegate void Action();
实多种途径例化,参数既可以当前类的普通方法也可以是静态方法,也可以别的类的普通方法或是静态方法,唯一限制就是方法的参数列表和返回值类型必须和委托约束的一致
public void Show()
{
Action action = new Action(this.DoSomething);// 1
Action action2 = this.DoSomething;// 2 这是语法糖,在编译的时候编译器自动帮我们添加上new Action,方便我们的使用
}
public void DoSomething()
{
Console.WriteLine("DoSomething");
}
泛型版本的Action共有16种,分别对应1-16个泛型参数,无返回值
public delegate void Action<in T>(T obj);
...
public delegate void Action<in T1, in T2, in T3, in T4, in T5, in T6, in T7, in T8, in T9, in T10, in T11, in T12, in T13, in T14, in T15, in T16>(
T1 arg1,
T2 arg2,
T3 arg3,
T4 arg4,
T5 arg5,
T6 arg6,
T7 arg7,
T8 arg8,
T9 arg9,
T10 arg10,
T11 arg11,
T12 arg12,
T13 arg13,
T14 arg14,
T15 arg15,
T16 arg16);
与无参无返回值的加到一块,Action一共有17种,分别对应0-16泛型参数,无返回值
2 Func
Func也是委托,跟Action区别是带了一个返回值,一共也有17种,最后一个泛型参数代表返回值
public void Show()
{
Func<string> func = new Func<string>(this.SayHi);// 无参一个返回值
Func<int, string> func2 = new Func<int, string>(this.ShowAge);//一个参数 一个返回值
}
public string SayHi()
{
return "hello world";
}
public string ShowAge(int age)
{
return $"我的年龄是{age}";
}
3 为什么框架要给我们提供Action Func呢
先看代码
using System;
using System.Collections.Generic;
using System.Text;
namespace MyDelegate
{
public delegate void NoReturnNoParameter(); // 1 声明委托
public class DelegateStudy
{
public void Show()
{
NoReturnNoParameter method = this.DoSomething;
Action action = this.DoSomething;
this.DoAction(action);//
//this.DoAction(method); 会编译不通过
}
public void DoAction(Action action)
{
action.Invoke();
}
public void DoSomething()
{
Console.WriteLine("DoSomething");
}
}
}
NoReturnNoParameter 与 Action 都是无参无返回值的委托 但在执行DoAction函数时,却不能传递method参数
原因是委托的本质是类,Action与NoReturnNoParameter 是不同的类,虽然实例化的时候可以传递相同的方法,但是两个委托之间是没有父子关系的,所以不能替换。
就像Student1 与 Student2 虽然都是学生,实例化传递的参数是一样的,但是二者不能替换的
再进一步,这样的情况,也导致了即使是参数返回值类型相同的委托,都不能通用,需要提供它需要的那个委托类型
例如
new Thread(new ParameterizedThreadStart())
ThreadPool.QueueUserWorkItem(new WaitCallback())
Task.Run(new Action<object>())
代码中,ParameterizedThreadStart、WaitCallback等都是签名相同的委托,但是互相之间不能通用,造成很多冗余、麻烦,所以自从Framework3.0之后,框架就提供了Action与Func,意在 统一所有的委托,只要委托返回值参数类型相同就能通用,不用再进行类型转换,而我们在使用委托的时候,直接使用Action与Func就可以了。
之所以框架中还有各式各样的不是Action、Func的委托,是因为在Framework3.0之前声明的,框架要向前兼容,没法改了,所以还存在,这是历史原因。