13

我了解使用标准 MS 事件处理程序委托签名的好处,因为它允许您轻松扩展通过事件传递的信息,而不会破坏任何基于旧委托签名的旧关系。

我想知道的是,在实践中,人们遵循这条规则的频率如何?假设我有一个像这样的简单事件

public event NameChangedHandler NameChanged;
public delegate void NameChangedHandler(Object sender, string oldName, string newName);

这是一个简单的事件,我几乎可以肯定,我需要从 NameChanged 事件中知道的唯一参数是名称更改的对象、旧名称和新名称。那么创建一个单独的 NameChangedEventArgs 类是否值得,或者对于像这样的简单事件,直接通过委托参数返回参数是否可以接受?

4

3 回答 3

10

为您的事件使用EventHandler<T>通用委托并创建一个派生自的类型EventArgs来保存您的事件数据。换句话说,总是。当你遇到它时,你总是知道它是如何工作的,因为它从来没有做过。

编辑:

代码分析CA1003:使用通用事件处理程序实例
代码分析CA1009:正确声明事件处理程序

于 2009-07-21T03:04:37.613 回答
6

如果你是唯一一个必须处理它的人,那么你可以用错误的方式做任何事情。但是学习标准并遵守它们并不是一个坏主意,这样当你与他人一起编写代码时,你就会保持良好的习惯。

所以我给你做个交易。如果您承诺以正确的方式进行操作,我会给您一个代码片段,这将减少您的痛苦。只需将其放入 .snippet 文件中,然后将该文件放入:

我的文档\Visual Studio 2008\Code Snippets\Visual C#\My Code Snippets\
(或 Visual Studio 2005,如果适用)

这是片段;通过键入 ev2Generic 并点击 Tab 在 VS 中使用它:

<?xml version="1.0" encoding="utf-8" ?>
<CodeSnippets  xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">
  <CodeSnippet Format="1.0.0">
    <Header>
      <Title>Generic event with two types/arguments.</Title>
      <Shortcut>ev2Generic</Shortcut>
      <Description>Code snippet for event handler and On method</Description>
      <Author>Kyralessa</Author>
      <SnippetTypes>
        <SnippetType>Expansion</SnippetType>
      </SnippetTypes>
    </Header>
    <Snippet>
      <Declarations>
        <Literal>
          <ID>type1</ID>
          <ToolTip>Type of the first property in the EventArgs subclass.</ToolTip>
          <Default>propertyType1</Default>
        </Literal>
        <Literal>
          <ID>arg1Name</ID>
          <ToolTip>Name of the first argument in the EventArgs subclass constructor.</ToolTip>
          <Default>property1Name</Default>
        </Literal>
        <Literal>
          <ID>property1Name</ID>
          <ToolTip>Name of the first property in the EventArgs subclass.</ToolTip>
          <Default>Property1Name</Default>
        </Literal>
        <Literal>
          <ID>type2</ID>
          <ToolTip>Type of the second property in the EventArgs subclass.</ToolTip>
          <Default>propertyType2</Default>
        </Literal>
        <Literal>
          <ID>arg2Name</ID>
          <ToolTip>Name of the second argument in the EventArgs subclass constructor.</ToolTip>
          <Default>property2Name</Default>
        </Literal>
        <Literal>
          <ID>property2Name</ID>
          <ToolTip>Name of the second property in the EventArgs subclass.</ToolTip>
          <Default>Property2Name</Default>
        </Literal>
        <Literal>
          <ID>eventName</ID>
          <ToolTip>Name of the event</ToolTip>
          <Default>NameOfEvent</Default>
        </Literal>
      </Declarations>
      <Code Language="CSharp">
        <![CDATA[public class $eventName$EventArgs : System.EventArgs
      {
        public $eventName$EventArgs($type1$ $arg1Name$, $type2$ $arg2Name$)
        {
          this.$property1Name$ = $arg1Name$;
          this.$property2Name$ = $arg2Name$;
        }

        public $type1$ $property1Name$ { get; private set; }
        public $type2$ $property2Name$ { get; private set; }
      }

      public event EventHandler<$eventName$EventArgs> $eventName$;
            protected virtual void On$eventName$($eventName$EventArgs e)
            {
                var handler = $eventName$;
                if (handler != null)
                    handler(this, e);
            }]]>
      </Code>
    </Snippet>
  </CodeSnippet>
</CodeSnippets>
于 2009-07-21T03:08:52.597 回答
4

在实践中,人们 [不使用 EventArgs 派生类] 的频率。

我从来没有遇到过没有使用 EventArgs 派生类的情况。正如您自己所说,它增加了您以后更改代码的能力。我还认为可读性得到了提高,因为很容易看出这是一个事件处理程序。

创建一个单独的 NameChangedEventArgs 类是否值得,或者对于像这样的简单事件,直接通过委托参数返回参数是否可以接受?

您似乎说您会将 EventArgs 用于具有更多参数的事件处理程序,而不是将其用于此类实例。老实说,在用 C# 编程时,这根本不是一个选择。一致性是必须的,尤其是在当今这样的论坛、开源项目等很容易失去一致性的世界中。当然,如果您正在对此进行编程,您可以做任何您喜欢的事情,但是更大的 C# 社区会感谢您遵循标准,尤其是在代码中使用一致性。

于 2009-07-21T03:15:38.857 回答