.NET 倾向于避开数组,但最简单和最传统的用例除外。对于其他一切,有各种可枚举/集合实现。
当您想将一组数据标记为不可变时,您将超越传统数组提供的功能。 .NET 提供了等效的功能,但在技术上不是以数组的形式。要从数组中获取不可变集合,请使用Array.AsReadOnly<T>:
var mutable = new[]
{
'a', 'A',
'b', 'B',
'c', 'C',
};
var immutable = Array.AsReadOnly(mutable);
immutable 将是一个 ReadOnlyCollection<char> 实例。作为更一般的用例,您可以从任何通用的 IList<T> 实现创建 ReadOnlyCollection<T>。
var immutable = new ReadOnlyCollection<char>(new List<char>(mutable));
请注意,它必须是通用实现;普通的旧IList 将不起作用,这意味着您不能在传统数组上使用此方法,它仅实现IList。这揭示了使用Array.AsReadOnly<T> 作为一种快速访问通常无法通过传统数组访问的通用实现的方法的可能性。
ReadOnlyCollection<T> 将使您能够访问不可变数组所期望的所有功能:
// Note that .NET favors Count over Length; all but traditional arrays use Count:
for (var i = 0; i < immutable.Count; i++)
{
// this[] { get } is present, as ReadOnlyCollection<T> implements IList<T>:
var element = immutable[i]; // Works
// this[] { set } has to be present, as it is required by IList<T>, but it
// will throw a NotSupportedException:
immutable[i] = element; // Exception!
}
// ReadOnlyCollection<T> implements IEnumerable<T>, of course:
foreach (var character in immutable)
{
}
// LINQ works fine; idem
var lowercase =
from c in immutable
where c >= 'a' && c <= 'z'
select c;
// You can always evaluate IEnumerable<T> implementations to arrays with LINQ:
var mutableCopy = immutable.ToArray();
// mutableCopy is: new[] { 'a', 'A', 'b', 'B', 'c', 'C' }
var lowercaseArray = lowercase.ToArray();
// lowercaseArray is: new[] { 'a', 'b', 'c' }