Насколько неправильно создавать делегат обработчика событий без стандартной подписи (Obj sender, EventArgs args)?

StackOverflow https://stackoverflow.com/questions/1157072

  •  18-09-2019
  •  | 
  •  

Вопрос

Я понимаю преимущества использования стандартной подписи делегата обработчика событий MS, поскольку она позволяет вам легко расширять информацию, передаваемую через событие, не нарушая никаких старых связей, основанных на старой подписи делегата.

Что мне интересно, так это как часто люди следуют этому правилу на практике?Допустим, у меня есть такое простое событие, как это

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

Это простое событие, и я почти уверен, что единственные аргументы, которые мне когда-либо понадобится узнать из события NameChanged, - это объект, имя которого изменилось, старое имя и новое имя.Итак, стоит ли создавать отдельный класс NameChangedEventArgs, или для простых событий, подобных этому, приемлемо ли просто возвращать аргументы непосредственно через аргументы делегата?

Это было полезно?

Решение

Вы можете сделать что угодно неправильно, если вы единственный, кому приходится с этим иметь дело.Но неплохо было бы изучить стандарты и придерживаться их, чтобы сохранить хорошие привычки, когда вы работаете над кодом вместе с другими.

Так что я заключу с тобой сделку.Если вы пообещаете сделать это правильно, я дам вам фрагмент кода, который сделает это гораздо менее болезненным.Просто поместите это в файл .snippet и вставьте этот файл:

Мои документы\Visual Studio 2008\Фрагменты кода\Visual C#\Мои фрагменты кода\
(или 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>

Другие советы

Использовать EventHandler<T> универсальные делегаты для ваших событий и создайте тип, производный от EventArgs для хранения данных вашего мероприятия.Другими словами, всегда.Это то, что вы всегда точно знаете, как это работает, когда сталкиваетесь с этим, потому что иначе никогда не делалось.

Редактировать:

Анализ кода СА1003:Используйте общие экземпляры обработчиков событий.
Анализ кода СА1009:Объявляйте обработчики событий правильно

На практике, как часто люди [не используют производные классы EventArgs].

Я никогда не сталкивался с тем, чтобы производные от EventArgs классы не использовались.Как вы сами сказали, это увеличивает вашу способность изменять свой код позже.Я бы также сказал, что читаемость улучшена, поскольку легко увидеть, что это обработчик событий.

Стоит ли создавать отдельный класс NameChangedEventArgs, или для простых событий, подобных этому, приемлемо ли просто возвращать аргументы непосредственно через аргументы делегата?

Кажется, вы говорили, что вы бы использовали EventArgs для обработчиков событий с большим количеством параметров и не использовали бы его для подобных случаев.Честно говоря, это просто невозможно при программировании на C #.Последовательность обязательна, особенно в современном мире подобных форумов, проектов с открытым исходным кодом и т.д., где ее легко потерять.Конечно, если вы программируете это под прикрытием, вы можете делать все, что вам нравится, но более широкое сообщество C # поблагодарит вас за соблюдение стандартов и особенно за использование согласованности в вашем коде.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top