Solved

Covariance and Contravariance in Delegates examples needed in C#

Posted on 2011-03-21
12
372 Views
Last Modified: 2013-12-17
Hi,

Can you please provide end-to-end examples in C# on:

Covariance and Contravariance in Delegates

Thanks
0
Comment
Question by:milani_lucie
  • 6
  • 5
12 Comments
 
LVL 33

Expert Comment

by:Todd Gerbert
ID: 35183665
As luck would have it, MSDN has an article that's actually titled "Covariance and Contravariance in Delegates", with code examples. http://msdn.microsoft.com/en-us/library/ms173174(v=vs.80).aspx

Is that explanation enough, or something there not making sense?
0
 

Author Comment

by:milani_lucie
ID: 35184314
I hate MSDN. Here is the nice article:

http://codebetter.com/raymondlewallen/2006/12/28/covariance-and-contravariance/

Can you please provide complete code for both of them ?

Thanks
0
 
LVL 33

Expert Comment

by:Todd Gerbert
ID: 35184412
Well, both articles seem to already include complete code examples of both covariance and contravariance, so I guess I'm not sure what more you want...?

I'll try and think of a real-world example, but after having just read those two articles I suspect anything I come up with is going to end up being about the same examples in the articles, just paraphrased. ;)
0
 

Author Comment

by:milani_lucie
ID: 35184521
This is the code i am having:

public class Car
{
      private string m_Model;

      public string Model
      {
           get
           {
                  return m_Model;
           }
           set
          {
                  m_Model = value;
          }              
      }
}

public class Toyota : Car
{
      private string m_Color;

      public string Color
      {
           get
           {
                  return m_Color;
           }
           set
          {
                  m_Color = value;
          }              
      }
}

class Demo
{
    public delegate Car MyMethod();

    public static Car FunctionOne()
    {
        return new Car();
    }
 
    public static Toyota FunctionTwo()
    {
        return new Toyota();
    }

    static void Main()
    {
        MyMethod abc = FunctionOne;
        MyMethod xyz = FunctionTwo;
    }

   //  Now what ? What we can do ?

}

Thanks
0
 
LVL 10

Accepted Solution

by:
Mathiyazhagan earned 250 total points
ID: 35189683
Some Input on Covariance :
    Covariance mainly is used to genearize delegate. as we know, Base class refrence may refer to derived class object , covariance  helps. let us say an example, we are having variable classes like Square,Rectangle,Circle which are derived from Shape class and each class is having Draw() which draws those shapes. Now, we can have a delegate to create shape and some methods which produce those shape with measurement. so a single delegate can invoke all those methods (which inturns returns particular shapes) and we can draw the object (as it is invoking overrided method).
          I have changed some thing in your example to explain the scenario.Don't hesitate to ask any clarification if you have.hope this helps.
public class Car
    {
        private string m_Model;
        
        public string Model
        {
            get
            {
                return m_Model;
            }
            set
            {
                m_Model = value;
            }
        }
        private int m_price;

        public int Price
        {
            get { return m_price; }
            set { m_price = value; }
        }

        public virtual void Print()
        {
            Console.WriteLine("Model : {0}", m_Model);  
        }
    }

    public class Toyota : Car
    {
        private string m_Color;

        public string Color
        {
            get
            {
                return m_Color;
            }
            set
            {
                m_Color = value;
            }
        }
        private int m_discount;

        public int Discount
        {
            get { return m_discount; }
            set { m_discount = value; }
        }
        public override void Print()
        {
            Console.WriteLine("Model : {0}, Color : {1}",base.Model,m_Color);  
        }
    }
-------------------
//delegate declaration
 public delegate Car GetVechicle();
---------------------
//Main code
          public static Car GetCar()
        {
            //Building a car object is local matter
            Car c = new Car();
            c.Model = "NISSAN";
            c.Price = 400000;
            return c;
        }

        public static Toyota GetToyoto()
        {
            Toyota t = new Toyota();
            t.Model = "Version 2.0";
            t.Color = "Red";
            t.Price = 500000;
            t.Discount = 2;
            return t;
        }

//invoking
  GetVechicle v1 = GetCar;
  GetVechicle v2 = GetToyoto;
  List<Car> cars = new List<Car>();
  cars.Add(v1.Invoke());
  cars.Add(v2.Invoke());
  foreach (Car c in cars )
   {
        c.Print(); 
   }
/******************Output *****/
Model : NISSAN
Model : Version 2.0, Color : Red

Open in new window

0
 

Author Comment

by:milani_lucie
ID: 35190467
Mathiyazhagan:

