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.
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.