The terms covariance and contravariance enable implicit references to conversion of array type, delegate type, and generic type arguments. Covariance preserves assignment compatibility and contravariance reverses it.**Assignment Compatibility**

If we have a string name "avinash", programmatically we can declare it as:

string strVal = "avinash";

We can assign a strVal in a more derived type to an object of less derived type. Like:

object obj = str; **Covariance**

We can use IEnumerable<string> in places where IEnumerable<object> is expected. It converts a larger data type to a smaller one (for exzmple Long to Int). We can understand it as in the following.

An object that is instantiated with a more derived type is assigned to an object with a less derived type.

IEnumerable<string> stringVal = new List<string>();

IEnumerable<object> obj = stringVal;

In this case assignment compatibility is preserved. **Contravariance**

We can pass IComparable<object> as an argument of a method taking IComparable<string>. It converts a smaller data type to larger one (for exzmple Int to Float).

Suppose we have a method in our class as in the following:

Private void SetObjectField(object o){ }

An object that is instantiated with a less derived type is assigned to a more derived type.

Action<object> objAction = SetObject;

Action<string> obj = actObject;

In this case assignment compatibility is also reversed.

**Mathematical Understanding of Covariance and Contravariance**

Now, let's try to understand covariance and contravariance mathematically:

First, let's understand Projection. Projection is a simple function that takes a single integer and returns a single integer value as is explained in the following example:

x -> x + x

In this example we call it D for double.

Let's consider another example:

y -> 0-y

Here, we call it N as Negation.

Hence, we have two interesting scenarios. At first, we will discuss D (Double):

(a <= b) = (D(a) <= D(b)) // <= less than and equal to

If a is less than b then twice of a will be less than twice of b. If a is equal to b then twice of a will be equal to twice of b, and if a is greater than b then twice of a will be greater than twice of b. So projection D preserves the direction of the size.

Now to discuss N (negation):

(a <= y) = (N(a) <= N(b)) // <= less than and equal to

See:

1 <=2 is true, but

-1 <= -2 is false.

Since this is negation, the reverse is always true. The projection N reverses the direction of the size.

Clearly, we can say mathematically that D is a "Covariance" since it preserves the direction of the size. Similarly, the Projection N is "Contravariance" since it reverses the ordering direction.

Any recommendation and feedback will be highly appreciated. I hope this article proves useful for you. Thanks for reading!!!