Excellent ! Can you please provide me for contravarience also ? Here is the code i do have:

    public class Car
    {
        private int m_Price;

        public int Price
        {
            get
            {
                return m_Price;
            }
            set
            {
                m_Price = value;
            }
        }

        public virtual void Print()
        {
            Console.WriteLine("Price : {0}", m_Price);
        }
    }

    public class Toyota : Car
    {
        private string m_Model;

        public string Model
        {
            get
            {
                return m_Model;
            }
            set
            {
                m_Model = value;
            }
        }
       
        public override void Print()
        {
            Console.WriteLine("Price : {0}, Model : {1}", base.Price, m_Model);
        }
    }

    public delegate void GetVechicle(Toyota value);

    public static void GetCar(Car value)
        {  
            Car c = value;
            c.Price = 4000;
            return c;
        }

        public static void GetToyota(Toyota value)
        {
            Toyota t = value;
            t.Price = 5000;
            t.Model = "Corolla";
            return t;
        }

Can you please provide the sample code for this also ?

Thanks
0
Highfive + Dolby Voice = No More Audio Complaints!

Poor audio quality is one of the top reasons people don’t use video conferencing. Get the crispest, clearest audio powered by Dolby Voice in every meeting. Highfive and Dolby Voice deliver the best video conferencing and audio experience for every meeting and every room.

 
LVL 33

Expert Comment

by:Todd Gerbert
ID: 35191323
Okay, first a quick word on the definition of covariance and contravariance.  In very simple terms covariance is conversion from a wider (or base) type to a narrower (or derived type); and contravariance is the opposite - a conversion from a narrower (or derived) type to a wider (or base) type.


Given this simple example, with two classes.  Mammals being the wider, or less-derived, of the two (it serves as the base class for Dog), and Dog, which inherits from Mammals, is the narrower (or more derived).
using System;

class Program
{
	static void Main(string[] args)
	{
		// Declare a variable of a "wide" or less-derived type
		Mammals mammalObject = new Mammals();

		// Declare a variable of a "narrow" or more-derived type
		Dog dogObject;

		// Assigning the mammalObject to a narrower, or more derived, type is covariance
		// Casting the less derived mammalObject to a more derived type of "Dog" is an
		// example of covariance
		// Note that C# doesn't allow this type of covariance for classes, I'm just trying
		// to demonstrate a concept.
		dogObject = (Dog)mammalObject;


		// The opposite is contravariance (which is permissable in C# for classes)
		// Assign a new Dog object to the more derived (or narrower) variable
		dogObject = new Dog();

		// Cast the narrower dogObject to the wider type Mammal, and assign it
		// to the mammalObject variable
		mammalObject = (Mammals)dogObject;
	}
}

// Mammals is the base class
class Mammals
{
}

// Dog inherits from Mammals, so it is said to be "derived" (and Mammals is "less derived")
class Dog : Mammals
{
}

Open in new window



As far as delegates go, I'm going to refer you to the examples in the MSDN article. Perhaps this commented version of that example will make more sense (sorry, I still can't seem to come up with a real-world example of this):
using System;

class Program
{
	// Define a delegate that will point to a method which takes no
	// parameters and returns an object of type "Mammals"
	delegate Mammals MyMammalsDelegate();

	// Define a method that takes no parameters
	// and returns a Dog object
	static Dog MyDogMethod()
	{
		return new Dog();
	}

	static void Main(string[] args)
	{
		// Declare a variable of type "MyMammalsDelegate"
		MyMammalsDelegate theDelegate;

		// Assign the method "MyDogMethod" to "theDelegate"
		// even though the MyDogMethod returns a "Dog" object,
		// and the MyMammalsDelegate expects a method that returns
		// a Mammals object, covariance in delegates allows this
		// This is covariance because theDelegate is defined with the return type "Mammals"
		// so we'll say theDelegate is a Mammals variable, and MyDogMethod is defined with
		// the return type Dog, so we'll say MyDogMethod is a Dog variable (not really, just for the sake of explanation),
		// so we're assigning a Dog object to a Mammals object, which is assigning
		// a narrower type to a wider type
		theDelegate = MyDogMethod;
	}
}

// Mammals is the base class
class Mammals
{
}

// Dog inherits from Mammals, so it is said to be "derived" (and Mammals is "less derived")
class Dog : Mammals
{
}

Open in new window




Contravariance I can see some practical application for...see the comments in code.
// These classes are actually defined in the .Net Framework, so 
// they are commented-out - these comments are included here
// to make obvious their inheritance relationship to each other
/*
class EventArgs // Base EventArgs Class
{
}

class KeyEventArgs : EventArgs // Derived class that inherits from EventArgs
{
}

class MouseEventArgs : EventArgs // Another derived class, that also inherits from EventArgs
{
}
*/

