如何制作类的只读版本?

Eri*_*tas 17 .net c# readonly-attribute

我有一个具有各种公共属性的类,我允许用户通过属性网格进行编辑.对于持久性,此类还通过DataContractSerializer与XML文件进行序列化/反序列化.

有时我希望用户能够将他们所做的更改保存(序列化)到类的实例中.但在其他时候,我不想让用户保存他们的更改,而应该将属性网格中的所有属性都看作只读.我不想让用户进行以后永远无法保存的更改.类似于MS Word将允许用户打开当前由其他人打开但仅作为只读的文档.

我的类有一个布尔属性,用于确定该类是否应该是只读的,但是是否可以使用此属性以某种方式在运行时动态地向类属性添加只读属性?如果不是什么是替代解决方案?我应该将我的类包装在只读包装类中吗?

LBu*_*kin 20

不变性是C#仍有改进空间的领域.虽然可以创建具有readonly属性的简单不可变类型,但是一旦您需要对类型可变的更复杂的控制,您就开始遇到障碍.

您有三种选择,具体取决于您需要"强制执行"只读行为的强度:

  1. 在您的类型中使用只读标志(就像您正在做的那样)并让调用者负责不尝试更改类型的属性 - 如果进行了写入尝试,则抛出异常.

  2. 创建一个只读接口,让您的类型实现它.这样,您可以通过该接口将类型传递给只应执行读取的代码.

  3. 创建一个聚合您的类型的包装类,只显示读取操作.

第一个选项通常是最简单的,因为它可以减少对现有代码的重构,但是为类型的作者提供了在实例不可变时与不实例时通知消费者的最小机会.此选项还提供编译器在检测不当使用方面的最少支持 - 并将错误检测降级到运行时.

第二个选项很方便,因为实现一个接口是可能的,没有太多的重构努力.不幸的是,调用者仍然可以转换为基础类型并尝试对其进行编写.通常,此选项与只读标志组合以确保不违反不变性.

就强制执行而言,第三种选择是最强的,但它可能导致代码重复,更多的是重构工作.通常,组合选项2和3非常有用,以便在只读包装器和可变类型多态之间建立关系.

就个人而言,在编写需要强制执行不变性的新代码时,我倾向于使用第三种选择. 我喜欢这样一个事实:不可能"抛弃"不可变包装器,它通常允许你避免在每个setter中编写凌乱的if-read-only-throw-exception检查.