在 C# 中创建只读数组的最佳方法是什么?
我遇到了一种极不可能的原始情况,即想要从我的财产返回只读数组。到目前为止,我只知道一种方法 - 通过 System.Collections.ObjectModel.ReadOnlyCollection更不用说这个类失去了通过索引访问数组元素的能力(补充:哎呀,我错过了索引器)。难道就没有更好的办法了吗?有什么可以使数组本身不可变的吗?
I've got the extremely unlikely and original situation of wanting to return a readonly array from my property. So far I'm only aware of one way of doing it - through the System.Collections.ObjectModel.ReadOnlyCollection<T>
. But that seems somehow awkward to me, not to mention that this class loses the ability to access array elements by their index (added: whoops, I missed the indexer). Is there no better way? Something that could make the array itself immutable?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(8)
使用
ReadOnlyCollection
。它是只读的,并且与您的想法相反,它有一个索引器。数组不是不可变的,如果不使用像
ReadOnlyCollection
这样的包装器,就无法使它们成为不可变的。请注意,创建
ReadOnlyCollection
包装器是 O(1) 操作,并且不会产生任何性能成本。更新
其他答案建议将集合转换为较新的
IReadOnlyList
,它扩展了IReadOnlyCollection
以添加索引器。不幸的是,这实际上并不能让您控制集合的可变性,因为它可以被强制转换回原始集合类型并发生变化。相反,您仍然应该使用
ReadOnlyCollection
(List
方法AsReadOnly()
或Array
的静态方法 < code>AsReadOnly() 有助于相应地包装列表和数组)以创建对集合的不可变访问,然后直接公开它或作为它支持的任何一个接口(包括) IReadOnlyList
。Use
ReadOnlyCollection<T>
. It is read-only and, contrary to what you believe, it has an indexer.Arrays are not immutable and there is no way of making them so without using a wrapper like
ReadOnlyCollection<T>
.Note that creating a
ReadOnlyCollection<T>
wrapper is an O(1) operation, and does not incur any performance cost.Update
Other answers have suggested just casting collections to the newer
IReadOnlyList<T>
, which extendsIReadOnlyCollection<T>
to add an indexer. Unfortunately, this doesn't actually give you control over the mutability of the collection since it could be cast back to the original collection type and mutated.Instead, you should still use the
ReadOnlyCollection<T>
(theList<T>
methodAsReadOnly()
, orArray
s static methodAsReadOnly()
helps to wrap lists and arrays accordingly) to create an immutable access to the collection and then expose that, either directly or as any one of the interfaces it supports, includingIReadOnlyList<T>
..NET Framework 4.5 引入了
IReadOnlyList
,它从IReadOnlyCollection
扩展而来,添加了T this[int index] { /*..*/ get; }
。您可以从
T[]
转换为IReadOnlyList
。这样做的一个优点是(IReadOnlyList)array
可以理解为等于array
;不涉及拳击。当然,由于未使用包装器,
(T[])GetReadOnlyList()
将是可变的。.NET Framework 4.5 introduced
IReadOnlyList<T>
which extends fromIReadOnlyCollection<T>
addingT this[int index] { /*..*/ get; }
.You can cast from
T[]
toIReadOnlyList<T>
. One advantage of this is that(IReadOnlyList<T>)array
understandably equalsarray
; no boxing is involved.Of course, as a wrapper is not being used,
(T[])GetReadOnlyList()
would be mutable.从 .NET Framework 2.0 及更高版本开始,Array.AsReadOnly 会自动创建为您提供的 ReadOnlyCollection 包装器。
From .NET Framework 2.0 and up there is Array.AsReadOnly which automatically creates a ReadOnlyCollection wrapper for you.
我认识到这是一个老问题,但现在有一些 .NET 包包含 ImmutableArray 类型。内置于 .NET Core 3,并可通过 NuGet 获取完整框架 4.5 及以上版本
I recognise that this is an old question, but there are packages for .NET now that contain an ImmutableArray type. Built in to .NET Core 3, and available via NuGet for Full framework 4.5 onwards
如果你确实想要返回一个数组,但又担心数组的使用者会弄乱内部数据,那么只需返回数组的副本即可。就我个人而言,我仍然认为
ReadOnlyCollection
是可行的方法,但如果您真的想要一个数组......If you really want an array returned, but are afraid that the consumer of the array will mess with the internal data, just return a copy of the Array. Personally I still think
ReadOnlyCollection<T>
is the way to go, but if you REALLY want an array.....现在支持不可变集合。
请参阅 https://www.nuget.org/packages/System.Collections.Immutable
支持以下任意版本:
There is now support for Immutable collections.
See https://www.nuget.org/packages/System.Collections.Immutable
This supports any of the following:
我想到了 IEnumerable。
IEnumerable comes to mind.
您可能想要实现 IEnumerable 接口并重载 this[int] 运算符以拒绝对其 setter 的访问
You might want to implement the IEnumerable interface and overload the this[int] operator to deny access to it's setter