public partial class Form1 : Form
{
	public Form1()
	{
		InitializeComponent();

		// The KeyDown event expects a KeyEventHandler method,
		// which accepts a KeyEventArgs as a parameter, so we'll
		// say this.KeyDown is a KeyEventArgs (again, not really, just for explanation).
		// We are assigning it a method that takes a EventArgs object, so we'll say
		// MultiEventHandler is a EventArgs.  Since KeyEventArgs inherits from
		// EventArgs, we are assigning the wider (or less-derived, or base) type EventArgs
		// to the narrower (or more-derived) type EventArgs, this is conravariance
		this.KeyDown += MultiEventHandler;

		// The practical application of this being, for example, that
		// completely different events can share the same event handler
		// Here the MouseClick event expects a method that takes a MouseEventArgs
		// as a parameter, but because MouseEventArgs also inherits from EventArgs,
		// we can use the MultiEventHandler method.
		this.MouseClick += MultiEventHandler;
	}

	private void MultiEventHandler(object sender, EventArgs e)
	{
		if (e is KeyEventArgs)
			MessageBox.Show("This method running as result of Form1's KeyDown event.");
		else if (e is MouseEventArgs)
			MessageBox.Show("This method running as result of Form1's MouseClick event.");
	}
}

Open in new window

0
 

Author Comment

by:milani_lucie
ID: 35208588
Mathiyazhagan: / tgerbert:

Here is the sample code i am having. Can you please complete the code ? It is throwing some errors.

namespace ConsoleApplication1
{
    class Program
    {
        private delegate void GetVechicle(Car c);

        public static void GetCar(Car c)
        {
            c.Price = 4000;
        }

        public static void GetToyota(Toyota t)
        {
            t.Price = 5000;
            t.Model = "Corolla";
        }

        static void Main(string[] args)
        {
            GetVechicle v1 = GetCar;
            GetVechicle v2 = GetToyota;

            Corolla c = new Corolla();

            v1.Invoke(c);
            v2.Invoke(c);

            c.Print();
        }
    }

    public class Car
    {
        private int m_Price;

        public int Price
        {
            get
            {
                return m_Price;
            }
            set
            {
                m_Price = value;
            }
        }

        public virtual void Print()
        {
            Console.WriteLine("Price : {0}", m_Price);
        }
    }

    public class Toyota : Car
    {
        private string m_Model;

        public string Model
        {
            get
            {
                return m_Model;
            }
            set
            {
                m_Model = value;
            }
        }

        public override void Print()
        {
            Console.WriteLine("Price : {0}, Model : {1}", base.Price, m_Model);
        }
    }

    public class Corolla : Toyota
    {
        private string m_Color;

        public string Color
        {
            get
            {
                return m_Color;
            }
            set
            {
                m_Color = value;
            }
        }

        public override void Print()
        {
            Console.WriteLine("Price : {0}, Model : {1}, Color : {2}", base.Price, base.Model, m_Color);
        }
    }
}

Thanks
0
 
LVL 33

Expert Comment

by:Todd Gerbert
ID: 35208592
What exception, and on what line?
0
 

Author Comment

by:milani_lucie
ID: 35208631
Sorry .... Here is the complete code:

namespace ConsoleApplication1
{
    class Program
    {
        private delegate void GetVechicle(Toyota t);

        public static void GetCar(Car c)
        {
            c.Price = 4000;
        }

        public static void GetToyota(Toyota t)
        {
            t.Price = 5000;
            t.Model = "Corolla";
        }

        static void Main(string[] args)
        {
            GetVechicle v1 = GetCar;
            GetVechicle v2 = GetToyota;

            Toyota t = new Toyota();

            v1.Invoke(t);
            v2.Invoke(t);

            t.Print();
        }
    }

    public class Car
    {
        private int m_Price;

        public int Price
        {
            get
            {
                return m_Price;
            }
            set
            {
                m_Price = value;
            }
        }

        public virtual void Print()
        {
            Console.WriteLine("Price : {0}", m_Price);
        }
    }

    public class Toyota : Car
    {
        private string m_Model;

        public string Model
        {
            get
            {
                return m_Model;
            }
            set
            {
                m_Model = value;
            }
        }

        public override void Print()
        {
            Console.WriteLine("Price : {0}, Model : {1}", base.Price, m_Model);
        }
    }
}

I want to do something like this as like in the above example:

List<Car> cars = new List<Car>();  
cars.Add(v1.Invoke());  
cars.Add(v2.Invoke());  
foreach (Car c in cars )  
{  
      c.Print();  
}  

Can you please provide me the code ?

Thanks
0
 
LVL 33

Expert Comment

by:Todd Gerbert
ID: 35213972
The List<Car>.Add() method expects you to provide a Car object. Your v1 and v2 point to methods that don't return anything (their return type is "void"), you need to use a method that returns a Car object.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

