×

委托的五个基本使用步骤

独孤求败 独孤求败 发表于2026-07-15 23:49:18 浏览4 评论0

抢沙发发表评论

委托的五个基本使用步骤

1. 委托使用流程

委托用于保存并调用符合指定签名的方法。

基本流程:

  1. 声明委托类型。
  2. 编写符合签名的方法。
  3. 创建委托变量。
  4. 关联具体方法。
  5. 调用委托变量。
    图片


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;

此时委托依次关联:

  1. ShowAlarm
  2. WriteAlarmLog

一个委托关联多个方法,称为多播委托

使用 -= 移除

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() 安全调用可能为空的委托。


群贤毕至

访客