如何高效处理相似建筑类并存储,实现属性直接访问?
嘿,我完全懂你纠结的点——要把不同类型的建筑统一存起来方便管理,又不想每次访问专属属性都要强制转换、靠反射或者写一堆switch语句拖慢效率。你提到的用List/Dictionary结合类型键来处理的思路真的很靠谱,我来给你拆解下具体怎么落地这个方案,兼顾灵活性和性能。
第一步:定义基础接口和类型枚举
先搞一个IBuilding接口来统一所有建筑的公共属性,再用枚举区分不同建筑类型,这样后续不管是存储还是创建都有明确的标识:
public enum BuildingType { Farm, Mill, Bakery } public interface IBuilding { string Name { get; set; } float Timer { get; set; } } // 实现各自的建筑类 public class Farm : IBuilding { public string Name { get; set; } public int CropType { get; set; } public float Timer { get; set; } } public class Mill : IBuilding { public string Name { get; set; } public float Timer { get; set; } } public class Bakery : IBuilding { public string Name { get; set; } public int ProductionType { get; set; } public bool IsOpen { get; set; } public float Timer { get; set; } }
第二步:用Dictionary实现无反射/switch的实例工厂
接下来创建一个工厂类,用Dictionary<BuildingType, Func<IBuilding>>来映射类型到创建实例的委托,这样创建新建筑时直接通过键获取创建逻辑,完全不用switch或者反射:
public static class BuildingFactory { private static readonly Dictionary<BuildingType, Func<IBuilding>> _buildingCreators = new() { { BuildingType.Farm, () => new Farm { Name = "Default Farm", CropType = 0, Timer = 0f } }, { BuildingType.Mill, () => new Mill { Name = "Default Mill", Timer = 0f } }, { BuildingType.Bakery, () => new Bakery { Name = "Default Bakery", ProductionType = 0, IsOpen = true, Timer = 0f } } }; public static T CreateBuilding<T>(BuildingType type) where T : class, IBuilding { if (_buildingCreators.TryGetValue(type, out var creator)) { return creator() as T; } throw new ArgumentException($"Unsupported building type: {type}"); } // 通用创建方法,返回IBuilding public static IBuilding CreateBuilding(BuildingType type) { if (_buildingCreators.TryGetValue(type, out var creator)) { return creator(); } throw new ArgumentException($"Unsupported building type: {type}"); } }
第三步:用Dictionary+强类型列表高效存储玩家建筑
现在来处理存储问题——用一个Dictionary<BuildingType, object>来存放每种类型的强类型列表,这样既可以统一管理,又能直接获取特定类型的建筑集合,不用强制转换:
public class PlayerBuildingManager { private readonly Dictionary<BuildingType, object> _buildingsByType = new() { { BuildingType.Farm, new List<Farm>() }, { BuildingType.Mill, new List<Mill>() }, { BuildingType.Bakery, new List<Bakery>() } }; // 添加建筑到对应类型的列表 public void AddBuilding(IBuilding building) { switch (building) { case Farm farm: ((List<Farm>)_buildingsByType[BuildingType.Farm]).Add(farm); break; case Mill mill: ((List<Mill>)_buildingsByType[BuildingType.Mill]).Add(mill); break; case Bakery bakery: ((List<Bakery>)_buildingsByType[BuildingType.Bakery]).Add(bakery); break; default: throw new ArgumentException($"Unknown building type: {building.GetType().Name}"); } } // 强类型获取方法,直接返回对应列表,无需转换 public List<Farm> GetFarms() => (List<Farm>)_buildingsByType[BuildingType.Farm]; public List<Mill> GetMills() => (List<Mill>)_buildingsByType[BuildingType.Mill]; public List<Bakery> GetBakeries() => (List<Bakery>)_buildingsByType[BuildingType.Bakery]; // 获取所有建筑(用于发送给玩家等场景) public IEnumerable<IBuilding> GetAllBuildings() { foreach (var list in _buildingsByType.Values) { if (list is IEnumerable<IBuilding> buildings) { foreach (var building in buildings) { yield return building; } } } } }
第四步:实际使用示例
现在你可以在业务代码里这样用,全程高效访问,没有冗余的转换操作:
public class GameServer { private readonly PlayerBuildingManager _playerBuildings = new(); public void HandlePlayerJoin() { // 给玩家创建一个农场 var farm = BuildingFactory.CreateBuilding<Farm>(BuildingType.Farm); farm.CropType = 1; // 直接访问专属属性,无需强制转换 _playerBuildings.AddBuilding(farm); // 处理所有磨坊的计时逻辑 foreach (var mill in _playerBuildings.GetMills()) { mill.Timer += 1f; // 直接操作Mill的Timer属性 } // 获取所有建筑发送给玩家 var allBuildings = _playerBuildings.GetAllBuildings(); // 序列化allBuildings并发送给客户端 } }
为什么这个方案适合你?
- 无强制转换/反射/switch(创建环节):工厂用委托映射类型,创建实例直接调用委托,性能拉满
- 高效访问专属属性:通过强类型的Get方法直接拿到对应列表,操作属性不用任何转换
- 符合开闭原则:新增建筑类型时,只需要加枚举值、实现IBuilding、在工厂和管理器里加对应逻辑,不用修改现有代码
- 统一管理+灵活处理:既可以通过GetAllBuildings统一获取所有建筑(比如发送给玩家),又能针对单类型建筑做高效逻辑处理
内容的提问来源于stack exchange,提问作者Penca53
相关产品推荐
相关产品推荐

