C# Action和Func的用法详解
委托是一个类,定义了方法的类型,使得可以将方法当作另一个方法的参数来进行传递。
把一个 参数类型 返回值 相同 方法名不同 的方法当变量 的方法 叫委托。
为了实现程序的六大设计中的开闭原则:解耦,对修改关闭,对扩展开放。逻辑分离。
直接调用函数和使用委托调用函数的区别就是是否方便对外扩展。
当我们窗体传值、线程启动时绑定方法、lambda表达式、异步等等情况下需要用到。
事件是一种特殊的委托,本质就是委托,事件是回调机制的一种应用。
当委托调用的函数达到某种条件时,可以通过回调通知调用者。
1. delegate 至少0个参数,至多32个参数,可以无返回值,可以指定返回值类型
private delegate int MethodDelegate(int x,int y); //两个参数,返回int类型 static void Main(string[] args) { MethodDelegate method = new MethodDelegate(Add); int result = method(10,20); } private static int Add(int x, int y) { return x +y; }
平时用委托的一般方式,先声明委托,然后再去使用,有点麻烦,.net中有已经定义好的委托类型Action 和 Func,可以拿来直接用。
2. Action 至少0个参数,至多16个参数,没有返回值的泛型委托
static void Main(string[] args) { Action<string> BookAction = new Action<string>(Book); //一个参数 BookAction("百年孤独"); } public static void Book(string BookName) { Console.WriteLine("我是买书的是:{0}",BookName); }
using System; using System.Collections; using System.Collections.Generic; using UnityEngine; public class ActionDemo : MonoBehaviour { Action action;//表示无参 Action<int> action1;//表示有传入参数int void Start() { action = actionH1;//没有参数 action(); action1 = actionH2;//一个 int参数 action1(456); actionH3(() => { Debug.Log("执行完actionH3了"); });//lambda 表达式 来执行委托 actionH3(actionH4);//执行完 actionH3后回调 actionH4方法 } private void actionH1()//没有参数 { Debug.Log(123); } private void actionH2(int index)//参数int { Debug.Log(index); } private void actionH3(Action act)//参数 Action { Debug.Log("在执行actionH3"); act();//回调 这个 委托方法 } private void actionH4()//执行完 actionH3后的回调执行 { Debug.Log("执行完actionH3了"); } }
3. Func 至少0个参数,至多16个参数,必须有返回值的泛型委托
没有参数只有返回值的方法
static void Main(string[] args) { Func<string> RetBook = new Func<string>(FuncBook); //无参的Func 返回一个string //Func<string> RetBook = FuncBook; //也可以直接这样 Console.WriteLine(RetBook); //执行 这个委托 } public static string FuncBook() { return "送书来了"; }
有参数有返回值的方法
static void Main(string[] args) { Func<string, string> RetBook = new Func<string, string>(FuncBook); //有一个参数的Func,返回一个string //Func<string,string> RetBook = FuncBook; //也可以直接这样 Console.WriteLine(RetBook("aaa")); //执行 这个委托 } public static string FuncBook(string BookName) { return BookName; }
Func一个很重要的用处就是传递值,下面举一个简单的代码来说明
Func<string> funcValue = delegate { return "我是即将传递的值3"; }; DisPlayValue(funcValue);
注释1:DisplayVaue是处理传来的值,比喻缓存的处理,或者统一添加数据库等
private static void DisPlayValue(Func<string> func) { string RetFunc = func(); Console.WriteLine("我在测试一下传过来值:{0}",RetFunc); }
完整示列如下:
public class Person { public string Name { set; get; } public int Age { set; get; } public bool Gender { set; get; } /// <summary> /// 重写tostring方法,方便输出结果 /// </summary> /// <returns></returns> public override string ToString() { return Name + "\t" + Age + "\t" + Gender; } } class Program { static void Main(string[] args) { Func<Person, Person> funcUpdateAge = new Func<Person, Person>(UpdateAge); Func<Person, Person> funcUpdateAge2 = UpdateAge; Func<Person, Person> funcUpdateGender = (p1) => { p1.Gender = false; return p1; };//lambda表达式方式 Func<Person, Person> funUpdateName = delegate(Person p2)//匿名方法 { p2.Name = "Wolfy2"; return p2; }; Person p = new Person() { Name = "Wolfy", Age = 24, Gender = true }; Person result = funcUpdateAge(p); Person result2 = funcUpdateAge2(p); Console.WriteLine(result.ToString()); Console.WriteLine(result2.ToString()); Console.WriteLine(funcUpdateGender(p).ToString()); Console.WriteLine(funUpdateName(p).ToString()); Console.Read(); } static Person UpdateAge(Person p) { p.Age = 25; return p; } }
记住无返回值就用Action,有返回值就用Func
Action:无参数无返回值委托。
Action<T>:泛型委托,无返回值,根据输入参数的个数不同有十六个重载。
Func<out T>:无输入参数,有返回值。
Func<in T,out T>:有输入参数,有返回值,根据输入参数个数不同,有十六个重载。
Action和Func中可以使用Lambda和匿名方法处理方法体内逻辑。