如何更优存储可用食材类信息?现有C#实现方案求改进
优化C#食材信息存储方案的探讨
当前实现代码
public static class IngredientDataStorage { public static List<Ingredient> GetIngredientList() { List<Ingredient> availIngredientsList = new List<Ingredient>() { new Butter(), new Cinnamon(), new Chocolate() }; return availIngredientsList; } public static Dictionary<int, Ingredient> GetIngredientDictionary() { Dictionary<int, Ingredient> availIngDict = new Dictionary<int, Ingredient>() { {3, new Chocolate() }, {2, new Butter() }, {4, new Cinnamon() } }; return availIngDict; } public static List<int> GetIDList() { var IDList = new List<int>(); foreach (Ingredient ingredient in GetIngredientList()) { IDList.Add(ingredient.ID); } return IDList; } public static void PrintAvailIngredients() { List<Ingredient> ingredientList = IngredientDataStorage.GetIngredientList(); foreach (Ingredient ingredient in ingredientList) { ingredient.PrintInfo(); } } }
问题描述
我目前有Butter、Cinnamon、Chocolate三个食材类,通过列表、字典存储它们的实例,还实现了获取ID列表及打印食材信息的方法,请问是否存在更优的可用食材信息存储方式?
优化方案
核心问题分析
当前实现存在几个明显弊端:
- 每次调用获取集合的方法都会重新创建食材实例,既浪费内存,又可能导致同一食材的实例状态不一致(若食材有可变属性)。
- 列表和字典的数据是重复维护的,新增或修改食材时需要同步更新两个集合,极易出现数据不一致。
GetIDList()需要遍历列表生成,效率低下,且依赖重复创建的实例。
具体优化实现
1. 单例化核心存储集合
将食材实例只初始化一次,存储在静态字段中,优先用字典作为核心存储(按ID查询是高频场景),列表可通过字典的Values属性直接获取,无需单独维护:
public static class IngredientDataStorage { // 核心存储:仅初始化一次的字典 private static readonly Dictionary<int, Ingredient> _ingredients = new Dictionary<int, Ingredient>() { {2, new Butter() }, {3, new Chocolate() }, {4, new Cinnamon() } }; // 返回只读字典包装,防止外部修改内部集合 public static IReadOnlyDictionary<int, Ingredient> GetIngredientDictionary() { return new ReadOnlyDictionary<int, Ingredient>(_ingredients); } // 通过字典Values获取只读列表,无需单独维护 public static IReadOnlyList<Ingredient> GetIngredientList() { return _ingredients.Values.ToList().AsReadOnly(); } // 直接从字典Keys获取ID列表,无需遍历 public static IReadOnlyList<int> GetIDList() { return _ingredients.Keys.ToList().AsReadOnly(); } public static void PrintAvailIngredients() { foreach (var ingredient in _ingredients.Values) { ingredient.PrintInfo(); } } }
2. 自动扫描注册食材(扩展性优化)
如果后续需要新增大量食材类,可通过反射自动扫描程序集中的食材类型,实现自动注册,避免手动维护字典:
public static class IngredientDataStorage { private static readonly Dictionary<int, Ingredient> _ingredients; static IngredientDataStorage() { _ingredients = new Dictionary<int, Ingredient>(); // 扫描当前程序集中所有继承自Ingredient的非抽象类 var ingredientTypes = typeof(Ingredient).Assembly.GetTypes() .Where(t => t.IsSubclassOf(typeof(Ingredient)) && !t.IsAbstract); foreach (var type in ingredientTypes) { // 假设所有食材类都有无参构造函数 var ingredient = (Ingredient)Activator.CreateInstance(type); if (!_ingredients.ContainsKey(ingredient.ID)) { _ingredients.Add(ingredient.ID, ingredient); } } } // 其余方法同方案1... }
3. 食材类单例化(实例一致性优化)
如果需要确保每个食材只有一个实例,可在食材类本身实现单例,再统一注册到存储类:
public abstract class Ingredient { public abstract int ID { get; } public abstract void PrintInfo(); } public class Butter : Ingredient { // 食材单例实例 public static readonly Butter Instance = new Butter(); private Butter() {} public override int ID => 2; public override void PrintInfo() => Console.WriteLine("Butter (ID: 2)"); } // Cinnamon、Chocolate类同理实现单例模式 public static class IngredientDataStorage { private static readonly Dictionary<int, Ingredient> _ingredients = new Dictionary<int, Ingredient>() { {Butter.Instance.ID, Butter.Instance}, {Chocolate.Instance.ID, Chocolate.Instance}, {Cinnamon.Instance.ID, Cinnamon.Instance} }; // 其余方法同方案1... }
优化后的优势
- 性能提升:避免重复创建实例,集合查询与遍历效率更高。
- 数据一致性:核心数据仅维护一份,新增/修改食材只需更新字典。
- 安全性:通过只读包装暴露集合,防止外部代码意外修改内部数据。
- 扩展性:反射扫描或单例模式能大幅降低新增食材时的维护成本。
内容的提问来源于stack exchange,提问作者Dragnipur
相关产品推荐
相关产品推荐