class Program
{
	// Declare a delegate that will point to a function
	// which will return a Car object
	delegate Car GetVehicleDelegate();

	// Define a method that returns a Car object
	static Car GetCarMethod()
	{
		Car c = new Car();
		c.Price = 4000;
		return c;
	}

	// Define a method that returns a Toyota object
	static Toyota GetToyotaMethod()
	{
		Toyota t = new Toyota();
		t.Price = 5000;
		t.Model = "Corolla";
		return t;
	}

	static void Main(string[] args)
	{
		// Declare a variable that's of the type GetVehicleDelegate,
		// which means it will point to a method that returns a Car
		GetVehicleDelegate getCar = GetCarMethod;

		// Declare another variable that's of type GetVehicleDelegate,
		// but instead of assigning it a method that returns a Car,
		// assign it a method that returns a Toyota. Covariance
		// allows this mismatch of return types because Toyota
		// inherits from Car
		GetVehicleDelegate getToyota = GetToyotaMethod;

		List<Car> cars = new List<Car>();

		cars.Add(getCar.Invoke());
		cars.Add(getToyota.Invoke());

		foreach (Car c in cars)
			Console.WriteLine(c);

		Console.ReadKey();
	}
}

public class Car
{
	private int _price;
	public int Price
	{
		get { return _price; }
		set { _price = value; }
	}
	public override string ToString()
	{
		return String.Format("Car, price: {0}", _price);
	}
}

public class Toyota : Car
{
	private string _model;
	public string Model
	{
		get { return _model; }
		set { _model = value; }
	}
	public override string ToString()
	{
		return String.Format("Toyota, price: {0}, model: {1}", this.Price, _model);
	}
}

Open in new window

0
 
LVL 33

Assisted Solution

by:Todd Gerbert
Todd Gerbert earned 250 total points
ID: 35214025
Following your car example, this would be contravariance:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

class Program
{
	// Declare a delegate that will point to a function
	// which returns nothing, and takes a Car parameter
	delegate void SetCarPriceDelegate(Car c, int newPrice);

	// Declare a delegate that will point to a function
	// which returns nothing, and takes a Toyota parameter
	delegate void SetToyotaPriceDelegate(Toyota t, int newPrice);

	// Define a method that will set the price of a vehicle
	static void SetVehiclePrice(Car c, int newPrice)
	{
		c.Price = newPrice;
	}

	static void Main(string[] args)
	{
		// Create a couple test objects
		Car c = new Car();
		c.Price = 4000;

		Toyota t = new Toyota();
		t.Price = 5000;
		t.Model = "Corolla";

		// Declare a variable of type SetCarPriceDelegate, which expects a Car parameter,
		// and assign a method to it that also expects a Car parameter
		SetCarPriceDelegate setPrice1 = SetVehiclePrice;

		// Declare a variable of type SetToyotaPriceDelegate, which expects a Toyota paramer,
		// but assign it a method that expects a Car parameter - mismatch of these
		// parameter types is allowed by contravariance
		SetToyotaPriceDelegate setPrice2 = SetVehiclePrice;

		setPrice1.Invoke(c, 8000);
		setPrice2.Invoke(t, 10000);

		Console.WriteLine(c);
		Console.WriteLine(t);

		Console.ReadKey();
	}
}

public class Car
{
	private int _price;
	public int Price
	{
		get { return _price; }
		set { _price = value; }
	}
	public override string ToString()
	{
		return String.Format("Car, price: {0}", _price);
	}
}

public class Toyota : Car
{
	private string _model;
	public string Model
	{
		get { return _model; }
		set { _model = value; }
	}
	public override string ToString()
	{
		return String.Format("Toyota, price: {0}, model: {1}", this.Price, _model);
	}
}

Open in new window

0

Featured Post

Maximize Your Threat Intelligence Reporting

Reporting is one of the most important and least talked about aspects of a world-class threat intelligence program. Here’s how to do it right.

Join & Write a Comment

Suggested Solutions

Title # Comments Views Activity
Data Saving 5 24
Get String split 5 31
Handle null when using linq in this line 1 20
Visual Studio editor? 1 11
Introduction Hi all and welcome to my first article on Experts Exchange. A while ago, someone asked me if i could do some tutorials on object oriented programming. I decided to do them on C#. Now you may ask me, why's that? Well, one of the re…
Today I had a very interesting conundrum that had to get solved quickly. Needless to say, it wasn't resolved quickly because when we needed it we were very rushed, but as soon as the conference call was over and I took a step back I saw the correct …
It is a freely distributed piece of software for such tasks as photo retouching, image composition and image authoring. It works on many operating systems, in many languages.
This tutorial demonstrates a quick way of adding group price to multiple Magento products.

708 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

10 Experts available now in Live!

Get 1:1 Help Now