如何通过泛型枚举优化C#函数以消除switch分支?
如何消除枚举判断的Switch语句?
我当前用Switch语句根据SubGroups枚举值来遍历对应的子枚举类型,实现将面板对应组的所有输入置为false,再激活指定的子项。代码能正常运行,但想找更优方案,请问能不能通过传递泛型枚举类型来消除Switch?或者有没有枚举以外的实现方式?
原代码:
public static void ShowGroupSub(List<BasicTriListWithSmartObject> panels, uint type,uint sub) { foreach (BasicTriListWithSmartObject panel in panels) { switch(type) { case (uint)SubGroups.Control: foreach (uint index in Enum.GetValues(typeof(ControlSubs))) panel.BooleanInput[index].BoolValue = false; panel.BooleanInput[sub].BoolValue = true; break; case (uint)SubGroups.Presets: foreach (uint index in Enum.GetValues(typeof(PresetSubs))) panel.BooleanInput[index].BoolValue = false; panel.BooleanInput[sub].BoolValue = true; break; case (uint)SubGroups.VideoCall: foreach (uint index in Enum.GetValues(typeof(VideoCallSubs))) panel.BooleanInput[index].BoolValue = false; panel.BooleanInput[sub].BoolValue = true; break; } } } public enum SubGroups : uint { Control = 1, Presets = 2, VideoCall = 3 } public enum ControlSubs : uint { Bluray = 60, PC = 61, Laptop = 62, AirMedia = 63, ClickShare = 64, CamControl = 65, DocCam = 66, CATV = 67, } public enum PresetSubs : uint { Main = 60, Edit = 61 } public enum VideoCallSubs : uint { Contacts = 271, Keyboard = 272, Camera = 273, CallActive = 274, AddCallContacts = 275, AddCallKeyboard = 276 }
方案一:泛型+映射字典消除Switch
通过建立SubGroups与子枚举类型的映射,结合泛型方法提取重复逻辑,完全移除Switch:
// 提前定义映射字典,关联主枚举和对应的子枚举类型 private static readonly Dictionary<SubGroups, Type> _subGroupEnumMap = new() { { SubGroups.Control, typeof(ControlSubs) }, { SubGroups.Presets, typeof(PresetSubs) }, { SubGroups.VideoCall, typeof(VideoCallSubs) } }; public static void ShowGroupSub(List<BasicTriListWithSmartObject> panels, SubGroups type, uint sub) { // 处理无效的组类型 if (!_subGroupEnumMap.TryGetValue(type, out var subEnumType)) return; // 调用泛型方法处理核心逻辑 ToggleSubGroup(panels, subEnumType, sub); } private static void ToggleSubGroup(List<BasicTriListWithSmartObject> panels, Type subEnumType, uint sub) { // 可选:验证sub是否属于当前子枚举,避免无效索引报错 if (!Enum.IsDefined(subEnumType, sub)) throw new ArgumentOutOfRangeException(nameof(sub), "该子项不属于当前组"); foreach (var panel in panels) { // 遍历子枚举所有值,置为false foreach (uint index in Enum.GetValues(subEnumType).Cast<uint>()) panel.BooleanInput[index].BoolValue = false; // 激活目标子项 panel.BooleanInput[sub].BoolValue = true; } }
后续新增SubGroups枚举值时,只需要在字典中添加一行映射即可,扩展性大幅提升。同时把参数uint type改为SubGroups type,避免强制转换,类型更安全。
方案二:策略模式(面向对象替代方案)
如果想彻底脱离枚举的限制,可将每组逻辑封装为独立策略类,实现完全的解耦:
// 定义策略接口,规范组操作 public interface ISubGroupStrategy { IEnumerable<uint> GetAllSubIndices(); bool IsValidSub(uint sub); } // 实现Control组策略 public class ControlSubGroupStrategy : ISubGroupStrategy { public IEnumerable<uint> GetAllSubIndices() => Enum.GetValues(typeof(ControlSubs)).Cast<uint>(); public bool IsValidSub(uint sub) => Enum.IsDefined(typeof(ControlSubs), sub); } // 实现Presets组策略 public class PresetSubGroupStrategy : ISubGroupStrategy { public IEnumerable<uint> GetAllSubIndices() => Enum.GetValues(typeof(PresetSubs)).Cast<uint>(); public bool IsValidSub(uint sub) => Enum.IsDefined(typeof(PresetSubs), sub); } // 实现VideoCall组策略 public class VideoCallSubGroupStrategy : ISubGroupStrategy { public IEnumerable<uint> GetAllSubIndices() => Enum.GetValues(typeof(VideoCallSubs)).Cast<uint>(); public bool IsValidSub(uint sub) => Enum.IsDefined(typeof(VideoCallSubs), sub); } // 映射主枚举到对应策略 private static readonly Dictionary<SubGroups, ISubGroupStrategy> _subGroupStrategies = new() { { SubGroups.Control, new ControlSubGroupStrategy() }, { SubGroups.Presets, new PresetSubGroupStrategy() }, { SubGroups.VideoCall, new VideoCallSubGroupStrategy() } }; public static void ShowGroupSub(List<BasicTriListWithSmartObject> panels, SubGroups type, uint sub) { if (!_subGroupStrategies.TryGetValue(type, out var strategy)) return; if (!strategy.IsValidSub(sub)) throw new ArgumentOutOfRangeException(nameof(sub)); foreach (var panel in panels) { foreach (var index in strategy.GetAllSubIndices()) panel.BooleanInput[index].BoolValue = false; panel.BooleanInput[sub].BoolValue = true; } }
这种方式适合逻辑复杂的场景,新增组只需添加对应的策略类和字典映射,各组逻辑完全隔离,维护性更好。
额外优化建议
- 缓存枚举值:如果子枚举不会动态修改,可提前将
Enum.GetValues的结果缓存起来,避免重复调用的性能开销。 - 类型安全:始终使用枚举类型而非
uint作为参数,减少类型转换错误。
内容的提问来源于stack exchange,提问作者Steven Amos
相关产品推荐
相关产品推荐

