In the .NET Framework, there are interfaces for immutable dictionaries, lists, queues, sets, stacks.
But there is no interface for immutable arrays to be found.
Also, immutable arrays are implemented as a struct
in contrast to others which are class
.
Can you explain why such design?
CodePudding user response:
ImmutableArray<T>
and ImmutableList<T>
are functionally compatible types, so implementing just IImmutableList<T>
is enough for both.
They differ only in characteristics, which is described in the documentation:
ImmutableArray<T>
uses an actual underlying array, so accessing an element by index is an O(1) operation, whereas adding a new element (and thus creating a new array and copying all items from the previous one) has an O(n) cost- In contrast,
ImmutableList<T>
is represented as a binary tree, so both element access by index and adding a new item have O(log N) cost.
Additionally, ImmutableArray<T>
is a struct
so if used directly, accessing the underlying array is very fast. However, if it is boxed (eg. using as an interface implementation, including LINQ), its usage will be somewhat slower.
Conclusion: you must decide which one fits better for your needs. If you typically create it once and then just access elements ImmutableArray<T>
(or even a simple List<T>
can be better). But if you add new elements more frequently than access them by index, then ImmutableList<T>
can be a more optimal choice.
CodePudding user response:
In general interfaces and classes don't have an one-to-one relationship in .NET. For example see a recent comment by a Microsoft engineer on GitHib:
We generally don't expose collection abstractions, unless the BCL contains a reasonable number of implementations that share the same feature set.
By "collection abstractions" they mean interfaces. Some immutable collections do have such a relationship, like the ImmutableQueue<T>
collection and the IImmutableQueue<T>
interface, but you could see them more as an exception than the rule.
The ImmutableArray<T>
struct is interesting. You can learn why it was implemented as a struct
in this blog post by Immo Landwerth. Quote:
ImmutableArray<T>
is a very thin wrapper around a regular array and thus shares all the benefits with them. We even made it a value type (struct) as it only has a single field which holds the array it wraps. This makes the size of the value type identical to the reference of the array. In other words: passing around an immutable array is as cheap as passing around the underlying array. Since it’s a value type, there is also no additional object allocation necessary to create the immutable wrapper, which can reduce GC pressure.
The ImmutableArray<T>
implements many interfaces, but if you store it as an interface in a variable or field, it will be boxed. So you generally don't want to do this. Preferably you'd want to store it and pass it around as is.