简体   繁体   English

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

[英]What's the best way of creating a readonly array in C#?

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> .到目前为止,我只知道一种方法 - 通过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?可以使数组本身不可变的东西?

Use ReadOnlyCollection<T> .使用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> .数组不是一成不变的,如果不使用像ReadOnlyCollection<T>这样的包装器,就无法使它们如此。

Note that creating a ReadOnlyCollection<T> wrapper is an O(1) operation, and does not incur any performance cost.请注意,创建ReadOnlyCollection<T>包装器是一个 O(1) 操作,并且不会产生任何性能成本。

Update更新
Other answers have suggested just casting collections to the newer IReadOnlyList<T> , which extends IReadOnlyCollection<T> to add an indexer.其他答案建议只将集合转换为更新的IReadOnlyList<T> ,它扩展IReadOnlyCollection<T>以添加索引器。 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> (the List<T> method AsReadOnly() , or Array s static method AsReadOnly() 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, including IReadOnlyList<T> .相反,您仍然应该使用ReadOnlyCollection<T>List<T>方法AsReadOnly()Array的静态方法AsReadOnly()有助于相应地包装列表和数组)来创建对集合的不可变访问,然后公开它,直接或作为它支持的任何一种接口,包括IReadOnlyList<T>

.NET Framework 4.5 introduced IReadOnlyList<T> which extends from IReadOnlyCollection<T> adding T this[int index] { /*..*/ get; } .NET Framework 4.5 引入了IReadOnlyList<T> ,它从IReadOnlyCollection<T>添加T this[int index] { /*..*/ get; } T this[int index] { /*..*/ get; } . T this[int index] { /*..*/ get; } .

You can cast from T[] to IReadOnlyList<T> .您可以从T[]IReadOnlyList<T> One advantage of this is that (IReadOnlyList<T>)array understandably equals array ;这样做的一个优点是(IReadOnlyList<T>)array理解地等于array no boxing is involved.不涉及拳击。

Of course, as a wrapper is not being used, (T[])GetReadOnlyList() would be mutable.当然,由于没有使用包装器, (T[])GetReadOnlyList()将是可变的。

从 .NET Framework 2.0 开始, Array.AsReadOnly会自动为您创建一个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.....我个人仍然认为ReadOnlyCollection<T>是要走的路,但如果你真的想要一个数组......

I recognise that this is an old question, but there are packages for .NET now that contain an ImmutableArray type.我认识到这是一个老问题,但现在有包含ImmutableArray类型的 .NET 包。 Built in to .NET Core 3, and available via NuGet for Full framework 4.5 onwards内置于 .NET Core 3,可通过NuGet for Full framework 4.5 使用

IEnumerable 浮现在脑海中。

您可能想要实现 IEnumerable 接口并重载 this[int] 运算符以拒绝访问它的 setter

There is now support for Immutable collections.现在支持不可变集合。 See https://www.nuget.org/packages/System.Collections.Immutable请参阅https://www.nuget.org/packages/System.Collections.Immutable

This supports any of the following:这支持以下任何一项:

  • .NET 4.5 (or higher) .NET 4.5(或更高版本)
  • .NETStandard 1.0 (or higher) .NETStandard 1.0(或更高版本)
  • Windows 8.0视窗 8.0
  • WindowsPhone 8.0视窗电话 8.0
  • WindowsPhoneApp 8.1视窗手机应用程序 8.1
  • Portable Class Library (.NETFramework 4.5, Windows 8.0, WindowsPhone 8.0, WindowsPhoneApp 8.1)可移植类库(.NETFramework 4.5、Windows 8.0、WindowsPhone 8.0、WindowsPhoneApp 8.1)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM