.NET tends to steer away from arrays for all but the simplest and most traditional use cases. For everything else, there are various enumerable/collection implementations.
When you want to mark a set of data as immutable, you're going beyond the capability provided by a traditional array. .NET provides equivalent capability, but not technically in the form of an array. To get an immutable collection from an array, use Array.AsReadOnly<T>
:
var mutable = new[]
{
'a', 'A',
'b', 'B',
'c', 'C',
};
var immutable = Array.AsReadOnly(mutable);
immutable
will be a ReadOnlyCollection<char>
instance. As a more general use case, you can create a ReadOnlyCollection<T>
from any generic IList<T>
implementation.
var immutable = new ReadOnlyCollection<char>(new List<char>(mutable));
Note that it has to be a generic implementation; plain old IList
won't work, meaning that you can't use this method on a traditional array, which only implements IList
. This brings to light the possibility of using Array.AsReadOnly<T>
as a quick means of obtaining access to generic implementations that are normally inaccessible via a traditional array.
ReadOnlyCollection<T>
will give you access to all of the features that you would expect from an immutable array:
// 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' }
System.Collections.Immutable.ImmutableArray
in.net – Untruthful