ReadOnlyCollection
是不可变的事实意味着该集合不能被修改,即不能添加或从集合中删除对象。这并不意味着它包含的对象是不可变的。
This article作者:Eric Lippert,解释了不同种类的不变性是如何工作的。基本上,ReadOnlyCollection
是一个不可改变的外观,可以读取底层集合(_myDataList
),但无法修改它。但是,您仍然可以更改基础集合,因为您可以通过执行诸如_myDataList[0] = null
之类的操作来参考_myDataList
。
此外,由ReadOnlyCollection
返回的对象与由_myDataList
返回的对象相同,即this._myDataList.First() == this.MyReadOnlyList.First()
(具有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; }
}
:
public struct Point
{
public int X { get; set; }
public int Y { get; set; }
}
编辑:在这种情况下,如Ian Goldby指出,无论是结构允许修改集合中的元素的属性。发生这种情况是因为结构是值类型,当您访问元素时,集合会返回该值的副本。如果它是一个类,则只能修改Point
类型的属性,这意味着将返回对实际对象的引用,而不是其值的副本。
其实,如果在ReadOnlyCollection对象是结构,而不是类,然后他们有效地只读的集合,因为访问一个元素给你一个* boxed *结构。你不能直接修改它(“不能修改拆箱转换的结果”),如果你将它赋给本地结构变量,你会得到一个副本。 (尽管您仍然可以通过Items属性修改ReadOnlyCollection。) –
如果集合是泛型并返回类型为“T”的元素,为什么集合返回的值会被装箱?除此之外,我更新了我的答案,说集合中的结构是有效的,因为你只能得到它们的值的副本。 –
我怀疑这是框架的优化,以防止刚刚读取的结构副本。当然,如果你编写'roList [i] .X = 5',编译器会抱怨“无法修改拆箱转换的结果”。如果编译器没有这样做,那么'x = roList [i] .X'总是需要为了读取一个属性而创建一个完整的结构副本。 –