C#编程中,“On”前缀在事件情况下实现了什么?

5
我觉得在使用“On”作为C#方法前缀方面存在相当的混淆。
在MSDN文章“处理和引发事件”https://msdn.microsoft.com/en-us/library/edzehd2t(v=vs.110).aspx中,它说:
通常,要引发一个事件,您需要添加一个标记为受保护和虚拟(在C#中)或Protected和Overridable(在Visual Basic中)的方法。将此方法命名为OnEventName;例如,OnDataReceived。该方法应该接受一个参数,指定事件数据对象。您提供此方法以使派生类能够重写引发事件的逻辑。派生类应始终调用基类的OnEventName方法,以确保已注册的委托接收事件。

表明 On... 方法是用于引发事件的。然而,在许多编码示例中,甚至包括 Microsoft 提供的一些示例,我们可以看到 On 方法被用作事件处理程序,例如此处 https://msdn.microsoft.com/en-us/windows/uwp/gaming/tutorial--adding-move-look-controls-to-your-directx-game?f=255&MSPPError=-2147217396

首先,让我们填充鼠标和触摸指针事件处理程序。在第一个事件处理程序 OnPointerPressed() 中,当用户单击鼠标或在查看控制器区域触摸屏幕时,我们从管理我们显示的 CoreWindow 中获取指针的 x-y 坐标。

void MoveLookController::OnPointerPressed(
_In_ CoreWindow^ sender,
_In_ PointerEventArgs^ args)
{
    // Get the current pointer position.
    uint32 pointerID = args->CurrentPoint->PointerId;
    DirectX::XMFLOAT2 position = DirectX::XMFLOAT2( args->CurrentPoint->Position.X, args->CurrentPoint->Position.Y );

    auto device = args->CurrentPoint->PointerDevice;
    auto deviceType = device->PointerDeviceType;
    if ( deviceType == PointerDeviceType::Mouse )
    {
        // Action, Jump, or Fire
    }

    // Check  if this pointer is in the move control.
    // Change the values  to percentages of the preferred screen resolution.
    // You can set the x value to <preferred resolution> * <percentage of width>
    // for example, ( position.x < (screenResolution.x * 0.15) ).

    if (( position.x < 300 && position.y > 380 ) && ( deviceType != PointerDeviceType::Mouse ))
    {
        if ( !m_moveInUse ) // if no pointer is in this control yet
        {
            // Process a DPad touch down event.
            m_moveFirstDown = position;                 // Save the location of the initial contact.
            m_movePointerPosition = position;
            m_movePointerID = pointerID;                // Store the id of the pointer using this control.
            m_moveInUse = TRUE;
        }
    }
    else // This pointer must be in the look control.
    {
        if ( !m_lookInUse ) // If no pointer is in this control yet...
        {
            m_lookLastPoint = position;                         // save the point for later move
            m_lookPointerID = args->CurrentPoint->PointerId;  // store the id of pointer using this control
            m_lookLastDelta.x = m_lookLastDelta.y = 0;          // these are for smoothing
            m_lookInUse = TRUE;
        }
    }
}

我的问题是:

  1. 是否确实存在关于“On”前缀用法的歧义,还是只是我的误解?人们是否真的在引发处理事件方法中都使用“On”?
  2. 实现引发处理事件方法的标准样式是什么?流行的样式有哪些?你建议使用哪种样式?

虽然我个人认为这是一个有趣的问题,但这个问题是否应该被视为离题?正如所使用的标签“编码风格”的描述已经表明的那样,这是一个完全基于个人观点的主题,因此这个标签不应再被使用,因为它是离题的。因为我对此不确定,所以我没有提出旗帜,但我希望有人能为我解释/阐述一下。在 meta 上也没有找到任何有用的东西。但是 http://codereview.stackexchange.com/ 可能是这个问题的正确场所? - Chris Schmitz
1
我认为这是一个有效的问题,但OP混淆了编码风格和惯用模式。前者是主观的,后者则不是。使用受保护的虚拟OnEvenName方法来引发事件确实是一种惯用模式,应该遵循(请参见https://dev59.com/PHRA5IYBdhLWcg3w_DHF和/或https://msdn.microsoft.com/en-us/library/hy3sefw3.aspx)。现在,将事件*处理程序*(外部于事件源)命名为`OnEventName`更多的是编码风格而不是模式,它是一个(稍微令人困惑的)巧合,它们最终被命名为相同的名称。 - GSerg
你引用的文章根本没有使用 .NET。因此,它并不是一个使用 .NET 约定的好指南。这也只是事件处理程序方法,而不是触发事件的事件或方法。你已经知道正确的 MSDN 页面,第一个链接,所以直接使用它即可。 - Hans Passant
1个回答

2
对于触发事件的类:当“某个条件”发生时,在该类中调用方法OnSomeCondition()是有意义的。然后,如果您想要通知外部方关于此条件,您需要在OnSomeCondition()方法中引发一个名为SomeCondition的事件。
对于处理事件的类:当Visual Studio自动生成处理程序方法时,它将其命名为someClass_SomeCondition(至少在C#中是这样的,这也是您标记问题的语言)。然而,第二段文档摘录和示例并不是C#,这可能解释了差异(我不知道是否有一个“官方”的事件处理程序命名约定)。
但是,当您从引发事件的类继承,并且基类遵循了protected virtual建议时,“事件”一词变得模糊:您仍然可以处理SomeCondition事件,但您也可以选择重写OnSomeCondition()方法。
因此,我不会说On前缀“用于引发事件”,而是“用于处理条件”,并且您可以选择在OnCondition()方法中引发事件-对于消费方,您可以处理事件或覆盖OnCondition()行为。这也是第一个文档摘录所说的:
“您提供此方法以使派生类能够覆盖引发事件的逻辑。”

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接