Delphi record类型只读属性赋值及属性与底层字段使用疑问
问题1:为什么可以对只读属性执行写入操作
你看到的并不是对只读属性本身的写入,本质分两种情况:
- 对于映射到内部字段的只读属性(也就是属性声明为
property RecDirect: TRec read FRec;的形式):只读属性的限制仅为不允许对属性整体赋值(也就是不允许写RecDirect := 其他TRec实例),但没有限制修改属性指向的记录内部字段。此时你写RecDirect.Field := xxx本质是直接修改内部存储的FRec的对应字段,属于合法操作。 - 对于通过函数返回值的只读属性(也就是属性声明为
property RecFunction: TRec read GetRec;的形式):此时你修改的是函数返回的栈上临时副本的字段,这个操作不会影响类内部存储的原始记录,写完临时副本就会被丢弃,属于无意义的无效操作,编译器不会拦截但不会产生你预期的效果。
问题2:有属性的情况下为什么还要直接访问底层字段
主要有三个原因:
- 避免值类型临时副本陷阱:如果属性是通过函数返回的记录值,对属性成员的修改只会作用于临时副本,不会修改原始数据。直接访问底层字段可以100%确定是修改原始存储的内容,不会出现无效操作的问题。
- 减少不必要的性能开销:记录作为值类型,通过函数返回时会产生一次完整的内存拷贝,当记录结构比较大、访问频次高的时候,拷贝开销会非常明显。直接访问底层字段没有拷贝开销,性能更高。
- 满足引用传递的需求:如果需要把记录作为
var/out参数传递给其他方法,属性无法直接作为引用参数传递,必须直接传入底层存储的字段。
内容的提问来源于stack exchange,提问作者Adriano
相关产品推荐
相关产品推荐

