tags:

views:

159

answers:

3

Suppose I have code segment

namespace Test
{
    public delegate void StaticticsDelegate(object sender,EventArgs e);

    class DynamicDelegates
    {

        static void Main()
        {
            StaticticsDelegate del = BowlerStatistics;
            BallThrownEventArgs be = new BallThrownEventArgs(90, 145);
            del(DynamicDelegates.Main,be);

            del = BatsmanStatistics;
            RunsScoredEventArgs re = new RunsScoredEventArgs("Skeet", 55);
            del(DynamicDelegates.Main, re);
            Console.ReadLine();
        }


        static void BowlerStatistics(object sender, BallThrownEventArgs e)
        {
         Console.WriteLine
         ("{0} sender is ; Bowler Statistics :speed {1} angle {2}",
          sender, e.Speed, e.Angle);
        }

        static void BatsmanStatistics(object sender, RunsScoredEventArgs e)
        {
            Console.WriteLine
            ("{0} sender is ; Batsman Statistics :name {1} runs {2}",
            sender, e.PlayerName, e.Runs);
        }

    }

    class BallThrownEventArgs:EventArgs
    {
        int angle;
        int speed;
        public BallThrownEventArgs(int angle, int speed)
        {
            this.angle = angle;
            this.speed = speed;
        }

        public int Angle
        {
            get { return angle; }
        }

        public int Speed
        {
            get { return speed; }
        }

    }

    class RunsScoredEventArgs : EventArgs
    {
        string playerName;
        int runs;
        public RunsScoredEventArgs(string playerName, int runs)
        {
            this.playerName = playerName;
            this.runs = runs;
        }

        public string PlayerName
        {
            get { return playerName; }
        }

        public int Runs
        {
            get { return runs; }
        }
    }

 }

1) Since "BallThrownEventArgs" and "RunsScoredEventsArgs" are derived from "EventArgs", why did the error "No overloads for Matches..." generate when i "Main()" is executed.

2) What do you mean by "ContraVariance" and "Covariance" (Please give me an example to understand) ?

3) The term "Contravariance" and "Covariance" are related to delegates only ?

A: 

Just trying to help here, have you watched the video by Eric Lippert where he explains some code for Contravariance and Covariance. Here are the link for the 2 videos, http://msdn.microsoft.com/en-us/vcsharp/ee672314.aspx and http://msdn.microsoft.com/en-us/vcsharp/ee672319.aspx

theraneman
A: 

Related question about co/contravariance: http://stackoverflow.com/questions/1120688/event-and-delegate-contravariance-in-net-4-0-and-c-4-0

Konamiman
+2  A: 

The problem is that you're trying to use variance the wrong way round.

The idea of variance is that if your method doesn't need as specific information as the delegate says it will provide, and if your method returns more specific information than the delegate has to return, then you're okay to build the a delegate using that method.

In your case, things are the other way round:

public delegate void StatisticsDelegate(object sender, EventArgs e);

static void BowlerStatistics(object sender, BallThrownEventArgs e)

BowlerStatistics has to be given a BallThrownEventArgs, but StatisticsDelegate only guarantees it will provide an EventArgs.

Suppose you could create a StatisticsDelegate from BowlerStatistics: what would you expect the following code to do?

StaticticsDelegate del = BowlerStatistics;
del(null, new EventArgs());

BowlerStatistics wouldn't have any ball-related information to work with.

Or to use your existing code, but move it around a bit:

    StaticticsDelegate del = BowlerStatistics; // *
    RunsScoredEventArgs re = new RunsScoredEventArgs("Skeet", 55);
    del(DynamicDelegates.Main, re);

    del = BatsmanStatistics; // *
    BallThrownEventArgs be = new BallThrownEventArgs(90, 145);
    del(DynamicDelegates.Main,be);
    Console.ReadLine();

This time you're trying to make a bowler statistics delegate cope with a batsman's statistics and vice versa! The only lines which can possibly not compile are the method group conversion ones (labelled with // * above) - so to achieve type safety, they don't compile.

Covariance and contravariance are tricky topics - you may find Eric Lippert's series of blog posts useful. Prior to C# 4, variance only applies to creating delegates; as of C# 4 there's also interface and delegate generic variance, allowing you to write:

// Covariance
IEnumerable<string> strings = new List<string>();
IEnumerable<object> objects = strings;

// Contravariance
Comparer<Shape> areaSorter = (s1, s2) => s1.Area.CompareTo(s2.Area);
Comparer<Triangle> triangleAreaSorter = areaSorter;
Jon Skeet