No, this is not really covariance. This is just the implementation of an interface. Specifically, it is an example of assignment compatibility. Because the Car
class implements the ICarInterface
interface, a Car
object can be assigned to a variable of type ICarInterface
. An object of a more-specific type (Car
) was assigned to a storage area for a less-specific type (ICarInterface
), which works because the two types are compatible for the purposes of assignment.
Covariance is a slightly different thing. A type relationship is covariant if it preserves the ordering of types (from the more-specific to the more-generic). For example, IEnumerable<T>
is covariant with respect to type T
, so it preserves the ordering of types IEnumerable<Vehicle>
(more-generic) and IEnumerable<Car>
(more-specific). (In this example, we are of course assuming that Car
is a subclass of Vehicle
).
Eric Lippert has written an excellent article that distinguishes between covariance and assignment-compatibility. It gets slightly technical and theoretical, but you should definitely read it. I would not do it justice by trying to summarize it any further here.
An easier-to-understand example of covariance (at least in my opinion) is return-type covariance. This is where a derived class's override of a base-class method returns a more specific type. For example:
abstract class Habitat
{
public abstract Animal ApexPredator();
}
class Savanna : Habitat
{
public override Lion ApexPredator()
{ ... }
}
class Ocean : Habitat
{
public override Shark ApexPredator()
{ ... }
}
In this example, the abstract class Habitat
has two concrete subclasses: Savanna
and Ocean
. All habitats have an ApexPredator
, which is of type Animal
. But in a Savanna
object, the apex predator is a Lion
, whereas in an Ocean
object, the apex predator is a Shark
. This is legal and safe because Lion
and Shark
are both types of Animal
s.
Unfortunately, C# does not support return type covariance. It is, however, supported by C++ (including C++/CLI), Java, and a number of other object-oriented languages.
Here are some more concrete examples of covariance.