委托的五个基本使用步骤
1. 委托使用流程
委托用于保存并调用符合指定签名的方法。
基本流程:
声明委托类型。 编写符合签名的方法。 创建委托变量。 关联具体方法。 调用委托变量。
2. 第一步:声明委托类型
使用 delegate 关键字声明委托:
public delegate void AlarmHandler(
string equipmentId,
string message);
该声明规定了方法签名:
返回值必须为 void。参数数量、类型和顺序必须兼容。 方法名称不受限制。
委托可以声明在命名空间中,也可以嵌套在类中。需要被多个类使用时,通常放在命名空间中。
3. 第二步:编写匹配方法
static void ShowAlarm(
string equipmentId,
string message)
{
Console.WriteLine(
$"界面报警:{equipmentId},{message}");
}
static void WriteAlarmLog(
string equipmentId,
string message)
{
Console.WriteLine(
$"写入日志:{equipmentId},{message}");
}
下面的方法不能关联到 AlarmHandler:
// 错误:缺少 message 参数
// static void InvalidMethod(string equipmentId)
// {
// }
签名不匹配时会产生编译错误。
4. 第三步:创建委托变量
委托是引用类型,可以先创建空变量:
AlarmHandler handler = null;
也可以在创建时直接指定方法:
AlarmHandler handler = ShowAlarm;
完整写法如下,但通常不需要:
AlarmHandler handler =
new AlarmHandler(ShowAlarm);
5. 第四步:关联委托方法
使用 = 赋值
handler = ShowAlarm;
= 会替换委托变量原来关联的方法。
使用 += 添加
handler += WriteAlarmLog;
此时委托依次关联:
ShowAlarmWriteAlarmLog
一个委托关联多个方法,称为多播委托。
使用 -= 移除
handler -= ShowAlarm;
-= 会移除一个匹配的方法关联。方法不存在时不会报错。
6. 第五步:调用委托
可以像调用普通方法一样调用委托:
handler("EQ-001", "温度过高");
更安全的写法:
handler?.Invoke(
"EQ-001",
"温度过高");
?.Invoke() 会先检查委托是否为 null,避免 NullReferenceException。
7. 完整工控示例
public delegate void AlarmHandler(
string equipmentId,
string message);
classProgram
{
static void Main()
{
AlarmHandler handler = ShowAlarm;
handler += WriteAlarmLog;
CheckTemperature(86.5, handler);
handler -= ShowAlarm;
CheckTemperature(90, handler);
}
static void CheckTemperature(
double temperature,
AlarmHandler handler)
{
if (temperature > 80)
{
handler?.Invoke(
"EQ-001",
$"温度过高:{temperature}");
}
}
static void ShowAlarm(
string equipmentId,
string message)
{
Console.WriteLine(
$"界面报警:{equipmentId},{message}");
}
static void WriteAlarmLog(
string equipmentId,
string message)
{
Console.WriteLine(
$"报警日志:{equipmentId},{message}");
}
}
第一次检测会显示界面报警并记录日志。移除 ShowAlarm 后,第二次检测只记录日志。
8. 关联实例方法
委托既可以关联静态方法,也可以关联实例方法。
public class AlarmService
{
public void Save(
string equipmentId,
string message)
{
Console.WriteLine(
$"保存报警:{equipmentId},{message}");
}
}
AlarmService service = new AlarmService();
AlarmHandler handler = service.Save;
handler("EQ-002", "压力过高");
关联实例方法时,委托会同时保存对象引用和方法引用。
9. 多播委托注意事项
方法按照添加顺序依次执行。 某个方法抛出未处理异常时,后续方法不会继续执行。 多播委托有返回值时,调用结果是最后一个方法的返回值。 =会覆盖原有关联,添加方法应使用+=。长期保存实例方法的委托,会同时保留对应对象的引用。
查看已关联的方法:
foreach (Delegate item in handler.GetInvocationList())
{
Console.WriteLine(item.Method.Name);
}
10. WinForms 事件中的委托
buttonStart.Click += buttonStart_Click;
这段代码将 buttonStart_Click 方法关联到 Click 事件内部使用的委托。
private void buttonStart_Click(
object sender,
EventArgs e)
{
Console.WriteLine("启动设备");
}
事件处理方法必须符合 EventHandler 规定的签名。
11. 常见错误
+= 写成 = | |
12. 小结
委托类型规定可关联方法的签名。 委托变量用于保存具体方法。 =负责赋值,+=负责添加,-=负责移除。调用多播委托时,方法按照关联顺序执行。 推荐使用 ?.Invoke()安全调用可能为空的委托。