重载PlayerSkillsClass运算符引发StackOverflowException问题求助
解决思路与实现方案
一、先搞定StackOverflowException的问题
你遇到的栈溢出,百分百是因为运算符重载代码里自己调用了自己,陷入无限循环了。比如你可能写了这种坑人的代码:
public static PlayerSkillsClass operator +(PlayerSkillsClass a, float b) { // 错在这:这里又调用了+运算符,等于无限套娃 return a + b; }
这种写法会让方法反复调用自己,直到栈内存被撑爆,直接报错。
二、通用属性运算实现(不用逐个写属性逻辑)
既然后续要加很多技能属性,就别一个个写运算代码了,用反射遍历所有数值属性来统一处理,新增属性时完全不用改运算逻辑。
1. 核心思路
- 用反射找出类里所有float、int类型的公开属性
- 运算时挨个遍历这些属性,执行对应的加减操作
- 运算返回新的实例,别改原对象,避免莫名其妙的bug
2. 完整代码示例
using System; using System.Linq; using System.Reflection; public class PlayerSkillsClass { public float Speed { get; set; } public float Agility { get; set; } public float Jump { get; set; } public float Strength { get; set; } // 以后加新属性比如Stamina,直接加就行,不用改下面的运算代码 // 提前缓存所有数值属性,避免每次运算都反射(优化性能) private static readonly PropertyInfo[] _skillProperties; static PlayerSkillsClass() { // 只筛选float和int类型的公开实例属性 _skillProperties = typeof(PlayerSkillsClass) .GetProperties(BindingFlags.Public | BindingFlags.Instance) .Where(p => p.PropertyType == typeof(float) || p.PropertyType == typeof(int)) .ToArray(); } // 重载 +:技能实例 + 数值(给所有属性加同一个值) public static PlayerSkillsClass operator +(PlayerSkillsClass skills, float value) { var newSkills = new PlayerSkillsClass(); foreach (var prop in _skillProperties) { float currentVal = Convert.ToSingle(prop.GetValue(skills)); prop.SetValue(newSkills, currentVal + value); } return newSkills; } // 重载 +:技能实例 + 技能实例(对应属性相加) public static PlayerSkillsClass operator +(PlayerSkillsClass a, PlayerSkillsClass b) { var newSkills = new PlayerSkillsClass(); foreach (var prop in _skillProperties) { float valA = Convert.ToSingle(prop.GetValue(a)); float valB = Convert.ToSingle(prop.GetValue(b)); prop.SetValue(newSkills, valA + valB); } return newSkills; } // 可选:重载 += 运算符,直接复用上面的+逻辑 public static PlayerSkillsClass operator +=(PlayerSkillsClass skills, float value) { skills = skills + value; return skills; } public static PlayerSkillsClass operator +=(PlayerSkillsClass a, PlayerSkillsClass b) { a = a + b; return a; } }
3. 代码说明
- 自动适配新属性:以后加新的技能属性(比如
Stamina),只要是float/int类型,自动会被纳入运算逻辑,不用改任何重载代码 - 避免递归:运算符重载里直接操作属性值,不再调用自身的+运算符,彻底解决栈溢出
- 缓存属性:静态构造函数里提前把要运算的属性缓存好,避免每次运算都反射,提升性能
三、测试用例
// 测试1:给所有属性加2 var skills1 = new PlayerSkillsClass { Speed = 5, Agility = 3, Jump = 2, Strength = 4 }; skills1 = skills1 + 2; // 结果:Speed=7, Agility=5, Jump=4, Strength=6 // 测试2:两个实例属性对应相加 var skills2 = new PlayerSkillsClass { Speed = 3, Agility = 2, Jump = 1, Strength = 5 }; var skills3 = skills1 + skills2; // 结果:Speed=10, Agility=7, Jump=5, Strength=11
内容的提问来源于stack exchange,提问作者David Martin
相关产品推荐
相关产品推荐

