12,881,367 members (27,206 online)
Tip/Trick
alternative version

#### Stats

21.6K views
22 bookmarked
Posted 4 Aug 2013

# Covariance in C#

, 4 Aug 2013 CPOL
 Rate this:
Understand the use of covariance in .NET 4.0

## Introduction

If we think about the word Covariance in general, then we will get that it is a word that is used mostly for mathematics or statics . More specific from Wikipedia is "In probability theory and statistics, Covariance is a measure of how much two random variables change together." And in .NET 4.0 world, it also comes to measure of how much two inherited variables change together .

## Background

From the polymorphism, we can write the following:

`BaseClass objbaseClass = new DeriveClass();  `

If the above line is Ok, then what about the below code:

`List<BaseClass> listObjbaseClass =new List<DeriveClass>();    ---> will give a compile error.`

#### Why the Error?

If a=b then a+a = b+b or `List<a>= List<b>`.

Yes to come across this, the Covariance is introduced in .NET 4.0.

## Using the Code

Let's consider an example to make it more understandable. In my house, I have electronics and furniture. If I want to represent them through C# classes:

```public abstract class HomeAppliance
{
public int Price { get; set; }
}
public abstract class ElectronicProduct : HomeAppliance
{

}
public abstract class Furniture : HomeAppliance
{

}
```

I have `LcdTV `and `Laptop `as an `Electronic `items and `Bed `and `Table `as `Furniture `items. So the classes are:

```public class Bed : Furniture
{
public Bed()
{
Price = 320;
}
}
public class Table : Furniture
{
public Table()
{
Price = 120;
}
}
public class LcdTV : ElectronicProduct
{
public LcdTV()
{
Price = 100;
}
}
public class Laptop : ElectronicProduct
{
public Laptop()
{
Price = 200;
}
}
```

Fig 1.1 : Class Diagram

All the above code is very straight forward, just simple inheritance. Now I want the total price of my `Electronic `and `Furniture `products. So need a method like below:

```class Utility
{
public int CalCulatePrice(List<HomeAppliance> lstHomeAppliance)
{
var total = 0;
lstHomeAppliance.ForEach(p =>
{
total += p.Price;
});
}
} ```

So I need total price of my `Electronic `goods.

```var listOfElectronicProducts = new List<ElectronicProduct>() { new LcdTV(), new Laptop() };
int totalPriceOfElectronicProducts = new Utility().CalCulatePrice(listOfElectronicProducts);
```

At compile time, it generates an error.

```    The best overloaded method match for
'Covariance.Utility.CalCulatePrice(System.Collections.Generic.List
<Covariance.HomeAppliance>)' has some invalid arguments
Argument 1: cannot convert from 'System.Collections.Generic.List
<Covariance.ElectronicProduct>' to 'System.Collections.Generic.List
<Covariance.HomeAppliance>'   ```

Suppose it allows the above code, then what will be the problem? In my `CalculatePrice `method, if I add the below line before the `foreach `loop:

`lstHomeAppliance.Add(new Bed());`

So I am passing `ElectronicProduct `list and also can add `Furniture `product. If you look at the class `diagram(Fig:1.1)` you will notice `Electronic `product and `Furniture `are in different branches, so:

`List<ElectronicProduct>() { new LcdTV(), new Laptop() };  `

`listOfElectronicProducts `will not allow any `Furniture `product on it as it is a generic list for `ElectronicProduct`. So I hope now you get the point. Ok, let's proceed with the discussion, did I need to change my method `CalculatePrice `parameter for each of the products?

`List<ElectronicProduct>  or  List<Furniture> `

No, not at all in .NET 4.0, we have `covariant `to handle this type of situations. The IEnumerable<out T> interface in .NET 4.0 has the out keyword as a parameter. It tells the compiler that you can use either the type you specified (HomeAppliance) or any type that is more derived (ElectronicProduct).

`IEnumerable<out T> : IEnumerable       `

So if I change the `CalculatePrice `parameter, it will compile and run successfully. So what's the matter, why it works not the previous one? Because when we use `out` parameter at that time, we are telling the compiler that the subtype can also replace the base type here.

`CalCulatePrice(IEnumerable<HomeAppliance> lstHomeAppliance) `

Covariant type parameters enable the compiler to make assignments that look much like ordinary polymorphism. Suppose you have a base class and a derived class, named `Base `and `Derived`. Polymorphism enables you to assign an instance of `Derived `to a variable of type `Base`. Similarly, because the type parameter of the IEnumerable<T> interface is `covariant`, I can assign an instance of `IEnumerable<Derived>` to a variable of type `IEnumerable<Base>` as shown in the following code:

