
.NET 4.0+Generic Variance in .NET 4.0
With the release of .NET 4.0, Microsoft introduced covariance and contravariance to generic interfaces and delegates. Generic variance allows conversion and interchangeability of types in a logical manner that was not previously possible.
What is Variance?
In this article I will describe the new generic variance features in the .NET framework version 4.0. Variance, when applied in computer programming, describe the manner in which operations that use different types are interchangeable, convertible or equivalent. There are three types of variance considered in this article. These are covariance, contravariance and invariance. Before we look at what these are, we first need a basic understanding of type ordering.
Type Ordering
In object-oriented programming languages like C#, you can create inheritance hierarchies. These include base types, or supertypes, which define some functionality. Subtypes inherit from supertypes, automatically obtaining all of their parent's functionality. The subtype may add further functionality and override members that it has inherited. Multiple classes can be organised into complex hierarchies in this manner.
In inheritance relationships, the base type is said to be wider, or larger, than its subtypes. The subtypes in turn are said to be narrower or smaller. When comparing a type to itself, you can say that the type is equivalent in size. If you have two types where neither is a supertype of the other, the types are said to be unrelated, even if they share a base class. When working with instances of types, polymorphism means that a smaller type can be represented by a larger type. A larger type instance cannot be held as a smaller type.
We can see this with an example inheritance hierarchy. In the diagram below we have four classes. These are Employee, Manager, AreaManager and CasualWorker.

In the diagram, Employee is a supertype of all of the other types. Employee is therefore the widest type present. We can assign an instance of any of the four types to an Employee variable. The Manager class is narrower than Employee but wider than AreaManager so we can hold an AreaManager in a Manager variable but cannot assign a Manager object to an AreaManager variable. The CasualWorker class is narrower than Employee but is unrelated to Manager and AreaManager. A CasualWorker variable cannot, therefore, hold an instance of any of the other three types.
During this article we will see several code samples that use the above classes. To recreate the samples, you will need to define the four types of employee. To do so, use the following code:
public class Employee
{
public string Name { get; set; }
public decimal Salary { get; set; }
}
public class Manager : Employee
{
public IList<Employee> Subordinates { get; set; }
}
public class AreaManager : Manager
{
public string Area { get; set; }
}
public class CasualWorker : Employee
{
public int DaysNoticeRequired { get; set; }
}
19 November 2011