在C#中,委托(Delegates)是一种强类型引用类型,它代表了对具有特定签名(参数类型和返回类型)的方法的引用。简单来说,你可以把委托理解为一个可以指向方法的“指针”,从而允许你将方法作为一个参数传递给其他方法,或者将方法的调用委托给其他的对象。以下是C#委托的一些关键概念及其使用方式:
1.定义委托类型
定义委托类型需要指定其参数类型和返回类型。下面是一个简单的委托定义的例子:
public delegate int SumDelegate(int num1, int num2);
这个委托表示一个接受两个整数参数并返回一个整数的方法。
2.创建委托实例
一旦定义了委托类型,就可以创建该类型的实例,并将其绑定到符合签名要求的方法:
public static int AddNumbers(int x, int y) => x + y;
SumDelegate sum = new SumDelegate(AddNumbers);
// C# 3.0 及更高版本可以用隐式类型推断简化为:
SumDelegate sum = AddNumbers;
3.调用委托
创建了委托实例后,可以像调用普通方法一样调用它:
int result = sum(10, 20); // 结果为 30
4.多播委托(Delegate Chaining)
一个委托实例可以关联多个方法,当调用委托时,会依次调用这些方法:
public static int MultiplyNumbers(int x, int y) => x * y;
sum += MultiplyNumbers; // 添加第二个方法到委托
result = sum(10, 20); // 先加后乘,结果为 60
5. 委托的使用场景
- 事件处理:委托常用于处理事件。例如,当用户点击按钮时触发一个事件,您可以将一个方法绑定到该事件的委托上,从而实现事件处理。
- 回调函数:委托也常用于回调函数的实现。例如,在异步编程中,您可以将一个方法作为参数传递给另一个方法,以便在适当的时候调用它。
- 扩展方法:委托还可以用于实现扩展方法,允许您在不修改原始类的情况下向其添加新的方法。
6. Lambda表达式
Lambda表达式是C#(以及其他支持函数式编程特性的语言,如Java 8+)中一种简洁的匿名函数形式。Lambda表达式的主要目的是方便编写更简洁、更灵活的代码,特别是在处理集合、事件处理、以及函数式接口等方面。
基本结构: Lambda表达式的基本语法格式如下:
(parameters) => expression
// 或者对于多条语句的情况,用花括号包围
(parameters) => { statement1; statement2; ... }
这里的 parameters
是零个或多个输入参数,参数类型可以根据上下文推断;expression
是一个返回单个值的表达式;而 { statement1; statement2; ... }
则是可以包含多条语句的代码块。
特点:
- 匿名性:Lambda表达式无需定义单独的方法,而是直接在代码中书写。
- 延迟执行:Lambda表达式不是立即执行的代码块,而是可以在满足特定条件时才执行。
- 类型推断:C#编译器可以根据上下文自动推断Lambda表达式的参数类型和返回类型。
- 函数式接口:Lambda表达式常与函数式接口(只有一个抽象方法的接口,如C#中的
Func<T1, T2, ..., TResult>
和Action<T1, T2, ..., Tn>
)一起使用,使得可以将Lambda表达式作为参数传递给方法。
使用场景:
- LINQ查询:Lambda表达式用于定义查询条件和投影操作。
- 事件处理:简化事件处理器的定义,可以直接在事件属性后面赋值Lambda表达式。
- 高阶函数:作为参数传递给其他函数,如
Array.Sort
中的比较器,或List.ForEach
中的动作。 - 并行处理和异步编程:在任务调度中定义工作单元。
示例:
// 使用Lambda表达式进行排序
var numbers = new List<int> { 3, 1, 4, 1, 5, 9 };
numbers.Sort((a, b) => a.CompareTo(b));
// 使用Lambda表达式作为LINQ查询的一部分
var evenNumbers = numbers.Where(n => n % 2 == 0);
// 使用Lambda表达式处理事件
button.Click += (sender, args) => Console.WriteLine("Button was clicked!");
// 使用Lambda表达式实现高阶函数
Enumerable.Range(1, 10).Select(x => x * x).ToList();