C# EventHandler<;T>;NET 4.0中的参数逆变。它是否匹配其定义类型?

C# EventHandler<;T>;NET 4.0中的参数逆变。它是否匹配其定义类型?,c#,events,.net-4.0,delegates,contravariance,C#,Events,.net 4.0,Delegates,Contravariance,根据事件处理程序中的委托支持逆变,例如,对于具有其他参数的不同事件,您可以使用一个带有EventArgs的事件处理程序作为其EventHandler的通用参数: static class Program { static void Main() { var a = new A(); a.event1 += a_event1; a.event2 += a_event1; } static void a_event1(o

根据事件处理程序中的委托支持逆变,例如,对于具有其他参数的不同事件,您可以使用一个带有
EventArgs
的事件处理程序作为其
EventHandler
的通用参数:

static class Program
{
    static void Main()
    {
       var a = new A();
        a.event1 += a_event1;
        a.event2 += a_event1;
    }

    static void a_event1(object sender, EventArgs e)
    {}
}

public class A
{
    public event EventHandler<EventArgs>        event1;
    public event EventHandler<EventArgsDerived> event2;
}

public class EventArgsDerived : EventArgs
{}
通用
TEventArgs
参数的定义没有在关键字中使用


因此,如何支持逆变以及编译器如何接受事件处理程序的
EventArgs
类型的基类参数?

逆变是通过在标准事件处理模式中使用
EventArgs
基类隐式实现的,而
TEventArgs
仅用作输入参数

您所指的差异(使用
in
out
)用于类型转换,例如:

var a = new EventHandler<EventArgs>((o, e) => { return; });
var b = new EventHandler<ErrorEventArgs>((o, e) => { return; });
b = a;
您将通用协方差/逆变换与方法组转换方差混淆

正如您所观察到的,由于在
关键字中缺少,EventHandler在其类型参数中不支持泛型逆变。在C#4.0中添加了这种类型的方差


但由于方法组转换的差异,您仍然可以分配在参数列表中采用较少派生类型的处理程序。这是C#2.0中添加的一种较旧类型的差异支持。您可以在Eric Lipperts中阅读更多关于它的信息。

您如何说它支持逆变?请举个例子?MSDN文档说明学员支持差异;它没有特别讨论事件处理程序。
KeyDown
MouseClick
没有使用
EventHandler
。它们自己声明单独的处理程序。参考这个@Sriram Sakthivel:没错。我修改了这个例子。@Dennis_E:是的,但事件中的事件处理程序是支持反向的委托。我查找了定义,并希望在关键字中找到。它给出了编译错误,因为它违反了构造函数参数。若你们像我的例子那个样在赋值中使用方法名,它将被编译。那个么为什么在第二种情况下它不生成一个错误呢?这样看,在您的例子中,event1需要一个对象作为第一个参数,一个EventArgs作为第二个参数,因此它不关心您是否向它传递了ErrorEventArgs或从EventArgs派生的任何其他内容。它所需要的只是EventArgs的功能。这正是委托中的矛盾问题和关键字中的需求。在您的情况下,
行动
被定义为
公共代表无效行动(T obj)
和具有关键字。是的,这就是为什么我不能将EventHandler强制转换为EventHandler,但我可以使用EventHander委托而不是EventHandler委托。如果泛型参数与in关键字(如“Action”)一起使用,这是允许的。我的问题是“EventHandler”中不存在此关键字。
var a = new EventHandler<EventArgs>((o, e) => { return; });
var b = new EventHandler<ErrorEventArgs>((o, e) => { return; });
b = a;
var x = new Action<EventArgs>((e) => { return; });
var y = new Action<ErrorEventArgs>((e) => { return; });
y = x;