I am reading C# in Depth from Jon Skeet. Although I have understood the concept of CoVariance and ContraVariance, but I am unable to understand this line:
Well, covariance is safe when SomeType only describes operations that return the type parameter—and contravariance is safe when SomeType only describes operations that accept the type parameter.
Can someone please explain with an example for both, why both are type safe in one direction and not in the other direction?
Updated Question:
I still didn't understand from the answers given. I will try to explain my concern using the same example from the book - C# In Depth
.
It explains using the following class hierarchy:
COVARIANCE is: Trying to convert from IEnumerable<Circle>
to IEnumerable<IShape>
, but it is mentioned that this conversion is type safe only when we are performing while returning it from some method, and not type safe when we are passing it as an IN parameter.
IEnumerable<IShape> GetShapes()
{
IEnumerable<Circle> circles = GetEnumerableOfCircles();
return circles; // Conversion from IEnumerable<Circle> to IEnumerable<IShape> - COVARIANCE
}
void SomeMethod()
{
IEnumerable<Circle> circles = GetEnumerableOfCircles();
DoSomethingWithShapes(circles); // Conversion from IEnumerable<Circle> to IEnumerable<IShape> - COVARIANCE
}
void DoSomethingWithShapes(IEnumerable<IShape> shapes) // Why this COVARIANCE is type unsafe??
{
// do something with Shapes
}
CONTRA VARIANCE is: Trying to convert from IEnumerable<IShape>
to IEnumerable<Circle>
, which is mentioned to be type safe only while performing it when sending it as an IN parameter.
IEnumerable<Circle> GetShapes()
{
IEnumerable<IShape> shapes = GetEnumerableOfIShapes();
return shapes; // Conversion from IEnumerable<IShape> to IEnumerable<Circle> - Contra-Variance
// Why this Contra-Variance is type unsafe??
}
void SomeMethod()
{
IEnumerable<IShape> shapes = GetEnumerableOfIShapes();
DoSomethingWithCircles(shapes); // Conversion from IEnumerable<IShape> to IEnumerable<Circle> - Contra-Variance
}
void DoSomethingWithCircles(IEnumerable<Circle> circles)
{
// do something with Circles
}