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

如何避免重复实现多泛型参数的SimpleEvent通知类?

避免泛型事件类的代码重复方案

你当前的SimpleEvent<T>和SimpleEvent<T,Y>核心逻辑完全一致,仅因泛型参数数量不同导致代码冗余,以下几种方案可解决这个问题:

方案一:用元组统一泛型参数

利用C#的元组特性,将多参数场景封装为单一元组类型,只需要维护一个SimpleEvent<T>类即可覆盖单参数、多参数的需求:

public class SimpleEvent<T>
{
    private event Action<T> listeners;
    private T storedValue;

    public void AddListener(Action<T> listener, bool notifySender = false)
    {
        listeners += listener;

        if (notifySender && storedValue != null)
            listener?.Invoke(storedValue);
    }

    // 补充更新存储值并触发事件的方法(原代码缺失,是事件类的必要功能)
    public void Trigger(T value)
    {
        storedValue = value;
        listeners?.Invoke(value);
    }
}

使用示例

  • 单参数场景:
var intEvent = new SimpleEvent<int>();
intEvent.AddListener(num => Console.WriteLine($"收到数值:{num}"));
intEvent.Trigger(100);
  • 双参数场景(利用元组解构):
var tupleEvent = new SimpleEvent<(string Msg, int Count)>();
// C# 7.0+支持直接解构元组参数
tupleEvent.AddListener((msg, count) => Console.WriteLine($"消息:{msg},计数:{count}"));
tupleEvent.Trigger(("Hello", 5));

方案二:抽象基类抽取公共逻辑

如果需要保留SimpleEvent<T>和SimpleEvent<T,Y>的原有类名结构,可以将重复的核心逻辑抽离到抽象基类中,子类仅实现参数相关的差异部分:

// 抽象基类:封装添加监听器的公共逻辑
public abstract class BaseSimpleEvent
{
    protected abstract void RegisterListener(object listener, bool notifyImmediately);

    public void AddListener(object listener, bool notifySender = false)
    {
        RegisterListener(listener, notifySender);
    }
}

// 单参数子类
public class SimpleEvent<T> : BaseSimpleEvent
{
    private event Action<T> listeners;
    private T storedValue;

    protected override void RegisterListener(object listener, bool notifyImmediately)
    {
        var action = listener as Action<T>;
        if (action == null) return;

        listeners += action;
        if (notifyImmediately && storedValue != null)
            action.Invoke(storedValue);
    }

    public void Trigger(T value)
    {
        storedValue = value;
        listeners?.Invoke(value);
    }
}

// 双参数子类
public class SimpleEvent<T, Y> : BaseSimpleEvent
{
    private event Action<T, Y> listeners;
    private (T, Y) storedValues;

    protected override void RegisterListener(object listener, bool notifyImmediately)
    {
        var action = listener as Action<T, Y>;
        if (action == null) return;

        listeners += action;
        if (notifyImmediately && storedValues.Item1 != null && storedValues.Item2 != null)
            action.Invoke(storedValues.Item1, storedValues.Item2);
    }

    public void Trigger(T tValue, Y yValue)
    {
        storedValues = (tValue, yValue);
        listeners?.Invoke(tValue, yValue);
    }
}

方案对比

  • 方案一更简洁,无需维护多个类,利用C#语言特性减少冗余,适合大多数场景;
  • 方案二保留了原有类的命名习惯,兼容已有代码的调用方式,但需要维护基类和子类结构。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 06:15:33