While investigating this question I got curious about how the new covariance/contravariance features in C# 4.0 will affect it.

In Beta 1, C# seems to disagree with the CLR. Back in C# 3.0, if you had:

public event EventHandler<ClickEventArgs> Click;

... and then elsewhere you had:

button.Click += new EventHandler<EventArgs>(button_Click);

... the compiler would barf because they're incompatible delegate types. But in C# 4.0, it compiles fine, because in CLR 4.0 the type parameter is now marked as in, so it is contravariant, and so the compiler assumes the multicast delegate += will work.

Here's my test:

public class ClickEventArgs : EventArgs { }

public class Button
{
    public event EventHandler<ClickEventArgs> Click;

    public void MouseDown()
    {
        Click(this, new ClickEventArgs());
    }
}

class Program
{    
    static void Main(string[] args)
    {
        Button button = new Button();

        button.Click += new EventHandler<ClickEventArgs>(button_Click);
        button.Click += new EventHandler<EventArgs>(button_Click);

        button.MouseDown();
    }

    static void button_Click(object s, EventArgs e)
    {
        Console.WriteLine("Button was clicked");
    }
}

But although it compiles, it doesn't work at runtime (ArgumentException: Delegates must be of the same type).

It's okay if you only add either one of the two delegate types. But the combination of two different types in a multicast causes the exception when the second one is added.

I guess this is a bug in the CLR in beta 1 (the compiler's behaviour looks hopefully right).

Update for Release Candidate:

The above code no longer compiles. It must be that the contravariance of TEventAr

Edit
Report