匿名方法、Lambda表达和自定义泛型委托以及Func、Action系统泛型委托
1.匿名方法的概念:一个方法没有具体的名称,而只有关键字delegate、方法参数、方法体、这种方法是匿名方法。
匿名方法的好处:将具体方法和委托直接关联在一起,如果我们基于委托只需要一个方法的时候,匿名方法肯定显得简单。
2.Lambda表达式:在C#3.0出现的。使用这种表达的可以更简练的编写代码块。
CalculatorDelegate cal3 = (int a, int b) => { return a + b; };
CalculatorDelegate cal4 = (a, b) => a - b;
【1】Lambad的参数类型可以是明确类型,也可以是推断类型。
【2】如果是推断类型,则参数类型可以由编译根据上下文自动推断出来
【3】运算符=>读作goes to,运算符左边输入参数,右边是表达式或者代码块。
【4】表达式有两种方式:
(input args)=>表达式
(input args)=>{ 语句1;语句2;语句3....}
【5】Lambda表达式和匿名方法的比较:
第一,Lambda本身就是匿名方法。
第二,Lambda表达式不允许指明参数类型,但是匿名方法必须要明确。
第三,Lambda表达式允许单一的表达式或者多条语句组成,而匿名方法不允许单一表达式。
3.自定义泛型委托
【1】为什么要用泛型委托?普通委托在数据类型上的限定是非常严格的,有时候我们的需求变化,可能适应不了,这时候考虑的就是泛型委托。
【2】泛型委托定义:本质上和泛型方法是非常类似的,泛型委托关联的时候可以是具体方法,匿名方法或者Lambda表达式。
【3】试想如果我们有五个参数、六个参数甚至更多的参数,按照目前的思路我们不得不定义很多种这种方法,很麻烦,这时候就要考虑系统泛型委托,所谓系统泛型委托,就是C#.NET为
我们定义好的泛型委托,可以直接拿来用。
4.自定义泛型委托:主要介绍两种,一种是有返回值的Func<T>和一种是没有返回值的Action<T>
Action<T>在多线程中用的非常多。
Func<T>在扩展方法中用的非常多。
结论:泛型委托作为方法参数,实际上传递的是一个具体方法或一个Lambda表达式! (多态一种表现)
a.自定义普通委托和Lambda表达式:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace AdVancedTest { public class LambdaDemo { public static void Test() { //委托关联独立的方法 CalCulatorDelegate MyCal1 = Add; int result1 = MyCal1(10, 20); Console.WriteLine("委托关联独立的方法来计算a+b=" + result1); //委托关联匿名方法 CalCulatorDelegate MyCal2 = delegate (int a, int b) { return a + b; }; int result2 = MyCal2(30, 30); Console.WriteLine("通过匿名方法来计算a+b" + result2); //将匿名方法简化为Lambda表达式:goes to 参数列表(参数1,参数2....)=>{函数体} CalCulatorDelegate MyCal3 = (int a, int b) => { Console.WriteLine(100); return a + b; }; //进一步简化:假如方法中只有一行代码,可以省略{} CalCulatorDelegate MyCal4 = (a, b) => a + b; int result4 = MyCal4(40,50); Console.WriteLine("简化Lambda表达式计算a+b="+result4); SayHelloDelegate sayHello = (msg) => msg; string result5= sayHello("Hello World"); Console.WriteLine("SayHello委托:"+result5); //Lambda表达式允许不指明参数类型,但是匿名方法必须要明确。 CalCulatorDelegate myCal5 = (a, b) => { return a + b; }; myCal5(10,12); } private static int Add(int a, int b) { return a + b; } } //【1】声明委托 public delegate int CalCulatorDelegate(int a, int b); public delegate string SayHelloDelegate(string msg); }
输出结果为:
委托关联独立的方法来计算a+b=30 通过匿名方法来计算a+b60 简化Lambda表达式计算a+b=90 SayHello委托:Hello World
b.自定义泛型委托
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace AdVancedTest { public class GenericClass { public static void Test() { //范型委托关联具体方法,基于泛型委托, MyGenericDelegate<int> myGenericDelegate1 = Add; int result1 = myGenericDelegate1(10, 30); Console.WriteLine("范型委托关联具体方法:" + result1); //泛型委托关联元祖方法 MyDelegate<string, int, int> myDelegate1 = Mymethod; var result2= myDelegate1(); //使用元组的默认参数名 var result4 = Mymethod(); Console.WriteLine(result4.str+"\t"+result4.a+"\t"+result4.b); Console.WriteLine(result2.Item1+result2.Item2+result2.Item3); //使用元组的自定义参数名 MyDelegate<string ,int ,int > myDelegate2 = Mymethod; var result3 = myDelegate2(); Console.WriteLine(result3); //使用泛型委托:匿名方法 MyGenericDelegate<int> myGenericDelegate4 = delegate(int a,int b){ return a + b; }; MyGenericDelegate<double> myGenericDelegate5 = delegate (double a, double b) { return a + b; }; int result5=myGenericDelegate4(20,30); Console.WriteLine(result5); double result6 = myGenericDelegate5(20,30); Console.WriteLine(result6); //使用泛型委托:Lambaa表达式 MyGenericDelegate<int> myGenericDelegate6 = (a, b) => a + b; int result7= myGenericDelegate6(20, 30); Console.WriteLine(result7); MyGenericDelegate<double> myGenericDelegate7 = (a, b) => a + b; double result8= myGenericDelegate7(20, 30); Console.WriteLine(result8); } private static int Add(int a, int b) { return a + b; } private static int Sub(int a, int b) { return a - b; } //元组C#7.0新操作:元組 private static (string str, int a, int b) Mymethod() { return ("C#.NET",4, 5); } } //定义泛型委托 public delegate T MyGenericDelegate<T>(T param1, T param2); public delegate (T1, T2, T3) MyDelegate<T1, T2, T3>(); }
输出结果
范型委托关联具体方法:40 C#.NET 4 5 C#.NET45 (C#.NET, 4, 5) 50 50 50 50
c.系统泛型委托
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace AdVancedTest { public class FuncDemo { /// <summary> /// Func的基本使用: 在扩展方法中用的非常多,最后一个表示返回自类型 /// </summary> /// <returns></returns> public static int Test1() { Func<int, int, int> func1 = Add1;//输入,输入,输出 int result1 = func1(10, 20); //直接使用Lambad表达式,第四个参数表示返回值为string类型 Func<int, int, int, string> fun3 = (a,b,c) => { return (a + b+c).ToString(); }; Func<int, int, int> func2 = (a, b) => a + b; int result2 = func2(40,40); string result3 = fun3(40,40,60); Console.WriteLine("------------------------------------------------------------------------"); Console.WriteLine(result1);//30 Console.WriteLine(result2);//80 Console.WriteLine(result3);//140 return result1; } private static int Add1(int a,int b) { return a + b; } private static int Mul1(int a, int b) { return a * b; } /// <summary> /// Func委托的重要使用 /// </summary> /// <returns></returns> /// //问题:给定一个数组 { 10, 9, 8, 7, 6, 5, 4, 3, 2 },从数组中指定位置抽取3个数,求和、求积 public int Test2() { //普通方法求和求积 int[] nums = new int[] { 10, 9, 8, 7, 6, 5, 4, 3, 2 }; Sum(nums,0,2); return Mul(nums,0,2); } private int Sum(int[]nums,int From,int To) { int sum = 0; for (int i=From;i<To;i++) { sum += nums[i]; } return sum; } private int Mul(int[] nums, int From, int To) { int mul = 1; for (int i = From; i < To; i++) { mul *= nums[i]; } return mul; } //把Func委托做为参数传递实际传递的是一个具体的方法或者一个Lambda表达式:也是多态的一种表现 private static int Operation(Func<int,int,int> method,int[]nums,int from,int to) { int result = nums[from]; for (int i=from+1;i<to;i++) { //method(result,nums[i]):方法的返回值 result = method(result, nums[i]); } return result; } public static void Test3 () { int[] nums = new int [] { 10, 9, 8, 7, 6, 5, 4, 3, 2 }; int result1= Operation(Add1,nums,0,3);//计算加运算 int result2 = Operation(Mul1,nums,0,3);//计算乘法运算 Console.WriteLine("返回10+9+8="+result1); Console.WriteLine("返回10*9*8="+result2); } } }
d.Func<T>委托
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace OperationXml { public class A { bool bDeviceConnected = false; public void test() { Variable.val = new VarRef<object>(() => bDeviceConnected, val => { bDeviceConnected = (bool)val; }); Console.WriteLine(bDeviceConnected); Variable.val.Value = true; Console.WriteLine(bDeviceConnected); } } public class VarRef<T> { public Func<T> _get; public Action<T> _set; /// <summary> /// 传递一个系统泛型委托,实际传递的是一个泛型方法 /// @get:传递() => bDeviceConnected,获取bDeviceConnected /// @set:设置bDeviceConnected的值 /// </summary> public VarRef(Func<T> @get, Action<T> @set) { _get = @get; _set = @set; } /// <summary> /// 属性,对bDeviceConnected进行读和写 /// </summary> public T Value { get { return _get(); } set { _set(value); } } } public class Variable { public static VarRef<object> val; } }
输出结果
False
True
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 因为Apifox不支持离线,我果断选择了Apipost!
· 通过 API 将Deepseek响应流式内容输出到前端