Variance in generic types of C#

Goud.Kv
Posted by in C# category on for Intermediate level | Points: 250 | Views : 4068 red flag

C# is an Object-oriented programming language. C# comes with simplicity, expressiveness and great performance to meet the programmer productivity.
Recommendation
Read Generic subclassing, type parameters and delegates in C# before this article.

Introduction

So far, we have seen subclassing, type parameters and delegates of C# in the previous chapter. Let's see the concept of Variance in C# generics.

Objective

The main objective of this article is to learn the concept of variance in C# generic types.

Variance in Generic types

We already know that C# has the greatest benefit of creating strongly typed collections easily by using System.Collections.Generic types. This feature is added in version 2.0 which has a good usability improvements over version 1.0.

But, there are some drawbacks of strongly typed collections. 
Let's have an example that explains about the drawbacks of these collections,
List<int> li = new List<int>();
li.Add(1);  // Compile time error
li.Add(2);  // Compile time error

List<object> obj = new List<object>();
In the above code, we are trying to append all the elements to List<int> which result in Compile time error.

But we need to make List<int> (which is IEnumerable<int>) as an IEnumerable<object>. To obtain this feature, we have to go for generic variance.

Generic variance treats an instantiation of a generic type.

As C# does not support variance for generic types, when we have situations like above, we have to try several other usable techniques to get rid of this problem.

For simple case, we can go like below method,
public static void AddItem<I, L>(List<I> item, List<L> list)
    where I : L
{
    foreach (I newItem in item)
    {
        list.Add(newItem);
    }
}
The above method is a simple work around for a single method as variance is unidirectional. This simple helper method helps us to do the conversion from int to object that we need.

Now let's see the complete example which doesn't give error,
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Example
{
    class Program
    {
        public class VarianceWork
        {
            public static void AddItem<I, L>(List<I> item, List<L> list)
                where I : L
            {
                foreach (I newItem in item)
                {
                    list.Add(newItem);
                    Console.WriteLine("Added");
                }
            }
        }

        static void Main()
        {
            List<int> li = new List<int>();
            li.Add(1);
            li.Add(2);
            List<object> obj = new List<object>();

            VarianceWork.AddItem<int, object>(li, obj);
        }
    }
}
This will not throw compile time error. Observe the code that we have added following line,
VarianceWork.AddItem<int, object>(li, obj);
The helper method takes these two parameters, for the item and list. This item type parameter I has a constraint which is the list type parameter L. This means that the List<> being read from must contain elements. These elements are convertible to the element type of the List<> being inserted too. This enables our compiler to enforce that int is convertible to an object.

The above program prints the following lines in your console,


Conclusion

In this simple article, we have learnt variance in generic types in C# programming. Hope you understand.

Thanks for reading,

Regards,
Krishna.
Recommendation
Read Co-variance and Contra-variance in C# after this article.
Page copy protected against web site content infringement by Copyscape

About the Author

Goud.Kv
Full Name: Krishna Vamshi Goud
Member Level: Gold
Member Status: Member,MVP
Member Since: 2/12/2014 2:34:09 AM
Country: India
Thanks & Regards, Krishna


Login to vote for this post.

Comments or Responses

Login to post response

Comment using Facebook(Author doesn't get notification)