C#委托用法详解:定义、实例化与多播机制
委托是C#中实现事件处理和回调机制的基础类型,它将方法封装为对象。本文系统梳理委托的定义规范、三种主要实例化方式(包括Lambda简化写法),解析Action、Func、Predicate三大内置泛型委托的应用场景,并详细说明多播委托的链式调用特性与注意事项。
1. 什么是委托
从数据结构角度理解,委托是一种用户自定义类型,其本质是对方法的抽象。它存储了一组具有相同签名(参数列表)和返回类型的方法的地址。当调用委托时,所有已注册的方法将按顺序依次执行。
2. 委托的定义
如同类需要声明一样,委托类型在使用前必须先定义。定义的语法原型如下:
delegate <返回类型> <委托名称>(<参数列表>)
示例:定义一个名为 MyDelegate 的委托,它可以指向那些返回 void 且接受一个 int 类型参数的方法:
public delegate void MyDelegate(int number);
3. 委托的实例化
定义委托类型后,需要通过实例化将其与方法关联。以下是三种常见的实例化方式:
第1步:使用 new 关键字
这是最传统的实例化方式。语法格式为:<委托类型> <变量名> = new <委托类型>(<方法名>)。
例如,通过 new 关键字将 GetSum 方法绑定到委托变量:
MyDelegate _myDelegate = new MyDelegate(GetSum);
static int GetSum(int x, int y)
{
return x + y;
}
第2步:使用匿名方法
匿名方法允许在委托实例化时直接定义方法体,无需单独创建命名方法。语法中使用 delegate 关键字:
MyDelegate myDelegate = delegate(int x, int y)
{
return x + y;
};
第3步:使用 Lambda 表达式
Lambda 表达式是 C# 3.0 引入的更简洁的匿名方法语法,推荐使用的方式。利用 => 操作符连接输入参数和方法体:
MyDelegate myDelegateLambda = (int x, int y) => { return x + y; };
class Program
{
// 声明委托
delegate int MyDelegate(int x, int y);
static void Main(string[] args)
{
// 1、使用 new 关键字
MyDelegate _myDelegate = new MyDelegate(GetSum);
// 2、使用匿名方法
MyDelegate myDelegate = delegate(int x, int y)
{
return x + y;
};
// 3、使用 Lambda 表达式
MyDelegate myDelegateLambda = (int x, int y) => { return x + y; };
}
static int GetSum(int x, int y)
{
return x + y;
}
}4. 泛型委托
委托支持泛型,这使得同一个委托类型可以应用于多种不同的参数和返回类型,提高代码复用性。
泛型委托的原型结构为:delegate 。其中 T1 通常代表输入参数类型,T2 代表返回类型。
示例:定义一个接收 int 参数并返回 bool 的泛型委托:
// 定义泛型委托
public delegate bool CheckDelegate<T>(T t);
// 使用
CheckDelegate<int> checkMod = i => (i % 2) == 0;
Console.WriteLine(checkMod(9)); // 输出 False
5. C# 内置泛型委托
C# 提供了三种常用的内置泛型委托,涵盖了大多数常见场景:
- Action<T>:表示无返回值的方法。可以有多个输入参数,但必须没有返回值(void)。
- Func<TResult>:表示有返回值的方法。必须指定至少一个输入参数和一个 TResult 返回类型。
- Predicate<T>:特指返回 bool 值的委托,通常用于定义判断条件或过滤逻辑。
代码示例展示三者的用法:
namespace DelegateDemo
{
class Program
{
static void Main(string[] args)
{
// 1、Action 只能委托无返回值的方法
Action actionHello = SayHello;
actionHello("Hello World");
// 2、Func 委托必须有返回值的方法
Func funcCheck = IsEven;
Console.WriteLine(funcCheck(5)); // 输出 False
// 3、Predicate 返回 bool 值的判断委托
Predicate predicateCheck = IsEven;
// 也可以使用 Lambda 简化
Predicate predicate = p => p % 2 == 0;
Console.WriteLine(predicateCheck(26)); // 输出 True
}
static void SayHello(string strMsg)
{
Console.WriteLine(strMsg);
}
static bool IsEven(int i)
{
return i % 2 == 0;
}
}
} 6. 多播委托
一个委托实例可以注册多个方法,这种机制称为多播委托。执行委托时,注册的每个方法都会按添加顺序依次调用。
第1步:注册方法
使用 += 运算符将方法追加到委托链中。注意:委托必须先通过 = 初始化至少一个方法,之后才能使用 += 注册其他方法。
MyDelegate _myDelegate = new MyDelegate(fun1); // 初始化为 fun1
_myDelegate += fun2; // 追加 fun2
第2步:解除注册
使用 -= 运算符可以将指定方法从委托链中移除:
_myDelegate -= fun2;
第3步:返回值处理
如果委托类型有返回值,调用多播委托时,返回的将是最后一个执行的方法的返回值。之前方法产生的返回值会被丢弃。若涉及异常处理,建议谨慎使用多播委托,或者手动维护委托链以捕获中间异常。
class Program
{
delegate int MyDelegate(int x, int y);
static void Main(string[] args)
{
// 注册多个方法
MyDelegate _myDelegate = new MyDelegate(fun1);
_myDelegate += fun2;
// 调用委托,仅返回最后一个方法 fun2 的结果
Console.WriteLine(_myDelegate(10, 23)); // 输出 10
Console.ReadKey();
}
static int fun1(int x, int y)
{
return x + y; // 结果 33,被丢弃
}
static int fun2(int x, int y)
{
return x; // 结果 10,作为最终返回值
}
}总结
委托是C#面向对象编程的重要基石,灵活掌握其定义、Lambda实例化以及内置泛型委托的选用,能显著提升代码的解耦程度与可读性。在处理多任务回调时,合理使用多播委托并留意其返回值特性,可避免潜在的逻辑陷阱。以上就是C#委托用法的详细内容,更多关于C#高级特性的资料请关注本站其它相关文章!
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









