为什么在 Visual Studio 中自动创建事件处理程序时使用 Object Sender

Why do event handlers use Object Sender when being automatically created in Visual Studio

例如,如果我有:

初始化控件

MyControl mc = new MyControl();
mc.MouseUp += mc_MouseUp;

事件处理器

void mc_MouseUp(object sender, MouseButtonEventArgs e)
{
    //annoying cast...
    MyControl control = (MyControl)sender;

    //Do some stuff to MyControl
}

这不是暗示 sender 将永远是一个 MyControl 对象吗?

但是事件处理程序

void mc_MouseUp(MyObject sender, MouseButtonEventArgs e)
{
}

报错:

No Overload for mc_MouseDown matches delegate System.Windows.Input.MouseButtonEventHandler

这是为什么?

No Overload for mc_MouseDown matches delegate System.Windows.Input.MouseButtonEventHandler

因为 MouseEventHandler 事件处理程序声明为

public delegate void MouseEventHandler(
    Object sender,
    MouseEventArgs e
)

您需要引用相同的签名。

备注

如果是这样的话

public delegate void MouseEventHandler(
    MyObject sender,
    MouseEventArgs e
)

那么两个签名都有效。

My point is you can make scope big not small by specifying MyObject as first parameter instead of object.

它是决定其事件签名的控件(它想使用什么代表),大多数事件签名总是使用第一个参数sender 类型 object。在 guidelines:

之后
  • The return type is Void.

  • The first parameter is named sender and is of type Object. This is the object that raised the event.

  • The second parameter is named e and is of type EventArgs or a derived class of EventArgs.This is the event-specific data.

您可以使用相同的处理程序代码来侦听来自不同类型的多个控件的多个事件,因此限制发送者类型不一定好。

在 .NET 3.5 中引入 delegate variance 之前,这些指南更有意义。

is it not implicit that sender will always be a MyControl object?

没有。 mc_MouseUp 只是一个定义的方法,它匹配 MouseUp 的委托签名。任何调用者都可以在 class 内部调用它(如果声明为 private),它可以传递任意 object。如果您从 Control 派生的类型决定将 FooBar 作为对象发送者发送,他可以这样做。

No Overload for mc_MouseDown matches delegate System.Windows.Input.MouseButtonEventHandler

Why is this?

规范规定:

• For each value parameter (a parameter with no ref or out modifier), an identity conversion (§6.1.1) or implicit reference conversion (§6.1.6) exists from the parameter type in D to the corresponding parameter type in M.

由于不存在从 objectMyObject 的标识或隐式引用转换,因此无法编译。