如何编写泛型方法填充自动售货机中不同类型Snack的列表?
解决方案
你当前的FillWithProducts方法硬编码了Drink的判断逻辑,新增Sweets类型时还要修改方法,违背了开闭原则。可以通过以下两种方式优化,彻底避免重复代码:
方式一:用字典维护类型与列表的映射
在VendingMachine类里定义一个字典,把每种Snack子类对应的列表存起来,泛型方法直接通过类型找到对应列表,不用硬编码判断:
public class VendingMachine { // 各产品列表 private List<Drink> _drinks = new List<Drink>(); private List<Sweets> _sweets = new List<Sweets>(); // 公共只读属性 public List<Drink> Drinks => _drinks; public List<Sweets> Sweets => _sweets; // 类型到对应列表的映射字典 private readonly Dictionary<Type, IList> _productLists; public VendingMachine() { // 初始化映射关系 _productLists = new Dictionary<Type, IList> { { typeof(Drink), _drinks }, { typeof(Sweets), _sweets } }; } private void FillWithProducts<Product>(params Product[] products) where Product : Snack { if (_productLists.TryGetValue(typeof(Product), out var targetList)) { foreach (var product in products) { ((IList<Product>)targetList).Add(product); } } } }
这种方式扩展性极强,新增Snack子类时,只需要添加对应的列表属性和字典映射,完全不用修改填充方法的逻辑。
方式二:泛型辅助方法+模式匹配
如果不想用字典,也可以写一个泛型辅助方法来匹配对应类型的列表,填充方法直接复用逻辑:
public class VendingMachine { private List<Drink> _drinks = new List<Drink>(); private List<Sweets> _sweets = new List<Sweets>(); public List<Drink> Drinks => _drinks; public List<Sweets> Sweets => _sweets; private void FillWithProducts<Product>(params Product[] products) where Product : Snack { var targetList = GetProductList<Product>(); targetList?.AddRange(products); } private List<Product> GetProductList<Product>() where Product : Snack { return typeof(Product) switch { Type t when t == typeof(Drink) => _drinks as List<Product>, Type t when t == typeof(Sweets) => _sweets as List<Product>, _ => null }; } }
这里用了C#的模式匹配语法,比原有的if判断更简洁。新增类型时,只需要在GetProductList的switch里加一个分支,填充方法的逻辑完全不用改动。
补充说明
两种方案都遵循了DRY(Don't Repeat Yourself)原则,避免为每种产品类型编写重复的填充逻辑。如果后续会频繁新增Snack子类,优先选方式一;类型较少的场景下,方式二更直观。
内容的提问来源于stack exchange,提问作者luffydavor
相关产品推荐
相关产品推荐

