You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为什么Swift允许结构体属性自我赋值,却禁止类属性执行该操作?

这个差异是由Swift编译器的冗余赋值诊断规则、值类型与引用类型的属性赋值语义差异共同导致的,具体逻辑如下:

1. 普通无观察者属性的默认诊断规则

对于没有附加willSet/didSet观察者的存储属性,无论是类还是结构体的属性,x = x都属于完全无副作用的冗余操作:不会修改属性值,也不会触发任何额外逻辑,纯粹是无意义的代码,大概率是开发者把两个命名相似的属性写混的笔误,因此编译器默认会抛出编译错误,和你观察到的第一个示例行为一致。
示例触发报错的代码:

class Foo {
    var foo = 1
}

var a = Foo()
a.foo = a.foo // 触发冗余赋值错误

2. 带didSet观察者的结构体属性豁免诊断的原因

当结构体的存储属性附加了didSet/willSet观察者时,foo = foo不再是无意义操作:哪怕新值和旧值完全相等,赋值操作也会主动触发属性观察者的执行,产生可观测的副作用(比如你示例中的打印逻辑,或者实际开发中常用的触发UI刷新、状态同步等业务逻辑)。
编译器会识别到这个赋值操作存在明确的业务用途,因此会豁免冗余赋值的报错,这也是你给出的第二个示例可以正常编译运行的原因,执行时会正常输出Did set。

3. 类即使带didSet依然报错的原因

对于引用类型(类)的存储属性,哪怕附加了属性观察者,编译器当前依然会对x = x的自我赋值触发错误诊断:这是Swift编译器诊断规则的刻意设计,因为类属性的自我赋值绝大多数场景下依然属于笔误,即使能触发观察者也不属于常规合理用法,因此没有纳入豁免范围。
你观察到的「仅结构体+didSet组合支持自我赋值」的表现,完全符合Swift 5.3.2版本的编译器设计规则,不属于异常bug。

内容的提问来源于stack exchange,提问作者Sweeper

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.15 18:54:02