在C#中创建只读数组的最佳方法是什么?

时间:2010-01-25 16:11:04

标签: c# arrays readonly

我想要从我的财产中返回一个只读数组的极不可能和原始情况。到目前为止,我只知道一种方法 - 通过System.Collections.ObjectModel.ReadOnlyCollection<T>。但这对我来说似乎有些尴尬,更不用说这个类失去了通过索引访问数组元素的能力(添加:哎呀,我错过了索引器)。有没有更好的方法?可以使数组本身不可变的东西吗?

8 个答案:

答案 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

这支持以下任何一项:

  • .NET 4.5(或更高版本)
  • .NETStandard 1.0(或更高版本)
  • Windows 8.0
  • WindowsPhone 8.0
  • WindowsPhoneApp 8.1
  • 便携式类库(.NETFramework 4.5,Windows 8.0,WindowsPhone 8.0,WindowsPhoneApp 8.1)