Is it possible to somehow mark a System.Array
as immutable. When put behind a public-get/private-set they can't be added to, since it requires re-allocation and re-assignment, but a consumer can still set any subscript they wish:
public class Immy
{
public string[] { get; private set; }
}
I thought the readonly
keyword might do the trick, but no such luck.
.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>
:immutable
will be aReadOnlyCollection<char>
instance. As a more general use case, you can create aReadOnlyCollection<T>
from any genericIList<T>
implementation.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 implementsIList
. This brings to light the possibility of usingArray.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:The Framework Design Guidelines suggest returning a copy of the Array. That way, consumers can't change items from the array.
these are better:
The examples are straight from the book.
You could use Array.AsReadOnly method to return.
Further to Matt's answer, IList is a complete abstract interface to an array, so it allows add, remove, etc. I'm not sure why Lippert appears to suggest it as an alternative to IEnumerable where immutability is needed. (Edit: because the IList implementation can throw exceptions for those mutating methods, if you like that kind of thing).
Maybe another thing to bear in mind that the items on the list may also have mutable state. If you really don't want the caller to modify such state, you have some options:
Make sure the items on the list are immutable (as in your example: string is immutable).
Return a deep clone of everything, so in that case you could use an array anyway.
Return an interface that gives readonly access to an item:
Note that every value accessible from the IImmutable interface must itself be immutable (e.g. string), or else be a copy that you make on-the-fly.
ReadOnlyCollection<T>
is probably what you are looking for. It doesn't have anAdd()
method.The only thing to add is that Arrays imply mutability. When you return an Array from a function, you are suggesting to the client programmer that they can/should change things.