I read recently about covariance and contravariance - little code example below:
public class BaseClass{
public int x = 1;
public static void print(BaseClass objClass)
{
Console.WriteLine(objClass.GetType().Name + " " + objClass.x);
}
}
public class DerivedClass : BaseClass{
public int x = 2;
}
public class Program
{
public static void Main(string[] args)
{
BaseClass bC = new BaseClass();
DerivedClass dC = new DerivedClass();
BaseClass.print(bC); //DerivedClass 1
DerivedClass.print(bC); //DerivedClass 1
BaseClass.print(dC); //DerivedClass 1
DerivedClass.print(dC); //DerivedClass 1
}
}
My question is - what contravariance give us in practice ? I know that I can pass object of DerivedClass as argument into BaseClass method (where parameter is BaseClass type) but what are the benefits of such operation ? And why when I pass DerivedClass object it returns me value of x in BaseClass ?
Maybe this is bad example for explain benefits of contravariance then I would be grateful for another example.
why when I pass DerivedClass object it returns me value of x in BaseClass ?
You are hiding the field in the derived class. In effect DerivedClass
has two x
fields - one from the base class, one from the derived class. Since the parameter to print
is of type BaseClass
the compiler will bind objClass.x
to the field in the base class.
If instead you have a virtual property and an override:
public class BaseClass{
public virtual int x {get {return 1;}}
public static void print(BaseClass objClass)
{
Console.WriteLine(objClass.GetType().Name + " " + objClass.x);
}
}
public class DerivedClass : BaseClass{
public override int x {get {return 2;}}
}
Or just set the base field to a different value in the derived class:
public class DerivedClass : BaseClass{
public DerivedClass() {x = 2;}
}
You would see the results you expect.