So as you may know, arrays in C# implement IList<T>, among other interfaces. Somehow though, they do this without publicly implementing the Count property of IList<T>! Arrays have only a Length property.
Is this a blatant example of C#/.NET breaking its own rules about the interface implementation or am I missing something?
New answer in the light of Hans’s answer
Thanks to the answer given by Hans, we can see the implementation is somewhat more complicated than we might think. Both the compiler and the CLR try very hard to give the impression that an array type implements
IList<T>– but array variance makes this trickier. Contrary to the answer from Hans, the array types (single-dimensional, zero-based anyway) do implement the generic collections directly, because the type of any specific array isn’tSystem.Array– that’s just the base type of the array. If you ask an array type what interfaces it supports, it includes the generic types:Output:
For single-dimensional, zero-based arrays, as far as the language is concerned, the array really does implement
IList<T>too. Section 12.1.2 of the C# specification says so. So whatever the underlying implementation does, the language has to behave as if the type ofT[]implementsIList<T>as with any other interface. From this perspective, the interface is implemented with some of the members being explicitly implemented (such asCount). That’s the best explanation at the language level for what’s going on.Note that this only holds for single-dimensional arrays (and zero-based arrays, not that C# as a language says anything about non-zero-based arrays).
T[,]doesn’t implementIList<T>.From a CLR perspective, something funkier is going on. You can’t get the interface mapping for the generic interface types. For example:
Gives an exception of:
So why the weirdness? Well, I believe it’s really due to array covariance, which is a wart in the type system, IMO. Even though
IList<T>is not covariant (and can’t be safely), array covariance allows this to work:… which makes it look like
typeof(string[])implementsIList<object>, when it doesn’t really.The CLI spec (ECMA-335) partition 1, section 8.7.1, has this:
…
(It doesn’t actually mention
ICollection<W>orIEnumerable<W>which I believe is a bug in the spec.)For non-variance, the CLI spec goes along with the language spec directly. From section 8.9.1 of partition 1:
(A vector is a single-dimensional array with a zero base.)
Now in terms of the implementation details, clearly the CLR is doing some funky mapping to keep the assignment compatibility here: when a
string[]is asked for the implementation ofICollection<object>.Count, it can’t handle that in quite the normal way. Does this count as explicit interface implementation? I think it’s reasonable to treat it that way, as unless you ask for the interface mapping directly, it always behaves that way from a language perspective.What about
ICollection.Count?So far I’ve talked about the generic interfaces, but then there’s the non-generic
ICollectionwith itsCountproperty. This time we can get the interface mapping, and in fact the interface is implemented directly bySystem.Array. The documentation for theICollection.Countproperty implementation inArraystates that it’s implemented with explicit interface implementation.If anyone can think of a way in which this kind of explicit interface implementation is different from “normal” explicit interface implementation, I’d be happy to look into it further.
Old answer around explicit interface implementation
Despite the above, which is more complicated because of the knowledge of arrays, you can still do something with the same visible effects through explicit interface implementation.
Here’s a simple standalone example: