C# 委托
一、方法的描述
假设有如下方法,Method1,Method2,Method3,Method4,Method5,抛开方法的内容,我们来观察一下他们的名字、参数和它的返回值。
class Example { public void Method1(int a) { Console.WriteLine("this is method1: " + a); } public void Method2(int b) { Console.WriteLine("this is method2: " + b); } public int Method3(int m) { Console.WriteLine("this is method3: " + m); return m * m; } public int Method4(int n) { Console.WriteLine("this is method4: " + n); return n + n; } public int Method5(int x, int y) { Console.WriteLine("this is method5"); return x + y; } }
当我们来描述一个方法的时候,其实有两个特征:一个是参数类型列表,一个是返回值。比如:
public void Method1(int a)
"一个参数为(int), 返回值为void的方法";
public void Method2(int b)
"一个参数为(int), 返回值为void的方法";
public int Method3(int m)
"一个参数为(int), 返回值为int的方法";
public int Method4(int n)
"一个参数为(int), 返回值为int的方法";
public int Method5(int x, int y)
"一个参数为(int,int), 返回值为int的方法"。
可以发现,Method1,Method2属于同一类,Method3,Method4属于同一类。思考一下,一般的类型都是由一个属于来描述的,比如整数类型用int,学生类型用Student这种class类型,接口用interface,如何用一个标准的术语来描述一个方法类型?
二、委托
委托(delegate),是对一个方法类型的描述。例如:
public delegate void DelegateType(int a);
DelegateType类型指的是“一种参数为(int), 返回值为void的方法”,其中delegate声明它是个委托类型,DelegateType是类型的名字。
一个委托对象,就是一个方法的实例,传参时要指定某个对象的某个方法,例如:
// 第一类方法 public delegate void DelegateType1(int a); // 第二类方法 public delegate int DelegateType2(int a); // 第三类方法 public delegate int DelegateType3(int a, int b); static void Main(string[] args) { Example ex = new Example(); DelegateType1 method1 = new DelegateType1(ex.Method1); method1(2022); //相当于 ex.Method1(2022); }
三、匿名委托
每次实例化一个委托时,都需要事先定义一个委托所要调用的方法。为了简化这个流程,官方给出了一种匿名方法来实例化委托。这样我们在实例化委托时可以非常方便的实例化它的方法。
// 第一类方法 public delegate void DelegateType1(int a); // 第二类方法 public delegate int DelegateType2(int a); // 第三类方法 public delegate int DelegateType3(int a, int b); static void Main(string[] args) { // 等号后面为匿名委托 DelegateType1 type1 = delegate (int a) { Console.WriteLine("this is type1: " + a); }; type1(2022); }
四、Lambda表达式
纵然匿名方法使用很方便,官方还是用了一种更加方便的写法代替了匿名方法,Lambda表达式。
以上的匿名委托的实例化最佳改进
static void Main(string[] args) { // Lambda表达式 DelegateType1 type1 = a => Console.WriteLine("this is type1: " + a); type1(2022); }
其中=>符号代表Lambda表达式,它的左侧是参数,右侧是要返回或执行的语句。参数要放在圆括号中,若只有一个参数,为了方便起见可省略圆括号。有多个参数或者没有参数时,不可省略圆括号。
相比匿名函数,在表达式Lambda中,方法体的花括号{}和return关键字被省略掉了。
五、Action与Func
上面讲到,委托实际上是对一类方法的特征描述。其实官方已经给出了两个通用的Delegate:
System.Action 表示返回值为void的方法;
System.Func 表示返回值不为void的方法;
几乎所有的方法,都可以用这两种委托来表示。因此上面介绍的方法可以如下表示
static void Main(string[] args) { Example ex = new Example(); Action<int> action1 = new Action<int>(ex.Method1); action1(2022); //相当于 ex.Method1(2022); Func<int, int, int> func1 = new Func<int, int, int>(ex.Method5); func1(2, 6); //相当于 ex.Method5(2, 6); }
六、委托参数的定义和使用
委托的运用,最具代表性的就是LINQ,LINQ 查询表达式模式依赖于其所有功能的委托。比如:
var smallNumbers = numbers.Where(n => n < 10);
其中,Where方法内传递的就是一个以Lambda表示的委托类型,那么我们自己是否也可以定义参数为委托类型的方法呢?当然是可以的。
static void Main(string[] args) { // 创建一个 0-9 的数组 int[] arr = new int[10]; for (int i = 0; i < 10; i++) { arr[i] = i; } // 累加大于5的值 6 + 7 + 8 + 9 = 30 var num = SumNumber(arr, a => a > 5); } // 参数中有委托类型的方法 private static long SumNumber(int[] array, Func<int, bool> predicate) { long number = 0; foreach(var item in array) { // 表达式条件成立,则累加 if (predicate(item)) { number += item; } } return number; }
我们先定义一个返回值是(long),参数是(int[], Func<int, bool>)的SumNumber方法。在调用此方法时传递数组,和lambda表达式。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南