C#委托是一种类型安全的函数指针,用于封装方法引用,开发者可以根据使用需求选择不同类型的委托。C#中的委托主要分为自定义委托、Action委托、Func委托、Predicate委托这几种类型,每种类型都有其特定的使用场景。

C#委托的主要类型
1. 自定义委托
自定义委托是开发者根据自身的业务需求手动定义的委托类型,需要明确指定委托的参数列表和返回值类型。定义自定义委托需要使用delegate关键字,定义后就可以创建该委托的实例,绑定对应的方法。
自定义委托适合需要特定参数和返回值格式的场景,比如需要封装带多个参数、或者返回值类型不是常规类型的场景。
// 定义自定义委托,无参数无返回值
public delegate void MyCustomDelegate();
// 定义带两个int参数,返回string的自定义委托
public delegate string MyCalcDelegate(int a, int b);
class Program
{
static void PrintHello()
{
Console.WriteLine("Hello");
}
static string Add(int x, int y)
{
return (x + y).ToString();
}
static void Main()
{
// 创建自定义委托实例并绑定方法
MyCustomDelegate del1 = PrintHello;
del1(); // 输出 Hello
MyCalcDelegate del2 = Add;
string result = del2(3, 5);
Console.WriteLine(result); // 输出 8
}
}
2. Action委托
Action委托是C#内置的委托类型,位于System命名空间下,它封装的方法没有返回值。Action委托有多个重载版本,支持0到16个输入参数,开发者可以根据需要传递对应数量的参数。
Action委托适合封装不需要返回结果的方法,比如执行一些操作、输出日志、修改状态等场景。
using System;
class Program
{
static void PrintNum(int num)
{
Console.WriteLine($"当前数字是:{num}");
}
static void PrintSum(int a, int b)
{
Console.WriteLine($"两数之和是:{a + b}");
}
static void Main()
{
// 无参数的Action
Action action1 = () => Console.WriteLine("无参数Action执行");
action1();
// 带1个int参数的Action
Action<int> action2 = PrintNum;
action2(10);
// 带2个int参数的Action
Action<int, int> action3 = PrintSum;
action3(3, 7);
}
}
3. Func委托
Func委托同样是C#内置的委托类型,位于System命名空间下,它封装的方法必须有返回值。Func委托的最后一个泛型参数表示返回值类型,前面的泛型参数表示输入参数,支持0到16个输入参数。
Func委托适合封装需要返回结果的方法,比如计算数值、获取数据、处理字符串等场景。
using System;
class Program
{
static int Multiply(int a, int b)
{
return a * b;
}
static string GetName()
{
return "张三";
}
static void Main()
{
// 无参数,返回string的Func
Func<string> func1 = GetName;
string name = func1();
Console.WriteLine(name); // 输出 张三
// 带2个int参数,返回int的Func
Func<int, int, int> func2 = Multiply;
int product = func2(4, 6);
Console.WriteLine(product); // 输出 24
}
}
4. Predicate委托
Predicate委托是C#内置的委托类型,位于System命名空间下,它封装的方法接收一个输入参数,返回值为bool类型。Predicate委托本质上是一种特殊的Func委托,等价于Func<T, bool>,但语义更明确,专门用于判断条件。
Predicate委托适合封装条件判断的方法,常用于集合的筛选操作,比如List的Find、FindAll方法的参数就经常使用Predicate委托。
using System;
using System.Collections.Generic;
class Program
{
static bool IsEven(int num)
{
return num % 2 == 0;
}
static void Main()
{
Predicate<int> isEvenPredicate = IsEven;
List<int> nums = new List<int> { 1, 2, 3, 4, 5, 6 };
// 使用Predicate筛选偶数
List<int> evenNums = nums.FindAll(isEvenPredicate);
foreach (int n in evenNums)
{
Console.WriteLine(n); // 输出 2 4 6
}
}
}
不同类型委托的选择建议
在实际开发中,选择委托类型可以遵循以下原则:
- 如果需要的方法参数和返回值不符合内置委托的格式,或者需要更明确的语义,选择自定义委托。
- 如果封装的方法没有返回值,优先选择Action委托,减少自定义委托的定义成本。
- 如果封装的方法有返回值,优先选择Func委托,根据参数数量和返回值类型选择对应的泛型版本。
- 如果是条件判断场景,需要返回bool值,优先选择Predicate委托,语义更清晰,也符合很多内置方法的参数要求。
合理使用不同类型的委托,可以让代码更简洁,可读性更强,也能减少不必要的重复代码定义。