防止字典修改

时间:2014-10-29 13:57:49

标签: c# dictionary pass-by-reference readonly

如何防止字典项目在课堂外修改? 我必须将对象集合作为属性公开,但是每个人都可以使用我的对象完成所有操作。我尝试使用ReadOnlyDictionary来包装我的公共属性,但IntegerValue属性仍然可以从外部修改。

示例代码如下:

internal class MyRefClass
{
    public object ReferenceStrig;
    public int IntegerValue;

    public MyRefClass()
    {
     ReferenceStrig = "Initialized string";
        IntegerValue = 100;
    }
}

class Program
{
    static void Main(string[] args)
    {
        var writableDict = new Dictionary<int, MyRefClass>();
        writableDict.Add(1,new MyRefClass());

        ReadOnlyDictionary<int, MyRefClass> dict = new ReadOnlyDictionary<int, MyRefClass>(writableDict);

    MyRefClass variable;
    dict.TryGetValue(1, out variable); #get an object from dictionary
    variable.IntegerValue = 0; #changing property of the object

    writableDict.TryGetValue(1, out variable); #get the same object once again
    #now property variable.IntegerValue == 0 instead of 100!
    }
}

2 个答案:

答案 0 :(得分:5)

如果要将对象公开给“客户端代码”,但又想要不修改该对象,那么必须返回“不可变类型”。以不可变类的形式或仅具有只读属性的接口。

这也意味着你的类型的所有属性和嵌套属性等也应该是“不可变的”,否则它们仍然可以修改嵌套成员。换句话说,您公开的类型的对象图中的所有类型必须是不可变的。

另一种选择是克隆对象并返回副本并忘记修改。但请确保您正在执行深层复制而不是浅层复制。浅拷贝遭遇上述问题。

答案 1 :(得分:1)

使您的类不可变,例如:

class MyImmutableRefClass
{
    public readonly object ReferenceStrig;
    public readonly int IntegerValue;

    public MyImmutableRefClass(): this("Initialized string", 100)
    {
    }

    public MyImmutableRefClass(string referenceStrig, int integerValue)
    {
        ReferenceStrig = referenceStrig;
        IntegerValue   = integerValue;
    }
}

如果ReferenceStrig是一个本身不是不可变的对象,这还不够。它适用于这个特定的例子,因为它只能是一个字符串(它本身是不可变的)。 但是如果它是某种其他类型,则 类型本身必须是不可变的 - 并且(递归地)它包含的任何公共字段和属性也必须是不可变的。 (我称之为“深刻不变”。)

这是一系列关于C#不变性的有趣文章:

http://blogs.msdn.com/b/ericlippert/archive/2007/11/13/immutability-in-c-part-one-kinds-of-immutability.aspx