C# · 12月 21, 2021

c# – 在不违反类型安全的情况下将不透明对象返回给调用者

我有一个方法应该返回当前状态的快照,另一个方法是恢复该状态. public class MachineModel{ public Snapshot CurrentSnapshot { get; } public void RestoreSnapshot (Snapshot saved) { /* etc */ };}

状态Snapshot类对调用者应该是完全不透明的 – 没有可见的方法或属性 – 但是它的属性必须在MachineModel类中可见.我显然可以通过向下转换来实现这一点,即让CurrentSnapshot返回一个对象,并让RestoreSnapshot接受一个对象参数,它将其转换回快照.

但这样的强迫铸造让我觉得很脏.什么是最好的替代设计,允许我既是类型安全的又是不透明的?

更新解决方案:

我结束了接受的答案和关于接口的建议. Snapshot类是一个公共抽象类,在MachineModel中有一个私有实现:

public class MachineModel{ public abstract class Snapshot { protected internal Snapshot() {} abstract internal void Restore(MachineModel model); } private class SnapshotImpl : Snapshot { /* etc */ } public void Restore(Snapshot state) { state.Restore(this); }}

由于Snapshot的构造函数和方法是内部的,因此程序集外部的调用者将其视为完全不透明且无法从中继承.程序集中的调用者可以调用Snapshot.Restore而不是MachineModel.Restore,但这不是一个大问题.此外,在实践中,您永远无法实现Snapshot.Restore而无法访问MachineModel的私有成员,这应该阻止人们尝试这样做.

解决方法 您可以反转依赖关系并使Snapshot成为MachineModel的子(嵌套类).然后,Snapshot只有一个公共(或内部)Restore()方法,该方法将MachineModel的实例作为参数.由于Snapshot被定义为MachineModel的子级,因此可以看到MachineModel的私有字段.

要恢复状态,下面的示例中有两个选项.您可以调用Snapshot.RestoreState(MachineModel)或MachineModel.Restore(Snapshot)*.

public class MachineModel{ public class Snapshot { int _mmPrivateField; public Snapshot(MachineModel mm) { // get mm’s state _mmPrivateField = mm._privateField; } public void RestoreState(MachineModel mm) { // restore mm’s state mm._privateField = _mmPrivateField; } } int _privateField; public Snapshot CurrentSnapshot { get { return new Snapshot(this); } } public void RestoreState(Snapshot ss) { ss.Restore(this); }}

例:

MachineModel mm1 = new MachineModel(); MachineModel.Snapshot ss = mm1.CurrentSnapshot; MachineModel mm2 = new MachineModel(); mm2.RestoreState(ss);

*将Snapshot.RestoreState()作为内部并将所有调用者放在程序集之外是最简洁的,因此执行还原的唯一方法是通过MachineModel.RestoreState().但是你在Jon的回答中提到在同一个程序集中会有调用者,所以没有多大意义.