调用方法后Struct值未改变?C#结构体AnimationCommand问题排查
结构体SetDuration方法修改值无效的问题解析
你定义了存储动画数据的AnimationCommand结构体,调用其SetDuration方法后,时长值始终未发生变化,相关代码如下:
结构体代码
public struct AnimationCommand { float _duration; Action _onCompleteCallback; Action<float> _onUpdateCallback; public float Duration => _duration; public AnimationCommand(float animationTime, Action onComplete = null, Action<float> onUpdate = null) { _duration = animationTime; _onCompleteCallback = onComplete; _onUpdateCallback = onUpdate; } public void SetDuration(float animationTime) => _duration = animationTime; }
子类调用代码
/*AnimationData是基类中的属性 [SerializeField] AnimationCommand _animationData; protected AnimationCommand AnimationData => _animationData; */ float delta = 10; //测试值 AnimationData.SetDuration(delta); Debug.Log(delta + " :: " + AnimationData.Duration);
输出结果为10 :: 0,原因及解决方式如下:
问题核心:结构体的值类型特性 + 只读属性的拷贝行为
- 结构体是值类型:值类型的实例在赋值、传递或通过属性返回时,都会创建一个全新的拷贝,而非操作原实例。
- 只读属性的拷贝问题:你的
AnimationData属性是表达式体只读属性(=> _animationData),每次访问AnimationData都会返回_animationData的一个新拷贝。 - 方法修改的是拷贝:调用
AnimationData.SetDuration(delta)时,实际是在这个临时拷贝上修改_duration,原字段_animationData完全不受影响。后续再次访问AnimationData,又会返回一个基于原字段的新拷贝(初始值为0),所以日志输出不符合预期。
你的误解在于:调用结构体的方法无法避开值拷贝语义。结构体方法操作的是当前实例,但如果这个实例本身是一个拷贝(比如通过只读属性返回的),修改只会作用于拷贝,原实例不会变化。
解决方案
方案1:将结构体改为类(最直接)
类是引用类型,所有操作都针对同一个实例,不存在值拷贝问题,适合需要频繁修改内部状态的场景:
public class AnimationCommand { // 其余代码逻辑保持不变 }
方案2:修改属性为可读写,替换整个结构体实例
修改基类的AnimationData属性为可读写:
protected AnimationCommand AnimationData { get => _animationData; set => _animationData = value; }
调用时先获取拷贝,修改后赋值回属性:
float delta = 10; var tempAnimData = AnimationData; tempAnimData.SetDuration(delta); AnimationData = tempAnimData; Debug.Log(delta + " :: " + AnimationData.Duration);
方案3:采用不可变结构体模式,返回新实例
修改SetDuration方法,返回一个修改后的新结构体实例:
public AnimationCommand SetDuration(float animationTime) { return new AnimationCommand(animationTime, _onCompleteCallback, _onUpdateCallback); }
调用时直接将返回的新实例赋值给属性:
float delta = 10; AnimationData = AnimationData.SetDuration(delta); Debug.Log(delta + " :: " + AnimationData.Duration);
内容的提问来源于stack exchange,提问作者WDUK
相关产品推荐
相关产品推荐

