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

C#中不同枚举类型的同逻辑方法优化设计模式咨询

针对C#枚举重载方法逻辑重复的优化方案

你的核心问题是两个逻辑完全一致的异步泛型方法,因依赖无继承关系的枚举导致代码重复,且需判断不同枚举的特定值执行相同后端逻辑。以下是几种适配C#特性的优化方案:

方案1:提取核心逻辑+传递判断委托(最简方案)

直接将重复逻辑抽离到私有泛型方法,通过委托传入不同枚举的判断规则,快速消除代码冗余。

// 对外暴露的重载方法
public async Task<T> Foo<T>(string id, IList<UserSettingType> settings, Func<IMyService, Task<T>> backendFunc)
{
    return await FooCore(id, settings, s => s == UserSettingType.Permission, backendFunc);
}

public async Task<T> Foo<T>(string id, IList<TeamsSettingType> settings, Func<IMyService, Task<T>> backendFunc)
{
    return await FooCore(id, settings, s => s == TeamsSettingType.PermissionPolicy, backendFunc);
}

// 公共核心逻辑,泛型适配任意枚举类型
private async Task<T> FooCore<T, TSetting>(string id, IList<TSetting> settings, Func<TSetting, bool> shouldTrigger, Func<IMyService, Task<T>> backendFunc)
{
    // 原重复逻辑统一实现
    foreach (var setting in settings)
    {
        if (shouldTrigger(setting))
        {
            return await backendFunc(_myService);
        }
    }

    // 其他通用逻辑
    return default;
}

优点:实现简单,无额外类型定义,快速解决重复问题;缺点:新增枚举时需新增重载方法。

方案2:适配器模式(适配异构枚举)

将无继承关系的枚举适配为统一的抽象接口,让核心逻辑仅处理抽象类型,符合开闭原则。

  1. 定义抽象接口:
public interface ISetting
{
    bool ShouldTriggerBackend();
}
  1. 为每个枚举实现适配器:
public class UserSettingAdapter : ISetting
{
    private readonly UserSettingType _setting;

    public UserSettingAdapter(UserSettingType setting) => _setting = setting;

    public bool ShouldTriggerBackend() => _setting == UserSettingType.Permission;
}

public class TeamsSettingAdapter : ISetting
{
    private readonly TeamsSettingType _setting;

    public TeamsSettingAdapter(TeamsSettingType setting) => _setting = setting;

    public bool ShouldTriggerBackend() => _setting == TeamsSettingType.PermissionPolicy;
}
  1. 重构核心方法:
public async Task<T> Foo<T>(string id, IList<UserSettingType> settings, Func<IMyService, Task<T>> backendFunc)
{
    var adaptedSettings = settings.Select(s => new UserSettingAdapter(s)).ToList();
    return await FooCore(id, adaptedSettings, backendFunc);
}

public async Task<T> Foo<T>(string id, IList<TeamsSettingType> settings, Func<IMyService, Task<T>> backendFunc)
{
    var adaptedSettings = settings.Select(s => new TeamsSettingAdapter(s)).ToList();
    return await FooCore(id, adaptedSettings, backendFunc);
}

private async Task<T> FooCore<T>(string id, IList<ISetting> settings, Func<IMyService, Task<T>> backendFunc)
{
    foreach (var setting in settings)
    {
        if (setting.ShouldTriggerBackend())
        {
            return await backendFunc(_myService);
        }
    }

    // 其他通用逻辑
    return default;
}

优点:新增枚举仅需添加对应适配器,核心逻辑无需修改;缺点:需额外定义适配器类,代码量略增。

方案3:策略模式(解耦判断逻辑)

将不同枚举的判断逻辑封装为独立策略,核心方法依赖策略接口,进一步解耦判断规则与业务逻辑。

  1. 定义策略接口:
public interface ISettingTriggerStrategy<TSetting>
{
    bool ShouldTrigger(TSetting setting);
}
  1. 实现枚举专属策略:
public class UserSettingTriggerStrategy : ISettingTriggerStrategy<UserSettingType>
{
    public bool ShouldTrigger(UserSettingType setting) => setting == UserSettingType.Permission;
}

public class TeamsSettingTriggerStrategy : ISettingTriggerStrategy<TeamsSettingType>
{
    public bool ShouldTrigger(TeamsSettingType setting) => setting == TeamsSettingType.PermissionPolicy;
}
  1. 重构核心方法:
public async Task<T> Foo<T>(string id, IList<UserSettingType> settings, Func<IMyService, Task<T>> backendFunc)
{
    return await FooCore(id, settings, new UserSettingTriggerStrategy(), backendFunc);
}

public async Task<T> Foo<T>(string id, IList<TeamsSettingType> settings, Func<IMyService, Task<T>> backendFunc)
{
    return await FooCore(id, settings, new TeamsSettingTriggerStrategy(), backendFunc);
}

private async Task<T> FooCore<T, TSetting>(string id, IList<TSetting> settings, ISettingTriggerStrategy<TSetting> triggerStrategy, Func<IMyService, Task<T>> backendFunc)
{
    foreach (var setting in settings)
    {
        if (triggerStrategy.ShouldTrigger(setting))
        {
            return await backendFunc(_myService);
        }
    }

    // 其他通用逻辑
    return default;
}

优点:判断逻辑完全独立,可单独修改或替换;缺点:需定义多个策略类,适合判断规则复杂或易变的场景。

方案4:标记接口+扩展方法(简洁适配)

通过标记接口约束枚举,结合扩展方法统一处理判断逻辑,兼顾简洁性与一定扩展性。

  1. 定义标记接口:
public interface ISettingEnum { }
  1. 让枚举实现标记接口:
public enum UserSettingType : byte, ISettingEnum
{
    // 其他枚举值
    Permission
}

public enum TeamsSettingType : byte, ISettingEnum
{
    // 其他枚举值
    PermissionPolicy
}
  1. 编写扩展方法实现判断:
public static class SettingEnumExtensions
{
    public static bool ShouldTriggerBackend(this ISettingEnum setting)
    {
        return setting switch
        {
            UserSettingType us => us == UserSettingType.Permission,
            TeamsSettingType ts => ts == TeamsSettingType.PermissionPolicy,
            _ => false
        };
    }
}
  1. 重构核心方法:
public async Task<T> Foo<T>(string id, IList<UserSettingType> settings, Func<IMyService, Task<T>> backendFunc)
{
    return await FooCore(id, settings.Cast<ISettingEnum>().ToList(), backendFunc);
}

public async Task<T> Foo<T>(string id, IList<TeamsSettingType> settings, Func<IMyService, Task<T>> backendFunc)
{
    return await FooCore(id, settings.Cast<ISettingEnum>().ToList(), backendFunc);
}

private async Task<T> FooCore<T>(string id, IList<ISettingEnum> settings, Func<IMyService, Task<T>> backendFunc)
{
    foreach (var setting in settings)
    {
        if (setting.ShouldTriggerBackend())
        {
            return await backendFunc(_myService);
        }
    }

    // 其他通用逻辑
    return default;
}

优点:无需额外类,代码简洁;缺点:新增枚举需修改扩展方法的switch分支,不符合开闭原则,适合枚举类型稳定的场景。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 09:25:08