```IEnumerable<Derived> d = new List<Derived>();
IEnumerable<Base> b = d; ```

So in our scenario:

```IEnumerable<ElectronicProduct> listOfElectronicProducts = new List<ElectronicProduct>();
IEnumerable<HomeAppliance> lstHomeAppliance= listOfElectronicProducts ; ```

`List<ElectronicProduct> List<Furniture>` is a subtype of `IEnumerable<HomeAppliance>`. So, each of the below code will run successfully:

```var listOfElectronicProducts = new List<ElectronicProduct>() { new LcdTV(), new Laptop() };
int totalPriceOfElectronicProducts = new Utility().CalCulatePrice(listOfElectronicProducts);
//Output : 300
var listOfFurnitures = new List<Furniture>() { new Bed(), new Table() };
int totalPricecOfFurnitures = new Utility().CalCulatePrice(listOfFurnitures);
//Output:440
var listOfHomeAppliance = new List<HomeAppliance>() { new Bed(), new Table(), new LcdTV(), new Laptop() };
int totalOfHomeAppliance = new Utility().CalCulatePrice(listOfHomeAppliance);
//Output:740  ```

Now so far it's ok. Let's think from the point of view of `Generics`. Now if I want to print the product information of each individual product. Just remove the `Price` property from the `HomeAppliance `and its derived classes. Let's introduce a generic interface `IProductItem<T>` and add properties here.

```interface IProductItem<T>
{
string Name { get; set; }
int Price { get; set; }
}```

and a generic class for the product:

```class HouseProductItem<T> : IProductItem<T>
{
public string Name
{
get;
set;
}
public int Price
{
get;
set;
}
public HouseProductItem(int price, string name)
{
this.Name = name;
this.Price = price;
}
}```

Here, I need the below method to print the individual product information.

```public string GetProductInfo(IProductItem<HomeAppliance> HomeAppliance)
{
return "Product name is " +
HomeAppliance.Name + " price is " + HomeAppliance.Price;
}
```

So here also, everything is simple implementation. To print, I need to call `GetProductInfo:`

```var laptop = new HouseProductItem<Laptop>(100, "Laptop");
var info = new Utility().GetProductInfo(laptop);  ```

But the same compilation error occurs as we experienced earlier. So what's the issue? The issue is passing more derived generic class `HouseProductItem<T> `to `IProductItem`<T> but did not enable the subtyping conversion using the `out` parameter.

```The best overloaded method match for 'Covariance.Utility.GetProductInfo
(Covariance.IProductItem<Covariance.HomeAppliance>)' has some invalid arguments
Argument 1: cannot convert from 'Covariance.HouseProductItem
<Covariance.Laptop>' to 'Covariance.IProductItem<Covariance.HomeAppliance>'	```

So a small change can make all the code error free and that is:

```interface IProductItem<out T>
{
string Name { get; set; }
int Price { get; set; }
}```

Now it will allow more derived class as a parameter. Hope now it's more clear to you what covariance is all about.

## Points of Interest

Rather than using an `List<T>` or `IEnumerable<T>` if someone wants to use simple `Array`, then we get a compilation error for that. Let's see.

```public int CalCulatePrice(HomeAppliance[] homeApplicance)
{
var total = 0;
homeApplicance[0] = new Laptop();
homeApplicance.ToList().ForEach(p =>
{
total += p.Price;
});
}```
```var arrayOfFurniture = new Furniture[] { new Bed(), new Table() };
int totalPricecOfFurnitures = new Utility().CalCulatePrice(arrayOfFurniture);```

This will not give any compilation error, unfortunately the runtime error will be thrown.

`Attempted to access an element as a type incompatible with the array.    `

So while assigning more derived to less derived class, try to use `IEnumerable<out T>` in .NET 4.0.

## Share

I am a Sr.Software Engineer at Brain Station -23. I have 5+ years of work experience in .Net technology. I strongly believe that before software can be reusable it first has to be usable.

My contact info :

mfrony2003@yahoo.com
mfrony2003@hotmail.com

## You may also be interested in...

 First Prev Next
 My vote of 5 Md Nazmoon Noor14-May-14 3:52 Md Nazmoon Noor 14-May-14 3:52
 My vote of 3 suday4-Aug-13 21:54 suday 4-Aug-13 21:54
 Article more like... Vitaly Tomilov4-Aug-13 11:52 Vitaly Tomilov 4-Aug-13 11:52
 Re: Article more like... Faisal(mfrony)4-Aug-13 21:37 Faisal(mfrony) 4-Aug-13 21:37
 Last Visit: 31-Dec-99 18:00     Last Update: 22-Apr-17 23:17 Refresh 1