To clarify usr's correct but somewhat sparse answer:
C# supports a feature -- my candidate for "worst feature in C#" -- called array type covariance. That is, if you have an array of turtles, you can assign it to a variable of type "array of animals":
class Animal {}
class Turtle : Animal {}
...
Animal[] animals = new Turtle[10];
This is "covariance" because the assignment compatibility rule for arrays is an arrow in the same direction as the assignment compatibility rule for its elements:
Turtle --> Animal
Turtle[] --> Animal[]
This is feature is not type safe because, well...
animals[0] = new Giraffe();
And we just put a giraffe into an array that is actually an array of turtles. The compiler cannot determine that type safety is violated here -- a giraffe is an animal -- so the check has to be performed by the runtime.
To prevent this from happening at runtime, the runtime inserts a check every time you put a Giraffe into an array of Animals to check if it is really an array of Turtles. Which it almost never is. But this check takes time, and so the feature effectively slows down every successful array access.
Unsafe array covariance only applies to arrays whose element types are reference types. It does not apply to value types. (This is a small lie; the CLR will allow you to cast int[]
to object
and then object
to uint[]
. But in general, covariance does not apply to value types.)
Therefore you can save on the expense of the check by making your array actually an array of value type, where the value type is just a wrapper for the reference. The size of the array will be unaffected, but the access to it will be slightly faster.
You should not pull these sorts of crazy tricks unless you have empirical evidence that doing so actually solves a practical performance problem. The number of situations in which this optimization is warranted is quite small, but there are a few places where this sort of thing can make a difference.
I note that you can also avoid the cost of the check by sealing the Turtle type and then using an array of Turtles. The runtime will reason that the array type cannot really be more derived because then its element type would derive from a sealed type, which is impossible.