Saturday, 12 April 2014

CoVariance and ContraVariance in CSharp

I am going to discuss about the Variance in csharp. But before that we have to know about some keyword

Subtyping: is a polymorphism rule in programming language which refers to how 2 complex types A (subtype or more specific type) can substitute or can be used where B(super type or generic type) is required.

Variance: refers to how subtyping between components of A and B are related depending on the subtyping relations between A and B.

Covariant: A is subtype of B. Then A can be used where B is required.
Contravariant: Reverse of above.
Bivariant: Both covariant and contravariant is applicable.
Invariant: None of the above


In this content I am going to discuss how Delegates uses co- and contraVariant.

Contravariant Delegates Arguments:

FamilyCar <: Car (FamilyCar is a derived class of Car.)

In the below example delegate CardetailDelegate expects an argument of type FamilyCar but it is assigned to a method with base class argument Car.



using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Variance
{
    class Program
    {
        delegate string CardetailDelegate(FamilyCar car);
        static void Main(string[] args)
        {
            FamilyCar fmCar = new FamilyCar();
            fmCar.EnginePower = "80";
            fmCar.EngineDisplacement = "1300";
            fmCar.Color = "RED";
            fmCar.Length = 4;
            fmCar.Price = 350000;
            fmCar.SeatingCapacity = 5;         

            CardetailDelegate cardetaildel = CarDetail; //delegate is assigned to a method with base class argument Car

            Console.WriteLine(cardetaildel(fmCar));
            Console.Read();
        }
        static string CarDetail(Car car)
        {
      
            return string.Format("I am a car with {0} BHP power and {1} cc displacement. I am {2} mt in length and {3} in color. {4} passengers can sit together.", car.EnginePower,

car.EngineDisplacement, car.Length, car.Color, car.SeatingCapacity);
       
   
        }
    }
}

public  class Car
{
    public string Color { get; set; }
    public virtual string EnginePower { get; set; }
    public virtual string EngineDisplacement { get; set; }
    public virtual int SeatingCapacity { get; set; }
    public  int Length { get; set; }
    public bool AC { get; set; }
    public decimal Price { get; set; }

   

}


public class FamilyCar : Car
{
    string enginePower;
    string engineDisplacement;
     int seatingCapacity;

    public override string EnginePower
    {
        get
        {
            return enginePower;
        }
        set
        {
            enginePower = value;
        }
    }

    public override string EngineDisplacement
    {
        get
        {
            return engineDisplacement;
        }
        set
        {
            engineDisplacement = value;
        }
    }

    public override int SeatingCapacity
    {
        get
        {
            return seatingCapacity;
        }
        set
        {
            seatingCapacity = value;
        }
    }

   
}
 


CoVariance delegates return type:

In the below example delegate NewCarDelegate returns type Car but it is assigned to a method with derived class return type FamilyCar.



using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Variance
{
    class Program
    {
       
       
        delegate Car NewCarDelegate();


        static void Main(string[] args)
        {
          

          
            NewCarDelegate newCar = GetNewCar; //contravariance GetNewCar return FamilyCar but NewCarDelegate has return type Car which base class of FamilyCar
           
            Console.WriteLine(CarDetail(newCar()));

            Console.Read();
        }
        static string CarDetail(Car car)
        {       
            return string.Format("I am a car with {0} BHP power and {1} cc displacement. I am {2} mt in length and {3} in color. {4} passengers can sit together.", car.EnginePower,

car.EngineDisplacement, car.Length, car.Color, car.SeatingCapacity);       
   
        }

        static FamilyCar GetNewCar()
        {
            FamilyCar fmCar = new FamilyCar();
            fmCar.EnginePower = "180";
            fmCar.EngineDisplacement = "3000";
            fmCar.Color = "White";
            fmCar.Length = 6;
            fmCar.Price = 1500000;
            fmCar.SeatingCapacity = 5;
            return fmCar;
        }
    }
}

public  class Car
{
    public string Color { get; set; }
    public virtual string EnginePower { get; set; }
    public virtual string EngineDisplacement { get; set; }
    public virtual int SeatingCapacity { get; set; }
    public  int Length { get; set; }
    public bool AC { get; set; }
    public decimal Price { get; set; }

   

}


public class FamilyCar : Car
{
    string enginePower;
    string engineDisplacement;
     int seatingCapacity;

    public override string EnginePower
    {
        get
        {
            return enginePower;
        }
        set
        {
            enginePower = value;
        }
    }

    public override string EngineDisplacement
    {
        get
        {
            return engineDisplacement;
        }
        set
        {
            engineDisplacement = value;
        }
    }

    public override int SeatingCapacity
    {
        get
        {
            return seatingCapacity;
        }
        set
        {
            seatingCapacity = value;
        }
    }   
}



We will discuss more on this in coming blogs.

1 comment: