禁止修改词典
本文关键字:修改 禁止 | 更新日期: 2023-09-27 18:28:12
如何防止字典项在类外进行修改?我必须将对象集合公开为一个属性,但这样每个人都可以对我的对象执行任何操作。我尝试使用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!
}
}
如果您想向"客户端代码"公开一个对象,但又不想修改该对象,则必须返回一个"不可变类型"。可以是不可变类的形式,也可以是只具有只读属性的接口。
这也意味着,您类型的所有属性和嵌套属性等也应该是"不可变的",否则它们仍然可以修改嵌套成员。换句话说,您公开的类型的对象图中的所有类型都必须是不可变的
另一种选择是克隆对象并返回副本,然后忘记修改。但请确保您正在执行深度复制,而不是浅层复制
使类不可变,例如:
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;
}
}
如果ReferenceTrig是一个本身不是不可变的对象,那么这还不够。它适用于这个特定的例子,因为它只能是一个字符串(它本身是不可变的)。但是,如果它是其他类型,那么类型本身就必须是不可变的,并且(递归地)它包含的任何公共字段和属性也必须是不不变的。(我称之为"深度不可变"。)
以下是一系列关于C#中不变性的有趣文章:
http://blogs.msdn.com/b/ericlippert/archive/2007/11/13/immutability-in-c-part-one-kinds-of-immutability.aspx