class Person {
static int runningId = 0;
public int Id { get; } = runningId++;
public string
FirstName { get; set; }
public string LastName
{ get; set; }
}
class Student : Person {
public double
ClassHours { get; set; }
}
class Employee : Person {
public double Wage { get; set; }
}
class Teacher : Employee {
public double
TeachingHours { get; set; }
}
class Program
{
static void Main(string[] args)
{
Person student = new Student();
Person Teacher = new Teacher();
//not allowed; Employee does not derive from student
Student Employee = new Employee();
}
}
If you take a look at our program again
class Program
{
static void Print(Person p) {
Console.WriteLine(p.ToString());
}
static void
Print<T>(T p) {
Console.WriteLine(p.ToString());
}
static void Main(string[] args)
{
Print(new Teacher { Name = "Pawel" });
Print<Employee>(new Teacher{ Name = "Tomek" });
}
}
now let's take a look at covariance in the context of delegates
class Program
{
delegate Person GetPersonDelegate();
static void Main(string[] args)
{
GetPersonDelegate gpd = ()=> new Teacher { FirstName = "Mirek"};
Console.WriteLine(gpd.Invoke().ToString());
}
}
notice that we've created a GetPersonDelegate definition that returns a "Person", but then when we create an instance of it we assign a Func that returns a Teacher. Again this is covariance, in which we expect a less derived type in this case a "Person", but we return a more derived type an "Employee" however since an employee is a person there's no worries.
Take Away
Covariance is a property of polymorphism that let's us use a fatter or more derived object; for example an "Employee" class as a thinner less derived object for example a "Person"