Unity中C# 8反射设置结构体字段值失败的原因及解决方法
问题原因与修复方案
原因分析
PlayerData是值类型(struct),反射的FieldInfo.SetValue方法处理值类型时,会创建该实例的副本进行修改。你传入的playerData是值类型实例,SetValue实际修改的是这个副本的health字段,原变量完全没被改动,所以断言时health还是初始的100f。
修复方案
方案1:装箱+拆箱修改原实例
将值类型装箱为引用类型,修改装箱后的对象后再拆箱赋值回原变量,这样原实例就能被更新:
[Test] public void SetValue_ChangesHealthUsingReflection() { // Arrange var playerData = new PlayerData { name = "Test Player", level = 1, health = 100f }; // Act object boxedPlayer = playerData; // 装箱为引用类型 var healthField = typeof(PlayerData).GetField("health"); healthField.SetValue(boxedPlayer, 75.5f); playerData = (PlayerData)boxedPlayer; // 拆箱赋值回原变量 // Assert Assert.AreEqual(75.5f, playerData.health); }
方案2:使用SetValueDirect直接操作内存(高效但需注意安全)
SetValueDirect可以跳过装箱,直接操作值类型实例的内存,性能更优,但需要正确使用__makeref生成类型引用:
[Test] public void SetValue_ChangesHealthUsingReflection() { // Arrange var playerData = new PlayerData { name = "Test Player", level = 1, health = 100f }; // Act var healthField = typeof(PlayerData).GetField("health"); healthField.SetValueDirect(__makeref(playerData), 75.5f); // 直接操作内存 // Assert Assert.AreEqual(75.5f, playerData.health); }
内容的提问来源于stack exchange,提问作者tribbloid
相关产品推荐
相关产品推荐

