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

C#中带get/set的虚属性仅重写getter仍可赋值?原因解析

关于C#中重写属性后仍可赋值的困惑解答

这个问题涉及到C#属性重写机制里一个容易混淆的细节,我来一步步拆解清楚:

1. 为什么child.Property = true;能正常执行?

当你在Child类中重写Property时,只定义了get访问器,但并没有重写或隐藏父类的set访问器。因为父类的Property是virtual修饰的,子类会自动继承父类的set访问器实现——也就是说,Child类的Property实际上依然拥有可调用的set方法,只是你没有在子类代码中显式重写它而已。

执行child.Property = true;时,编译器会调用父类Parent中定义的set访问器,修改父类内部维护的属性值(编译器会为自动属性生成隐藏字段),所以赋值操作完全合法。

2. 为什么IDE会显示重写后的属性为“只读”?

这是IDE(比如Visual Studio、Rider)的智能提示逻辑导致的差异。当IDE检查Child类的Property定义时,看到你只显式实现了get访问器,没有写set,就会直观标记它为“只读”——但这只是基于你写的代码的表面判断,没有考虑到子类从父类继承来的set访问器。

简单来说,IDE的提示是“代码写法层面”的直观反馈,而实际编译行为是“继承机制层面”的逻辑,两者在这里出现了认知差。

3. 为什么你觉得只有调用base.Property的getter才允许这种写法?

其实这个观察有个小误区——即使你在子类的getter里不调用base.Property,赋值操作依然是合法的。比如把Child的getter改成:

public override bool Property { get => true; }

此时执行child.Property = true;仍然能编译通过,只是调用get时永远返回true,但set操作确实会执行(父类的属性值会被修改,只是子类getter没有暴露这个变化)。

你之所以有这个感受,可能是因为当子类getter调用base.Property时,赋值后的结果能通过getter直接体现出来(比如赋值true后,child.Property会返回true),而如果不调用base,赋值的效果被getter掩盖了,看起来好像赋值没生效,但实际上setter已经正常执行了。

核心逻辑总结

  • 子类重写属性时,只需要重写需要修改的访问器,未重写的访问器会继承父类的virtual实现
  • IDE的“只读”提示是基于子类显式代码的判断,不代表实际编译后的运行行为
  • 赋值操作是否合法,取决于父类是否提供了可访问的set访问器,且子类没有通过new关键字隐藏它

内容的提问来源于stack exchange,提问作者rory.ap

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 04:07:00