Invariance is a concept that can be seen in almost all the programming languages that have a type system. And before we delve in to more language specific constructs, let’s see what all this big words mean when it comes to a language.

Covariance is the ability to convert data from wider to narrow data types. (E.g. long to int).
Contra variance is the ability to convert data from narrow to wider data types. (E.g. int to float).
Invariance is the inability to do conversion between data types.

In other words if we read closely in between the lines you’ll see that covariance preserves assignment compatibility while contra variance reverses it, and when both covariance and contra variance work together in tandem they make sure that invariance is avoided when needed.

Ok, with that theory part covered let’s look at an example, where which can expose the invariant behavior of C#
And the example I’ll be using will be a scenario where we will implement a generic interface for an imaginary inventory.

Let’s have a look at the code first































The IStorage interface defines two generic methods that facilitate storing and retrieving items from a generic List, and as you can see since there are no restrictions applied for type “T” in the implementing class BasicStorage or in the interface, any kind of data can be stored in our List repository. Let’s write some code to use this inventory of ours.












In the above code I’m using the generic interface as the base type to access the implemented functionality because the class has implemented the methods explicitly in its code.
And when the above code is written all will work fine just the way we planned.
Ok, now what will happen if we try to store data of type object in our repository, to do that we will have to convert our inventory01 variable to an instance of type IStorage<object>
And since all strings are objects and object is the base type for all types we should be able to do just that in our code. So let’s write some code to do that.


Hmm…
Although it makes sense to convert a string to an object the .net framework is throwing an error when we try to do that, but why?
If you look at it closely you will see that although all strings are objects, the converse is not true, all objects are not strings.
If the above restriction was not applied by the framework you would have been able to does something like this.





As you can see this code will try to store an ArrayList on a memory location which is structured to store a string, and it will clearly mess up the type safety of the .net framework.
This is the invariant behavior of .net. C# adds invariance to the type system to ensure type safety in our programming constructs.

According to the language specification, In C# Generic Interfaces are Invariant by default while Generic Classes are always Invariant.

With that in mind, let’s have a look at the same example from a deferent perspective.
This time, let’s use two deferent interfaces to store and retrieve data.


































Now IDepostior have the storage facility while IRetriever provides us with reading functionality
The code that uses this new structure will look like this.














Here we cast an instance of “Storage<string> inventory02” to typeIDepostior<string> store” to store data, while we cast the sameinventory02” object toIRetriever<string> retriever” to retrieve data.
With that said, will the following line of code work now?

    Storage<string> inventory02 = new Storage<string>();
   IRetriever<string> retreiver = inventory02;
   IRetriever<object> objectRetreivor = inventory02;

The answer is “NO”.
In the previous example it made sense. Does it make the same sense now?
Here IRetriever interface only provides you with means to read data, and it doesn’t expose any method to store data. Because of that, you cannot store incompatible types in the underlying storage now. So the loop hole that allowed the previous example to break the type safety is no longer present in this interface. In other words, now it’s perfectly safe to convert IRetriever<string> to IRetriever<object>.

In situations like this, where the type parameter only acts as a return value of a method in a generic interface, we can tell to the compiler that some implicit conversions are legal and type safety does not have to be imposed on a type all the time. To do that we can use the “out” keyword.

And the modified IRetriever interface will look something like this.







Now we have just used Covariance to preserve assignment compatibility where it makes sense.

Right! Now let’s have a look at the other interface which allows us to store data. Will this be ok?

   Storage<object> inventory03 = new Storage<object>();
   IDepostior<string> depositor = inventory03;

Let’s think of it like this. All strings are objects, so if you can perform a specific behavior on a variable of type object, you should be able to carry out the same thing on a variable of type string.
In other words, if “B” derives from “A” and if type “A” exposes a set of members (behaviors, properties, etc…), type “B” must also expose the same set of members too.
So anything that can be carried out on A must also be supported by B.
So if we consider our IDepostior example, if we can store objects and do some exercises on them, we should be able to store strings and do the same set of exercise on them too.
That sounds correct, but there must be a way for us to tell to the complier that operations which will be carried out on the generic typed items will only be operations which are specified on the most generalized type in the inheritance hierarchy. Or in other words only the operations supported by objects will be carried out on our type.
We do that using the keyword “in”.

The “in” keyword tells the compiler that, you can either pass type “T” as a parameter type to methods or pass any type that derives from “T”.  And you cannot use “T” as a return type of a method.

So the modified interface will look something like this.






Now we can reference an object either through a generic interface based on the object type or through a type that derived from that object type. And by adding the “in” key word, we’ve had made sure that the needed restrictions are there to make our assignment type safe.

With that, we have just used Contra variance to reverse Covariance and made classes in an inheritance hierarchy reference each other when the reference is type safe.

The completed interfaces will be…

































If you have any questions, just add a comment and I’ll answer it as soon as I can.

Hope this clears thing up.