C# is an Object-oriented programming language. C# comes with simplicity, expressiveness and great performance to meet the programmer productivity.
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.
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.