如何实现FruitsCombined与Fruits枚举的关联映射及筛选优化?
枚举绑定ComboBox后的多值映射优化方案
问题背景
我定义了两个枚举类型:
public enum Fruits { Apple = 1, Banana = 2, Strawberry = 3, Blueberry = 4 } public enum FruitsCombined { Apple = 1, Banana = 2, Berries = 0 //Strawberry和Blueberry的合并项 }
将ComboBox绑定到FruitsCombined枚举后,需要在后台逻辑中实现:选中Berries选项时,匹配Fruits枚举里的Strawberry(3)和Blueberry(4);选中其他选项时,直接匹配对应数值。现有实现代码如下,希望找到更优方案:
if ((int)cboFilterFruitType.SelectedValue == 0) { order = order.FindAll(o => o.FruitID == 3 || o.FruitID == 4); } else { order = order.FindAll(o => o.FruitID == (int) cboFilterFruitType.SelectedValue); }
优化方案
方案一:使用映射字典(推荐,简单直观)
提前定义FruitsCombined到对应Fruits集合的映射关系,后续过滤时直接通过字典取值,避免硬编码数值和条件判断:
// 定义映射字典,可放在类的静态构造函数或全局初始化处 private static readonly Dictionary<FruitsCombined, IEnumerable<Fruits>> _fruitMapping = new() { [FruitsCombined.Apple] = new[] { Fruits.Apple }, [FruitsCombined.Banana] = new[] { Fruits.Banana }, [FruitsCombined.Berries] = new[] { Fruits.Strawberry, Fruits.Blueberry } }; // 过滤逻辑 var selectedType = (FruitsCombined)cboFilterFruitType.SelectedValue; var targetFruits = _fruitMapping[selectedType]; order = order.FindAll(o => targetFruits.Contains((Fruits)o.FruitID));
优势:逻辑清晰,新增合并项或修改映射关系时,只需更新字典,无需改动过滤代码;避免直接使用魔法数值,可读性更高。
方案二:自定义特性+反射(适合扩展性要求高的场景)
通过自定义特性标记FruitsCombined枚举项对应的Fruits值,再用反射获取特性信息,实现解耦:
- 定义自定义特性:
[AttributeUsage(AttributeTargets.Field)] public class MapToFruitsAttribute : Attribute { public IEnumerable<Fruits> TargetFruits { get; } public MapToFruitsAttribute(params Fruits[] targetFruits) { TargetFruits = targetFruits; } }
- 给
FruitsCombined枚举添加特性:
public enum FruitsCombined { [MapToFruits(Fruits.Apple)] Apple = 1, [MapToFruits(Fruits.Banana)] Banana = 2, [MapToFruits(Fruits.Strawberry, Fruits.Blueberry)] Berries = 0 }
- 编写辅助方法获取映射的水果集合:
public static IEnumerable<Fruits> GetTargetFruits(this FruitsCombined combined) { var fieldInfo = combined.GetType().GetField(combined.ToString()); var attribute = fieldInfo.GetCustomAttribute<MapToFruitsAttribute>(); return attribute?.TargetFruits ?? Enumerable.Empty<Fruits>(); }
- 过滤逻辑:
var selectedType = (FruitsCombined)cboFilterFruitType.SelectedValue; var targetFruits = selectedType.GetTargetFruits(); order = order.FindAll(o => targetFruits.Contains((Fruits)o.FruitID));
优势:映射关系直接标注在枚举项上,代码侵入性低;新增枚举项时只需添加特性即可,无需修改其他逻辑。
方案三:扩展方法封装逻辑
如果不想引入字典或特性,可将映射逻辑封装到扩展方法中,让过滤代码更简洁:
public static IEnumerable<Fruits> ToTargetFruits(this FruitsCombined combined) { return combined switch { FruitsCombined.Apple => new[] { Fruits.Apple }, FruitsCombined.Banana => new[] { Fruits.Banana }, FruitsCombined.Berries => new[] { Fruits.Strawberry, Fruits.Blueberry }, _ => Enumerable.Empty<Fruits>() }; } // 过滤逻辑 var selectedType = (FruitsCombined)cboFilterFruitType.SelectedValue; var targetFruits = selectedType.ToTargetFruits(); order = order.FindAll(o => targetFruits.Contains((Fruits)o.FruitID));
优势:逻辑集中,过滤代码干净;使用模式匹配语法,可读性优于传统if-else。
内容的提问来源于stack exchange,提问作者user14618331
相关产品推荐
相关产品推荐

