lun*_*c84 3 c# readonly-collection immutable-collections
我正在尝试使用ReadOnlyCollection使对象不可变,我希望对象的属性是不可变的.
public ReadOnlyCollection<FooObject> MyReadOnlyList
{
get
{
return new ReadOnlyCollection<FooObject>(_myDataList);
}
}
Run Code Online (Sandbox Code Playgroud)
但我有点困惑.
我试图使用foreach将对象的属性更改为MyReadOnlyList并且...我可以更改value属性,是否正确?我理解ReadOnlyCollection设置一个添加级别,使对象不可变.
ReadOnlyCollection不可变的事实意味着不能修改集合,即不能从集合中添加或删除任何对象.这并不意味着它包含的对象是不可变的.
Eric Lippert 撰写的这篇文章解释了不同类型的不变性如何发挥作用.基本上,a ReadOnlyCollection是一个不可变的外观,它可以读取底层的collection(_myDataList),但不能修改它.但是,您仍然可以更改基础集合,因为您可以_myDataList通过执行类似操作来引用它_myDataList[0] = null.
此外,返回的对象与返回的对象ReadOnlyCollection相同_myDataList,即this._myDataList.First() == this.MyReadOnlyList.First()(with LINQ).这意味着如果一个对象_myDataList是可变的,那么对象也是如此MyReadOnlyList.
如果您希望对象是不可变的,则应相应地设计它们.例如,您可以使用:
public struct Point
{
public Point(int x, int y)
{
this.X = x;
this.Y = y;
}
// In C#6, the "private set;" can be removed
public int X { get; private set; }
public int Y { get; private set; }
}
Run Code Online (Sandbox Code Playgroud)
代替:
public struct Point
{
public int X { get; set; }
public int Y { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
编辑:在这种情况下,如Ian Goldby所述,两种结构都不允许您修改集合中元素的属性.发生这种情况是因为结构是值类型,当您访问元素时,集合会返回值的副本.您只能修改Point类型的属性(如果它是类),这意味着将返回对实际对象的引用,而不是其值的副本.