C#中如何创建含不同子类Tuple列表的列表以简化商店代码
解决方法:利用LINQ投影+协变接口统一集合
核心思路是把每个子类物品列表,通过LINQ转换成统一的Item基类+价格的枚举集合,然后把这些集合放到支持协变的容器里,就能用嵌套foreach统一处理了,完全不用修改Item基类或新建额外类。
代码示例
假设你的类结构如下:
public class Item { /* 基类属性,比如Name、Id等 */ } public class TestItem : Item { } public class AnotherItem : Item { } public class ShopInventory { public List<Tuple<TestItem, int>> TestItems { get; set; } = new(); public List<Tuple<AnotherItem, int>> AnotherItems { get; set; } = new(); // 统一展示所有商店物品的方法 public void DisplayAllShopItems() { // 将各个子类列表转换为统一的(Item, int)枚举集合 var allShopItemGroups = new List<IEnumerable<(Item Item, int Price)>> { TestItems.Select(t => ((Item)t.Item1, t.Item2)), AnotherItems.Select(t => ((Item)t.Item1, t.Item2)) }; // 嵌套foreach统一处理所有物品 foreach (var itemGroup in allShopItemGroups) { foreach (var (item, price) in itemGroup) { // 这里写统一的展示逻辑,比如 Console.WriteLine($"物品名称:{item.Name},售价:{price}金币"); } } } }
更简化的方式:直接合并成单个集合
如果不需要区分原列表的分组,还可以直接把所有物品合并成一个枚举集合,省去嵌套循环:
public void DisplayAllShopItems() { var allItems = TestItems.Select(t => ((Item)t.Item1, t.Item2)) .Concat(AnotherItems.Select(t => ((Item)t.Item1, t.Item2))); foreach (var (item, price) in allItems) { Console.WriteLine($"物品名称:{item.Name},售价:{price}金币"); } }
为什么原来的List<List<Tuple<Item,int>>>不行?
泛型列表List<T>是不变类型,List<Tuple<TestItem, int>>和List<Tuple<Item, int>>是完全独立的类型,不存在继承关系,所以无法直接添加。而IEnumerable<T>是协变类型(因为T是out参数),加上我们用Select把每个元素转换成基类类型,就能实现类型兼容。
额外优化:改用值元组替代Tuple
如果你的项目使用C# 7.0及以上版本,建议把原来的Tuple换成值元组,语法更简洁,转换也更直观:
// 修改库存列表的类型 public List<(TestItem Item, int Price)> TestItems { get; set; } = new(); public List<(AnotherItem Item, int Price)> AnotherItems { get; set; } = new(); // 转换逻辑更清晰 var allItems = TestItems.Select(t => ((Item)t.Item, t.Price)) .Concat(AnotherItems.Select(t => ((Item)t.Item, t.Price)));
内容的提问来源于stack exchange,提问作者Aijokoryu
相关产品推荐
相关产品推荐

