Насколько неправильно создавать делегат обработчика событий без стандартной подписи (Obj sender, EventArgs args)? - PullRequest
13 голосов
/ 21 июля 2009

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

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

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

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

Ответы [ 3 ]

10 голосов
/ 21 июля 2009

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

Edit:

Анализ кода CA1003: Использовать универсальные экземпляры обработчиков событий
Анализ кода CA1009: правильно объявить обработчики событий

6 голосов
/ 21 июля 2009

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

Так что я заключу с тобой сделку. Если вы пообещаете сделать это правильно, я дам вам фрагмент кода, который облегчит вам задачу. Просто поместите это в файл .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>
4 голосов
/ 21 июля 2009

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

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

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...