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