CODEDIGEST
Home » Articles
Search
 

Technologies
 

Sponsored links
 

CodeDigest Navigation
 

Technology News
No News Feeds available at this time.
 

Community News
No News Feeds available at this time.
 
The concept of Covariance and Contravariance in .Net 4.0

By BalaMurali Balaji
Posted On Nov 25,2009
Article Rating:
Be first to rate
this article.
No of Comments: 9
Category: .Net 4.0
Print this article.

The concept of Covariance and Contravariance in .Net 4.0

 

With .NET 4.0, the CLR supports covariance and contravariance of types in generic interfaces and delegates. Before dwelling into these new changes, let us get a quick view on the concept of variances in simple terms.

 

We know that .Net types are classified into value-types and reference-types. The value types are invariant in nature in the sense that types can’t be exchanged while assigning or passing values to the parameters. We can’t use int[] in place of double[] even though some types of higher order may be used in place of lower order while assigning values or passing parameters to a function. A type must be a sub-type for another type to be a variant.

 

When we use string data for an object type of variable, an implicit conversion takes place and that is the variant behaviour of a type. Variances can also be seen as a benefit for type-safe nature of .Net languages.A type must be a sub-type for another type to be a variant. When we use string data for an object type of variable, an implicit conversion takes place and that is the variant behaviour of a type. Variances can also be seen as a benefit for type-safe nature of .Net languages.

Covariance:

 

The following is an example for the covariant behaviour of a string array. String is a sub-type of an object type and hence the code works fine with no error.

 

string[] a = new string[1];

object[] b = a;

Console.WriteLine(b[0]);

 

A is a single-element array of System.String and B is an array of System.Object. The reading of a value from b works better. On the otherhand, if we try to write an value into b,

 b[0] = 120

it rises an ArrayTypeMismatchException and message "Attempted to store an element of the incorrect type into the array".

 

Even, the following code will work.

string a = "bala";

object b = a;

 

So, reference types are covariant, but with some caveats. Covariance is applicable not only for assignments as stated above, but also for return types from methods. It permits a method to have a more derived return type than what is defined in the delegate.

 

Consider the following example:

 

        class Automobile

        {

            public Automobile CreateAuto() { return new Automobile(); }

        }

 

        class Car : Automobile

        {

            public Car CreateCar()

{ Console.WriteLine("Car created");

  return new Car();

}

        }

 

        class Application

        {

            public delegate Automobile CreateVehicle();

            public static void GetVehicle(CreateVehicle c)

            {

                c();

            }

            public static void Main()

            {

                CreateVehicle c2 = new CreateVehicle(new Car().CreateCar);

                GetVehicle(c2);

            }

        }

In the above program, Car is a sub-type of Automobile and the delegate CreateVehicle is invoked, the car object is created and returned. But the delegate is not declared as returning the object of type Car, instead, Automobile.

 

 

Contra-variance:

 

Contravariance permits a method with parameter types that are less derived than in the delegate type. This means how delegates can be used with methods that have parameters of a type that are base types of the delegate signature parameter type.

 

The following example shows how to use one event handler in places where we would have had to use separate handlers. It creates an event handler that accepts an EventArgs input parameter and use it with the Button.MouseClick event that sends a MouseEventArgs type as a parameter, and also with TextBox.KeyDown event that sends a KeyEventArgs parameter.

 

 

System.DateTime lastActivity;

public Form1()

{

    InitializeComponent();

    lastActivity = new System.DateTime();

    this.textBox1.KeyDown += this.MultiHandler; //works with KeyEventArgs

    this.button1.MouseClick += this.MultiHandler; //works with MouseEventArgs

}

private void MultiHandler(object sender, System.EventArgs e)

{

    lastActivity = System.DateTime.Now;

}

 

 

Generic Covariance:

 

Strongly typed collections in System.Collections.Generic namespace now allow variance and we can directly assign IEnumerable<int> to IEnumerable<object> as shown in the code below.

 

List<int> ints = new List<int>();

ints.Add(1);

ints.Add(10);

ints.Add(42);

List<object> objects = new List<object>();

objects.AddRange(ints);

 

In .Net 4.0, the IEnumerable<T> interface has become IEnumerable<out T>. The out indicates that T has the output position in the interface, otherwise, the compiler emits an error. The generic type T now supports covariance between the objects A and B if A has a reference conversion to B.

 

The following code shows how a sequence strings can be combined with a sequence of objects Using LINQ method.

 

IList<string> strings = new List<string>();
IList<object> objects = new List<object>();

var result = strings.Union(objects);

 

Also,




 

objects = strings;

 

is allowed.

 

The following simple code will exemplify the covariance with generic type that is returned by a delegate.

 

    class Animal { }

    class Cat: Animal { }

    delegate T Func1<out T>();

    Func1<Cat> cat = () => new Cat();

    Func1<Animal> animal = cat;

    Console.WriteLine(animal());

 

Generic Contravariance

 

Generic Contravariance in .Net 4.0 is somewhat mystifying. Ever imagine that IComparer<object> and IComparer<string> are one and the same. It is possible because the interface IComparer<T> has become IComparer<in T>. The in indicates that the parameters are restricted to occur only in input positions.

 

The code below will exemplify contra-variance with generic type passed as a parameter to delegate.

 

    class Animal { }

    class Cat: Animal { }

    delegate void Action1<in T>(T a);

    Action1<Animal> act1 = (ani) => { Console.WriteLine(ani); };

    Action1<Cat> cat1 = act1;

    cat1(new Cat());

Conclusion

 

Covariance and Contravariance were not fully implemented in earlier .Net versions. With .Net 4.0, type-safe co-and contravariance offer greater flexibility for coding.

Similar Articles
You can contribute to CodeDiget.Com:
Donate to CodeDigest.com
Article Feedback
Comments
dFRyNk , [url=http://xfrpanvvipvf.com/]xfrpanvvipvf[/url], [link=http://rklkrxiisqgz.com/]rklkrxiisqgz[/link], http://aupwrvixqvbb.com/
dFRyNk , [url=http://xfrpanvvipvf.com/]xfrpanvvipvf[/url], [link=http://rklkrxiisqgz.com/]rklkrxiisqgz[/link], http://aupwrvixqvbb.com/
QykXYH <a href="http://kedaqeeqrmsz.com/">kedaqeeqrmsz</a>
QykXYH <a href="http://kedaqeeqrmsz.com/">kedaqeeqrmsz</a>
A4r1Pl <a href="http://lqwuufvrrzvo.com/">lqwuufvrrzvo</a>
A4r1Pl <a href="http://lqwuufvrrzvo.com/">lqwuufvrrzvo</a>
I found this is an informative and intnrestieg post for I think it is very useful and knowledgeable. I would like to thank you for the efforts you have made in writing this article. I am hoping the sa
I found this is an informative and intnrestieg post for I think it is very useful and knowledgeable. I would like to thank you for the efforts you have made in writing this article. I am hoping the same best work from you in the future as well. In fact your creative writing ability has inspired me.
great post
http://www.gucciofoutlet.com/,THIS IS A GOOD PAGE!
a little
<b><a href="http://www.gucciofoutlet.com/">Gucci outlet</a></b>
good articles
what you said in your article are really useful for me,thank you very much1
Thanks
Pls. wait for .net 4.0 complete release for further workarounds on these new inclusions.
Thanks for demystifying this subject for me
This is a really good overview of the subject.

Can you expand a little on the example for generic contra-variance?
Also, can you give an example showing the use of both with Func<in TParam, out TResult> (does that even exist?)