禁止设置酒店的财产

时间:2011-06-13 22:40:21

标签: c# .net

我不确定这叫什么,或者我确实看到了这个,所以我真的不知道要搜索什么。因此,我试图解释我的意思。

假设我有以下类结构,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中的更改,我想要BTypeA的值{{1}}被重新分配。

我认为我之前看到过类似的东西,有一些内置对象,这会引发错误和编译时间。这叫什么,我怎样才能在自定义类型中实现它?

5 个答案:

答案 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设为只读字段,该怎么办?这样它只能设置一个结构,之后不会改变。

另外,内部/私人二传手怎么样?这满足了需求吗?