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.