委托是 C# 中一种非常重要的引用类型,它是函数式编程在 C# 中的基础。
关键字:delegate (读音: /'dɛlɪɡət/)
核心概念:
通俗理解:委托就像是一个“办事处代表”。你定义了这个代表能办什么事(比如能接收两个整数,返回一个整数)。任何符合这个标准的具体办事员(具体方法),都可以被指派给这个代表去执行任务。
使用自定义委托通常分为三步:
// 1. 声明委托 (规定了必须是:两个int参数,返回bool) public delegate bool CompareDelegate(int a, int b); class Program { static void Main() { // 2. 实例化委托,指向 IsGreater 方法 // 注意:这里只写方法名,不要带括号() CompareDelegate compare = IsGreater; // 3. 调用委托 bool result = compare(5, 3); Console.WriteLine($"Is 5 greater than 3? {result}"); } // 具体方法:签名必须与委托一致 static bool IsGreater(int a, int b) { return a > b; } }
委托允许我们将判断逻辑从主流程中剥离出来。
using System; // 定义委托:接收 string,返回 bool public delegate bool StringFilter(string input); class Program { static void Main() { // 这里的逻辑是可以动态替换的 StringFilter filter = IsLongEnough; bool result = filter("Hello, World!"); Console.WriteLine($"Is 'Hello, World!' long enough? {result}"); } static bool IsLongEnough(string input) { return input.Length >= 10; } }
如果委托需要指向另一个类的方法,需要先实例化那个类。
class Program { // 自定义委托类型 public delegate int MathOpDelegate(int a, int b); static void Main(string[] args) { // 1. 实例化包含方法的类 Calculator calc = new Calculator(); // 2. 委托指向该实例的成员方法 MathOpDelegate myDelegate = calc.Multiply; // 注意:不要加括号() // 3. 执行委托 int result = myDelegate(5, 7); Console.WriteLine($"结果: {result}"); // 输出 35 } } class Calculator { public int Multiply(int a, int b) { return a * b; } }
为了避免每次使用委托都要先写 `public delegate …`,C# 提供了两个通用的泛型委托。
| 委托类型 | 返回值 | 用途 | 格式示例 |
|---|---|---|---|
| Action | 无 (void) | 执行动作,不需结果 | Action<T1, T2> |
| Func | 有 (TResult) | 计算并返回结果 | Func<T1, T2, TResult> |
`Action` 后面尖括号里的类型全是输入参数。
static void Main() { // Action<string> 表示:接收一个 string 参数,无返回值 Action<string> print = PrintMessage; print("Hello, System Delegate!"); } static void PrintMessage(string message) { Console.WriteLine(message); }
`Func` 后面尖括号里,最后一个类型永远是返回值类型,前面的都是输入参数类型。
static void Main() { // Func<int, int, int> 表示: // 输入参数1: int // 输入参数2: int // 返回值: int Func<int, int, int> addFunc = Add; int sum = addFunc(3, 4); Console.WriteLine($"3 + 4 = {sum}"); } static int Add(int a, int b) { return a + b; }
有时我们只需要一个简单的逻辑,专门写一个静态函数太麻烦,这时可以使用匿名方法。
在实例化委托时,直接使用 `delegate` 关键字定义方法体。
public delegate int MathDelegate(int a, int b); static void Main(string[] args) { // 直接内联定义逻辑,没有方法名 MathDelegate multiply = delegate (int a, int b) { return a * b; }; int result = multiply(5, 7); Console.WriteLine(result); }
现代 C# 开发中,几乎不再使用 `delegate (…) {}` 的匿名方法写法,而是使用更简洁的 Lambda 表达式 (`⇒`)。
static void Main(string[] args) { // 这里的 (a, b) => a * b 等同于上面的匿名方法 // => 读作 "goes to" Func<int, int, int> multiply = (a, b) => a * b; int result = multiply(5, 7); Console.WriteLine(result); }