You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C#委托能否容纳对象集合?如何用委托实现观察者模式?

问题解答

问题1:C#中的委托能否包含对象集合?

C# 里的委托本身并不是对象集合,但它支持多播特性——一个委托实例可以包含多个方法引用,这些方法可以属于不同的对象。你可以把多个对象的同签名方法注册到同一个委托实例上,调用委托时会依次执行所有注册的方法。本质上是委托内部维护了一个方法调用列表,而非直接存储对象,但通过关联对象的方法,间接实现了对多个对象的回调能力。

问题2:用委托实现观察者模式,替代集合触发更新

实现思路

之前你用List<Student>存储订阅者并遍历触发Update,现在可以用多播委托替代集合,实现更简洁的逻辑:

  1. 定义一个和Student.Update方法签名匹配的委托类型;
  2. 在Academy类中声明该委托的字段,用来存储所有订阅的更新方法;
  3. Attach方法负责将学生的Update方法注册到委托实例,Detach方法则移除对应方法;
  4. 在Message属性的setter中调用委托,自动触发所有已注册学生的Update方法。

完整代码实现

// 定义委托,签名与Student.Update方法一致
public delegate void UpdateMessageHandler(string message);

public class Academy
{
    private string _message;
    // 用委托替代List<Student>存储订阅者的更新方法
    private UpdateMessageHandler _updateHandlers;

    public string Name { get; }
    public string Address { get; }

    public Academy(string name, string address)
    {
        Name = name;
        Address = address;
    }

    public string Message
    {
        get => _message;
        set
        {
            _message = value;
            // 调用委托,触发所有订阅者的更新(空判断避免空引用)
            _updateHandlers?.Invoke(_message);
        }
    }

    public void Attach(Student student)
    {
        // 将学生的Update方法添加到委托实例
        _updateHandlers += student.Update;
    }

    public void Detach(Student student)
    {
        // 从委托实例中移除学生的Update方法
        _updateHandlers -= student.Update;
    }
}

public class Student
{
    public string Name { get; }

    public Student(Academy academy, string name)
    {
        Name = name;
    }

    // 符合委托签名的更新方法
    public void Update(string message)
    {
        Console.WriteLine($"学生{Name}收到通知:{message}");
    }
}

// 测试代码
class Program
{
    static void Main()
    {
        var p = new Academy("College", "3rd Street");
        var s1 = new Student(p, "Joe");
        var s2 = new Student(p, "John");
        var s3 = new Student(p, "Susan");
        p.Attach(s1);
        p.Attach(s2);
        p.Attach(s3);
        p.Message = "Module A has been cancelled!";
        p.Detach(s2);
        p.Message = "Module B has been cancelled!";
    }
}

关于“将对象添加到非集合类型中”的说明

这里不是把对象直接存入委托(非集合类型),而是把对象的方法注册到多播委托中。委托内部会维护一个方法调用列表,每个注册的方法都关联着对应的对象实例,调用委托时就会触发对应对象的Update方法,最终实现和集合存储对象然后遍历调用完全一致的效果。

内容的提问来源于stack exchange,提问作者Aleksandar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 01:11:20