Information Technology Reference
In-Depth Information
public class
Asteroid
:
CelestialBody
{
// elided
}
This method treats arrays of CelestialBody objects covariantly, and does so
safely:
public static void
CoVariantArray(
CelestialBody
[] baseItems)
{
foreach
(
var
thing
in
baseItems)
Console
.WriteLine(
"{0} has a mass of {1} Kg"
,
thing.Name, thing.Mass);
}
This method also treats arrays of CelestialBody objects covariantly, but it
is not safe. The assignment statement will throw an exception.
public static void
UnsafeVariantArray(
CelestialBody
[] baseItems)
{
baseItems[
0
] =
new
Asteroid
{ Name =
"Hygiea"
, Mass =
8.85e19
};
}
Yo u c a n h a v e t h e s a m e p r o b l e m s i m p l y b y a s s i g n i n g a n a r r a y o f a d e r i v e d
class to a variable that is an array of a base type:
CelestialBody
[] spaceJunk =
new
Asteroid
[
5
];
spaceJunk[
0
] =
new
Planet
();
Tr e a t i n g c o l l e c t i o n s a s c o v a r i a n t m e a n s t h a t w h e n t h e r e i s a n i n h e r i t a n c e
relationship between two types, you can imagine there is a similar inher-
itance relationship between arrays of those two types. This isn't a strict
definition, but it's a useful picture to keep in your mind. A Planet can be
passed to any method that expects CelestialBody. That's because Planet is
derived from CelestialBody. Similarly, you can pass a Planet[] to any
method that expects a CelestialBody[]. But, as the above example shows,
that doesn't always work the way you'd expect.
When generics were first introduced, this issue was dealt with in a rather
draconian fashion. Generics were always treated invariantly. Generic types
had to have an exact match. However, in C# 4.0, you can now decorate