C# 创建没有标准(Obj sender,EventArgs args)签名的事件处理程序委托有多大的错误?

C# 创建没有标准(Obj sender,EventArgs args)签名的事件处理程序委托有多大的错误?,c#,events,eventargs,C#,Events,Eventargs,我理解使用标准MS事件处理程序委托签名的好处,因为它允许您轻松地扩展通过事件传递的信息,而不会破坏任何基于旧委托签名的旧关系 我想知道的是,在实践中,人们遵循这条规则的频率是多少?假设我有一个像这样的简单事件 public event NameChangedHandler NameChanged; public delegate void NameChangedHandler(Object sender, string oldName, string newName); 这是一个简单的事件,我

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

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

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

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

为事件使用
EventHandler
通用委托,并创建一个派生自
EventArgs
的类型来保存事件数据。换句话说,永远如此。当你遇到它时,你总是确切地知道它是如何工作的,因为它从来没有以其他方式做过

编辑:

代码分析

代码分析

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

所以我跟你做个交易。如果你保证用正确的方法来做,我会给你一个代码片段,这会让你不那么痛苦。只需将其放入.snippet文件,然后将该文件放入:

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

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

<?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>

具有两种类型/参数的泛型事件。
EV2通用
事件处理程序和方法的代码段
基拉莱萨
膨胀
类型1
EventArgs子类中第一个属性的类型。
属性类型1
arg1名称
EventArgs子类构造函数中第一个参数的名称。
物业名称
物业名称
EventArgs子类中第一个属性的名称。
物业名称
类型2
EventArgs子类中第二个属性的类型。
属性类型2
arg2名称
EventArgs子类构造函数中第二个参数的名称。
物业名称
物业名称
EventArgs子类中第二个属性的名称。
物业名称
事件名
活动名称
事件名称

$eventName$;
$eventName$($eventName$EventArgs e)上受保护的虚拟空间
{
变量处理程序=$eventName$;
if(处理程序!=null)
处理者(本,e);
}]]>

实际上,人们[不]的频率是多少 使用EventArgs派生类]

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

是否值得创建一个单独的 NameChangedEventArgs类,或 像这样的简单事件就是这样 可接受只退还 直接通过 委托参数


您似乎说您将对具有更多参数的事件处理程序使用EventArgs,而不是对这样的实例使用它。老实说,在用C语言编程时,这根本不是一个选项。一致性是必须的,尤其是在今天这样的论坛、开放源码项目等领域,很容易失去一致性。当然,如果你是在石头下编程,你可以做任何你想做的事情,但更大的C#社区会感谢你遵循标准,尤其是在代码中使用一致性。

当然,你可以调整它,只拥有一个或三个属性,或者任意多个属性。我有1、2或3个属性的代码段,以及创建没有特定事件数据的事件的简单示例。我知道这是一个旧答案,但我只想添加指向此线程的链接:。我认为,如果一个惯例会导致糟糕的编码实践(例如,抛出
发送者
参数),那么就没有理由武断地遵循它。
EventArgs
类本身也没有任何好处,尽管您可能会认为最好包装传递的数据以保持源代码的兼容性。@Groo,这是一个有趣的想法。我以前没见过那根线。请注意,这里提出问题的人说的是使用具有两个以上属性的事件处理程序委托,而不是使用标准的
sender、EventArgs
模式。这里讨论的问题不是如何使用
sender
,而是是否使用单个
EventArgs
EventArgs
参数而不是多个参数。哦,没错,我读得不够透彻。我得到了
CA1009
设计警告,在谷歌上搜索了一下,看看大家对它有什么看法,因为我想抑制它,却意外地发现了这一点。呃,它发生了。:)我真的很讨厌没有解释的情况。@JhonnyD.Cano-Leftware-,我发布的代码片段使用了
EventHandler
。是的,这确实是我的问题。如果它是一个复杂的事件,那么我理解为什么您希望灵活使用EventArgs。但如果这是一件简单的事情,我可以99%确定我知道我需要的所有论据,我不确定这对cr是否真的重要