Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/286.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
什么';在C#中创建只读数组的最佳方法是什么?_C#_Arrays_Readonly - Fatal编程技术网

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

什么';在C#中创建只读数组的最佳方法是什么?,c#,arrays,readonly,C#,Arrays,Readonly,我有一种极不可能的原始情况,就是希望从我的属性返回一个只读数组。到目前为止,我只知道一种方法——通过System.Collections.ObjectModel.ReadOnlyCollection。但这对我来说似乎有些尴尬,更不用说这个类失去了通过索引访问数组元素的能力(添加:哎呀,我错过了索引器)。没有更好的办法了吗?可以使数组本身不可变的东西?我想到了IEnumerable。您可能希望实现IEnumerable接口并重载this[int]操作符,以拒绝访问其setter使用。它是只读的,与

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

我想到了IEnumerable。

您可能希望实现IEnumerable接口并重载this[int]操作符,以拒绝访问其setter使用。它是只读的,与您所相信的相反,它有一个索引器


数组不是不可变的,如果不使用像
ReadOnlyCollection
这样的包装器,就无法使它们不变


请注意,创建
ReadOnlyCollection
包装器是一个O(1)操作,不会产生任何性能成本

更新
其他答案建议只将集合强制转换为较新的集合,这扩展了
IReadOnlyCollection
以添加索引器。不幸的是,这实际上并不能让您控制集合的易变性,因为它可能会被转换回原始集合类型并进行变异


相反,您仍然应该使用
ReadOnlyCollection
List
方法,或
Array
s静态方法有助于相应地包装列表和数组)来创建对集合的不可变访问,然后直接或作为其支持的任何一个接口公开,include
IReadOnlyList

如果您确实希望返回数组,但又担心数组的使用者会弄乱内部数据,只需返回数组的副本即可。我个人仍然认为,
ReadOnlyCollection
是一条路,但是,如果你真的想要一个数组,…

来自.NET Framework 2.0和更高版本,它会自动为你创建一个包装器。

.NET Framework 4.5引入了
IReadOnlyList
,它扩展自
IReadOnlyCollection
添加
T这个[int index]{/*.*/get;}

您可以从
T[]
强制转换为
IReadOnlyList
。这样做的一个优点是
(IReadOnlyList)数组
可以理解为等于
数组
;不涉及拳击


当然,由于没有使用包装器,
(T[])GetReadOnlyList()
是可变的。

现在支持不可变集合。 看

这支持以下任何一项:

  • .NET 4.5(或更高版本)
  • .NETStandard 1.0(或更高版本)
  • Windows 8.0
  • WindowsPhone 8.0
  • WindowsPhoneApp 8.1
  • 可移植类库(.NETFramework 4.5、Windows 8.0、Windows Phone 8.0、Windows PhoneApp 8.1)

我承认这是一个老问题,但现在有一些.NET包包含一个类型。内置于.NET Core 3中,可通过获取完整的framework 4.5版本

ReadOnlyCollection有一个索引器,它支持索引。您不能使数组不可变。实际上,ReadOnlyCollection确实有一个indexer属性…@BFree-但(重要的是)它不允许您通过indexer@nobugz-当然可以:
新字符串[0]
-不可变-p两点:(1)我们正在考虑为C#的未来版本使用不可变数组,但这相当棘手;如果数组的内容无法更改,如何初始化该数组?我们正在努力,但没有承诺,这只是在构思阶段。(2)不要忘记只读集合只是可变对象上的不可变外观;如果其他人对底层对象进行了变异,facade将公开该变异。您的意思是将我的数组强制转换为IEnumerable并返回它吗?这将比只读集合更糟糕。首先,任何人都可以轻松地将其投射回数组并进行修改。其次,它提供了数组提供的更小的功能子集。您可以使用迭代器(yield-return语句)使其正常工作。这似乎是个好主意,直到您意识到类.MyArray[i]将在循环中执行什么操作。这样做1000次,您就有1000个阵列副本@RichardOD是真的,但你不能那样做。如果您是通过主类上的索引访问它,那么您只需返回元素。如果你返回数组,那么给用户一个函数,该函数将返回数组的一个副本,并对其进行迭代。说什么?在哪些方面它比上面提到的ReadOnlyCollection更好?翻译:“您可能想要实现一个接口,但没有实现它”-1
ReadOnlyCollection
不能用作不可变的集合。它比数组小一点,但是周围有更多的代码。它唯一的“功能”是不允许用户修改集合,但它甚至不能保证用户。。。底线:没用@加托皮奇:无用是没有根据的说法。请提供您的来源,以了解其缺乏使用。不过,这句话很好听。我希望这个类能够实现IReadOnlyList接口。另请参见.NET 4.5中@Warty对
IReadOnlyList
的回答。@Mike EEE:在小型阵列上,它的速度似乎确实慢了约10倍。然而,在较大的阵列上,它的速度要慢约2倍。不太理想,我同意,不过我想知道你在做什么,这意味着在这种情况下,性能很重要。我刚刚做了一个1亿次的迭代测试,用了不到一秒钟的时间。正如您所指出的,仅仅对接口进行强制转换的问题是它可以再次被强制转换。这意味着您无法控制数据的可变性。您仍然应该先使用
ReadOnlyCollection
进行包装,然后再使用
IReadOnlyList
进行包装,这样您就可以控制数据的保存方式