Labels

Thursday, August 20, 2009

C# 4.0 : Co-variance and Contra-variance

Hi,

This is about new feature in C# 4.0 (VS 2010)

CoVariance

If you have a class hierarchy, Parent and Child (as name mentioned). Now ideally you can assign Child to any Parent object as Parent is larger type and hold properties of Child.
Now if you try to write come code as mentioned below,

namespace CoVarinace
{
    class Vegetable { }
    class Potato : Vegetable { }

    class Program
    {
        delegate T MyFunc<T>();

         static void Main(string[] args)
         {
             //Covariance
             MyFunc<Potato> potato1 = () => new Potato();

             MyFunc<Vegetable> veg = potato1;
         }
    }
}

This code will fail with the below error message
“Cannot implicitly convert type ' CoVarinace.Program.MyFunc<CoVarinace.Potato>' to 'CoVarinace.Program.MyFunc<CoVarinace.Vegetable>'      C:\..\CoVarinace\Program.cs”   
Now in Visual Studio 2010 with a minor change this code will work.

delegate T MyFunc<out T>();

Now with the modified code it will look like,
CoVariance
namespace CoVarinace
{
    class Vegetable { }
    class Potato : Vegetable { }

    class Program
    {
        delegate T MyFunc<out T>();

         static void Main(string[] args)
         {
             //Covariance
             MyFunc<Potato> potato1 = () => new Potato();

             MyFunc<Vegetable> veg = potato1;
         }
    }
}


With no error, the support is only from Visual Studio 2010.

ContraVariance

This works with generic delegate which returns nothing but takes a parameter.

If you write the code,
namespace ContraVarinace
{
    class Vegetable { }
    class Potato : Vegetable { }

    class Program
    {
        delegate void MyAction<T>(T a);

        static void Main(string[] args)
        {
            MyAction<Vegetable> action1 = (veg) => {Console.WriteLine(veg); };

            MyAction<Potato> potato1 = action1;
        }
    }
}

This will throw you an error,
Cannot implicitly convert type 'ContraVarinace.Program.MyAction<ContraVarinace.Vegetable>' to ' ContraVarinace.Program.MyAction<ContraVarinace.Potato>'         C:\..\ContraVarinace\Program.cs
With a little modification the below code will work without any issue, you just need to put the keyword in.

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

ContraVariance
namespace ContraVarinace
{
    class Vegetable { }
    class Potato : Vegetable { }

    class Program
    {       
        delegate void MyAction<in T>(T a);

        static void Main(string[] args)
        {
            MyAction<Vegetable> action1 = (veg) => { Console.WriteLine(veg); };

            MyAction<Potato> potato1 = action1;
        }
    }
}



Thanks & Regards,
Arun Manglick || Senior Tech Lead


No comments:

Post a Comment