C#中基于索引/引用高效访问变量的方案探讨
优化C#中飞船升级重复代码的几种方案
你现在写的重复switch代码确实很冗余,C#里有不少优雅的方式来解决这个问题,下面给你几个实用的方案,涵盖你提到的数组思路,以及类似“指针式”变量引用的实现:
1. 数组+循环处理(简洁高效的基础方案)
你的数组思路本身就很好,我帮你优化一下——注意原来的代码是累积相乘而不是直接赋值,所以要避免覆盖之前的升级效果,同时把四次重复的逻辑合并成循环:
首先定义对应枚举长度的数组,初始化默认值为1(乘法的单位元,不影响初始值):
// 假设UPGRADES_HULL是枚举类型,先获取它的成员数量初始化数组 private float[] _hullUpgrades = new float[Enum.GetValues(typeof(UPGRADES_HULL)).Length]; // 在构造函数里初始化所有元素为1 public YourShipClass() { Array.Fill(_hullUpgrades, 1f); }
然后处理升级的方法可以改成循环遍历四个升级项,不用重复写四次switch:
void GetHullUpgradeVals(GDEHullData hullDat) { // 把四个升级项打包成一个集合,方便循环处理 var upgrades = new[] { (Type: hullDat.upgd_1_type, Amount: hullDat.upgd_1_amnt), (Type: hullDat.upgd_2_type, Amount: hullDat.upgd_2_amnt), (Type: hullDat.upgd_3_type, Amount: hullDat.upgd_3_amnt), (Type: hullDat.upgd_4_type, Amount: hullDat.upgd_4_amnt) }; foreach (var upgrade in upgrades) { var upgradeType = (UPGRADES_HULL)upgrade.Type; float multiplier = upgrade.Amount; // 针对COST和MASS需要取倒数,其他直接用原值 if (upgradeType == UPGRADES_HULL.COST || upgradeType == UPGRADES_HULL.MASS) { multiplier = 1 / multiplier; } // 累积相乘,多个同类型升级会叠加效果 _hullUpgrades[(int)upgradeType] *= multiplier; } }
这个方案性能很好,适合游戏场景,代码也简洁很多。
2. 字典映射(实现“指针式”变量选择)
如果你想保留原来的独立变量,又不想写重复switch,可以用Dictionary把枚举类型映射到修改变量的委托——这就类似你说的“通过索引直接选择变量”,不用指针也能实现类似的效果:
首先定义你的独立变量和映射字典:
// 原来的独立变量,初始化默认值为1 private float _upgHullCost = 1f; private float _upgHullImpactRes = 1f; private float _upgHullMass = 1f; private float _upgHullMaxHealth = 1f; private float _upgHullPickRad = 1f; private float _upgHullRegen = 1f; // 初始化字典,把每个升级类型对应到修改变量的操作 private Dictionary<UPGRADES_HULL, Action<float>> _upgradeActions; public YourShipClass() { _upgradeActions = new Dictionary<UPGRADES_HULL, Action<float>> { { UPGRADES_HULL.COST, multiplier => _upgHullCost *= multiplier }, { UPGRADES_HULL.IMPACT_RES, multiplier => _upgHullImpactRes *= multiplier }, { UPGRADES_HULL.MASS, multiplier => _upgHullMass *= multiplier }, { UPGRADES_HULL.MAX_HEALTH, multiplier => _upgHullMaxHealth *= multiplier }, { UPGRADES_HULL.PICK_RAD, multiplier => _upgHullPickRad *= multiplier }, { UPGRADES_HULL.REGEN, multiplier => _upgHullRegen *= multiplier } }; }
然后处理升级的方法就变得非常简洁:
void GetHullUpgradeVals(GDEHullData hullDat) { var upgrades = new[] { (Type: (UPGRADES_HULL)hullDat.upgd_1_type, Amount: hullDat.upgd_1_amnt), (Type: (UPGRADES_HULL)hullDat.upgd_2_type, Amount: hullDat.upgd_2_amnt), (Type: (UPGRADES_HULL)hullDat.upgd_3_type, Amount: hullDat.upgd_3_amnt), (Type: (UPGRADES_HULL)hullDat.upgd_4_type, Amount: hullDat.upgd_4_amnt) }; foreach (var upgrade in upgrades) { if (_upgradeActions.TryGetValue(upgrade.Type, out var action)) { float multiplier = upgrade.Amount; if (upgrade.Type == UPGRADES_HULL.COST || upgrade.Type == UPGRADES_HULL.MASS) { multiplier = 1 / multiplier; } action.Invoke(multiplier); } } }
以后新增升级类型,只需要在字典里加一行就行,扩展非常方便。
3. 面向对象封装(更规范的长期方案)
如果想让代码更符合面向对象设计,把船体属性封装成一个类是更好的选择,所有升级逻辑都集中在类里,维护起来更清晰:
public class HullAttributes { public float CostMultiplier { get; private set; } = 1f; public float ImpactResistance { get; private set; } = 1f; public float MassMultiplier { get; private set; } = 1f; public float MaxHealth { get; private set; } = 1f; public float PickupRadius { get; private set; } = 1f; public float RegenRate { get; private set; } = 1f; public void ApplyUpgrade(UPGRADES_HULL type, float amount) { float multiplier = amount; if (type == UPGRADES_HULL.COST || type == UPGRADES_HULL.MASS) { multiplier = 1 / multiplier; } switch (type) { case UPGRADES_HULL.COST: CostMultiplier *= multiplier; break; case UPGRADES_HULL.IMPACT_RES: ImpactResistance *= multiplier; break; case UPGRADES_HULL.MASS: MassMultiplier *= multiplier; break; case UPGRADES_HULL.MAX_HEALTH: MaxHealth *= multiplier; break; case UPGRADES_HULL.PICK_RAD: PickupRadius *= multiplier; break; case UPGRADES_HULL.REGEN: RegenRate *= multiplier; break; } } }
使用的时候就很简单:
// 声明船体属性实例 private HullAttributes _hullAttributes = new HullAttributes(); void GetHullUpgradeVals(GDEHullData hullDat) { _hullAttributes.ApplyUpgrade((UPGRADES_HULL)hullDat.upgd_1_type, hullDat.upgd_1_amnt); _hullAttributes.ApplyUpgrade((UPGRADES_HULL)hullDat.upgd_2_type, hullDat.upgd_2_amnt); _hullAttributes.ApplyUpgrade((UPGRADES_HULL)hullDat.upgd_3_type, hullDat.upgd_3_amnt); _hullAttributes.ApplyUpgrade((UPGRADES_HULL)hullDat.upgd_4_type, hullDat.upgd_4_amnt); }
这个方案把所有船体相关的逻辑都封装在一起,代码结构更清晰,适合长期维护。
内容的提问来源于stack exchange,提问作者David Coombes
相关产品推荐
相关产品推荐

