我想要从我的财产中返回一个只读数组的极不可能和原始情况。到目前为止,我只知道一种方法 - 通过System.Collections.ObjectModel.ReadOnlyCollection<T>
。但这对我来说似乎有些尴尬,更不用说这个类失去了通过索引访问数组元素的能力(添加:哎呀,我错过了索引器)。有没有更好的方法?可以使数组本身不可变的东西吗?
答案 0 :(得分:47)
使用ReadOnlyCollection<T>
。它是只读的,与你的信念相反,它有一个索引器。
数组不是不可变的,如果不使用像ReadOnlyCollection<T>
这样的包装器,就无法实现它们。
请注意,创建ReadOnlyCollection<T>
包装器是O(1)操作,不会产生任何性能成本。
<强>更新强>
其他答案建议只将集合转换为较新的IReadOnlyList<T>
,扩展IReadOnlyCollection<T>
以添加索引器。不幸的是,这实际上并没有让你控制集合的可变性,因为它可以被转换回原始集合类型并进行变异。
相反,您仍应使用ReadOnlyCollection<T>
(List<T>
方法AsReadOnly()
,或Array
静态方法AsReadOnly()
有助于相应地包装列表和数组)创建对集合的不可变访问,然后直接或作为它支持的任何一个接口公开它,包括IReadOnlyList<T>
。
答案 1 :(得分:10)
.NET Framework 4.5引入了IReadOnlyList<T>
,IReadOnlyCollection<T>
扩展了T this[int index] { /*..*/ get; }
。
您可以从T[]
投射到IReadOnlyList<T>
。这样做的一个好处是(IReadOnlyList<T>)array
可以理解等于array
;没有拳击。
当然,由于没有使用包装器,(T[])GetReadOnlyList()
将是可变的。
答案 2 :(得分:6)
从.NET Framework 2.0开始,Array.AsReadOnly会自动为您创建ReadOnlyCollection包装。
答案 3 :(得分:5)
如果你真的想要一个返回的数组,但是担心数组的使用者会弄乱内部数据,只需返回一个数组的副本。就个人而言,我仍然认为ReadOnlyCollection<T>
是要走的路,但如果你真的想要一个阵列......
答案 4 :(得分:1)
IEnumerable浮现在脑海中。
答案 5 :(得分:1)
我认识到这是一个老问题,但是现在有.NET软件包包含ImmutableArray类型。内置于.NET Core 3中,可通过NuGet从Full Framework 4.5开始使用
答案 6 :(得分:0)
您可能希望实现IEnumerable接口并重载此[int]运算符以拒绝访问它的setter
答案 7 :(得分:0)
现在支持不可变集合。 参见https://www.nuget.org/packages/System.Collections.Immutable
这支持以下任何一项: