我不确定这叫什么,或者我确实看到了这个,所以我真的不知道要搜索什么。因此,我试图解释我的意思。
假设我有以下类结构,TypeB
中使用了TypeA
:
class TypeA
{
public TypeB B
{ get; set }
}
class TypeB
{
public int X
{ get; set }
}
现在当我有一个TypeA实例时,我想不允许,我可以直接修改TypeB的值而无需重新分配。所以基本上我想阻止这个:
TypeA a = new TypeA();
// this should not be possible:
a.B.X = 1234;
// but this should work:
TypeB b = a.B;
b.X = 1234;
a.B = b;
原因是我以特殊方式持久保存对象,因此为了正确跟踪TypeB
中的更改,我想要B
中TypeA
的值{{1}}被重新分配。
我认为我之前看到过类似的东西,有一些内置对象,这会引发错误和编译时间。这叫什么,我怎样才能在自定义类型中实现它?
答案 0 :(得分:3)
在WPF / Silverlight中,有两个概念是“密封”和“冻结”对象。基本上,一旦密封/冷冻,物体就不能改变。您可以在此处应用相同的逻辑:
public class SealableObject {
public bool IsSealed { get; private set; }
public void Seal() {
if (this.IsSealed)
throw new InvalidOperationException("The object is already sealed");
this.IsSealed = true;
}
protected void VerifyNotSealed() {
if (this.IsSealed)
throw new InvalidOperationException("Object is sealed");
}
}
然后您需要检查派生类IsSealed
中的TypeB
,如下所示:
class TypeB : SealableObject
{
private int x;
public int X
{
get { return this.x; }
set {
this.VerifyNotSealed();
this.x = value;
}
}
然后,当分配给TypeA属性时,你需要密封TypeB。
答案 1 :(得分:3)
您可以在TypeB
中的属性获取器中返回TypeA
对象的副本:
class TypeA
{
private TypeB _b;
public TypeB B
{
get { return (TypeB)_b.Clone(); }
set { _b = value; }
}
}
这将阻止直接修改_b的属性。但是,它实际上不会禁止执行a.B.X = 1234;
,但该指令将不起作用(它只会修改将立即丢弃的副本)。
除非TypeB
是结构,否则无法阻止这样的指令:
也无法在运行时检测到,因为您无法区分:
TypeB b = a.B;
b.X = 1234;
和
a.B.X = 1234;
在这两种情况下,属性都以相同的方式调用,并且无法知道调用代码对结果的影响...
答案 2 :(得分:1)
让TypeB
实现一个仅使用getter定义X
的接口。在TypeA
上公开具有此接口类型的属性。现在,您只能在进行向下转换时修改属性的属性,这是您可以实现的目标。
此方法将为您提供编译时安全性。如果您只需要运行时安全性,请查看CodeNaked的答案。
答案 3 :(得分:0)
您当前的代码不允许您想要的内容。你不能让int X读/写,只有当B存储在A中时才能读取它。如果你真的想保持int X不可变,那么不要把它保存在B类中。而是将int值保留在A中,并将其作为只读值。
答案 4 :(得分:-2)
如果您将A类中的属性B设为只读字段,该怎么办?这样它只能设置一个结构,之后不会改变。
另外,内部/私人二传手怎么样?这满足了需求吗?